diff --git a/Cargo.lock b/Cargo.lock index 48d9fdb3d0..51d937d4dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,7 +9,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd" dependencies = [ "compiler_builtins", - "gimli", + "gimli 0.25.0", "rustc-std-workspace-alloc", "rustc-std-workspace-core", ] @@ -87,9 +87,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.34" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf8dcb5b4bbaa28653b647d8c77bd4ed40183b48882e130c1f1ffb73de069fd7" +checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203" [[package]] name = "array_tool" @@ -175,9 +175,7 @@ dependencies = [ "filetime", "getopts", "ignore", - "lazy_static", "libc", - "merge", "num_cpus", "once_cell", "opener", @@ -276,7 +274,7 @@ dependencies = [ [[package]] name = "cargo" -version = "0.59.0" +version = "0.60.0" dependencies = [ "anyhow", "atty", @@ -370,7 +368,7 @@ version = "0.1.0" dependencies = [ "directories", "rustc-workspace-hack", - "rustc_version 0.3.3", + "rustc_version", "serde", "serde_json", "vergen", @@ -419,7 +417,7 @@ dependencies = [ [[package]] name = "cargo-util" -version = "0.1.1" +version = "0.1.2" dependencies = [ "anyhow", "core-foundation", @@ -492,9 +490,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chalk-derive" -version = "0.55.0" +version = "0.75.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3983193cacd81f0f924acb666b7fe5e1a0d81db9f113fa69203eda7ea8ce8b6c" +checksum = "d54e3b5f9e3425e6b119ff07568d8d006bfa5a8d6f78a9cbc3530b1e962e316c" dependencies = [ "proc-macro2", "quote", @@ -504,9 +502,9 @@ dependencies = [ [[package]] name = "chalk-engine" -version = "0.55.0" +version = "0.75.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05a171ce5abbf0fbd06f221ab80ab182c7ef78603d23b858bc44e7ce8a86a396" +checksum = "bdc891073396b167163db77123b0a3c00088edc00466cecc5531f33e3e989523" dependencies = [ "chalk-derive", "chalk-ir", @@ -517,9 +515,9 @@ dependencies = [ [[package]] name = "chalk-ir" -version = "0.55.0" +version = "0.75.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a522f53af971e7678f472d687e053120157b3ae26e2ebd5ecbc0f5ab124f2cb6" +checksum = "2b79e5a1d04b79311e90c69356a2c62027853906a7e33b3e070b93c055fc3e8a" dependencies = [ "bitflags", "chalk-derive", @@ -528,14 +526,14 @@ dependencies = [ [[package]] name = "chalk-solve" -version = "0.55.0" +version = "0.75.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf79fb77a567e456a170f7ec84ea6584163d4ba3f13660cd182013d34ca667c" +checksum = "a5d2a1db6605aba70a58820bd80ac422b218913a510f1a40beef9efc5371ea1d" dependencies = [ "chalk-derive", "chalk-ir", "ena", - "itertools 0.9.0", + "itertools 0.10.1", "petgraph", "rustc-hash", "tracing", @@ -558,11 +556,11 @@ dependencies = [ [[package]] name = "clap" -version = "2.33.3" +version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ - "ansi_term 0.11.0", + "ansi_term 0.12.1", "atty", "bitflags", "strsim", @@ -574,7 +572,7 @@ dependencies = [ [[package]] name = "clippy" -version = "0.1.58" +version = "0.1.59" dependencies = [ "cargo_metadata 0.14.0", "clippy_lints", @@ -584,6 +582,7 @@ dependencies = [ "filetime", "if_chain", "itertools 0.10.1", + "parking_lot", "quote", "regex", "rustc-workspace-hack", @@ -600,6 +599,7 @@ name = "clippy_dev" version = "0.0.1" dependencies = [ "bytecount", + "cargo_metadata 0.14.0", "clap", "indoc", "itertools 0.10.1", @@ -611,13 +611,13 @@ dependencies = [ [[package]] name = "clippy_lints" -version = "0.1.58" +version = "0.1.59" dependencies = [ "cargo_metadata 0.14.0", "clippy_utils", "if_chain", "itertools 0.10.1", - "pulldown-cmark 0.8.0", + "pulldown-cmark", "quine-mc_cluskey", "regex-syntax", "rustc-semver", @@ -632,7 +632,7 @@ dependencies = [ [[package]] name = "clippy_utils" -version = "0.1.58" +version = "0.1.59" dependencies = [ "if_chain", "rustc-semver", @@ -678,9 +678,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.53" +version = "0.1.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2467ff455350a4df7d02f1ed1449d0279605a763de5d586dcf6aa7d732508bcb" +checksum = "a68c69e9451f1df4b215c9588c621670c12286b53e60fb5ec4b59aaa1138d18e" dependencies = [ "cc", "rustc-std-workspace-core", @@ -766,7 +766,7 @@ checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634" [[package]] name = "crates-io" -version = "0.33.0" +version = "0.33.1" dependencies = [ "anyhow", "curl", @@ -1158,6 +1158,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + [[package]] name = "filetime" version = "0.2.14" @@ -1446,6 +1452,17 @@ dependencies = [ "rustc-std-workspace-core", ] +[[package]] +name = "gimli" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" +dependencies = [ + "fallible-iterator", + "indexmap", + "stable_deref_trait", +] + [[package]] name = "git2" version = "0.13.23" @@ -1713,9 +1730,12 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.6" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b141fdc7836c525d4d594027d318c84161ca17aaf8113ab1f81ab93ae897485" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if 1.0.0", +] [[package]] name = "itertools" @@ -1900,9 +1920,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a60553f9a9e039a333b4e9b20573b9e9b9c0bb3a11e201ccc48ef4283456d673" +checksum = "8521a1b57e76b1ec69af7599e75e38e7b7fad6610f037db8c79b127201b5d119" dependencies = [ "rustc-std-workspace-core", ] @@ -1921,6 +1941,16 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "libloading" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cf036d15402bea3c5d4de17b3fce76b3e4a56ebc1f577be0e7a72f7c607cf0" +dependencies = [ + "cfg-if 1.0.0", + "winapi", +] + [[package]] name = "libm" version = "0.1.4" @@ -1939,9 +1969,9 @@ dependencies = [ [[package]] name = "libssh2-sys" -version = "0.2.19" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca46220853ba1c512fc82826d0834d87b06bcd3c2a42241b7de72f3d2fe17056" +checksum = "b094a36eb4b8b8c8a7b4b8ae43b2944502be3e59cd87687595cf6b0a71b3f4ca" dependencies = [ "cc", "libc", @@ -1992,9 +2022,9 @@ version = "0.1.0" [[package]] name = "lock_api" -version = "0.4.1" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28247cc5a5be2f05fbcd76dd0cf2c7d3b5400cb978a28042abcd4fa0b3f8261c" +checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" dependencies = [ "scopeguard", ] @@ -2092,9 +2122,9 @@ dependencies = [ [[package]] name = "matchers" -version = "0.0.1" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ "regex-automata", ] @@ -2124,9 +2154,9 @@ dependencies = [ [[package]] name = "mdbook" -version = "0.4.12" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0651782b4cc514c3f98c0acf9b5af1101a735bbe1ac6852bb1a90cb91bdf0ed4" +checksum = "241f10687eb3b4e0634b3b4e423f97c5f1efbd69dc9522e24a8b94583eeec3c6" dependencies = [ "ammonia", "anyhow", @@ -2138,8 +2168,8 @@ dependencies = [ "lazy_static", "log", "memchr", - "open", - "pulldown-cmark 0.7.2", + "opener", + "pulldown-cmark", "regex", "serde", "serde_derive", @@ -2147,6 +2177,7 @@ dependencies = [ "shlex", "tempfile", "toml", + "topological-sort", ] [[package]] @@ -2205,28 +2236,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "merge" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10bbef93abb1da61525bbc45eeaff6473a41907d19f8f9aa5168d214e10693e9" -dependencies = [ - "merge_derive", - "num-traits", -] - -[[package]] -name = "merge_derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "209d075476da2e63b4b29e72a2ef627b840589588e71400a25e3565c4f849d07" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "minifier" version = "0.0.41" @@ -2284,7 +2293,7 @@ dependencies = [ "measureme 9.1.2", "rand 0.8.4", "rustc-workspace-hack", - "rustc_version 0.4.0", + "rustc_version", "shell-escape", "smallvec", ] @@ -2347,6 +2356,18 @@ dependencies = [ "rustc-std-workspace-core", ] +[[package]] +name = "object" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" +dependencies = [ + "crc32fast", + "flate2", + "indexmap", + "memchr", +] + [[package]] name = "odht" version = "0.3.1" @@ -2374,15 +2395,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" -[[package]] -name = "open" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c283bf0114efea9e42f1a60edea9859e8c47528eae09d01df4b29c1e489cc48" -dependencies = [ - "winapi", -] - [[package]] name = "opener" version = "0.5.0" @@ -2511,9 +2523,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", @@ -2522,9 +2534,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" dependencies = [ "cfg-if 1.0.0", "instant", @@ -2796,9 +2808,9 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.7.2" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca36dea94d187597e104a5c8e4b07576a8a45aa5db48a65e12940d3eb7461f55" +checksum = "34f197a544b0c9ab3ae46c359a7ec9cbbb5c7bf97054266fecb7ead794a181d6" dependencies = [ "bitflags", "getopts", @@ -2806,17 +2818,6 @@ dependencies = [ "unicase", ] -[[package]] -name = "pulldown-cmark" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffade02495f22453cd593159ea2f59827aae7f53fa8323f756799b670881dcf8" -dependencies = [ - "bitflags", - "memchr", - "unicase", -] - [[package]] name = "punycode" version = "0.4.1" @@ -3085,15 +3086,15 @@ dependencies = [ "anyhow", "cargo", "cargo-util", - "cargo_metadata 0.12.0", + "cargo_metadata 0.14.0", "clippy_lints", "crossbeam-channel", "difference", - "env_logger 0.7.1", + "env_logger 0.9.0", "futures 0.3.12", "heck", "home", - "itertools 0.9.0", + "itertools 0.10.1", "jsonrpc-core", "lazy_static", "log", @@ -3102,7 +3103,7 @@ dependencies = [ "num_cpus", "ordslice", "racer", - "rand 0.7.3", + "rand 0.8.4", "rayon", "regex", "rls-analysis", @@ -3692,6 +3693,7 @@ dependencies = [ "rustc_expand", "rustc_feature", "rustc_lexer", + "rustc_lint_defs", "rustc_parse", "rustc_parse_format", "rustc_session", @@ -3708,6 +3710,7 @@ dependencies = [ "bitflags", "cstr", "libc", + "libloading", "measureme 10.0.0", "rustc-demangle", "rustc_arena", @@ -3728,7 +3731,6 @@ dependencies = [ "rustc_span", "rustc_target", "smallvec", - "snap", "tracing", ] @@ -3741,10 +3743,11 @@ dependencies = [ "itertools 0.9.0", "jobserver", "libc", - "object", + "object 0.26.2", "pathdiff", "regex", "rustc_apfloat", + "rustc_arena", "rustc_ast", "rustc_attr", "rustc_data_structures", @@ -3763,7 +3766,9 @@ dependencies = [ "rustc_symbol_mangling", "rustc_target", "smallvec", + "snap", "tempfile", + "thorin-dwp", "tracing", ] @@ -3823,7 +3828,6 @@ dependencies = [ name = "rustc_driver" version = "0.0.0" dependencies = [ - "atty", "libc", "rustc_ast", "rustc_ast_pretty", @@ -3837,6 +3841,7 @@ dependencies = [ "rustc_hir_pretty", "rustc_interface", "rustc_lint", + "rustc_log", "rustc_metadata", "rustc_middle", "rustc_parse", @@ -3848,8 +3853,6 @@ dependencies = [ "rustc_target", "rustc_typeck", "tracing", - "tracing-subscriber", - "tracing-tree", "winapi", ] @@ -3967,6 +3970,7 @@ dependencies = [ "arrayvec", "rustc_macros", "rustc_serialize", + "smallvec", ] [[package]] @@ -3992,6 +3996,7 @@ name = "rustc_interface" version = "0.0.0" dependencies = [ "libc", + "libloading", "rustc-rayon", "rustc-rayon-core", "rustc_ast", @@ -4090,6 +4095,17 @@ dependencies = [ "libc", ] +[[package]] +name = "rustc_log" +version = "0.0.0" +dependencies = [ + "atty", + "rustc_span", + "tracing", + "tracing-subscriber", + "tracing-tree", +] + [[package]] name = "rustc_macros" version = "0.1.0" @@ -4104,7 +4120,7 @@ dependencies = [ name = "rustc_metadata" version = "0.0.0" dependencies = [ - "libc", + "libloading", "odht", "rustc_ast", "rustc_attr", @@ -4124,7 +4140,6 @@ dependencies = [ "smallvec", "snap", "tracing", - "winapi", ] [[package]] @@ -4297,6 +4312,7 @@ dependencies = [ name = "rustc_plugin_impl" version = "0.0.0" dependencies = [ + "libloading", "rustc_ast", "rustc_errors", "rustc_hir", @@ -4590,15 +4606,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "rustc_version" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" -dependencies = [ - "semver 0.11.0", -] - [[package]] name = "rustc_version" version = "0.4.0" @@ -4616,7 +4623,7 @@ dependencies = [ "expect-test", "itertools 0.9.0", "minifier", - "pulldown-cmark 0.8.0", + "pulldown-cmark", "rayon", "regex", "rustdoc-json-types", @@ -5006,7 +5013,7 @@ dependencies = [ "hermit-abi", "libc", "miniz_oxide", - "object", + "object 0.26.2", "panic_abort", "panic_unwind", "profiler_builtins", @@ -5070,9 +5077,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" -version = "0.3.16" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de5472fb24d7e80ae84a7801b7978f95a19ec32cb1876faea59ab711eb901976" +checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c" dependencies = [ "clap", "lazy_static", @@ -5081,9 +5088,9 @@ dependencies = [ [[package]] name = "structopt-derive" -version = "0.4.9" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0eb37335aeeebe51be42e2dc07f031163fbabfa6ac67d7ea68b5c2f68d5f99" +checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ "heck", "proc-macro-error", @@ -5123,9 +5130,9 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.12.4" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ "proc-macro2", "quote", @@ -5262,24 +5269,36 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.20" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dfdd070ccd8ccb78f4ad66bf1982dc37f620ef696c6b5028fe2ed83dd3d0d08" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.20" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" dependencies = [ "proc-macro2", "quote", "syn", ] +[[package]] +name = "thorin-dwp" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "039d1fc0bfdb73910c2702893515580e38c192f47a987bc98ddd38a36f2d953a" +dependencies = [ + "gimli 0.26.1", + "indexmap", + "object 0.27.1", + "tracing", +] + [[package]] name = "thread_local" version = "1.0.1" @@ -5393,6 +5412,12 @@ dependencies = [ "serde", ] +[[package]] +name = "topological-sort" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa7c7f42dea4b1b99439786f5633aeb9c14c1b53f75e282803c2ec2ad545873c" + [[package]] name = "tower-service" version = "0.3.1" @@ -5401,9 +5426,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84f96e095c0c82419687c20ddf5cb3eadb61f4e1405923c9dc8e53a1adacbda8" +checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" dependencies = [ "cfg-if 1.0.0", "pin-project-lite", @@ -5413,9 +5438,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4f915eb6abf914599c200260efced9203504c4c37380af10cdf3b7d36970650" +checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e" dependencies = [ "proc-macro2", "quote", @@ -5442,49 +5467,34 @@ dependencies = [ "tracing-core", ] -[[package]] -name = "tracing-serde" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b" -dependencies = [ - "serde", - "tracing-core", -] - [[package]] name = "tracing-subscriber" -version = "0.2.16" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ab8966ac3ca27126141f7999361cc97dd6fb4b71da04c02044fa9045d98bb96" +checksum = "245da694cc7fc4729f3f418b304cb57789f1bed2a78c575407ab8a23f53cb4d3" dependencies = [ "ansi_term 0.12.1", - "chrono", "lazy_static", "matchers", "parking_lot", "regex", - "serde", - "serde_json", "sharded-slab", "smallvec", "thread_local", "tracing", "tracing-core", "tracing-log", - "tracing-serde", ] [[package]] name = "tracing-tree" -version = "0.1.9" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1712b40907f8d9bc2bc66763ab61dec914b7123d7149e59feb0d4e2a95fc4967" +checksum = "3ce989c9962c7f61fe084dd4a230eec784649dfc2392467c790007c3a6e134e7" dependencies = [ "ansi_term 0.12.1", "atty", - "termcolor", - "tracing", + "tracing-core", "tracing-log", "tracing-subscriber", ] diff --git a/RELEASES.md b/RELEASES.md index bee6da2e67..37b41d2642 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,184 @@ +Version 1.59.0 (2022-02-24) +========================== + +Language +-------- + +- [Stabilize default arguments for const generics][90207] +- [Stabilize destructuring assignment][90521] +- [Relax private in public lint on generic bounds and where clauses of trait impls][90586] +- [Stabilize asm! and global_asm! for x86, x86_64, ARM, Aarch64, and RISC-V][91728] + +Compiler +-------- + +- [Stabilize new symbol mangling format, leaving it opt-in (-Csymbol-mangling-version=v0)][90128] +- [Emit LLVM optimization remarks when enabled with `-Cremark`][90833] +- [Fix sparc64 ABI for aggregates with floating point members][91003] +- [Warn when a `#[test]`-like built-in attribute macro is present multiple times.][91172] +- [Add support for riscv64gc-unknown-freebsd][91284] +- [Stabilize `-Z emit-future-incompat` as `--json future-incompat`][91535] +- [Soft disable incremental compilation][94124] + +This release disables incremental compilation, unless the user has explicitly +opted in via the newly added RUSTC_FORCE_INCREMENTAL=1 environment variable. +This is due to a known and relatively frequently occurring bug in incremental +compilation, which causes builds to issue internal compiler errors. This +particular bug is already fixed on nightly, but that fix has not yet rolled out +to stable and is deemed too risky for a direct stable backport. + +As always, we encourage users to test with nightly and report bugs so that we +can track failures and fix issues earlier. + +See [94124] for more details. + +[94124]: https://github.com/rust-lang/rust/issues/94124 + +Libraries +--------- + +- [Remove unnecessary bounds for some Hash{Map,Set} methods][91593] + +Stabilized APIs +--------------- + +- [`std::thread::available_parallelism`][available_parallelism] +- [`Result::copied`][result-copied] +- [`Result::cloned`][result-cloned] +- [`arch::asm!`][asm] +- [`arch::global_asm!`][global_asm] +- [`ops::ControlFlow::is_break`][is_break] +- [`ops::ControlFlow::is_continue`][is_continue] +- [`TryFrom for u8`][try_from_char_u8] +- [`char::TryFromCharError`][try_from_char_err] + implementing `Clone`, `Debug`, `Display`, `PartialEq`, `Copy`, `Eq`, `Error` +- [`iter::zip`][zip] +- [`NonZeroU8::is_power_of_two`][is_power_of_two8] +- [`NonZeroU16::is_power_of_two`][is_power_of_two16] +- [`NonZeroU32::is_power_of_two`][is_power_of_two32] +- [`NonZeroU64::is_power_of_two`][is_power_of_two64] +- [`NonZeroU128::is_power_of_two`][is_power_of_two128] +- [`DoubleEndedIterator for ToLowercase`][lowercase] +- [`DoubleEndedIterator for ToUppercase`][uppercase] +- [`TryFrom<&mut [T]> for [T; N]`][tryfrom_ref_arr] +- [`UnwindSafe for Once`][unwindsafe_once] +- [`RefUnwindSafe for Once`][refunwindsafe_once] +- [armv8 neon intrinsics for aarch64][stdarch/1266] + +Const-stable: + +- [`mem::MaybeUninit::as_ptr`][muninit_ptr] +- [`mem::MaybeUninit::assume_init`][muninit_init] +- [`mem::MaybeUninit::assume_init_ref`][muninit_init_ref] +- [`ffi::CStr::from_bytes_with_nul_unchecked`][cstr_from_bytes] + +Cargo +----- + +- [Stabilize the `strip` profile option][cargo/10088] +- [Stabilize future-incompat-report][cargo/10165] +- [Support abbreviating `--release` as `-r`][cargo/10133] +- [Support `term.quiet` configuration][cargo/10152] +- [Remove `--host` from cargo {publish,search,login}][cargo/10145] + +Compatibility Notes +------------------- + +- [Refactor weak symbols in std::sys::unix][90846] + This may add new, versioned, symbols when building with a newer glibc, as the + standard library uses weak linkage rather than dynamically attempting to load + certain symbols at runtime. +- [Deprecate crate_type and crate_name nested inside `#![cfg_attr]`][83744] + This adds a future compatibility lint to supporting the use of cfg_attr + wrapping either crate_type or crate_name specification within Rust files; + it is recommended that users migrate to setting the equivalent command line + flags. +- [Remove effect of `#[no_link]` attribute on name resolution][92034] + This may expose new names, leading to conflicts with preexisting names in a + given namespace and a compilation failure. +- [Cargo will document libraries before binaries.][cargo/10172] +- [Respect doc=false in dependencies, not just the root crate][cargo/10201] +- [Weaken guarantee around advancing underlying iterators in zip][83791] +- [Make split_inclusive() on an empty slice yield an empty output][89825] +- [Update std::env::temp_dir to use GetTempPath2 on Windows when available.][89999] +- [unreachable! was updated to match other formatting macro behavior on Rust 2021][92137] + +Internal Changes +---------------- + +These changes provide no direct user facing benefits, but represent significant +improvements to the internals and overall performance of rustc +and related tools. + +- [Fix many cases of normalization-related ICEs][91255] +- [Replace dominators algorithm with simple Lengauer-Tarjan][85013] +- [Store liveness in interval sets for region inference][90637] + +- [Remove `in_band_lifetimes` from the compiler and standard library, in preparation for removing this + unstable feature.][91867] + +[91867]: https://github.com/rust-lang/rust/issues/91867 +[83744]: https://github.com/rust-lang/rust/pull/83744/ +[83791]: https://github.com/rust-lang/rust/pull/83791/ +[85013]: https://github.com/rust-lang/rust/pull/85013/ +[89825]: https://github.com/rust-lang/rust/pull/89825/ +[89999]: https://github.com/rust-lang/rust/pull/89999/ +[90128]: https://github.com/rust-lang/rust/pull/90128/ +[90207]: https://github.com/rust-lang/rust/pull/90207/ +[90521]: https://github.com/rust-lang/rust/pull/90521/ +[90586]: https://github.com/rust-lang/rust/pull/90586/ +[90637]: https://github.com/rust-lang/rust/pull/90637/ +[90833]: https://github.com/rust-lang/rust/pull/90833/ +[90846]: https://github.com/rust-lang/rust/pull/90846/ +[91003]: https://github.com/rust-lang/rust/pull/91003/ +[91172]: https://github.com/rust-lang/rust/pull/91172/ +[91255]: https://github.com/rust-lang/rust/pull/91255/ +[91284]: https://github.com/rust-lang/rust/pull/91284/ +[91535]: https://github.com/rust-lang/rust/pull/91535/ +[91593]: https://github.com/rust-lang/rust/pull/91593/ +[91728]: https://github.com/rust-lang/rust/pull/91728/ +[91878]: https://github.com/rust-lang/rust/pull/91878/ +[91896]: https://github.com/rust-lang/rust/pull/91896/ +[91926]: https://github.com/rust-lang/rust/pull/91926/ +[91984]: https://github.com/rust-lang/rust/pull/91984/ +[92020]: https://github.com/rust-lang/rust/pull/92020/ +[92034]: https://github.com/rust-lang/rust/pull/92034/ +[92483]: https://github.com/rust-lang/rust/pull/92483/ +[cargo/10088]: https://github.com/rust-lang/cargo/pull/10088/ +[cargo/10133]: https://github.com/rust-lang/cargo/pull/10133/ +[cargo/10145]: https://github.com/rust-lang/cargo/pull/10145/ +[cargo/10152]: https://github.com/rust-lang/cargo/pull/10152/ +[cargo/10165]: https://github.com/rust-lang/cargo/pull/10165/ +[cargo/10172]: https://github.com/rust-lang/cargo/pull/10172/ +[cargo/10201]: https://github.com/rust-lang/cargo/pull/10201/ +[cargo/10269]: https://github.com/rust-lang/cargo/pull/10269/ + +[cstr_from_bytes]: https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html#method.from_bytes_with_nul_unchecked +[muninit_ptr]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.as_ptr +[muninit_init]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.assume_init +[muninit_init_ref]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.assume_init_ref +[unwindsafe_once]: https://doc.rust-lang.org/stable/std/sync/struct.Once.html#impl-UnwindSafe +[refunwindsafe_once]: https://doc.rust-lang.org/stable/std/sync/struct.Once.html#impl-RefUnwindSafe +[tryfrom_ref_arr]: https://doc.rust-lang.org/stable/std/convert/trait.TryFrom.html#impl-TryFrom%3C%26%27_%20mut%20%5BT%5D%3E +[lowercase]: https://doc.rust-lang.org/stable/std/char/struct.ToLowercase.html#impl-DoubleEndedIterator +[uppercase]: https://doc.rust-lang.org/stable/std/char/struct.ToUppercase.html#impl-DoubleEndedIterator +[try_from_char_err]: https://doc.rust-lang.org/stable/std/char/struct.TryFromCharError.html +[available_parallelism]: https://doc.rust-lang.org/stable/std/thread/fn.available_parallelism.html +[result-copied]: https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.copied +[result-cloned]: https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.cloned +[asm]: https://doc.rust-lang.org/stable/core/arch/macro.asm.html +[global_asm]: https://doc.rust-lang.org/stable/core/arch/macro.global_asm.html +[is_break]: https://doc.rust-lang.org/stable/std/ops/enum.ControlFlow.html#method.is_break +[is_continue]: https://doc.rust-lang.org/stable/std/ops/enum.ControlFlow.html#method.is_continue +[try_from_char_u8]: https://doc.rust-lang.org/stable/std/primitive.char.html#impl-TryFrom%3Cchar%3E +[zip]: https://doc.rust-lang.org/stable/std/iter/fn.zip.html +[is_power_of_two8]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroU8.html#method.is_power_of_two +[is_power_of_two16]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroU16.html#method.is_power_of_two +[is_power_of_two32]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroU32.html#method.is_power_of_two +[is_power_of_two64]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroU64.html#method.is_power_of_two +[is_power_of_two128]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroU128.html#method.is_power_of_two +[stdarch/1266]: https://github.com/rust-lang/stdarch/pull/1266 + Version 1.58.1 (2022-01-19) =========================== @@ -7,7 +188,7 @@ Version 1.58.1 (2022-01-19) * [Fix wrong error message displayed when some imports are missing][91254] * [Fix rustfmt not formatting generated files from stdin][92912] -[CVE-2022-21658]: https://www.cve.org/CVERecord?id=CVE-2022-21658] +[CVE-2022-21658]: https://www.cve.org/CVERecord?id=CVE-2022-21658 [91254]: https://github.com/rust-lang/rust/pull/91254 [92912]: https://github.com/rust-lang/rust/pull/92912 [clippy/8075]: https://github.com/rust-lang/rust-clippy/pull/8075 @@ -58,7 +239,6 @@ Stabilized APIs - [`Option::unwrap_unchecked`] - [`Result::unwrap_unchecked`] - [`Result::unwrap_err_unchecked`] -- [`NonZero{unsigned}::is_power_of_two`] - [`File::options`] These APIs are now usable in const contexts: @@ -71,10 +251,6 @@ These APIs are now usable in const contexts: - [`Duration::checked_mul`] - [`Duration::saturating_mul`] - [`Duration::checked_div`] -- [`MaybeUninit::as_ptr`] -- [`MaybeUninit::as_mut_ptr`] -- [`MaybeUninit::assume_init`] -- [`MaybeUninit::assume_init_ref`] Cargo ----- @@ -115,19 +291,14 @@ and related tools. [87467]: https://github.com/rust-lang/rust/pull/87467/ [87704]: https://github.com/rust-lang/rust/pull/87704/ [88041]: https://github.com/rust-lang/rust/pull/88041/ -[88300]: https://github.com/rust-lang/rust/pull/88300/ [88447]: https://github.com/rust-lang/rust/pull/88447/ [88601]: https://github.com/rust-lang/rust/pull/88601/ -[88624]: https://github.com/rust-lang/rust/pull/88624/ [89062]: https://github.com/rust-lang/rust/pull/89062/ [89174]: https://github.com/rust-lang/rust/pull/89174/ -[89542]: https://github.com/rust-lang/rust/pull/89542/ [89551]: https://github.com/rust-lang/rust/pull/89551/ [89558]: https://github.com/rust-lang/rust/pull/89558/ [89580]: https://github.com/rust-lang/rust/pull/89580/ [89652]: https://github.com/rust-lang/rust/pull/89652/ -[89677]: https://github.com/rust-lang/rust/pull/89677/ -[89951]: https://github.com/rust-lang/rust/pull/89951/ [90041]: https://github.com/rust-lang/rust/pull/90041/ [90058]: https://github.com/rust-lang/rust/pull/90058/ [90104]: https://github.com/rust-lang/rust/pull/90104/ @@ -143,11 +314,9 @@ and related tools. [90733]: https://github.com/rust-lang/rust/pull/90733/ [90833]: https://github.com/rust-lang/rust/pull/90833/ [90846]: https://github.com/rust-lang/rust/pull/90846/ -[90896]: https://github.com/rust-lang/rust/pull/90896/ [91026]: https://github.com/rust-lang/rust/pull/91026/ [91207]: https://github.com/rust-lang/rust/pull/91207/ [91255]: https://github.com/rust-lang/rust/pull/91255/ -[91301]: https://github.com/rust-lang/rust/pull/91301/ [cargo/10082]: https://github.com/rust-lang/cargo/pull/10082/ [cargo/10107]: https://github.com/rust-lang/cargo/pull/10107/ [`Metadata::is_symlink`]: https://doc.rust-lang.org/stable/std/fs/struct.Metadata.html#method.is_symlink @@ -156,34 +325,8 @@ and related tools. [`Option::unwrap_unchecked`]: https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.unwrap_unchecked [`Result::unwrap_unchecked`]: https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.unwrap_unchecked [`Result::unwrap_err_unchecked`]: https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.unwrap_err_unchecked -[`NonZero{unsigned}::is_power_of_two`]: https://doc.rust-lang.org/stable/std/num/struct.NonZeroU8.html#method.is_power_of_two [`File::options`]: https://doc.rust-lang.org/stable/std/fs/struct.File.html#method.options -[`unix::process::ExitStatusExt::core_dumped`]: https://doc.rust-lang.org/stable/std/os/unix/process/trait.ExitStatusExt.html#tymethod.core_dumped -[`unix::process::ExitStatusExt::stopped_signal`]: https://doc.rust-lang.org/stable/std/os/unix/process/trait.ExitStatusExt.html#tymethod.stopped_signal -[`unix::process::ExitStatusExt::continued`]: https://doc.rust-lang.org/stable/std/os/unix/process/trait.ExitStatusExt.html#tymethod.continued -[`unix::process::ExitStatusExt::into_raw`]: https://doc.rust-lang.org/stable/std/os/unix/process/trait.ExitStatusExt.html#tymethod.into_raw [`Duration::new`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.new -[`Duration::checked_add`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.checked_add -[`Duration::saturating_add`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.saturating_add -[`Duration::checked_sub`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.checked_sub -[`Duration::saturating_sub`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.saturating_sub -[`Duration::checked_mul`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.checked_mul -[`Duration::saturating_mul`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.saturating_mul -[`Duration::checked_div`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.checked_div -[`Duration::as_secs_f64`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.as_secs_f64 -[`Duration::as_secs_f32`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.as_secs_f32 -[`Duration::from_secs_f64`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.from_secs_f64 -[`Duration::from_secs_f32`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.from_secs_f32 -[`Duration::mul_f64`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.mul_f64 -[`Duration::mul_f32`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.mul_f32 -[`Duration::div_f64`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.div_f64 -[`Duration::div_f32`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.div_f32 -[`Duration::div_duration_f64`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.div_duration_f64 -[`Duration::div_duration_f32`]: https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.div_duration_f32 -[`MaybeUninit::as_ptr`]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.as_ptr -[`MaybeUninit::as_mut_ptr`]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.as_mut_ptr -[`MaybeUninit::assume_init`]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.assume_init -[`MaybeUninit::assume_init_ref`]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.assume_init_ref Version 1.57.0 (2021-12-02) ========================== @@ -194,6 +337,7 @@ Language - [Macro attributes may follow `#[derive]` and will see the original (pre-`cfg`) input.][87220] - [Accept curly-brace macros in expressions, like `m!{ .. }.method()` and `m!{ .. }?`.][88690] - [Allow panicking in constant evaluation.][89508] +- [Ignore derived `Clone` and `Debug` implementations during dead code analysis.][85200] Compiler -------- @@ -254,6 +398,9 @@ Cargo Compatibility notes ------------------- +- [Ignore derived `Clone` and `Debug` implementations during dead code analysis.][85200] + This will break some builds that set `#![deny(dead_code)]`. + Internal changes ---------------- These changes provide no direct user facing benefits, but represent significant @@ -262,10 +409,10 @@ and related tools. - [Added an experimental backend for codegen with `libgccjit`.][87260] +[85200]: https://github.com/rust-lang/rust/pull/85200/ [86191]: https://github.com/rust-lang/rust/pull/86191/ [87220]: https://github.com/rust-lang/rust/pull/87220/ [87260]: https://github.com/rust-lang/rust/pull/87260/ -[88243]: https://github.com/rust-lang/rust/pull/88243/ [88321]: https://github.com/rust-lang/rust/pull/88321/ [88529]: https://github.com/rust-lang/rust/pull/88529/ [88690]: https://github.com/rust-lang/rust/pull/88690/ @@ -421,8 +568,6 @@ and related tools. as well as rustdoc. [`std::os::unix::fs::chroot`]: https://doc.rust-lang.org/stable/std/os/unix/fs/fn.chroot.html -[`Iterator::intersperse`]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.intersperse -[`Iterator::intersperse_with`]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.intersperse [`UnsafeCell::raw_get`]: https://doc.rust-lang.org/stable/std/cell/struct.UnsafeCell.html#method.raw_get [`BufWriter::into_parts`]: https://doc.rust-lang.org/stable/std/io/struct.BufWriter.html#method.into_parts [`core::panic::{UnwindSafe, RefUnwindSafe, AssertUnwindSafe}`]: https://github.com/rust-lang/rust/pull/84662 @@ -444,12 +589,7 @@ and related tools. [rust#86183]: https://github.com/rust-lang/rust/pull/86183 [rust#87385]: https://github.com/rust-lang/rust/pull/87385 [rust#88100]: https://github.com/rust-lang/rust/pull/88100 -[rust#86860]: https://github.com/rust-lang/rust/pull/86860 -[rust#84039]: https://github.com/rust-lang/rust/pull/84039 -[rust#86492]: https://github.com/rust-lang/rust/pull/86492 -[rust#88363]: https://github.com/rust-lang/rust/pull/88363 [rust#85305]: https://github.com/rust-lang/rust/pull/85305 -[rust#87832]: https://github.com/rust-lang/rust/pull/87832 [rust#88069]: https://github.com/rust-lang/rust/pull/88069 [rust#87472]: https://github.com/rust-lang/rust/pull/87472 [rust#87699]: https://github.com/rust-lang/rust/pull/87699 @@ -460,31 +600,12 @@ and related tools. [rust#87580]: https://github.com/rust-lang/rust/pull/87580 [rust#83342]: https://github.com/rust-lang/rust/pull/83342 [rust#83093]: https://github.com/rust-lang/rust/pull/83093 -[rust#88177]: https://github.com/rust-lang/rust/pull/88177 -[rust#88548]: https://github.com/rust-lang/rust/pull/88548 -[rust#88551]: https://github.com/rust-lang/rust/pull/88551 -[rust#88299]: https://github.com/rust-lang/rust/pull/88299 -[rust#88220]: https://github.com/rust-lang/rust/pull/88220 [rust#85835]: https://github.com/rust-lang/rust/pull/85835 -[rust#86879]: https://github.com/rust-lang/rust/pull/86879 [rust#86744]: https://github.com/rust-lang/rust/pull/86744 -[rust#84662]: https://github.com/rust-lang/rust/pull/84662 -[rust#86593]: https://github.com/rust-lang/rust/pull/86593 -[rust#81050]: https://github.com/rust-lang/rust/pull/81050 [rust#81363]: https://github.com/rust-lang/rust/pull/81363 [rust#84111]: https://github.com/rust-lang/rust/pull/84111 [rust#85769]: https://github.com/rust-lang/rust/pull/85769#issuecomment-854363720 -[rust#88490]: https://github.com/rust-lang/rust/pull/88490 -[rust#88269]: https://github.com/rust-lang/rust/pull/88269 -[rust#84176]: https://github.com/rust-lang/rust/pull/84176 [rust#88399]: https://github.com/rust-lang/rust/pull/88399 -[rust#88227]: https://github.com/rust-lang/rust/pull/88227 -[rust#88200]: https://github.com/rust-lang/rust/pull/88200 -[rust#82776]: https://github.com/rust-lang/rust/pull/82776 -[rust#88077]: https://github.com/rust-lang/rust/pull/88077 -[rust#87728]: https://github.com/rust-lang/rust/pull/87728 -[rust#87050]: https://github.com/rust-lang/rust/pull/87050 -[rust#87619]: https://github.com/rust-lang/rust/pull/87619 [rust#81825]: https://github.com/rust-lang/rust/pull/81825#issuecomment-808406918 [rust#88019]: https://github.com/rust-lang/rust/pull/88019 [rust#87666]: https://github.com/rust-lang/rust/pull/87666 @@ -590,20 +711,14 @@ Compatibility Notes [86294]: https://github.com/rust-lang/rust/pull/86294 [86858]: https://github.com/rust-lang/rust/pull/86858 [86761]: https://github.com/rust-lang/rust/pull/86761 -[85769]: https://github.com/rust-lang/rust/pull/85769 [85746]: https://github.com/rust-lang/rust/pull/85746 -[85305]: https://github.com/rust-lang/rust/pull/85305 [85270]: https://github.com/rust-lang/rust/pull/85270 -[84111]: https://github.com/rust-lang/rust/pull/84111 [83918]: https://github.com/rust-lang/rust/pull/83918 [79965]: https://github.com/rust-lang/rust/pull/79965 -[87370]: https://github.com/rust-lang/rust/pull/87370 -[87298]: https://github.com/rust-lang/rust/pull/87298 [cargo/9663]: https://github.com/rust-lang/cargo/pull/9663 [cargo/9675]: https://github.com/rust-lang/cargo/pull/9675 [cargo/9550]: https://github.com/rust-lang/cargo/pull/9550 [cargo/9680]: https://github.com/rust-lang/cargo/pull/9680 -[cargo/9663]: https://github.com/rust-lang/cargo/pull/9663 [`array::map`]: https://doc.rust-lang.org/stable/std/primitive.array.html#method.map [`Bound::cloned`]: https://doc.rust-lang.org/stable/std/ops/enum.Bound.html#method.cloned [`Drain::as_str`]: https://doc.rust-lang.org/stable/std/string/struct.Drain.html#method.as_str @@ -612,7 +727,6 @@ Compatibility Notes [`MaybeUninit::assume_init_mut`]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.assume_init_mut [`MaybeUninit::assume_init_ref`]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.assume_init_ref [`MaybeUninit::write`]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.write -[`Seek::rewind`]: https://doc.rust-lang.org/stable/std/io/trait.Seek.html#method.rewind [`ops::ControlFlow`]: https://doc.rust-lang.org/stable/std/ops/enum.ControlFlow.html [`str::from_utf8_unchecked`]: https://doc.rust-lang.org/stable/std/str/fn.from_utf8_unchecked.html [`x86::_bittest`]: https://doc.rust-lang.org/stable/core/arch/x86/fn._bittest.html @@ -716,7 +830,6 @@ Compatibility Notes [85574]: https://github.com/rust-lang/rust/issues/85574 [86831]: https://github.com/rust-lang/rust/issues/86831 [86063]: https://github.com/rust-lang/rust/issues/86063 -[86831]: https://github.com/rust-lang/rust/issues/86831 [79608]: https://github.com/rust-lang/rust/pull/79608 [84988]: https://github.com/rust-lang/rust/pull/84988 [84701]: https://github.com/rust-lang/rust/pull/84701 @@ -918,7 +1031,6 @@ related tools. [`Ordering::is_le`]: https://doc.rust-lang.org/std/cmp/enum.Ordering.html#method.is_le [`Ordering::is_lt`]: https://doc.rust-lang.org/std/cmp/enum.Ordering.html#method.is_lt [`Ordering::is_ne`]: https://doc.rust-lang.org/std/cmp/enum.Ordering.html#method.is_ne -[`OsStr::eq_ignore_ascii_case`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html#method.eq_ignore_ascii_case [`OsStr::is_ascii`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html#method.is_ascii [`OsStr::make_ascii_lowercase`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html#method.make_ascii_lowercase [`OsStr::make_ascii_uppercase`]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html#method.make_ascii_uppercase @@ -1249,7 +1361,6 @@ Internal Only [80053]: https://github.com/rust-lang/rust/pull/80053 [79502]: https://github.com/rust-lang/rust/pull/79502 [75180]: https://github.com/rust-lang/rust/pull/75180 -[79135]: https://github.com/rust-lang/rust/pull/79135 [81521]: https://github.com/rust-lang/rust/pull/81521 [80968]: https://github.com/rust-lang/rust/pull/80968 [80959]: https://github.com/rust-lang/rust/pull/80959 @@ -1563,7 +1674,6 @@ related tools. [`slice::select_nth_unstable`]: https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.select_nth_unstable [`slice::select_nth_unstable_by`]: https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.select_nth_unstable_by [`slice::select_nth_unstable_by_key`]: https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.select_nth_unstable_by_key -[`hint::spin_loop`]: https://doc.rust-lang.org/stable/std/hint/fn.spin_loop.html [`Poll::is_ready`]: https://doc.rust-lang.org/stable/std/task/enum.Poll.html#method.is_ready [`Poll::is_pending`]: https://doc.rust-lang.org/stable/std/task/enum.Poll.html#method.is_pending [rustdoc-ws-post]: https://blog.guillaume-gomez.fr/articles/2020-11-11+New+doc+comment+handling+in+rustdoc @@ -1810,8 +1920,6 @@ Internal Only [74869]: https://github.com/rust-lang/rust/pull/74869/ [73858]: https://github.com/rust-lang/rust/pull/73858/ [75716]: https://github.com/rust-lang/rust/pull/75716/ -[75908]: https://github.com/rust-lang/rust/pull/75908/ -[75516]: https://github.com/rust-lang/rust/pull/75516/ [75560]: https://github.com/rust-lang/rust/pull/75560/ [75568]: https://github.com/rust-lang/rust/pull/75568/ [75366]: https://github.com/rust-lang/rust/pull/75366/ @@ -1826,7 +1934,6 @@ Internal Only [73583]: https://github.com/rust-lang/rust/pull/73583/ [73084]: https://github.com/rust-lang/rust/pull/73084/ [73197]: https://github.com/rust-lang/rust/pull/73197/ -[72488]: https://github.com/rust-lang/rust/pull/72488/ [cargo/8456]: https://github.com/rust-lang/cargo/pull/8456/ [cargo/8478]: https://github.com/rust-lang/cargo/pull/8478/ [cargo/8485]: https://github.com/rust-lang/cargo/pull/8485/ @@ -1837,7 +1944,6 @@ Internal Only [`RangeInclusive::is_empty`]: https://doc.rust-lang.org/nightly/std/ops/struct.RangeInclusive.html#method.is_empty [`Result::as_deref_mut`]: https://doc.rust-lang.org/nightly/std/result/enum.Result.html#method.as_deref_mut [`Result::as_deref`]: https://doc.rust-lang.org/nightly/std/result/enum.Result.html#method.as_deref -[`TypeId::of`]: https://doc.rust-lang.org/nightly/std/any/struct.TypeId.html#method.of [`Vec::leak`]: https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.leak [`f32::TAU`]: https://doc.rust-lang.org/nightly/std/f32/consts/constant.TAU.html [`f64::TAU`]: https://doc.rust-lang.org/nightly/std/f64/consts/constant.TAU.html @@ -2605,6 +2711,11 @@ Language - [Visibility modifiers (e.g. `pub`) are now syntactically allowed on trait items and enum variants.][66183] These are still rejected semantically, but can be seen and parsed by procedural macros and conditional compilation. +- [You can now define a Rust `extern "C"` function with `Box` and use `T*` as the corresponding + type on the C side.][62514] Please see [the documentation][box-memory-layout] for more information, + including the important caveat about preferring to avoid `Box` in Rust signatures for functions defined in C. + +[box-memory-layout]: https://doc.rust-lang.org/std/boxed/index.html#memory-layout Compiler -------- @@ -2679,6 +2790,7 @@ Compatibility Notes [54733]: https://github.com/rust-lang/rust/pull/54733/ [61351]: https://github.com/rust-lang/rust/pull/61351/ +[62514]: https://github.com/rust-lang/rust/pull/62514/ [67255]: https://github.com/rust-lang/rust/pull/67255/ [66661]: https://github.com/rust-lang/rust/pull/66661/ [66771]: https://github.com/rust-lang/rust/pull/66771/ @@ -2815,7 +2927,6 @@ Compatibility Notes [63803]: https://github.com/rust-lang/rust/pull/63803/ [cargo/7450]: https://github.com/rust-lang/cargo/pull/7450/ [cargo/7507]: https://github.com/rust-lang/cargo/pull/7507/ -[cargo/7525]: https://github.com/rust-lang/cargo/pull/7525/ [cargo/7333]: https://github.com/rust-lang/cargo/pull/7333/ [(rfc 2008)]: https://rust-lang.github.io/rfcs/2008-non-exhaustive.html [`f32::to_be_bytes`]: https://doc.rust-lang.org/std/primitive.f32.html#method.to_be_bytes @@ -2948,13 +3059,6 @@ Compatibility Notes [63786]: https://github.com/rust-lang/rust/pull/63786/ [63827]: https://github.com/rust-lang/rust/pull/63827/ [63834]: https://github.com/rust-lang/rust/pull/63834/ -[63927]: https://github.com/rust-lang/rust/pull/63927/ -[63933]: https://github.com/rust-lang/rust/pull/63933/ -[63934]: https://github.com/rust-lang/rust/pull/63934/ -[63938]: https://github.com/rust-lang/rust/pull/63938/ -[63940]: https://github.com/rust-lang/rust/pull/63940/ -[63941]: https://github.com/rust-lang/rust/pull/63941/ -[63945]: https://github.com/rust-lang/rust/pull/63945/ [64010]: https://github.com/rust-lang/rust/pull/64010/ [64028]: https://github.com/rust-lang/rust/pull/64028/ [64334]: https://github.com/rust-lang/rust/pull/64334/ @@ -3183,7 +3287,6 @@ Compatibility Notes [`Cell::as_slice_of_cells`]: https://doc.rust-lang.org/std/cell/struct.Cell.html#method.as_slice_of_cells [`DoubleEndedIterator::nth_back`]: https://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html#method.nth_back [`Option::xor`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.xor -[`RefCell::try_borrow_unguarded`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html#method.try_borrow_unguarded [`Wrapping::reverse_bits`]: https://doc.rust-lang.org/std/num/struct.Wrapping.html#method.reverse_bits [`i128::reverse_bits`]: https://doc.rust-lang.org/std/primitive.i128.html#method.reverse_bits [`i16::reverse_bits`]: https://doc.rust-lang.org/std/primitive.i16.html#method.reverse_bits @@ -3682,7 +3785,6 @@ Compatibility Notes - [Libtest no longer creates a new thread for each test when `--test-threads=1`. It also runs the tests in deterministic order][56243] -[55982]: https://github.com/rust-lang/rust/pull/55982/ [56243]: https://github.com/rust-lang/rust/pull/56243 [56303]: https://github.com/rust-lang/rust/pull/56303/ [56351]: https://github.com/rust-lang/rust/pull/56351/ @@ -4082,7 +4184,6 @@ Cargo [52813]: https://github.com/rust-lang/rust/pull/52813/ [53218]: https://github.com/rust-lang/rust/pull/53218/ -[53555]: https://github.com/rust-lang/rust/issues/53555/ [54057]: https://github.com/rust-lang/rust/pull/54057/ [54240]: https://github.com/rust-lang/rust/pull/54240/ [54430]: https://github.com/rust-lang/rust/pull/54430/ @@ -4204,7 +4305,6 @@ Misc [53044]: https://github.com/rust-lang/rust/pull/53044/ [53165]: https://github.com/rust-lang/rust/pull/53165/ [53611]: https://github.com/rust-lang/rust/pull/53611/ -[53213]: https://github.com/rust-lang/rust/pull/53213/ [53236]: https://github.com/rust-lang/rust/pull/53236/ [53272]: https://github.com/rust-lang/rust/pull/53272/ [53370]: https://github.com/rust-lang/rust/pull/53370/ @@ -4212,7 +4312,6 @@ Misc [53774]: https://github.com/rust-lang/rust/pull/53774/ [53822]: https://github.com/rust-lang/rust/pull/53822/ [54057]: https://github.com/rust-lang/rust/pull/54057/ -[54146]: https://github.com/rust-lang/rust/pull/54146/ [54404]: https://github.com/rust-lang/rust/pull/54404/ [cargo/5877]: https://github.com/rust-lang/cargo/pull/5877/ [cargo/5878]: https://github.com/rust-lang/cargo/pull/5878/ @@ -4320,12 +4419,10 @@ Compatibility Notes [52330]: https://github.com/rust-lang/rust/pull/52330/ [52354]: https://github.com/rust-lang/rust/pull/52354/ [52402]: https://github.com/rust-lang/rust/pull/52402/ -[52103]: https://github.com/rust-lang/rust/pull/52103/ [52197]: https://github.com/rust-lang/rust/pull/52197/ [51807]: https://github.com/rust-lang/rust/pull/51807/ [51899]: https://github.com/rust-lang/rust/pull/51899/ [51912]: https://github.com/rust-lang/rust/pull/51912/ -[51511]: https://github.com/rust-lang/rust/pull/51511/ [51619]: https://github.com/rust-lang/rust/pull/51619/ [51656]: https://github.com/rust-lang/rust/pull/51656/ [51178]: https://github.com/rust-lang/rust/pull/51178/ @@ -4465,7 +4562,6 @@ Compatibility Notes [50855]: https://github.com/rust-lang/rust/pull/50855/ [51050]: https://github.com/rust-lang/rust/pull/51050/ [51196]: https://github.com/rust-lang/rust/pull/51196/ -[51200]: https://github.com/rust-lang/rust/pull/51200/ [51241]: https://github.com/rust-lang/rust/pull/51241/ [51276]: https://github.com/rust-lang/rust/pull/51276/ [51298]: https://github.com/rust-lang/rust/pull/51298/ @@ -4646,15 +4742,12 @@ Compatibility Notes [49664]: https://github.com/rust-lang/rust/pull/49664/ [49699]: https://github.com/rust-lang/rust/pull/49699/ [49707]: https://github.com/rust-lang/rust/pull/49707/ -[49719]: https://github.com/rust-lang/rust/pull/49719/ [49896]: https://github.com/rust-lang/rust/pull/49896/ [49968]: https://github.com/rust-lang/rust/pull/49968/ [50163]: https://github.com/rust-lang/rust/pull/50163 [50177]: https://github.com/rust-lang/rust/pull/50177/ [50378]: https://github.com/rust-lang/rust/pull/50378/ -[50398]: https://github.com/rust-lang/rust/pull/50398/ [50423]: https://github.com/rust-lang/rust/pull/50423/ -[cargo/5203]: https://github.com/rust-lang/cargo/pull/5203/ [cargo/5335]: https://github.com/rust-lang/cargo/pull/5335/ [cargo/5359]: https://github.com/rust-lang/cargo/pull/5359/ [cargo/5360]: https://github.com/rust-lang/cargo/pull/5360/ @@ -4856,7 +4949,6 @@ Compatibility Notes [47813]: https://github.com/rust-lang/rust/pull/47813 [48056]: https://github.com/rust-lang/rust/pull/48056 [48125]: https://github.com/rust-lang/rust/pull/48125 -[48166]: https://github.com/rust-lang/rust/pull/48166 [48235]: https://github.com/rust-lang/rust/pull/48235 [48274]: https://github.com/rust-lang/rust/pull/48274 [48281]: https://github.com/rust-lang/rust/pull/48281 @@ -4873,10 +4965,7 @@ Compatibility Notes [48978]: https://github.com/rust-lang/rust/pull/48978 [49101]: https://github.com/rust-lang/rust/pull/49101 [49109]: https://github.com/rust-lang/rust/pull/49109 -[49121]: https://github.com/rust-lang/rust/pull/49121 [49162]: https://github.com/rust-lang/rust/pull/49162 -[49184]: https://github.com/rust-lang/rust/pull/49184 -[49234]: https://github.com/rust-lang/rust/pull/49234 [49255]: https://github.com/rust-lang/rust/pull/49255 [49299]: https://github.com/rust-lang/rust/pull/49299 [49305]: https://github.com/rust-lang/rust/pull/49305 @@ -5123,7 +5212,6 @@ Compatibility Notes [44884]: https://github.com/rust-lang/rust/pull/44884 [45198]: https://github.com/rust-lang/rust/pull/45198 [45506]: https://github.com/rust-lang/rust/pull/45506 -[45904]: https://github.com/rust-lang/rust/pull/45904 [45990]: https://github.com/rust-lang/rust/pull/45990 [46012]: https://github.com/rust-lang/rust/pull/46012 [46077]: https://github.com/rust-lang/rust/pull/46077 @@ -5135,7 +5223,6 @@ Compatibility Notes [46671]: https://github.com/rust-lang/rust/pull/46671 [46713]: https://github.com/rust-lang/rust/pull/46713 [46735]: https://github.com/rust-lang/rust/pull/46735 -[46749]: https://github.com/rust-lang/rust/pull/46749 [46760]: https://github.com/rust-lang/rust/pull/46760 [46798]: https://github.com/rust-lang/rust/pull/46798 [46828]: https://github.com/rust-lang/rust/pull/46828 @@ -5306,7 +5393,6 @@ Compatibility Notes [42526]: https://github.com/rust-lang/rust/pull/42526 -[43017]: https://github.com/rust-lang/rust/pull/43017 [43716]: https://github.com/rust-lang/rust/pull/43716 [43949]: https://github.com/rust-lang/rust/pull/43949 [44015]: https://github.com/rust-lang/rust/pull/44015 @@ -5536,8 +5622,6 @@ Cargo - [Added `--no-fail-fast` flag to cargo to run all benchmarks regardless of failure.][cargo/4248] - [Changed the convention around which file is the crate root.][cargo/4259] -- [The `include`/`exclude` property in `Cargo.toml` now accepts gitignore paths - instead of glob patterns][cargo/4270]. Glob patterns are now deprecated. Compatibility Notes ------------------- @@ -5580,7 +5664,6 @@ Compatibility Notes [cargo/4229]: https://github.com/rust-lang/cargo/pull/4229 [cargo/4248]: https://github.com/rust-lang/cargo/pull/4248 [cargo/4259]: https://github.com/rust-lang/cargo/pull/4259 -[cargo/4270]: https://github.com/rust-lang/cargo/pull/4270 [`CStr::into_c_string`]: https://doc.rust-lang.org/std/ffi/struct.CStr.html#method.into_c_string [`CString::as_c_str`]: https://doc.rust-lang.org/std/ffi/struct.CString.html#method.as_c_str [`CString::into_boxed_c_str`]: https://doc.rust-lang.org/std/ffi/struct.CString.html#method.into_boxed_c_str @@ -5873,7 +5956,6 @@ Misc ---- - [rustdoc can now use pulldown-cmark with the `--enable-commonmark` flag][40338] -- [Added rust-windbg script for better debugging on Windows][39983] - [Rust now uses the official cross compiler for NetBSD][40612] - [rustdoc now accepts `#` at the start of files][40828] - [Fixed jemalloc support for musl][41168] @@ -5908,7 +5990,6 @@ Compatibility Notes [38165]: https://github.com/rust-lang/rust/pull/38165 [39799]: https://github.com/rust-lang/rust/pull/39799 [39891]: https://github.com/rust-lang/rust/pull/39891 -[39983]: https://github.com/rust-lang/rust/pull/39983 [40043]: https://github.com/rust-lang/rust/pull/40043 [40241]: https://github.com/rust-lang/rust/pull/40241 [40338]: https://github.com/rust-lang/rust/pull/40338 @@ -6204,7 +6285,6 @@ Compatibility Notes [cargo/3691]: https://github.com/rust-lang/cargo/pull/3691 [cargo/3699]: https://github.com/rust-lang/cargo/pull/3699 [cargo/3731]: https://github.com/rust-lang/cargo/pull/3731 -[mdbook]: https://crates.io/crates/mdbook [ubook]: https://doc.rust-lang.org/unstable-book/ @@ -6275,7 +6355,7 @@ Libraries * [Ctrl-Z returns from `Stdin.read()` when reading from the console on Windows][38274] * [std: Fix partial writes in `LineWriter`][38062] -* [std: Clamp max read/write sizes on Unix][38062] +* [std: Clamp max read/write sizes on Unix][38622] * [Use more specific panic message for `&str` slicing errors][38066] * [`TcpListener::set_only_v6` is deprecated][38304]. This functionality cannot be achieved in std currently. @@ -6341,7 +6421,7 @@ Compatibility Notes [38006]: https://github.com/rust-lang/rust/pull/38006 [38051]: https://github.com/rust-lang/rust/pull/38051 [38062]: https://github.com/rust-lang/rust/pull/38062 -[38062]: https://github.com/rust-lang/rust/pull/38622 +[38622]: https://github.com/rust-lang/rust/pull/38622 [38066]: https://github.com/rust-lang/rust/pull/38066 [38069]: https://github.com/rust-lang/rust/pull/38069 [38131]: https://github.com/rust-lang/rust/pull/38131 @@ -6349,7 +6429,6 @@ Compatibility Notes [38274]: https://github.com/rust-lang/rust/pull/38274 [38304]: https://github.com/rust-lang/rust/pull/38304 [38313]: https://github.com/rust-lang/rust/pull/38313 -[38314]: https://github.com/rust-lang/rust/pull/38314 [38327]: https://github.com/rust-lang/rust/pull/38327 [38401]: https://github.com/rust-lang/rust/pull/38401 [38413]: https://github.com/rust-lang/rust/pull/38413 @@ -6399,7 +6478,6 @@ Compatibility Notes [cargo/3546]: https://github.com/rust-lang/cargo/pull/3546 [cargo/3557]: https://github.com/rust-lang/cargo/pull/3557 [cargo/3604]: https://github.com/rust-lang/cargo/pull/3604 -[RFC 1623]: https://github.com/rust-lang/rfcs/blob/master/text/1623-static.md Version 1.15.1 (2017-02-09) @@ -6614,7 +6692,6 @@ Compatibility Notes [38192]: https://github.com/rust-lang/rust/pull/38192 [38279]: https://github.com/rust-lang/rust/pull/38279 [38835]: https://github.com/rust-lang/rust/pull/38835 -[RFC 1492]: https://github.com/rust-lang/rfcs/blob/master/text/1492-dotdot-in-patterns.md [RFC 1506]: https://github.com/rust-lang/rfcs/blob/master/text/1506-adt-kinds.md [RFC 1560]: https://github.com/rust-lang/rfcs/blob/master/text/1560-name-resolution.md [RFC 1681]: https://github.com/rust-lang/rfcs/blob/master/text/1681-macros-1.1.md @@ -6803,7 +6880,6 @@ Compatibility Notes [1.14wasm]: https://users.rust-lang.org/t/compiling-to-the-web-with-rust-and-emscripten/7627 [36430]: https://github.com/rust-lang/rust/pull/36430 [36595]: https://github.com/rust-lang/rust/pull/36595 -[36595]: https://github.com/rust-lang/rust/pull/36595 [36692]: https://github.com/rust-lang/rust/pull/36692 [36767]: https://github.com/rust-lang/rust/pull/36767 [36794]: https://github.com/rust-lang/rust/pull/36794 @@ -7031,7 +7107,6 @@ Compatibility Notes [34623]: https://github.com/rust-lang/rust/pull/34623 [34923]: https://github.com/rust-lang/rust/pull/34923 [34942]: https://github.com/rust-lang/rust/pull/34942 -[34982]: https://github.com/rust-lang/rust/pull/34982 [35021]: https://github.com/rust-lang/rust/pull/35021 [35048]: https://github.com/rust-lang/rust/pull/35048 [35074]: https://github.com/rust-lang/rust/pull/35074 @@ -7088,7 +7163,6 @@ Compatibility Notes [36586]: https://github.com/rust-lang/rust/pull/36586 [36592]: https://github.com/rust-lang/rust/pull/36592 [36631]: https://github.com/rust-lang/rust/pull/36631 -[36639]: https://github.com/rust-lang/rust/pull/36639 [36721]: https://github.com/rust-lang/rust/pull/36721 [36727]: https://github.com/rust-lang/rust/pull/36727 [36730]: https://github.com/rust-lang/rust/pull/36730 @@ -7120,7 +7194,6 @@ Compatibility Notes [cargo/3205]: https://github.com/rust-lang/cargo/pull/3205 [cargo/3241]: https://github.com/rust-lang/cargo/pull/3241 [cargo/3242]: https://github.com/rust-lang/cargo/pull/3242 -[rustup]: https://www.rustup.rs [`checked_abs`]: https://doc.rust-lang.org/std/primitive.i32.html#method.checked_abs [`wrapping_abs`]: https://doc.rust-lang.org/std/primitive.i32.html#method.wrapping_abs [`overflowing_abs`]: https://doc.rust-lang.org/std/primitive.i32.html#method.overflowing_abs @@ -8038,7 +8111,7 @@ Cargo targets can be specified together. [RFC 1361]. * [The environment variables `CARGO_TARGET_ROOT`, `RUSTC`, and `RUSTDOC` take precedence over the `build.target-dir`, - `build.rustc`, and `build.rustdoc` configuration values][1.8cv]. + `build.rustc`, and `build.rustdoc` configuration values][1.8cfv]. * [The child process tree is killed on Windows when Cargo is killed][1.8ck]. * [The `build.target` configuration value sets the target platform, @@ -8088,7 +8161,7 @@ Compatibility Notes [1.8ck]: https://github.com/rust-lang/cargo/pull/2370 [1.8ct]: https://github.com/rust-lang/cargo/pull/2335 [1.8cu]: https://github.com/rust-lang/rust/pull/31390 -[1.8cv]: https://github.com/rust-lang/cargo/issues/2365 +[1.8cfv]: https://github.com/rust-lang/cargo/issues/2365 [1.8cv]: https://github.com/rust-lang/rust/pull/30998 [1.8h]: https://github.com/rust-lang/rust/pull/31460 [1.8l]: https://github.com/rust-lang/rust/pull/31668 @@ -9011,13 +9084,13 @@ Misc * The compiler gained many new extended error descriptions, which can be accessed with the `--explain` flag. * The `dropck` pass, which checks that destructors can't access - destroyed values, [has been rewritten][dropck]. This fixes some + destroyed values, [has been rewritten][27261]. This fixes some soundness holes, and as such will cause some previously-compiling code to no longer build. * `rustc` now uses [LLVM to write archive files where possible][ar]. Eventually this will eliminate the compiler's dependency on the ar utility. -* Rust has [preliminary support for i686 FreeBSD][fb] (it has long +* Rust has [preliminary support for i686 FreeBSD][26959] (it has long supported FreeBSD on x86_64). * The [`unused_mut`][lum], [`unconditional_recursion`][lur], [`improper_ctypes`][lic], and [`negate_unsigned`][lnu] lints are @@ -9056,7 +9129,7 @@ Misc [ar]: https://github.com/rust-lang/rust/pull/26926 [b14]: https://static.rust-lang.org/dist/rust-beta-x86_64-pc-windows-msvc.msi [dms]: https://github.com/rust-lang/rust/pull/26241 -[dropck]: https://github.com/rust-lang/rust/pull/27261 +[27261]: https://github.com/rust-lang/rust/pull/27261 [dropckrfc]: https://github.com/rust-lang/rfcs/blob/master/text/0769-sound-generic-drop.md [ds]: https://github.com/rust-lang/rust/pull/26818 [dst1]: http://doc.rust-lang.org/nightly/std/mem/fn.size_of_val.html @@ -9064,9 +9137,8 @@ Misc [dst3]: https://github.com/rust-lang/rust/pull/27351 [e]: https://github.com/rust-lang/rust/pull/24793 [f]: https://github.com/rust-lang/rust/pull/26588 -[fb]: https://github.com/rust-lang/rust/pull/26959 +[26959]: https://github.com/rust-lang/rust/pull/26959 [fl]: https://github.com/rust-lang/rust-installer/pull/41 -[hs]: http://doc.rust-lang.org/nightly/std/hash/trait.Hash.html#method.hash_slice [ie]: http://doc.rust-lang.org/nightly/std/io/struct.Error.html [iec]: http://doc.rust-lang.org/nightly/std/io/struct.Error.html#method.cause [iegm]: http://doc.rust-lang.org/nightly/std/io/struct.Error.html#method.get_mut @@ -9337,7 +9409,7 @@ Misc to rustc. * [Android executables are always position independent][pie]. * [The `drop_with_repr_extern` lint warns about mixing `repr(C)` - with `Drop`][drop]. + with `Drop`][24935]. [`str::split_whitespace`]: https://doc.rust-lang.org/nightly/std/primitive.str.html#method.split_whitespace [`FromRawFd`]: https://doc.rust-lang.org/nightly/std/os/unix/io/trait.FromRawFd.html @@ -9367,7 +9439,7 @@ Misc [`BinaryHeap`]: https://doc.rust-lang.org/nightly/std/collections/struct.BinaryHeap.html [ll]: https://github.com/rust-lang/rust/pull/26022 [`split_off`]: https://doc.rust-lang.org/nightly/collections/linked_list/struct.LinkedList.html#method.split_off -[drop]: https://github.com/rust-lang/rust/pull/24935 +[24935]: https://github.com/rust-lang/rust/pull/24935 Version 1.0.0 (2015-05-15) ======================== @@ -9420,7 +9492,7 @@ Language property: generic code cannot behave differently for different type arguments except in minor ways. * The `unsafe_destructor` feature is now deprecated in favor of the - [new `dropck`][dropck]. This change is a major reduction in unsafe + [new `dropck`][rfc769]. This change is a major reduction in unsafe code. Libraries @@ -9428,7 +9500,7 @@ Libraries * The `thread_local` module [has been renamed to `std::thread`][th]. * The methods of `IteratorExt` [have been moved to the `Iterator` - trait itself][ie]. + trait itself][23300]. * Several traits that implement Rust's conventions for type conversions, `AsMut`, `AsRef`, `From`, and `Into` have been [centralized in the `std::convert` module][con]. @@ -9447,7 +9519,7 @@ Libraries * [In method resolution, object methods are resolved before inherent methods][meth]. * [`String::from_str` has been deprecated in favor of the `From` impl, - `String::from`][sf]. + `String::from`][24517]. * [`io::Error` implements `Sync`][ios]. * [The `words` method on `&str` has been replaced with `split_whitespace`][sw], to avoid answering the tricky question, 'what is @@ -9495,7 +9567,7 @@ Misc [con]: https://github.com/rust-lang/rust/pull/23875 [cr]: https://github.com/rust-lang/rust/pull/23419 [fe]: https://github.com/rust-lang/rust/pull/23879 -[ie]: https://github.com/rust-lang/rust/pull/23300 +[23300]: https://github.com/rust-lang/rust/pull/23300 [inv]: https://github.com/rust-lang/rust/pull/23938 [ios]: https://github.com/rust-lang/rust/pull/24133 [lex]: https://github.com/rust-lang/rfcs/blob/master/text/0879-small-base-lexing.md @@ -9503,7 +9575,7 @@ Misc [meth]: https://github.com/rust-lang/rust/pull/24056 [pat]: https://github.com/rust-lang/rfcs/blob/master/text/0528-string-patterns.md [po]: https://github.com/rust-lang/rust/pull/24270 -[sf]: https://github.com/rust-lang/rust/pull/24517 +[24517]: https://github.com/rust-lang/rust/pull/24517 [slp]: https://github.com/rust-lang/rust/pull/23949 [spl]: https://github.com/rust-lang/rfcs/blob/master/text/0979-align-splitn-with-other-languages.md [sw]: https://github.com/rust-lang/rfcs/blob/master/text/1054-str-words.md @@ -9521,7 +9593,7 @@ Misc [conversion]: https://github.com/rust-lang/rfcs/pull/529 [num-traits]: https://github.com/rust-lang/rust/pull/23549 [index-value]: https://github.com/rust-lang/rust/pull/23601 -[dropck]: https://github.com/rust-lang/rfcs/pull/769 +[rfc769]: https://github.com/rust-lang/rfcs/pull/769 [ci-compare]: https://gist.github.com/brson/a30a77836fbec057cbee [fn-inherit]: https://github.com/rust-lang/rust/pull/23282 [fn-blanket]: https://github.com/rust-lang/rust/pull/23895 diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs index c80fab9949..4edd095af1 100644 --- a/compiler/rustc/src/main.rs +++ b/compiler/rustc/src/main.rs @@ -1,25 +1,32 @@ -// Configure jemalloc as the `global_allocator` when configured. This is -// so that we use the sized deallocation apis jemalloc provides -// (namely `sdallocx`). +// A note about jemalloc: rustc uses jemalloc when built for CI and +// distribution. The obvious way to do this is with the `#[global_allocator]` +// mechanism. However, for complicated reasons (see +// https://github.com/rust-lang/rust/pull/81782#issuecomment-784438001 for some +// details) that mechanism doesn't work here. Also, we must use a consistent +// allocator across the rustc <-> llvm boundary, and `#[global_allocator]` +// wouldn't provide that. // -// The symbol overrides documented below are also performed so that we can -// ensure that we use a consistent allocator across the rustc <-> llvm boundary -#[cfg(feature = "jemalloc")] -#[global_allocator] -static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; - +// Instead, we use a lower-level mechanism. rustc is linked with jemalloc in a +// way such that jemalloc's implementation of `malloc`, `free`, etc., override +// the libc allocator's implementation. This means that Rust's `System` +// allocator, which calls `libc::malloc()` et al., is actually calling into +// jemalloc. +// +// A consequence of not using `GlobalAlloc` (and the `tikv-jemallocator` crate +// provides an impl of that trait, which is called `Jemalloc`) is that we +// cannot use the sized deallocation APIs (`sdallocx`) that jemalloc provides. +// It's unclear how much performance is lost because of this. +// +// As for the symbol overrides in `main` below: we're pulling in a static copy +// of jemalloc. We need to actually reference its symbols for it to get linked. +// The two crates we link to here, `std` and `rustc_driver`, are both dynamic +// libraries. So we must reference jemalloc symbols one way or another, because +// this file is the only object code in the rustc executable. #[cfg(feature = "tikv-jemalloc-sys")] use tikv_jemalloc_sys as jemalloc_sys; fn main() { - // Pull in jemalloc when enabled. - // - // Note that we're pulling in a static copy of jemalloc which means that to - // pull it in we need to actually reference its symbols for it to get - // linked. The two crates we link to here, std and rustc_driver, are both - // dynamic libraries. That means to pull in jemalloc we actually need to - // reference allocation symbols one way or another (as this file is the only - // object code in the rustc executable). + // See the comment at the top of this file for an explanation of this. #[cfg(feature = "tikv-jemalloc-sys")] { use std::os::raw::{c_int, c_void}; diff --git a/compiler/rustc_apfloat/src/lib.rs b/compiler/rustc_apfloat/src/lib.rs index 7eeec4aa86..143c6f7610 100644 --- a/compiler/rustc_apfloat/src/lib.rs +++ b/compiler/rustc_apfloat/src/lib.rs @@ -33,7 +33,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![no_std] #![forbid(unsafe_code)] -#![feature(iter_zip)] #![feature(nll)] #[macro_use] diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 55b243a84a..a2d32cdc00 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -332,10 +332,7 @@ pub type GenericBounds = Vec; pub enum ParamKindOrd { Lifetime, Type, - // `unordered` is only `true` if `sess.unordered_const_ty_params()` - // returns true. Specifically, if it's only `min_const_generics`, it will still require - // ordering consts after types. - Const { unordered: bool }, + Const, // `Infer` is not actually constructed directly from the AST, but is implicitly constructed // during HIR lowering, and `ParamKindOrd` will implicitly order inferred variables last. Infer, @@ -346,11 +343,7 @@ impl Ord for ParamKindOrd { use ParamKindOrd::*; let to_int = |v| match v { Lifetime => 0, - Infer | Type | Const { unordered: true } => 1, - // technically both consts should be ordered equally, - // but only one is ever encountered at a time, so this is - // fine. - Const { unordered: false } => 2, + Infer | Type | Const => 1, }; to_int(*self).cmp(&to_int(*other)) @@ -517,6 +510,10 @@ pub struct Crate { pub attrs: Vec, pub items: Vec>, pub span: Span, + /// Must be equal to `CRATE_NODE_ID` after the crate root is expanded, but may hold + /// expansion placeholders or an unassigned value (`DUMMY_NODE_ID`) before that. + pub id: NodeId, + pub is_placeholder: bool, } /// Possible values inside of compile-time attribute lists. @@ -1979,7 +1976,7 @@ pub enum InlineAsmRegOrRegClass { bitflags::bitflags! { #[derive(Encodable, Decodable, HashStable_Generic)] - pub struct InlineAsmOptions: u8 { + pub struct InlineAsmOptions: u16 { const PURE = 1 << 0; const NOMEM = 1 << 1; const READONLY = 1 << 2; @@ -1988,6 +1985,7 @@ bitflags::bitflags! { const NOSTACK = 1 << 5; const ATT_SYNTAX = 1 << 6; const RAW = 1 << 7; + const MAY_UNWIND = 1 << 8; } } diff --git a/compiler/rustc_ast/src/ast_like.rs b/compiler/rustc_ast/src/ast_like.rs index d586426d70..b9c397974a 100644 --- a/compiler/rustc_ast/src/ast_like.rs +++ b/compiler/rustc_ast/src/ast_like.rs @@ -1,7 +1,7 @@ use super::ptr::P; use super::token::Nonterminal; use super::tokenstream::LazyTokenStream; -use super::{Arm, ExprField, FieldDef, GenericParam, Param, PatField, Variant}; +use super::{Arm, Crate, ExprField, FieldDef, GenericParam, Param, PatField, Variant}; use super::{AssocItem, Expr, ForeignItem, Item, Local, MacCallStmt}; use super::{AttrItem, AttrKind, Block, Pat, Path, Ty, Visibility}; use super::{AttrVec, Attribute, Stmt, StmtKind}; @@ -276,7 +276,7 @@ derive_has_tokens_and_attrs! { // These ast nodes only support inert attributes, so they don't // store tokens (since nothing can observe them) derive_has_attrs_no_tokens! { - FieldDef, Arm, ExprField, PatField, Variant, Param, GenericParam + FieldDef, Arm, ExprField, PatField, Variant, Param, GenericParam, Crate } // These AST nodes don't support attributes, but can diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 927d7c6aaf..d66774040f 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -136,15 +136,15 @@ impl Attribute { pub fn value_str(&self) -> Option { match self.kind { - AttrKind::Normal(ref item, _) => item.meta(self.span).and_then(|meta| meta.value_str()), + AttrKind::Normal(ref item, _) => item.meta_kind().and_then(|kind| kind.value_str()), AttrKind::DocComment(..) => None, } } pub fn meta_item_list(&self) -> Option> { match self.kind { - AttrKind::Normal(ref item, _) => match item.meta(self.span) { - Some(MetaItem { kind: MetaItemKind::List(list), .. }) => Some(list), + AttrKind::Normal(ref item, _) => match item.meta_kind() { + Some(MetaItemKind::List(list)) => Some(list), _ => None, }, AttrKind::DocComment(..) => None, @@ -228,6 +228,10 @@ impl AttrItem { span, }) } + + pub fn meta_kind(&self) -> Option { + Some(MetaItemKind::from_mac_args(&self.args)?) + } } impl Attribute { @@ -242,7 +246,7 @@ impl Attribute { match self.kind { AttrKind::DocComment(.., data) => Some(data), AttrKind::Normal(ref item, _) if item.path == sym::doc => { - item.meta(self.span).and_then(|meta| meta.value_str()) + item.meta_kind().and_then(|kind| kind.value_str()) } _ => None, } @@ -270,6 +274,13 @@ impl Attribute { } } + pub fn meta_kind(&self) -> Option { + match self.kind { + AttrKind::Normal(ref item, _) => item.meta_kind(), + AttrKind::DocComment(..) => None, + } + } + pub fn tokens(&self) -> AttrAnnotatedTokenStream { match self.kind { AttrKind::Normal(_, ref tokens) => tokens @@ -436,6 +447,16 @@ impl MetaItem { } impl MetaItemKind { + pub fn value_str(&self) -> Option { + match self { + MetaItemKind::NameValue(ref v) => match v.kind { + LitKind::Str(ref s, _) => Some(*s), + _ => None, + }, + _ => None, + } + } + pub fn mac_args(&self, span: Span) -> MacArgs { match self { MetaItemKind::Word => MacArgs::Empty, diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index b9db2a7e08..ff3b501a0b 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -11,7 +11,6 @@ #![feature(box_patterns)] #![feature(crate_visibility_modifier)] #![feature(if_let_guard)] -#![feature(iter_zip)] #![feature(label_break_value)] #![feature(nll)] #![feature(min_specialization)] diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index fc5cc96399..9ef78aaf66 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1,5 +1,5 @@ //! A `MutVisitor` represents an AST modification; it accepts an AST piece and -//! and mutates it in place. So, for instance, macro expansion is a `MutVisitor` +//! mutates it in place. So, for instance, macro expansion is a `MutVisitor` //! that walks over an AST and modifies it. //! //! Note: using a `MutVisitor` (other than the `MacroExpander` `MutVisitor`) on @@ -14,13 +14,14 @@ use crate::tokenstream::*; use rustc_data_structures::map_in_place::MapInPlace; use rustc_data_structures::sync::Lrc; +use rustc_data_structures::thin_vec::ThinVec; use rustc_span::source_map::Spanned; use rustc_span::symbol::Ident; use rustc_span::Span; use smallvec::{smallvec, Array, SmallVec}; use std::ops::DerefMut; -use std::{panic, process, ptr}; +use std::{panic, ptr}; pub trait ExpectOne { fn expect_one(self, err: &'static str) -> A::Item; @@ -283,19 +284,21 @@ pub trait MutVisitor: Sized { /// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful /// when using a `flat_map_*` or `filter_map_*` method within a `visit_` -/// method. Abort the program if the closure panics. +/// method. // // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`. -pub fn visit_clobber(t: &mut T, f: F) -where - F: FnOnce(T) -> T, -{ +pub fn visit_clobber(t: &mut T, f: impl FnOnce(T) -> T) { unsafe { // Safe because `t` is used in a read-only fashion by `read()` before // being overwritten by `write()`. let old_t = ptr::read(t); - let new_t = panic::catch_unwind(panic::AssertUnwindSafe(|| f(old_t))) - .unwrap_or_else(|_| process::abort()); + let new_t = + panic::catch_unwind(panic::AssertUnwindSafe(|| f(old_t))).unwrap_or_else(|err| { + // Set `t` to some valid but possible meaningless value, + // and pass the fatal error further. + ptr::write(t, T::dummy()); + panic::resume_unwind(err); + }); ptr::write(t, new_t); } } @@ -1105,36 +1108,12 @@ pub fn noop_visit_fn_header(header: &mut FnHeader, vis: &mut T) { visit_unsafety(unsafety, vis); } -// FIXME: Avoid visiting the crate as a `Mod` item, flat map only the inner items if possible, -// or make crate visiting first class if necessary. pub fn noop_visit_crate(krate: &mut Crate, vis: &mut T) { - visit_clobber(krate, |Crate { attrs, items, span }| { - let item_vis = - Visibility { kind: VisibilityKind::Public, span: span.shrink_to_lo(), tokens: None }; - let item = P(Item { - ident: Ident::empty(), - attrs, - id: DUMMY_NODE_ID, - vis: item_vis, - span, - kind: ItemKind::Mod(Unsafe::No, ModKind::Loaded(items, Inline::Yes, span)), - tokens: None, - }); - let items = vis.flat_map_item(item); - - let len = items.len(); - if len == 0 { - Crate { attrs: vec![], items: vec![], span } - } else if len == 1 { - let Item { attrs, span, kind, .. } = items.into_iter().next().unwrap().into_inner(); - match kind { - ItemKind::Mod(_, ModKind::Loaded(items, ..)) => Crate { attrs, items, span }, - _ => panic!("visitor converted a module to not a module"), - } - } else { - panic!("a crate cannot expand to more than one item"); - } - }); + let Crate { attrs, items, span, id, is_placeholder: _ } = krate; + vis.visit_id(id); + visit_attrs(attrs, vis); + items.flat_map_in_place(|item| vis.flat_map_item(item)); + vis.visit_span(span); } // Mutates one item into possibly many items. @@ -1475,3 +1454,109 @@ pub fn noop_visit_vis(visibility: &mut Visibility, vis: &mut T) { } vis.visit_span(&mut visibility.span); } + +/// Some value for the AST node that is valid but possibly meaningless. +pub trait DummyAstNode { + fn dummy() -> Self; +} + +impl DummyAstNode for Option { + fn dummy() -> Self { + Default::default() + } +} + +impl DummyAstNode for P { + fn dummy() -> Self { + P(DummyAstNode::dummy()) + } +} + +impl DummyAstNode for ThinVec { + fn dummy() -> Self { + Default::default() + } +} + +impl DummyAstNode for Item { + fn dummy() -> Self { + Item { + attrs: Default::default(), + id: DUMMY_NODE_ID, + span: Default::default(), + vis: Visibility { + kind: VisibilityKind::Public, + span: Default::default(), + tokens: Default::default(), + }, + ident: Ident::empty(), + kind: ItemKind::ExternCrate(None), + tokens: Default::default(), + } + } +} + +impl DummyAstNode for Expr { + fn dummy() -> Self { + Expr { + id: DUMMY_NODE_ID, + kind: ExprKind::Err, + span: Default::default(), + attrs: Default::default(), + tokens: Default::default(), + } + } +} + +impl DummyAstNode for Ty { + fn dummy() -> Self { + Ty { + id: DUMMY_NODE_ID, + kind: TyKind::Err, + span: Default::default(), + tokens: Default::default(), + } + } +} + +impl DummyAstNode for Pat { + fn dummy() -> Self { + Pat { + id: DUMMY_NODE_ID, + kind: PatKind::Wild, + span: Default::default(), + tokens: Default::default(), + } + } +} + +impl DummyAstNode for Stmt { + fn dummy() -> Self { + Stmt { id: DUMMY_NODE_ID, kind: StmtKind::Empty, span: Default::default() } + } +} + +impl DummyAstNode for Block { + fn dummy() -> Self { + Block { + stmts: Default::default(), + id: DUMMY_NODE_ID, + rules: BlockCheckMode::Default, + span: Default::default(), + tokens: Default::default(), + could_be_bare_literal: Default::default(), + } + } +} + +impl DummyAstNode for Crate { + fn dummy() -> Self { + Crate { + attrs: Default::default(), + items: Default::default(), + span: Default::default(), + id: DUMMY_NODE_ID, + is_placeholder: Default::default(), + } + } +} diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index 9c6ad47427..1cc5ddfd8e 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -35,12 +35,12 @@ impl LitKind { LitKind::Bool(symbol == kw::True) } token::Byte => { - return unescape_byte(&symbol.as_str()) + return unescape_byte(symbol.as_str()) .map(LitKind::Byte) .map_err(|_| LitError::LexerError); } token::Char => { - return unescape_char(&symbol.as_str()) + return unescape_char(symbol.as_str()) .map(LitKind::Char) .map_err(|_| LitError::LexerError); } @@ -57,7 +57,7 @@ impl LitKind { // string in the token. let s = symbol.as_str(); let symbol = - if s.contains(&['\\', '\r'][..]) { + if s.contains(&['\\', '\r']) { let mut buf = String::with_capacity(s.len()); let mut error = Ok(()); unescape_literal(&s, Mode::Str, &mut |_, unescaped_char| { diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index be794ed221..6840f092da 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -211,6 +211,9 @@ pub trait Visitor<'ast>: Sized { fn visit_pat_field(&mut self, fp: &'ast PatField) { walk_pat_field(self, fp) } + fn visit_crate(&mut self, krate: &'ast Crate) { + walk_crate(self, krate) + } } #[macro_export] diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index cfa97ff84e..9c28f3c7f5 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -49,11 +49,27 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .struct_span_err(sp, "the `att_syntax` option is only supported on x86") .emit(); } + if asm.options.contains(InlineAsmOptions::MAY_UNWIND) + && !self.sess.features_untracked().asm_unwind + { + feature_err( + &self.sess.parse_sess, + sym::asm_unwind, + sp, + "the `may_unwind` option is unstable", + ) + .emit(); + } let mut clobber_abis = FxHashMap::default(); if let Some(asm_arch) = asm_arch { for (abi_name, abi_span) in &asm.clobber_abis { - match asm::InlineAsmClobberAbi::parse(asm_arch, &self.sess.target, *abi_name) { + match asm::InlineAsmClobberAbi::parse( + asm_arch, + |feature| self.sess.target_features.contains(&Symbol::intern(feature)), + &self.sess.target, + *abi_name, + ) { Ok(abi) => { // If the abi was already in the list, emit an error match clobber_abis.get(&abi) { diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index 14a894d61f..082c5bb783 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -2,7 +2,6 @@ use crate::{ImplTraitContext, ImplTraitPosition, LoweringContext}; use rustc_ast::{AttrVec, Block, BlockCheckMode, Expr, Local, LocalKind, Stmt, StmtKind}; use rustc_hir as hir; use rustc_session::parse::feature_err; -use rustc_span::symbol::Ident; use rustc_span::{sym, DesugaringKind}; use smallvec::SmallVec; @@ -39,8 +38,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let hir_id = self.lower_node_id(s.id); match &local.kind { LocalKind::InitElse(init, els) => { - let (s, e) = self.lower_let_else(hir_id, local, init, els, tail); - stmts.push(s); + let e = self.lower_let_else(hir_id, local, init, els, tail); expr = Some(e); // remaining statements are in let-else expression break; @@ -125,36 +123,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { init: &Expr, els: &Block, tail: &[Stmt], - ) -> (hir::Stmt<'hir>, &'hir hir::Expr<'hir>) { + ) -> &'hir hir::Expr<'hir> { let ty = local .ty .as_ref() .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Binding))); let span = self.lower_span(local.span); let span = self.mark_span_with_reason(DesugaringKind::LetElse, span, None); - let init = Some(self.lower_expr(init)); - let val = Ident::with_dummy_span(sym::val); - let (pat, val_id) = - self.pat_ident_binding_mode(span, val, hir::BindingAnnotation::Unannotated); + let init = self.lower_expr(init); let local_hir_id = self.lower_node_id(local.id); self.lower_attrs(local_hir_id, &local.attrs); - // first statement which basically exists for the type annotation - let stmt = { - let local = self.arena.alloc(hir::Local { + let let_expr = { + let lex = self.arena.alloc(hir::Let { hir_id: local_hir_id, + pat: self.lower_pat(&local.pat), ty, - pat, init, span, - source: hir::LocalSource::Normal, }); - let kind = hir::StmtKind::Local(local); - hir::Stmt { hir_id: stmt_hir_id, kind, span } - }; - let let_expr = { - let scrutinee = self.expr_ident(span, val, val_id); - let let_kind = hir::ExprKind::Let(self.lower_pat(&local.pat), scrutinee, span); - self.arena.alloc(self.expr(span, let_kind, AttrVec::new())) + self.arena.alloc(self.expr(span, hir::ExprKind::Let(lex), AttrVec::new())) }; let then_expr = { let (stmts, expr) = self.lower_stmts(tail); @@ -165,9 +152,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let block = self.lower_block(els, false); self.arena.alloc(self.expr_block(block, AttrVec::new())) }; + self.alias_attrs(let_expr.hir_id, local_hir_id); self.alias_attrs(else_expr.hir_id, local_hir_id); let if_expr = self.arena.alloc(hir::Expr { - hir_id: self.next_id(), + hir_id: stmt_hir_id, span, kind: hir::ExprKind::If(let_expr, then_expr, Some(else_expr)), }); @@ -180,6 +168,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) .emit(); } - (stmt, if_expr) + if_expr } } diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 9c579209fe..75f384405b 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -9,7 +9,6 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::definitions::DefPathData; -use rustc_session::parse::feature_err; use rustc_span::hygiene::ExpnId; use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned}; use rustc_span::symbol::{sym, Ident, Symbol}; @@ -35,7 +34,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } ExprKind::Repeat(ref expr, ref count) => { let expr = self.lower_expr(expr); - let count = self.lower_anon_const(count); + let count = self.lower_array_length(count); hir::ExprKind::Repeat(expr, count) } ExprKind::Tup(ref elts) => hir::ExprKind::Tup(self.lower_exprs(elts)), @@ -92,11 +91,15 @@ impl<'hir> LoweringContext<'_, 'hir> { let ohs = self.lower_expr(ohs); hir::ExprKind::AddrOf(k, m, ohs) } - ExprKind::Let(ref pat, ref scrutinee, span) => hir::ExprKind::Let( - self.lower_pat(pat), - self.lower_expr(scrutinee), - self.lower_span(span), - ), + ExprKind::Let(ref pat, ref scrutinee, span) => { + hir::ExprKind::Let(self.arena.alloc(hir::Let { + hir_id: self.next_id(), + span: self.lower_span(span), + pat: self.lower_pat(pat), + ty: None, + init: self.lower_expr(scrutinee), + })) + } ExprKind::If(ref cond, ref then, ref else_opt) => { self.lower_expr_if(cond, then, else_opt.as_deref()) } @@ -130,7 +133,15 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::AsyncGeneratorKind::Block, |this| this.with_new_scopes(|this| this.lower_block_expr(block)), ), - ExprKind::Await(ref expr) => self.lower_expr_await(e.span, expr), + ExprKind::Await(ref expr) => { + let span = if expr.span.hi() < e.span.hi() { + expr.span.shrink_to_hi().with_hi(e.span.hi()) + } else { + // this is a recovered `await expr` + e.span + }; + self.lower_expr_await(span, expr) + } ExprKind::Closure( capture_clause, asyncness, @@ -479,8 +490,12 @@ impl<'hir> LoweringContext<'_, 'hir> { expr: &'hir hir::Expr<'hir>, overall_span: Span, ) -> &'hir hir::Expr<'hir> { - let constructor = - self.arena.alloc(self.expr_lang_item_path(method_span, lang_item, ThinVec::new())); + let constructor = self.arena.alloc(self.expr_lang_item_path( + method_span, + lang_item, + ThinVec::new(), + None, + )); self.expr_call(overall_span, constructor, std::slice::from_ref(expr)) } @@ -584,8 +599,12 @@ impl<'hir> LoweringContext<'_, 'hir> { // `future::from_generator`: let unstable_span = self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone()); - let gen_future = - self.expr_lang_item_path(unstable_span, hir::LangItem::FromGenerator, ThinVec::new()); + let gen_future = self.expr_lang_item_path( + unstable_span, + hir::LangItem::FromGenerator, + ThinVec::new(), + None, + ); // `future::from_generator(generator)`: hir::ExprKind::Call(self.arena.alloc(gen_future), arena_vec![self; generator]) @@ -593,7 +612,7 @@ impl<'hir> LoweringContext<'_, 'hir> { /// Desugar `.await` into: /// ```rust - /// match { + /// match ::std::future::IntoFuture::into_future() { /// mut pinned => loop { /// match unsafe { ::std::future::Future::poll( /// <::std::pin::Pin>::new_unchecked(&mut pinned), @@ -607,6 +626,7 @@ impl<'hir> LoweringContext<'_, 'hir> { /// } /// ``` fn lower_expr_await(&mut self, await_span: Span, expr: &Expr) -> hir::ExprKind<'hir> { + let dot_await_span = expr.span.shrink_to_hi().to(await_span); match self.generator_kind { Some(hir::GeneratorKind::Async(_)) => {} Some(hir::GeneratorKind::Gen) | None => { @@ -623,13 +643,14 @@ impl<'hir> LoweringContext<'_, 'hir> { err.emit(); } } - let span = self.mark_span_with_reason(DesugaringKind::Await, await_span, None); + let span = self.mark_span_with_reason(DesugaringKind::Await, dot_await_span, None); let gen_future_span = self.mark_span_with_reason( DesugaringKind::Await, await_span, self.allow_gen_future.clone(), ); - let expr = self.lower_expr(expr); + let expr = self.lower_expr_mut(expr); + let expr_hir_id = expr.hir_id; let pinned_ident = Ident::with_dummy_span(sym::pinned); let (pinned_pat, pinned_pat_hid) = @@ -656,16 +677,19 @@ impl<'hir> LoweringContext<'_, 'hir> { span, hir::LangItem::PinNewUnchecked, arena_vec![self; ref_mut_pinned], + Some(expr_hir_id), ); let get_context = self.expr_call_lang_item_fn_mut( gen_future_span, hir::LangItem::GetContext, arena_vec![self; task_context], + Some(expr_hir_id), ); let call = self.expr_call_lang_item_fn( span, hir::LangItem::FuturePoll, arena_vec![self; new_unchecked, get_context], + Some(expr_hir_id), ); self.arena.alloc(self.expr_unsafe(call)) }; @@ -678,18 +702,28 @@ impl<'hir> LoweringContext<'_, 'hir> { let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident); let x_expr = self.expr_ident(span, x_ident, x_pat_hid); let ready_field = self.single_pat_field(span, x_pat); - let ready_pat = self.pat_lang_item_variant(span, hir::LangItem::PollReady, ready_field); + let ready_pat = self.pat_lang_item_variant( + span, + hir::LangItem::PollReady, + ready_field, + Some(expr_hir_id), + ); let break_x = self.with_loop_scope(loop_node_id, move |this| { let expr_break = hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr)); - this.arena.alloc(this.expr(await_span, expr_break, ThinVec::new())) + this.arena.alloc(this.expr(span, expr_break, ThinVec::new())) }); self.arm(ready_pat, break_x) }; // `::std::task::Poll::Pending => {}` let pending_arm = { - let pending_pat = self.pat_lang_item_variant(span, hir::LangItem::PollPending, &[]); + let pending_pat = self.pat_lang_item_variant( + span, + hir::LangItem::PollPending, + &[], + Some(expr_hir_id), + ); let empty_block = self.expr_block_empty(span); self.arm(pending_pat, empty_block) }; @@ -709,7 +743,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let unit = self.expr_unit(span); let yield_expr = self.expr( span, - hir::ExprKind::Yield(unit, hir::YieldSource::Await { expr: Some(expr.hir_id) }), + hir::ExprKind::Yield(unit, hir::YieldSource::Await { expr: Some(expr_hir_id) }), ThinVec::new(), ); let yield_expr = self.arena.alloc(yield_expr); @@ -746,10 +780,27 @@ impl<'hir> LoweringContext<'_, 'hir> { // mut pinned => loop { ... } let pinned_arm = self.arm(pinned_pat, loop_expr); - // match { + // `match ::std::future::IntoFuture::into_future() { ... }` + let into_future_span = self.mark_span_with_reason( + DesugaringKind::Await, + await_span, + self.allow_into_future.clone(), + ); + let into_future_expr = self.expr_call_lang_item_fn( + into_future_span, + hir::LangItem::IntoFutureIntoFuture, + arena_vec![self; expr], + Some(expr_hir_id), + ); + + // match { // mut pinned => loop { .. } // } - hir::ExprKind::Match(expr, arena_vec![self; pinned_arm], hir::MatchSource::AwaitDesugar) + hir::ExprKind::Match( + into_future_expr, + arena_vec![self; pinned_arm], + hir::MatchSource::AwaitDesugar, + ) } fn lower_expr_closure( @@ -914,24 +965,6 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_span(eq_sign_span), ); } - if !self.sess.features_untracked().destructuring_assignment { - let mut err = feature_err( - &self.sess.parse_sess, - sym::destructuring_assignment, - eq_sign_span, - "destructuring assignments are unstable", - ); - err.span_label(lhs.span, "cannot assign to this expression"); - if self.is_in_loop_condition { - err.span_suggestion_verbose( - lhs.span.shrink_to_lo(), - "you might have meant to use pattern destructuring", - "let ".to_string(), - rustc_errors::Applicability::MachineApplicable, - ); - } - err.emit(); - } let mut assignments = vec![]; @@ -1144,7 +1177,8 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind<'hir> { let e1 = self.lower_expr_mut(e1); let e2 = self.lower_expr_mut(e2); - let fn_path = hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span)); + let fn_path = + hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span), None); let fn_expr = self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new())); hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2]) @@ -1178,7 +1212,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ExprKind::Struct( - self.arena.alloc(hir::QPath::LangItem(lang_item, self.lower_span(span))), + self.arena.alloc(hir::QPath::LangItem(lang_item, self.lower_span(span), None)), fields, None, ) @@ -1373,6 +1407,7 @@ impl<'hir> LoweringContext<'_, 'hir> { head_span, hir::LangItem::IteratorNext, arena_vec![self; ref_mut_iter], + None, ); let arms = arena_vec![self; none_arm, some_arm]; @@ -1401,6 +1436,7 @@ impl<'hir> LoweringContext<'_, 'hir> { head_span, hir::LangItem::IntoIterIntoIter, arena_vec![self; head], + None, ) }; @@ -1456,6 +1492,7 @@ impl<'hir> LoweringContext<'_, 'hir> { unstable_span, hir::LangItem::TryTraitBranch, arena_vec![self; sub_expr], + None, ) }; @@ -1612,8 +1649,10 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, lang_item: hir::LangItem, args: &'hir [hir::Expr<'hir>], + hir_id: Option, ) -> hir::Expr<'hir> { - let path = self.arena.alloc(self.expr_lang_item_path(span, lang_item, ThinVec::new())); + let path = + self.arena.alloc(self.expr_lang_item_path(span, lang_item, ThinVec::new(), hir_id)); self.expr_call_mut(span, path, args) } @@ -1622,8 +1661,9 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, lang_item: hir::LangItem, args: &'hir [hir::Expr<'hir>], + hir_id: Option, ) -> &'hir hir::Expr<'hir> { - self.arena.alloc(self.expr_call_lang_item_fn_mut(span, lang_item, args)) + self.arena.alloc(self.expr_call_lang_item_fn_mut(span, lang_item, args, hir_id)) } fn expr_lang_item_path( @@ -1631,10 +1671,11 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, lang_item: hir::LangItem, attrs: AttrVec, + hir_id: Option, ) -> hir::Expr<'hir> { self.expr( span, - hir::ExprKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span))), + hir::ExprKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span), hir_id)), attrs, ) } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 692f393682..92cae4da89 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -247,12 +247,7 @@ impl<'hir> LoweringContext<'_, 'hir> { AnonymousLifetimeMode::PassThrough, |this, idty| { let ret_id = asyncness.opt_return_id(); - this.lower_fn_decl( - &decl, - Some((fn_def_id.to_def_id(), idty)), - true, - ret_id, - ) + this.lower_fn_decl(&decl, Some((fn_def_id, idty)), true, ret_id) }, ); let sig = hir::FnSig { @@ -1264,7 +1259,7 @@ impl<'hir> LoweringContext<'_, 'hir> { |this, idty| { this.lower_fn_decl( &sig.decl, - Some((fn_def_id.to_def_id(), idty)), + Some((fn_def_id, idty)), impl_trait_return_allow, is_async, ) @@ -1283,7 +1278,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } pub(super) fn lower_abi(&mut self, abi: StrLit) -> abi::Abi { - abi::lookup(&abi.symbol_unescaped.as_str()).unwrap_or_else(|| { + abi::lookup(abi.symbol_unescaped.as_str()).unwrap_or_else(|| { self.error_on_invalid_abi(abi); abi::Abi::Rust }) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 2b3a538772..35eb716949 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -32,7 +32,6 @@ #![feature(crate_visibility_modifier)] #![feature(box_patterns)] -#![feature(iter_zip)] #![feature(never_type)] #![recursion_limit = "256"] @@ -47,20 +46,19 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; -use rustc_errors::{struct_span_err, Applicability}; +use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{DefId, DefPathHash, LocalDefId, CRATE_DEF_ID}; use rustc_hir::definitions::{DefKey, DefPathData, Definitions}; use rustc_hir::intravisit; -use rustc_hir::{ConstArg, GenericArg, InferKind, ParamName}; +use rustc_hir::{ConstArg, GenericArg, ParamName}; use rustc_index::vec::{Idx, IndexVec}; use rustc_query_system::ich::StableHashingContext; -use rustc_session::lint::builtin::BARE_TRAIT_OBJECTS; -use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; +use rustc_session::lint::LintBuffer; +use rustc_session::parse::feature_err; use rustc_session::utils::{FlattenNonterminals, NtToTokenstream}; use rustc_session::Session; -use rustc_span::edition::Edition; use rustc_span::hygiene::ExpnId; use rustc_span::source_map::{respan, DesugaringKind}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -70,10 +68,9 @@ use smallvec::SmallVec; use tracing::{debug, trace}; macro_rules! arena_vec { - ($this:expr; $($x:expr),*) => ({ - let a = [$($x),*]; - $this.arena.alloc_from_iter(std::array::IntoIter::new(a)) - }); + ($this:expr; $($x:expr),*) => ( + $this.arena.alloc_from_iter([$($x),*]) + ); } mod asm; @@ -162,6 +159,7 @@ struct LoweringContext<'a, 'hir: 'a> { allow_try_trait: Option>, allow_gen_future: Option>, + allow_into_future: Option>, } pub trait ResolverAstLowering { @@ -228,7 +226,7 @@ enum ImplTraitContext<'b, 'a> { ReturnPositionOpaqueTy { /// `DefId` for the parent function, used to look up necessary /// information later. - fn_def_id: DefId, + fn_def_id: LocalDefId, /// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn, origin: hir::OpaqueTyOrigin, }, @@ -320,6 +318,7 @@ pub fn lower_crate<'a, 'hir>( in_scope_lifetimes: Vec::new(), allow_try_trait: Some([sym::try_trait_v2][..].into()), allow_gen_future: Some([sym::gen_future][..].into()), + allow_into_future: Some([sym::into_future][..].into()), } .lower_crate(krate) } @@ -645,31 +644,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// parameter while `f` is running (and restored afterwards). fn collect_in_band_defs( &mut self, - parent_def_id: LocalDefId, - anonymous_lifetime_mode: AnonymousLifetimeMode, - f: impl FnOnce(&mut Self) -> (Vec>, T), - ) -> (Vec>, T) { - assert!(!self.is_collecting_in_band_lifetimes); - assert!(self.lifetimes_to_define.is_empty()); - let old_anonymous_lifetime_mode = self.anonymous_lifetime_mode; + f: impl FnOnce(&mut Self) -> T, + ) -> (Vec<(Span, ParamName)>, T) { + let was_collecting = std::mem::replace(&mut self.is_collecting_in_band_lifetimes, true); + let len = self.lifetimes_to_define.len(); - self.anonymous_lifetime_mode = anonymous_lifetime_mode; - self.is_collecting_in_band_lifetimes = true; + let res = f(self); - let (in_band_ty_params, res) = f(self); - - self.is_collecting_in_band_lifetimes = false; - self.anonymous_lifetime_mode = old_anonymous_lifetime_mode; - - let lifetimes_to_define = self.lifetimes_to_define.split_off(0); - - let params = lifetimes_to_define - .into_iter() - .map(|(span, hir_name)| self.lifetime_to_generic_param(span, hir_name, parent_def_id)) - .chain(in_band_ty_params.into_iter()) - .collect(); - - (params, res) + let lifetimes_to_define = self.lifetimes_to_define.split_off(len); + self.is_collecting_in_band_lifetimes = was_collecting; + (lifetimes_to_define, res) } /// Converts a lifetime into a new generic parameter. @@ -784,27 +768,39 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { anonymous_lifetime_mode: AnonymousLifetimeMode, f: impl FnOnce(&mut Self, &mut Vec>) -> T, ) -> (hir::Generics<'hir>, T) { - let (in_band_defs, (mut lowered_generics, res)) = - self.with_in_scope_lifetime_defs(&generics.params, |this| { - this.collect_in_band_defs(parent_def_id, anonymous_lifetime_mode, |this| { - let mut params = Vec::new(); - // Note: it is necessary to lower generics *before* calling `f`. - // When lowering `async fn`, there's a final step when lowering - // the return type that assumes that all in-scope lifetimes have - // already been added to either `in_scope_lifetimes` or - // `lifetimes_to_define`. If we swapped the order of these two, - // in-band-lifetimes introduced by generics or where-clauses - // wouldn't have been added yet. - let generics = this.lower_generics_mut( - generics, - ImplTraitContext::Universal(&mut params, this.current_hir_id_owner), - ); - let res = f(this, &mut params); - (params, (generics, res)) + let (lifetimes_to_define, (mut lowered_generics, impl_trait_defs, res)) = self + .collect_in_band_defs(|this| { + this.with_anonymous_lifetime_mode(anonymous_lifetime_mode, |this| { + this.with_in_scope_lifetime_defs(&generics.params, |this| { + let mut impl_trait_defs = Vec::new(); + // Note: it is necessary to lower generics *before* calling `f`. + // When lowering `async fn`, there's a final step when lowering + // the return type that assumes that all in-scope lifetimes have + // already been added to either `in_scope_lifetimes` or + // `lifetimes_to_define`. If we swapped the order of these two, + // in-band-lifetimes introduced by generics or where-clauses + // wouldn't have been added yet. + let generics = this.lower_generics_mut( + generics, + ImplTraitContext::Universal( + &mut impl_trait_defs, + this.current_hir_id_owner, + ), + ); + let res = f(this, &mut impl_trait_defs); + (generics, impl_trait_defs, res) + }) }) }); - lowered_generics.params.extend(in_band_defs); + lowered_generics.params.extend( + lifetimes_to_define + .into_iter() + .map(|(span, hir_name)| { + self.lifetime_to_generic_param(span, hir_name, parent_def_id) + }) + .chain(impl_trait_defs), + ); let lowered_generics = lowered_generics.into_generics(self.arena); (lowered_generics, res) @@ -1116,7 +1112,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { return GenericArg::Infer(hir::InferArg { hir_id: self.lower_node_id(ty.id), span: self.lower_span(ty.span), - kind: InferKind::Type, }); } // We parse const arguments as path types as we cannot distinguish them during @@ -1188,11 +1183,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> hir::Ty<'hir> { let id = self.lower_node_id(t.id); let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx); - let ty = self.ty_path(id, t.span, qpath); - if let hir::TyKind::TraitObject(..) = ty.kind { - self.maybe_lint_bare_trait(t.span, t.id, qself.is_none() && path.is_global()); - } - ty + self.ty_path(id, t.span, qpath) } fn ty(&mut self, span: Span, kind: hir::TyKind<'hir>) -> hir::Ty<'hir> { @@ -1258,7 +1249,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { )) } TyKind::Array(ref ty, ref length) => { - hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_anon_const(length)) + hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_array_length(length)) } TyKind::Typeof(ref expr) => hir::TyKind::Typeof(self.lower_anon_const(expr)), TyKind::TraitObject(ref bounds, kind) => { @@ -1289,9 +1280,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lifetime_bound.unwrap_or_else(|| this.elided_dyn_bound(t.span)); (bounds, lifetime_bound) }); - if kind != TraitObjectSyntax::Dyn { - self.maybe_lint_bare_trait(t.span, t.id, false); - } hir::TyKind::TraitObject(bounds, lifetime_bound, kind) } TyKind::ImplTrait(def_node_id, ref bounds) => { @@ -1379,7 +1367,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_opaque_impl_trait( &mut self, span: Span, - fn_def_id: Option, + fn_def_id: Option, origin: hir::OpaqueTyOrigin, opaque_ty_node_id: NodeId, capturable_lifetimes: Option<&FxHashSet>, @@ -1451,7 +1439,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: lctx.lower_span(span), }, bounds: hir_bounds, - impl_trait_fn: fn_def_id, origin, }; @@ -1521,7 +1508,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_fn_decl( &mut self, decl: &FnDecl, - mut in_band_ty_params: Option<(DefId, &mut Vec>)>, + mut in_band_ty_params: Option<(LocalDefId, &mut Vec>)>, impl_trait_return_allow: bool, make_ret_async: Option, ) -> &'hir hir::FnDecl<'hir> { @@ -1579,7 +1566,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { Some((def_id, _)) if impl_trait_return_allow => { ImplTraitContext::ReturnPositionOpaqueTy { fn_def_id: def_id, - origin: hir::OpaqueTyOrigin::FnReturn, + origin: hir::OpaqueTyOrigin::FnReturn(def_id), } } _ => ImplTraitContext::disallowed(), @@ -1634,7 +1621,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_async_fn_ret_ty( &mut self, output: &FnRetTy, - fn_def_id: DefId, + fn_def_id: LocalDefId, opaque_ty_node_id: NodeId, ) -> hir::FnRetTy<'hir> { debug!( @@ -1688,18 +1675,29 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // this is because the elided lifetimes from the return type // should be figured out using the ordinary elision rules, and // this desugaring achieves that. - // - // The variable `input_lifetimes_count` tracks the number of - // lifetime parameters to the opaque type *not counting* those - // lifetimes elided in the return type. This includes those - // that are explicitly declared (`in_scope_lifetimes`) and - // those elided lifetimes we found in the arguments (current - // content of `lifetimes_to_define`). Next, we will process - // the return type, which will cause `lifetimes_to_define` to - // grow. - let input_lifetimes_count = self.in_scope_lifetimes.len() + self.lifetimes_to_define.len(); - let mut lifetime_params = Vec::new(); + debug!("lower_async_fn_ret_ty: in_scope_lifetimes={:#?}", self.in_scope_lifetimes); + debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", self.lifetimes_to_define); + + // Calculate all the lifetimes that should be captured + // by the opaque type. This should include all in-scope + // lifetime parameters, including those defined in-band. + // + // `lifetime_params` is a vector of tuple (span, parameter name, lifetime name). + + // Input lifetime like `'a` or `'1`: + let mut lifetime_params: Vec<_> = self + .in_scope_lifetimes + .iter() + .cloned() + .map(|name| (name.ident().span, name, hir::LifetimeName::Param(name))) + .chain( + self.lifetimes_to_define + .iter() + .map(|&(span, name)| (span, name, hir::LifetimeName::Param(name))), + ) + .collect(); + self.with_hir_id_owner(opaque_ty_node_id, |this| { // We have to be careful to get elision right here. The // idea is that we create a lifetime parameter for each @@ -1709,34 +1707,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // // Then, we will create `fn foo(..) -> Foo<'_, '_>`, and // hence the elision takes place at the fn site. - let future_bound = this - .with_anonymous_lifetime_mode(AnonymousLifetimeMode::CreateParameter, |this| { - this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span) + let (lifetimes_to_define, future_bound) = + this.with_anonymous_lifetime_mode(AnonymousLifetimeMode::CreateParameter, |this| { + this.collect_in_band_defs(|this| { + this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span) + }) }); - debug!("lower_async_fn_ret_ty: future_bound={:#?}", future_bound); + debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", lifetimes_to_define); - // Calculate all the lifetimes that should be captured - // by the opaque type. This should include all in-scope - // lifetime parameters, including those defined in-band. - // - // Note: this must be done after lowering the output type, - // as the output type may introduce new in-band lifetimes. - lifetime_params = this - .in_scope_lifetimes - .iter() - .cloned() - .map(|name| (name.ident().span, name)) - .chain(this.lifetimes_to_define.iter().cloned()) - .collect(); - - debug!("lower_async_fn_ret_ty: in_scope_lifetimes={:#?}", this.in_scope_lifetimes); - debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", this.lifetimes_to_define); + lifetime_params.extend( + // Output lifetime like `'_`: + lifetimes_to_define + .into_iter() + .map(|(span, name)| (span, name, hir::LifetimeName::Implicit(false))), + ); debug!("lower_async_fn_ret_ty: lifetime_params={:#?}", lifetime_params); let generic_params = - this.arena.alloc_from_iter(lifetime_params.iter().map(|(span, hir_name)| { - this.lifetime_to_generic_param(*span, *hir_name, opaque_ty_def_id) + this.arena.alloc_from_iter(lifetime_params.iter().map(|&(span, hir_name, _)| { + this.lifetime_to_generic_param(span, hir_name, opaque_ty_def_id) })); let opaque_ty_item = hir::OpaqueTy { @@ -1746,8 +1736,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: this.lower_span(span), }, bounds: arena_vec![this; future_bound], - impl_trait_fn: Some(fn_def_id), - origin: hir::OpaqueTyOrigin::AsyncFn, + origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id), }; trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id); @@ -1770,25 +1759,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // // For the "output" lifetime parameters, we just want to // generate `'_`. - let mut generic_args = Vec::with_capacity(lifetime_params.len()); - generic_args.extend(lifetime_params[..input_lifetimes_count].iter().map( - |&(span, hir_name)| { - // Input lifetime like `'a` or `'1`: + let generic_args = + self.arena.alloc_from_iter(lifetime_params.into_iter().map(|(span, _, name)| { GenericArg::Lifetime(hir::Lifetime { hir_id: self.next_id(), span: self.lower_span(span), - name: hir::LifetimeName::Param(hir_name), + name, }) - }, - )); - generic_args.extend(lifetime_params[input_lifetimes_count..].iter().map(|&(span, _)| - // Output lifetime like `'_`. - GenericArg::Lifetime(hir::Lifetime { - hir_id: self.next_id(), - span: self.lower_span(span), - name: hir::LifetimeName::Implicit, - }))); - let generic_args = self.arena.alloc_from_iter(generic_args); + })); // Create the `Foo<...>` reference itself. Note that the `type // Foo = impl Trait` is, internally, created as a child of the @@ -1804,7 +1782,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_async_fn_output_type_to_future_bound( &mut self, output: &FnRetTy, - fn_def_id: DefId, + fn_def_id: LocalDefId, span: Span, ) -> hir::GenericBound<'hir> { // Compute the `T` in `Future` from the return type. @@ -1815,7 +1793,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // generates. let context = ImplTraitContext::ReturnPositionOpaqueTy { fn_def_id, - origin: hir::OpaqueTyOrigin::FnReturn, + origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), }; self.lower_ty(ty, context) } @@ -1927,7 +1905,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }); let param_name = match lt.name { hir::LifetimeName::Param(param_name) => param_name, - hir::LifetimeName::Implicit + hir::LifetimeName::Implicit(_) | hir::LifetimeName::Underscore | hir::LifetimeName::Static => hir::ParamName::Plain(lt.name.ident()), hir::LifetimeName::ImplicitObjectLifetimeDefault => { @@ -2062,6 +2040,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.expr_block(block, AttrVec::new()) } + fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen { + match c.value.kind { + ExprKind::Underscore => { + if self.sess.features_untracked().generic_arg_infer { + hir::ArrayLen::Infer(self.lower_node_id(c.id), c.value.span) + } else { + feature_err( + &self.sess.parse_sess, + sym::generic_arg_infer, + c.value.span, + "using `_` for array lengths is unstable", + ) + .emit(); + hir::ArrayLen::Body(self.lower_anon_const(c)) + } + } + _ => hir::ArrayLen::Body(self.lower_anon_const(c)), + } + } + fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst { self.with_new_scopes(|this| hir::AnonConst { hir_id: this.lower_node_id(c.id), @@ -2139,21 +2137,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn pat_cf_continue(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { let field = self.single_pat_field(span, pat); - self.pat_lang_item_variant(span, hir::LangItem::ControlFlowContinue, field) + self.pat_lang_item_variant(span, hir::LangItem::ControlFlowContinue, field, None) } fn pat_cf_break(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { let field = self.single_pat_field(span, pat); - self.pat_lang_item_variant(span, hir::LangItem::ControlFlowBreak, field) + self.pat_lang_item_variant(span, hir::LangItem::ControlFlowBreak, field, None) } fn pat_some(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { let field = self.single_pat_field(span, pat); - self.pat_lang_item_variant(span, hir::LangItem::OptionSome, field) + self.pat_lang_item_variant(span, hir::LangItem::OptionSome, field, None) } fn pat_none(&mut self, span: Span) -> &'hir hir::Pat<'hir> { - self.pat_lang_item_variant(span, hir::LangItem::OptionNone, &[]) + self.pat_lang_item_variant(span, hir::LangItem::OptionNone, &[], None) } fn single_pat_field( @@ -2176,8 +2174,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: Span, lang_item: hir::LangItem, fields: &'hir [hir::PatField<'hir>], + hir_id: Option, ) -> &'hir hir::Pat<'hir> { - let qpath = hir::QPath::LangItem(lang_item, self.lower_span(span)); + let qpath = hir::QPath::LangItem(lang_item, self.lower_span(span), hir_id); self.pat(span, hir::PatKind::Struct(qpath, fields, false)) } @@ -2290,7 +2289,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { AnonymousLifetimeMode::ReportError => self.new_error_lifetime(None, span), - AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span), + AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span, false), } } @@ -2322,11 +2321,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &'s mut self, span: Span, count: usize, + param_mode: ParamMode, ) -> impl Iterator + Captures<'a> + Captures<'s> + Captures<'hir> { - (0..count).map(move |_| self.elided_path_lifetime(span)) + (0..count).map(move |_| self.elided_path_lifetime(span, param_mode)) } - fn elided_path_lifetime(&mut self, span: Span) -> hir::Lifetime { + fn elided_path_lifetime(&mut self, span: Span, param_mode: ParamMode) -> hir::Lifetime { match self.anonymous_lifetime_mode { AnonymousLifetimeMode::CreateParameter => { // We should have emitted E0726 when processing this path above @@ -2342,7 +2342,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // lifetime. Instead, we simply create an implicit lifetime, which will be checked // later, at which point a suitable error will be emitted. AnonymousLifetimeMode::PassThrough | AnonymousLifetimeMode::ReportError => { - self.new_implicit_lifetime(span) + self.new_implicit_lifetime(span, param_mode == ParamMode::Explicit) } } } @@ -2385,44 +2385,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { r } - fn new_implicit_lifetime(&mut self, span: Span) -> hir::Lifetime { + fn new_implicit_lifetime(&mut self, span: Span, missing: bool) -> hir::Lifetime { hir::Lifetime { hir_id: self.next_id(), span: self.lower_span(span), - name: hir::LifetimeName::Implicit, - } - } - - fn maybe_lint_bare_trait(&mut self, span: Span, id: NodeId, is_global: bool) { - // FIXME(davidtwco): This is a hack to detect macros which produce spans of the - // call site which do not have a macro backtrace. See #61963. - let is_macro_callsite = self - .sess - .source_map() - .span_to_snippet(span) - .map(|snippet| snippet.starts_with("#[")) - .unwrap_or(true); - if !is_macro_callsite { - if span.edition() < Edition::Edition2021 { - self.resolver.lint_buffer().buffer_lint_with_diagnostic( - BARE_TRAIT_OBJECTS, - id, - span, - "trait objects without an explicit `dyn` are deprecated", - BuiltinLintDiagnostics::BareTraitObject(span, is_global), - ) - } else { - let msg = "trait objects must include the `dyn` keyword"; - let label = "add `dyn` keyword before this trait"; - let mut err = struct_span_err!(self.sess, span, E0782, "{}", msg,); - err.span_suggestion_verbose( - span.shrink_to_lo(), - label, - String::from("dyn "), - Applicability::MachineApplicable, - ); - err.emit(); - } + name: hir::LifetimeName::Implicit(missing), } } } @@ -2451,17 +2418,12 @@ impl<'hir> GenericArgsCtor<'hir> { } } +#[tracing::instrument(level = "debug")] fn lifetimes_from_impl_trait_bounds( opaque_ty_id: NodeId, bounds: hir::GenericBounds<'_>, lifetimes_to_include: Option<&FxHashSet>, ) -> Vec<(hir::LifetimeName, Span)> { - debug!( - "lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \ - bounds={:#?})", - opaque_ty_id, bounds, - ); - // This visitor walks over `impl Trait` bounds and creates defs for all lifetimes that // appear in the bounds, excluding lifetimes that are created within the bounds. // E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`. @@ -2536,7 +2498,7 @@ fn lifetimes_from_impl_trait_bounds( fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) { let name = match lifetime.name { - hir::LifetimeName::Implicit | hir::LifetimeName::Underscore => { + hir::LifetimeName::Implicit(_) | hir::LifetimeName::Underscore => { if self.collect_elided_lifetimes { // Use `'_` for both implicit and underscore lifetimes in // `type Foo<'_> = impl SomeTrait<'_>;`. diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 0a9b264aa4..ebae779843 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -24,7 +24,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let lower_sub = |this: &mut Self| sub.as_ref().map(|s| this.lower_pat(&*s)); break self.lower_pat_ident(pattern, binding_mode, ident, lower_sub); } - PatKind::Lit(ref e) => break hir::PatKind::Lit(self.lower_expr(e)), + PatKind::Lit(ref e) => { + break hir::PatKind::Lit(self.lower_expr_within_pat(e, false)); + } PatKind::TupleStruct(ref qself, ref path, ref pats) => { let qpath = self.lower_qpath( pattern.id, @@ -81,8 +83,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } PatKind::Range(ref e1, ref e2, Spanned { node: ref end, .. }) => { break hir::PatKind::Range( - e1.as_deref().map(|e| self.lower_expr(e)), - e2.as_deref().map(|e| self.lower_expr(e)), + e1.as_deref().map(|e| self.lower_expr_within_pat(e, true)), + e2.as_deref().map(|e| self.lower_expr_within_pat(e, true)), self.lower_range_end(end, e2.is_some()), ); } @@ -314,4 +316,33 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { RangeEnd::Excluded | RangeEnd::Included(_) => hir::RangeEnd::Included, } } + + /// Matches `'-' lit | lit (cf. parser::Parser::parse_literal_maybe_minus)`, + /// or paths for ranges. + // + // FIXME: do we want to allow `expr -> pattern` conversion to create path expressions? + // That means making this work: + // + // ```rust,ignore (FIXME) + // struct S; + // macro_rules! m { + // ($a:expr) => { + // let $a = S; + // } + // } + // m!(S); + // ``` + fn lower_expr_within_pat(&mut self, expr: &Expr, allow_paths: bool) -> &'hir hir::Expr<'hir> { + match expr.kind { + ExprKind::Lit(..) | ExprKind::ConstBlock(..) | ExprKind::Err => {} + ExprKind::Path(..) if allow_paths => {} + ExprKind::Unary(UnOp::Neg, ref inner) if matches!(inner.kind, ExprKind::Lit(_)) => {} + _ => { + self.diagnostic() + .span_err(expr.span, "arbitrary expressions aren't allowed in patterns"); + return self.arena.alloc(self.expr_err(expr.span)); + } + } + self.lower_expr(expr) + } } diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 929f427484..46928a1846 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -7,8 +7,6 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, PartialRes, Res}; use rustc_hir::def_id::DefId; use rustc_hir::GenericArg; -use rustc_session::lint::builtin::ELIDED_LIFETIMES_IN_PATHS; -use rustc_session::lint::BuiltinLintDiagnostics; use rustc_span::symbol::Ident; use rustc_span::{BytePos, Span, DUMMY_SP}; @@ -231,15 +229,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { if let Ok(snippet) = self.sess.source_map().span_to_snippet(data.span) { // Do not suggest going from `Trait()` to `Trait<>` if !data.inputs.is_empty() { - if let Some(split) = snippet.find('(') { - let trait_name = &snippet[0..split]; - let args = &snippet[split + 1..snippet.len() - 1]; - err.span_suggestion( - data.span, - "use angle brackets instead", - format!("{}<{}>", trait_name, args), - Applicability::MaybeIncorrect, - ); + // Suggest replacing `(` and `)` with `<` and `>` + // The snippet may be missing the closing `)`, skip that case + if snippet.ends_with(')') { + if let Some(split) = snippet.find('(') { + let trait_name = &snippet[0..split]; + let args = &snippet[split + 1..snippet.len() - 1]; + err.span_suggestion( + data.span, + "use angle brackets instead", + format!("{}<{}>", trait_name, args), + Applicability::MaybeIncorrect, + ); + } } } }; @@ -270,12 +272,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let has_lifetimes = generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_))); - if !generic_args.parenthesized && !has_lifetimes { + if !generic_args.parenthesized && !has_lifetimes && expected_lifetimes > 0 { // Note: these spans are used for diagnostics when they can't be inferred. // See rustc_resolve::late::lifetimes::LifetimeContext::add_missing_lifetime_specifiers_label let elided_lifetime_span = if generic_args.span.is_empty() { // If there are no brackets, use the identifier span. - segment.ident.span + // HACK: we use find_ancestor_inside to properly suggest elided spans in paths + // originating from macros, since the segment's span might be from a macro arg. + segment.ident.span.find_ancestor_inside(path_span).unwrap_or(path_span) } else if generic_args.is_empty() { // If there are brackets, but not generic arguments, then use the opening bracket generic_args.span.with_hi(generic_args.span.lo() + BytePos(1)) @@ -284,67 +288,47 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { generic_args.span.with_lo(generic_args.span.lo() + BytePos(1)).shrink_to_lo() }; generic_args.args = self - .elided_path_lifetimes(elided_lifetime_span, expected_lifetimes) + .elided_path_lifetimes(elided_lifetime_span, expected_lifetimes, param_mode) .map(GenericArg::Lifetime) .chain(generic_args.args.into_iter()) .collect(); - if expected_lifetimes > 0 && param_mode == ParamMode::Explicit { + // In create-parameter mode we error here because we don't want to support + // deprecated impl elision in new features like impl elision and `async fn`, + // both of which work using the `CreateParameter` mode: + // + // impl Foo for std::cell::Ref // note lack of '_ + // async fn foo(_: std::cell::Ref) { ... } + if let (ParamMode::Explicit, AnonymousLifetimeMode::CreateParameter) = + (param_mode, self.anonymous_lifetime_mode) + { let anon_lt_suggestion = vec!["'_"; expected_lifetimes].join(", "); let no_non_lt_args = generic_args.args.len() == expected_lifetimes; let no_bindings = generic_args.bindings.is_empty(); - let (incl_angl_brckt, insertion_sp, suggestion) = if no_non_lt_args && no_bindings { + let (incl_angl_brckt, suggestion) = if no_non_lt_args && no_bindings { // If there are no generic args, our suggestion can include the angle brackets. - (true, path_span.shrink_to_hi(), format!("<{}>", anon_lt_suggestion)) + (true, format!("<{}>", anon_lt_suggestion)) } else { // Otherwise we'll insert a `'_, ` right after the opening bracket. - let span = generic_args - .span - .with_lo(generic_args.span.lo() + BytePos(1)) - .shrink_to_lo(); - (false, span, format!("{}, ", anon_lt_suggestion)) + (false, format!("{}, ", anon_lt_suggestion)) }; - match self.anonymous_lifetime_mode { - // In create-parameter mode we error here because we don't want to support - // deprecated impl elision in new features like impl elision and `async fn`, - // both of which work using the `CreateParameter` mode: - // - // impl Foo for std::cell::Ref // note lack of '_ - // async fn foo(_: std::cell::Ref) { ... } - AnonymousLifetimeMode::CreateParameter => { - let mut err = struct_span_err!( - self.sess, - path_span, - E0726, - "implicit elided lifetime not allowed here" - ); - rustc_errors::add_elided_lifetime_in_path_suggestion( - &self.sess.source_map(), - &mut err, - expected_lifetimes, - path_span, - incl_angl_brckt, - insertion_sp, - suggestion, - ); - err.note("assuming a `'static` lifetime..."); - err.emit(); - } - AnonymousLifetimeMode::PassThrough | AnonymousLifetimeMode::ReportError => { - self.resolver.lint_buffer().buffer_lint_with_diagnostic( - ELIDED_LIFETIMES_IN_PATHS, - CRATE_NODE_ID, - path_span, - "hidden lifetime parameters in types are deprecated", - BuiltinLintDiagnostics::ElidedLifetimesInPaths( - expected_lifetimes, - path_span, - incl_angl_brckt, - insertion_sp, - suggestion, - ), - ); - } - } + let insertion_sp = elided_lifetime_span.shrink_to_hi(); + let mut err = struct_span_err!( + self.sess, + path_span, + E0726, + "implicit elided lifetime not allowed here" + ); + rustc_errors::add_elided_lifetime_in_path_suggestion( + &self.sess.source_map(), + &mut err, + expected_lifetimes, + path_span, + incl_angl_brckt, + insertion_sp, + suggestion, + ); + err.note("assuming a `'static` lifetime..."); + err.emit(); } } diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 1822ba6ec9..6237a01f69 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -23,7 +23,7 @@ use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Span; use rustc_target::spec::abi; use std::mem; -use std::ops::DerefMut; +use std::ops::{Deref, DerefMut}; const MORE_EXTERN: &str = "for more information, visit https://doc.rust-lang.org/std/keyword.extern.html"; @@ -302,34 +302,6 @@ impl<'a> AstValidator<'a> { } } - /// Matches `'-' lit | lit (cf. parser::Parser::parse_literal_maybe_minus)`, - /// or paths for ranges. - // - // FIXME: do we want to allow `expr -> pattern` conversion to create path expressions? - // That means making this work: - // - // ```rust,ignore (FIXME) - // struct S; - // macro_rules! m { - // ($a:expr) => { - // let $a = S; - // } - // } - // m!(S); - // ``` - fn check_expr_within_pat(&self, expr: &Expr, allow_paths: bool) { - match expr.kind { - ExprKind::Lit(..) | ExprKind::ConstBlock(..) | ExprKind::Err => {} - ExprKind::Path(..) if allow_paths => {} - ExprKind::Unary(UnOp::Neg, ref inner) if matches!(inner.kind, ExprKind::Lit(_)) => {} - _ => self.err_handler().span_err( - expr.span, - "arbitrary expressions aren't allowed \ - in patterns", - ), - } - } - fn check_late_bound_lifetime_defs(&self, params: &[GenericParam]) { // Check only lifetime parameters are present and that the lifetime // parameters that are present have no bounds. @@ -580,8 +552,7 @@ impl<'a> AstValidator<'a> { /// An item in `extern { ... }` cannot use non-ascii identifier. fn check_foreign_item_ascii_only(&self, ident: Ident) { - let symbol_str = ident.as_str(); - if !symbol_str.is_ascii() { + if !ident.as_str().is_ascii() { let n = 83942; self.err_handler() .struct_span_err( @@ -894,7 +865,6 @@ impl<'a> AstValidator<'a> { /// Checks that generic parameters are in the correct order, /// which is lifetimes, then types and then consts. (`<'a, T, const N: usize>`) fn validate_generic_param_order( - sess: &Session, handler: &rustc_errors::Handler, generics: &[GenericParam], span: Span, @@ -911,8 +881,7 @@ fn validate_generic_param_order( GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident.to_string()), GenericParamKind::Const { ref ty, kw_span: _, default: _ } => { let ty = pprust::ty_to_string(ty); - let unordered = sess.features_untracked().unordered_const_ty_params(); - (ParamKindOrd::Const { unordered }, format!("const {}: {}", ident, ty)) + (ParamKindOrd::Const, format!("const {}: {}", ident, ty)) } }; param_idents.push((kind, ord_kind, bounds, idx, ident)); @@ -968,14 +937,7 @@ fn validate_generic_param_order( ); err.span_suggestion( span, - &format!( - "reorder the parameters: lifetimes, {}", - if sess.features_untracked().unordered_const_ty_params() { - "then consts and types" - } else { - "then types, then consts" - } - ), + "reorder the parameters: lifetimes, then consts and types", ordered_params.clone(), Applicability::MachineApplicable, ); @@ -1342,8 +1304,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } fn visit_generics(&mut self, generics: &'a Generics) { - let cg_defaults = self.session.features_untracked().unordered_const_ty_params(); - let mut prev_param_default = None; for param in &generics.params { match param.kind { @@ -1358,12 +1318,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { span, "generic parameters with a default must be trailing", ); - if matches!(param.kind, GenericParamKind::Const { .. }) && !cg_defaults { - err.note( - "using type defaults and const parameters \ - in the same parameter list is currently not permitted", - ); - } err.emit(); break; } @@ -1371,12 +1325,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } - validate_generic_param_order( - self.session, - self.err_handler(), - &generics.params, - generics.span, - ); + validate_generic_param_order(self.err_handler(), &generics.params, generics.span); for predicate in &generics.where_clause.predicates { if let WherePredicate::EqPredicate(ref predicate) = *predicate { @@ -1449,25 +1398,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { visit::walk_param_bound(self, bound) } - fn visit_pat(&mut self, pat: &'a Pat) { - match &pat.kind { - PatKind::Lit(expr) => { - self.check_expr_within_pat(expr, false); - } - PatKind::Range(start, end, _) => { - if let Some(expr) = start { - self.check_expr_within_pat(expr, true); - } - if let Some(expr) = end { - self.check_expr_within_pat(expr, true); - } - } - _ => {} - } - - visit::walk_pat(self, pat) - } - fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef, m: &'a TraitBoundModifier) { self.check_late_bound_lifetime_defs(&t.bound_generic_params); visit::walk_poly_trait_ref(self, t, m); @@ -1714,6 +1644,53 @@ fn deny_equality_constraints( } } } + // Given `A: Foo, A::Bar = RhsTy`, suggest `A: Foo`. + if let TyKind::Path(None, full_path) = &predicate.lhs_ty.kind { + if let [potential_param, potential_assoc] = &full_path.segments[..] { + for param in &generics.params { + if param.ident == potential_param.ident { + for bound in ¶m.bounds { + if let ast::GenericBound::Trait(trait_ref, TraitBoundModifier::None) = bound + { + if let [trait_segment] = &trait_ref.trait_ref.path.segments[..] { + let assoc = pprust::path_to_string(&ast::Path::from_ident( + potential_assoc.ident, + )); + let ty = pprust::ty_to_string(&predicate.rhs_ty); + let (args, span) = match &trait_segment.args { + Some(args) => match args.deref() { + ast::GenericArgs::AngleBracketed(args) => { + let Some(arg) = args.args.last() else { + continue; + }; + ( + format!(", {} = {}", assoc, ty), + arg.span().shrink_to_hi(), + ) + } + _ => continue, + }, + None => ( + format!("<{} = {}>", assoc, ty), + trait_segment.span().shrink_to_hi(), + ), + }; + err.multipart_suggestion( + &format!( + "if `{}::{}` is an associated type you're trying to set, \ + use the associated type binding syntax", + trait_segment.ident, potential_assoc.ident, + ), + vec![(span, args), (predicate.span, String::new())], + Applicability::MaybeIncorrect, + ); + } + } + } + } + } + } + } err.note( "see issue #20041 for more information", ); diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index ad539f2564..85e35c942b 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -61,7 +61,7 @@ impl<'a> PostExpansionVisitor<'a> { fn check_abi(&self, abi: ast::StrLit) { let ast::StrLit { symbol_unescaped, span, .. } = abi; - match &*symbol_unescaped.as_str() { + match symbol_unescaped.as_str() { // Stable "Rust" | "C" | "cdecl" | "stdcall" | "fastcall" | "aapcs" | "win64" | "sysv64" | "system" => {} @@ -347,7 +347,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { if let Some(modifiers) = nested_meta.value_str() { for modifier in modifiers.as_str().split(',') { - if let Some(modifier) = modifier.strip_prefix(&['+', '-'][..]) { + if let Some(modifier) = modifier.strip_prefix(&['+', '-']) { macro_rules! gate_modifier { ($($name:literal => $feature:ident)*) => { $(if modifier == $name { let msg = concat!("`#[link(modifiers=\"", $name, "\")]` is unstable"); @@ -383,7 +383,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } ast::ItemKind::Fn(..) => { - if self.sess.contains_name(&i.attrs[..], sym::start) { + if self.sess.contains_name(&i.attrs, sym::start) { gate_feature_post!( &self, start, @@ -396,7 +396,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } ast::ItemKind::Struct(..) => { - for attr in self.sess.filter_by_name(&i.attrs[..], sym::repr) { + for attr in self.sess.filter_by_name(&i.attrs, sym::repr) { for item in attr.meta_item_list().unwrap_or_else(Vec::new) { if item.has_name(sym::simd) { gate_feature_post!( @@ -724,15 +724,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { gate_all!(half_open_range_patterns, "half-open range patterns are unstable"); gate_all!(inline_const, "inline-const is experimental"); gate_all!(inline_const_pat, "inline-const in pattern position is experimental"); - gate_all!( - const_generics_defaults, - "default values for const generic parameters are experimental" - ); - if sess.parse_sess.span_diagnostic.err_count() == 0 { - // Errors for `destructuring_assignment` can get quite noisy, especially where `_` is - // involved, so we only emit errors where there are no other parsing errors. - gate_all!(destructuring_assignment, "destructuring assignments are unstable"); - } // All uses of `gate_all!` below this point were added in #65742, // and subsequently disabled (with the non-early gating readded). diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index 47666670b2..adc4d117b8 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -6,6 +6,7 @@ #![feature(iter_is_partitioned)] #![feature(box_patterns)] +#![feature(let_else)] #![recursion_limit = "256"] pub mod ast_validation; diff --git a/compiler/rustc_ast_pretty/src/helpers.rs b/compiler/rustc_ast_pretty/src/helpers.rs index dce856df9c..5ec71cddf7 100644 --- a/compiler/rustc_ast_pretty/src/helpers.rs +++ b/compiler/rustc_ast_pretty/src/helpers.rs @@ -35,4 +35,14 @@ impl Printer { self.word(w); self.nbsp() } + + // Synthesizes a comment that was not textually present in the original + // source file. + pub fn synth_comment(&mut self, text: impl Into>) { + self.word("/*"); + self.space(); + self.word(text); + self.space(); + self.word("*/") + } } diff --git a/compiler/rustc_ast_pretty/src/pprust/mod.rs b/compiler/rustc_ast_pretty/src/pprust/mod.rs index e74f38dd89..ac9e7d06c4 100644 --- a/compiler/rustc_ast_pretty/src/pprust/mod.rs +++ b/compiler/rustc_ast_pretty/src/pprust/mod.rs @@ -73,5 +73,14 @@ pub fn attribute_to_string(attr: &ast::Attribute) -> String { } pub fn to_string(f: impl FnOnce(&mut State<'_>)) -> String { - State::new().to_string(f) + State::to_string(f) +} + +pub fn crate_to_string_for_macros(krate: &ast::Crate) -> String { + State::to_string(|s| { + s.print_inner_attributes(&krate.attrs); + for item in &krate.items { + s.print_item(item); + } + }) } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index f1f2387866..fa9a20f2e0 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -204,14 +204,14 @@ pub fn literal_to_string(lit: token::Lit) -> String { }; if let Some(suffix) = suffix { - out.push_str(&suffix.as_str()) + out.push_str(suffix.as_str()) } out } fn visibility_qualified(vis: &ast::Visibility, s: &str) -> String { - format!("{}{}", State::new().to_string(|s| s.print_visibility(vis)), s) + format!("{}{}", State::to_string(|s| s.print_visibility(vis)), s) } impl std::ops::Deref for State<'_> { @@ -263,14 +263,17 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere self.strsep(",", false, b, elts, op) } - fn maybe_print_comment(&mut self, pos: BytePos) { + fn maybe_print_comment(&mut self, pos: BytePos) -> bool { + let mut has_comment = false; while let Some(ref cmnt) = self.next_comment() { if cmnt.pos < pos { + has_comment = true; self.print_comment(cmnt); } else { break; } } + has_comment } fn print_comment(&mut self, cmnt: &Comment) { @@ -346,6 +349,25 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere self.comments().as_mut().and_then(|c| c.next()) } + fn maybe_print_trailing_comment(&mut self, span: rustc_span::Span, next_pos: Option) { + if let Some(cmnts) = self.comments() { + if let Some(cmnt) = cmnts.trailing_comment(span, next_pos) { + self.print_comment(&cmnt); + } + } + } + + fn print_remaining_comments(&mut self) { + // If there aren't any remaining comments, then we need to manually + // make sure there is a line break at the end. + if self.next_comment().is_none() { + self.hardbreak(); + } + while let Some(ref cmnt) = self.next_comment() { + self.print_comment(cmnt) + } + } + fn print_literal(&mut self, lit: &ast::Lit) { self.maybe_print_comment(lit.span.lo()); self.word(lit.token.to_string()) @@ -362,26 +384,26 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere } fn print_symbol(&mut self, sym: Symbol, style: ast::StrStyle) { - self.print_string(&sym.as_str(), style); + self.print_string(sym.as_str(), style); } - fn print_inner_attributes(&mut self, attrs: &[ast::Attribute]) { + fn print_inner_attributes(&mut self, attrs: &[ast::Attribute]) -> bool { self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, true) } - fn print_inner_attributes_no_trailing_hardbreak(&mut self, attrs: &[ast::Attribute]) { + fn print_inner_attributes_no_trailing_hardbreak(&mut self, attrs: &[ast::Attribute]) -> bool { self.print_either_attributes(attrs, ast::AttrStyle::Inner, false, false) } - fn print_outer_attributes(&mut self, attrs: &[ast::Attribute]) { + fn print_outer_attributes(&mut self, attrs: &[ast::Attribute]) -> bool { self.print_either_attributes(attrs, ast::AttrStyle::Outer, false, true) } - fn print_inner_attributes_inline(&mut self, attrs: &[ast::Attribute]) { + fn print_inner_attributes_inline(&mut self, attrs: &[ast::Attribute]) -> bool { self.print_either_attributes(attrs, ast::AttrStyle::Inner, true, true) } - fn print_outer_attributes_inline(&mut self, attrs: &[ast::Attribute]) { + fn print_outer_attributes_inline(&mut self, attrs: &[ast::Attribute]) -> bool { self.print_either_attributes(attrs, ast::AttrStyle::Outer, true, true) } @@ -391,20 +413,21 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere kind: ast::AttrStyle, is_inline: bool, trailing_hardbreak: bool, - ) { - let mut count = 0; + ) -> bool { + let mut printed = false; for attr in attrs { if attr.style == kind { self.print_attribute_inline(attr, is_inline); if is_inline { self.nbsp(); } - count += 1; + printed = true; } } - if count > 0 && trailing_hardbreak && !is_inline { + if printed && trailing_hardbreak && !is_inline { self.hardbreak_if_not_bol(); } + printed } fn print_attribute(&mut self, attr: &ast::Attribute) { @@ -477,7 +500,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere ast::MetaItemKind::List(ref items) => { self.print_path(&item.path, false, 0); self.popen(); - self.commasep(Consistent, &items[..], |s, i| s.print_meta_list_item(i)); + self.commasep(Consistent, &items, |s, i| s.print_meta_list_item(i)); self.pclose(); } } @@ -570,7 +593,10 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere self.print_tts(tts, convert_dollar_crate); self.end(); match delim { - DelimToken::Brace => self.bclose(span), + DelimToken::Brace => { + let empty = tts.is_empty(); + self.bclose(span, empty); + } _ => { let token_str = self.token_kind_to_string(&token::CloseDelim(delim)); self.word(token_str) @@ -642,17 +668,20 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere self.end(); // Close the head-box. } - fn bclose_maybe_open(&mut self, span: rustc_span::Span, close_box: bool) { - self.maybe_print_comment(span.hi()); - self.break_offset_if_not_bol(1, -(INDENT_UNIT as isize)); + fn bclose_maybe_open(&mut self, span: rustc_span::Span, empty: bool, close_box: bool) { + let has_comment = self.maybe_print_comment(span.hi()); + if !empty || has_comment { + self.break_offset_if_not_bol(1, -(INDENT_UNIT as isize)); + } self.word("}"); if close_box { self.end(); // Close the outer-box. } } - fn bclose(&mut self, span: rustc_span::Span) { - self.bclose_maybe_open(span, true) + fn bclose(&mut self, span: rustc_span::Span, empty: bool) { + let close_box = true; + self.bclose_maybe_open(span, empty, close_box) } fn break_offset_if_not_bol(&mut self, n: usize, off: isize) { @@ -764,55 +793,55 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere } fn ty_to_string(&self, ty: &ast::Ty) -> String { - self.to_string(|s| s.print_type(ty)) + Self::to_string(|s| s.print_type(ty)) } fn bounds_to_string(&self, bounds: &[ast::GenericBound]) -> String { - self.to_string(|s| s.print_type_bounds("", bounds)) + Self::to_string(|s| s.print_type_bounds("", bounds)) } fn pat_to_string(&self, pat: &ast::Pat) -> String { - self.to_string(|s| s.print_pat(pat)) + Self::to_string(|s| s.print_pat(pat)) } fn expr_to_string(&self, e: &ast::Expr) -> String { - self.to_string(|s| s.print_expr(e)) + Self::to_string(|s| s.print_expr(e)) } fn tt_to_string(&self, tt: &TokenTree) -> String { - self.to_string(|s| s.print_tt(tt, false)) + Self::to_string(|s| s.print_tt(tt, false)) } fn tts_to_string(&self, tokens: &TokenStream) -> String { - self.to_string(|s| s.print_tts(tokens, false)) + Self::to_string(|s| s.print_tts(tokens, false)) } fn stmt_to_string(&self, stmt: &ast::Stmt) -> String { - self.to_string(|s| s.print_stmt(stmt)) + Self::to_string(|s| s.print_stmt(stmt)) } fn item_to_string(&self, i: &ast::Item) -> String { - self.to_string(|s| s.print_item(i)) + Self::to_string(|s| s.print_item(i)) } fn generic_params_to_string(&self, generic_params: &[ast::GenericParam]) -> String { - self.to_string(|s| s.print_generic_params(generic_params)) + Self::to_string(|s| s.print_generic_params(generic_params)) } fn path_to_string(&self, p: &ast::Path) -> String { - self.to_string(|s| s.print_path(p, false, 0)) + Self::to_string(|s| s.print_path(p, false, 0)) } fn path_segment_to_string(&self, p: &ast::PathSegment) -> String { - self.to_string(|s| s.print_path_segment(p, false)) + Self::to_string(|s| s.print_path_segment(p, false)) } fn vis_to_string(&self, v: &ast::Visibility) -> String { - self.to_string(|s| s.print_visibility(v)) + Self::to_string(|s| s.print_visibility(v)) } fn block_to_string(&self, blk: &ast::Block) -> String { - self.to_string(|s| { + Self::to_string(|s| { // Containing cbox, will be closed by `print_block` at `}`. s.cbox(INDENT_UNIT); // Head-ibox, will be closed by `print_block` after `{`. @@ -822,22 +851,22 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere } fn meta_list_item_to_string(&self, li: &ast::NestedMetaItem) -> String { - self.to_string(|s| s.print_meta_list_item(li)) + Self::to_string(|s| s.print_meta_list_item(li)) } fn attr_item_to_string(&self, ai: &ast::AttrItem) -> String { - self.to_string(|s| s.print_attr_item(ai, ai.path.span)) + Self::to_string(|s| s.print_attr_item(ai, ai.path.span)) } fn attribute_to_string(&self, attr: &ast::Attribute) -> String { - self.to_string(|s| s.print_attribute(attr)) + Self::to_string(|s| s.print_attribute(attr)) } fn param_to_string(&self, arg: &ast::Param) -> String { - self.to_string(|s| s.print_param(arg, false)) + Self::to_string(|s| s.print_param(arg, false)) } - fn to_string(&self, f: impl FnOnce(&mut State<'_>)) -> String { + fn to_string(f: impl FnOnce(&mut State<'_>)) -> String { let mut printer = State::new(); f(&mut printer); printer.s.eof() @@ -850,29 +879,29 @@ impl<'a> PrintState<'a> for State<'a> { } fn print_ident(&mut self, ident: Ident) { - self.s.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string()); + self.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string()); self.ann.post(self, AnnNode::Ident(&ident)) } fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool) { if colons_before_params { - self.s.word("::") + self.word("::") } match *args { ast::GenericArgs::AngleBracketed(ref data) => { - self.s.word("<"); + self.word("<"); self.commasep(Inconsistent, &data.args, |s, arg| match arg { ast::AngleBracketedArg::Arg(a) => s.print_generic_arg(a), ast::AngleBracketedArg::Constraint(c) => s.print_assoc_constraint(c), }); - self.s.word(">") + self.word(">") } ast::GenericArgs::Parenthesized(ref data) => { - self.s.word("("); + self.word("("); self.commasep(Inconsistent, &data.inputs, |s, ty| s.print_type(ty)); - self.s.word(")"); + self.word(")"); self.print_fn_ret_ty(&data.output); } } @@ -884,16 +913,6 @@ impl<'a> State<'a> { State { s: pp::mk_printer(), comments: None, ann: &NoAnn } } - // Synthesizes a comment that was not textually present in the original source - // file. - pub fn synth_comment(&mut self, text: String) { - self.s.word("/*"); - self.s.space(); - self.s.word(text); - self.s.space(); - self.s.word("*/") - } - crate fn commasep_cmnt(&mut self, b: Breaks, elts: &[T], mut op: F, mut get_span: G) where F: FnMut(&mut State<'_>, &T), @@ -907,7 +926,7 @@ impl<'a> State<'a> { op(self, elt); i += 1; if i < len { - self.s.word(","); + self.word(","); self.maybe_print_trailing_comment(get_span(elt), Some(get_span(&elts[i]).hi())); self.space_if_not_bol(); } @@ -936,7 +955,7 @@ impl<'a> State<'a> { pub fn print_assoc_constraint(&mut self, constraint: &ast::AssocTyConstraint) { self.print_ident(constraint.ident); constraint.gen_args.as_ref().map(|args| self.print_generic_args(args, false)); - self.s.space(); + self.space(); match &constraint.kind { ast::AssocTyConstraintKind::Equality { ty } => { self.word_space("="); @@ -961,27 +980,27 @@ impl<'a> State<'a> { self.ibox(0); match ty.kind { ast::TyKind::Slice(ref ty) => { - self.s.word("["); + self.word("["); self.print_type(ty); - self.s.word("]"); + self.word("]"); } ast::TyKind::Ptr(ref mt) => { - self.s.word("*"); + self.word("*"); self.print_mt(mt, true); } ast::TyKind::Rptr(ref lifetime, ref mt) => { - self.s.word("&"); + self.word("&"); self.print_opt_lifetime(lifetime); self.print_mt(mt, false); } ast::TyKind::Never => { - self.s.word("!"); + self.word("!"); } ast::TyKind::Tup(ref elts) => { self.popen(); - self.commasep(Inconsistent, &elts[..], |s, ty| s.print_type(ty)); + self.commasep(Inconsistent, &elts, |s, ty| s.print_type(ty)); if elts.len() == 1 { - self.s.word(","); + self.word(","); } self.pclose(); } @@ -999,39 +1018,39 @@ impl<'a> State<'a> { ast::TyKind::Path(Some(ref qself), ref path) => self.print_qpath(path, qself, false), ast::TyKind::TraitObject(ref bounds, syntax) => { let prefix = if syntax == ast::TraitObjectSyntax::Dyn { "dyn" } else { "" }; - self.print_type_bounds(prefix, &bounds[..]); + self.print_type_bounds(prefix, &bounds); } ast::TyKind::ImplTrait(_, ref bounds) => { - self.print_type_bounds("impl", &bounds[..]); + self.print_type_bounds("impl", &bounds); } ast::TyKind::Array(ref ty, ref length) => { - self.s.word("["); + self.word("["); self.print_type(ty); - self.s.word("; "); + self.word("; "); self.print_expr(&length.value); - self.s.word("]"); + self.word("]"); } ast::TyKind::Typeof(ref e) => { - self.s.word("typeof("); + self.word("typeof("); self.print_expr(&e.value); - self.s.word(")"); + self.word(")"); } ast::TyKind::Infer => { - self.s.word("_"); + self.word("_"); } ast::TyKind::Err => { self.popen(); - self.s.word("/*ERROR*/"); + self.word("/*ERROR*/"); self.pclose(); } ast::TyKind::ImplicitSelf => { - self.s.word("Self"); + self.word("Self"); } ast::TyKind::MacCall(ref m) => { self.print_mac(m); } ast::TyKind::CVarArgs => { - self.s.word("..."); + self.word("..."); } } self.end(); @@ -1069,7 +1088,7 @@ impl<'a> State<'a> { ast::ForeignItemKind::MacCall(m) => { self.print_mac(m); if m.args.need_semicolon() { - self.s.word(";"); + self.word(";"); } } } @@ -1097,13 +1116,15 @@ impl<'a> State<'a> { self.print_ident(ident); self.word_space(":"); self.print_type(ty); - self.s.space(); + if body.is_some() { + self.space(); + } self.end(); // end the head-ibox if let Some(body) = body { self.word_space("="); self.print_expr(body); } - self.s.word(";"); + self.word(";"); self.end(); // end the outer cbox } @@ -1125,11 +1146,11 @@ impl<'a> State<'a> { self.print_type_bounds(":", bounds); self.print_where_clause(&generics.where_clause); if let Some(ty) = ty { - self.s.space(); + self.space(); self.word_space("="); self.print_type(ty); } - self.s.word(";"); + self.word(";"); self.end(); // end inner head-block self.end(); // end outer head-block } @@ -1145,19 +1166,19 @@ impl<'a> State<'a> { self.head(visibility_qualified(&item.vis, "extern crate")); if let Some(orig_name) = orig_name { self.print_name(orig_name); - self.s.space(); - self.s.word("as"); - self.s.space(); + self.space(); + self.word("as"); + self.space(); } self.print_ident(item.ident); - self.s.word(";"); + self.word(";"); self.end(); // end inner head-block self.end(); // end outer head-block } ast::ItemKind::Use(ref tree) => { self.head(visibility_qualified(&item.vis, "use")); self.print_use_tree(tree); - self.s.word(";"); + self.word(";"); self.end(); // end inner head-block self.end(); // end outer head-block } @@ -1181,7 +1202,7 @@ impl<'a> State<'a> { ); } ast::ItemKind::Mod(unsafety, ref mod_kind) => { - self.head(self.to_string(|s| { + self.head(Self::to_string(|s| { s.print_visibility(&item.vis); s.print_unsafety(unsafety); s.word("mod"); @@ -1196,17 +1217,18 @@ impl<'a> State<'a> { for item in items { self.print_item(item); } - self.bclose(item.span); + let empty = item.attrs.is_empty() && items.is_empty(); + self.bclose(item.span, empty); } ModKind::Unloaded => { - self.s.word(";"); + self.word(";"); self.end(); // end inner head-block self.end(); // end outer head-block } } } ast::ItemKind::ForeignMod(ref nmod) => { - self.head(self.to_string(|s| { + self.head(Self::to_string(|s| { s.print_unsafety(nmod.unsafety); s.word("extern"); })); @@ -1216,7 +1238,8 @@ impl<'a> State<'a> { } self.bopen(); self.print_foreign_mod(nmod, &item.attrs); - self.bclose(item.span); + let empty = item.attrs.is_empty() && nmod.items.is_empty(); + self.bclose(item.span, empty); } ast::ItemKind::GlobalAsm(ref asm) => { self.head(visibility_qualified(&item.vis, "global_asm!")); @@ -1264,34 +1287,38 @@ impl<'a> State<'a> { self.print_visibility(&item.vis); self.print_defaultness(defaultness); self.print_unsafety(unsafety); - self.word_nbsp("impl"); - self.print_constness(constness); + self.word("impl"); - if !generics.params.is_empty() { + if generics.params.is_empty() { + self.nbsp(); + } else { self.print_generic_params(&generics.params); - self.s.space(); + self.space(); } + self.print_constness(constness); + if let ast::ImplPolarity::Negative(_) = polarity { - self.s.word("!"); + self.word("!"); } if let Some(ref t) = *of_trait { self.print_trait_ref(t); - self.s.space(); + self.space(); self.word_space("for"); } self.print_type(self_ty); self.print_where_clause(&generics.where_clause); - self.s.space(); + self.space(); self.bopen(); self.print_inner_attributes(&item.attrs); for impl_item in items { self.print_assoc_item(impl_item); } - self.bclose(item.span); + let empty = item.attrs.is_empty() && items.is_empty(); + self.bclose(item.span, empty); } ast::ItemKind::Trait(box ast::Trait { is_auto, @@ -1311,22 +1338,23 @@ impl<'a> State<'a> { let mut real_bounds = Vec::with_capacity(bounds.len()); for b in bounds.iter() { if let GenericBound::Trait(ref ptr, ast::TraitBoundModifier::Maybe) = *b { - self.s.space(); + self.space(); self.word_space("for ?"); self.print_trait_ref(&ptr.trait_ref); } else { real_bounds.push(b.clone()); } } - self.print_type_bounds(":", &real_bounds[..]); + self.print_type_bounds(":", &real_bounds); self.print_where_clause(&generics.where_clause); - self.s.word(" "); + self.word(" "); self.bopen(); self.print_inner_attributes(&item.attrs); for trait_item in items { self.print_assoc_item(trait_item); } - self.bclose(item.span); + let empty = item.attrs.is_empty() && items.is_empty(); + self.bclose(item.span, empty); } ast::ItemKind::TraitAlias(ref generics, ref bounds) => { self.head(""); @@ -1338,7 +1366,7 @@ impl<'a> State<'a> { // FIXME(durka) this seems to be some quite outdated syntax for b in bounds.iter() { if let GenericBound::Trait(ref ptr, ast::TraitBoundModifier::Maybe) = *b { - self.s.space(); + self.space(); self.word_space("for ?"); self.print_trait_ref(&ptr.trait_ref); } else { @@ -1346,14 +1374,14 @@ impl<'a> State<'a> { } } self.nbsp(); - self.print_type_bounds("=", &real_bounds[..]); + self.print_type_bounds("=", &real_bounds); self.print_where_clause(&generics.where_clause); - self.s.word(";"); + self.word(";"); } ast::ItemKind::MacCall(ref mac) => { self.print_mac(mac); if mac.args.need_semicolon() { - self.s.word(";"); + self.word(";"); } } ast::ItemKind::MacroDef(ref macro_def) => { @@ -1371,7 +1399,7 @@ impl<'a> State<'a> { fn print_formal_generic_params(&mut self, generic_params: &[ast::GenericParam]) { if !generic_params.is_empty() { - self.s.word("for"); + self.word("for"); self.print_generic_params(generic_params); self.nbsp(); } @@ -1394,7 +1422,7 @@ impl<'a> State<'a> { self.print_ident(ident); self.print_generic_params(&generics.params); self.print_where_clause(&generics.where_clause); - self.s.space(); + self.space(); self.print_variants(&enum_definition.variants, span) } @@ -1406,11 +1434,12 @@ impl<'a> State<'a> { self.print_outer_attributes(&v.attrs); self.ibox(INDENT_UNIT); self.print_variant(v); - self.s.word(","); + self.word(","); self.end(); self.maybe_print_trailing_comment(v.span, None); } - self.bclose(span) + let empty = variants.is_empty(); + self.bclose(span, empty) } crate fn print_visibility(&mut self, vis: &ast::Visibility) { @@ -1421,7 +1450,7 @@ impl<'a> State<'a> { ast::CrateSugar::JustCrate => self.word_nbsp("crate"), }, ast::VisibilityKind::Restricted { ref path, .. } => { - let path = self.to_string(|s| s.print_path(path, false, 0)); + let path = Self::to_string(|s| s.print_path(path, false, 0)); if path == "self" || path == "super" { self.word_nbsp(format!("pub({})", path)) } else { @@ -1441,20 +1470,24 @@ impl<'a> State<'a> { crate fn print_record_struct_body(&mut self, fields: &[ast::FieldDef], span: rustc_span::Span) { self.nbsp(); self.bopen(); - self.hardbreak_if_not_bol(); - for field in fields { + let empty = fields.is_empty(); + if !empty { self.hardbreak_if_not_bol(); - self.maybe_print_comment(field.span.lo()); - self.print_outer_attributes(&field.attrs); - self.print_visibility(&field.vis); - self.print_ident(field.ident.unwrap()); - self.word_nbsp(":"); - self.print_type(&field.ty); - self.s.word(","); + + for field in fields { + self.hardbreak_if_not_bol(); + self.maybe_print_comment(field.span.lo()); + self.print_outer_attributes(&field.attrs); + self.print_visibility(&field.vis); + self.print_ident(field.ident.unwrap()); + self.word_nbsp(":"); + self.print_type(&field.ty); + self.word(","); + } } - self.bclose(span) + self.bclose(span, empty); } crate fn print_struct( @@ -1481,7 +1514,7 @@ impl<'a> State<'a> { } self.print_where_clause(&generics.where_clause); if print_finalizer { - self.s.word(";"); + self.word(";"); } self.end(); self.end(); // Close the outer-box. @@ -1499,7 +1532,7 @@ impl<'a> State<'a> { let generics = ast::Generics::default(); self.print_struct(&v.data, &generics, v.ident, v.span, false); if let Some(ref d) = v.disr_expr { - self.s.space(); + self.space(); self.word_space("="); self.print_expr(&d.value) } @@ -1531,7 +1564,7 @@ impl<'a> State<'a> { ast::AssocItemKind::MacCall(m) => { self.print_mac(m); if m.args.need_semicolon() { - self.s.word(";"); + self.word(";"); } } } @@ -1557,11 +1590,11 @@ impl<'a> State<'a> { if let Some(els) = els { self.cbox(INDENT_UNIT); self.ibox(INDENT_UNIT); - self.s.word(" else "); + self.word(" else "); self.print_block(els); } } - self.s.word(";"); + self.word(";"); self.end(); // `let` ibox } ast::StmtKind::Item(ref item) => self.print_item(item), @@ -1569,24 +1602,24 @@ impl<'a> State<'a> { self.space_if_not_bol(); self.print_expr_outer_attr_style(expr, false); if classify::expr_requires_semi_to_be_stmt(expr) { - self.s.word(";"); + self.word(";"); } } ast::StmtKind::Semi(ref expr) => { self.space_if_not_bol(); self.print_expr_outer_attr_style(expr, false); - self.s.word(";"); + self.word(";"); } ast::StmtKind::Empty => { self.space_if_not_bol(); - self.s.word(";"); + self.word(";"); } ast::StmtKind::MacCall(ref mac) => { self.space_if_not_bol(); self.print_outer_attributes(&mac.attrs); self.print_mac(&mac.mac); if mac.style == ast::MacStmtStyle::Semicolon { - self.s.word(";"); + self.word(";"); } } } @@ -1619,7 +1652,7 @@ impl<'a> State<'a> { self.ann.pre(self, AnnNode::Block(blk)); self.bopen(); - self.print_inner_attributes(attrs); + let has_attrs = self.print_inner_attributes(attrs); for (i, st) in blk.stmts.iter().enumerate() { match st.kind { @@ -1633,15 +1666,16 @@ impl<'a> State<'a> { } } - self.bclose_maybe_open(blk.span, close_box); + let empty = !has_attrs && blk.stmts.is_empty(); + self.bclose_maybe_open(blk.span, empty, close_box); self.ann.post(self, AnnNode::Block(blk)) } /// Print a `let pat = expr` expression. crate fn print_let(&mut self, pat: &ast::Pat, expr: &ast::Expr) { - self.s.word("let "); + self.word("let "); self.print_pat(pat); - self.s.space(); + self.space(); self.word_space("="); let npals = || parser::needs_par_as_let_scrutinee(expr.precedence().order()); self.print_expr_cond_paren(expr, Self::cond_needs_par(expr) || npals()) @@ -1654,9 +1688,9 @@ impl<'a> State<'a> { ast::ExprKind::If(ref i, ref then, ref e) => { self.cbox(INDENT_UNIT - 1); self.ibox(0); - self.s.word(" else if "); + self.word(" else if "); self.print_expr_as_cond(i); - self.s.space(); + self.space(); self.print_block(then); self.print_else(e.as_deref()) } @@ -1664,7 +1698,7 @@ impl<'a> State<'a> { ast::ExprKind::Block(ref b, _) => { self.cbox(INDENT_UNIT - 1); self.ibox(0); - self.s.word(" else "); + self.word(" else "); self.print_block(b) } // Constraints would be great here! @@ -1678,7 +1712,7 @@ impl<'a> State<'a> { crate fn print_if(&mut self, test: &ast::Expr, blk: &ast::Block, elseopt: Option<&ast::Expr>) { self.head("if"); self.print_expr_as_cond(test); - self.s.space(); + self.space(); self.print_block(blk); self.print_else(elseopt) } @@ -1735,26 +1769,26 @@ impl<'a> State<'a> { fn print_expr_vec(&mut self, exprs: &[P]) { self.ibox(INDENT_UNIT); - self.s.word("["); + self.word("["); self.commasep_exprs(Inconsistent, exprs); - self.s.word("]"); + self.word("]"); self.end(); } fn print_expr_anon_const(&mut self, expr: &ast::AnonConst) { self.ibox(INDENT_UNIT); - self.s.word("const"); + self.word("const"); self.print_expr(&expr.value); self.end(); } fn print_expr_repeat(&mut self, element: &ast::Expr, count: &ast::AnonConst) { self.ibox(INDENT_UNIT); - self.s.word("["); + self.word("["); self.print_expr(element); self.word_space(";"); self.print_expr(&count.value); - self.s.word("]"); + self.word("]"); self.end(); } @@ -1770,7 +1804,7 @@ impl<'a> State<'a> { } else { self.print_path(path, true, 0); } - self.s.word("{"); + self.word("{"); self.commasep_cmnt( Consistent, fields, @@ -1790,26 +1824,26 @@ impl<'a> State<'a> { ast::StructRest::Base(_) | ast::StructRest::Rest(_) => { self.ibox(INDENT_UNIT); if !fields.is_empty() { - self.s.word(","); - self.s.space(); + self.word(","); + self.space(); } - self.s.word(".."); + self.word(".."); if let ast::StructRest::Base(ref expr) = *rest { self.print_expr(expr); } self.end(); } - ast::StructRest::None if !fields.is_empty() => self.s.word(","), + ast::StructRest::None if !fields.is_empty() => self.word(","), _ => {} } - self.s.word("}"); + self.word("}"); } fn print_expr_tup(&mut self, exprs: &[P]) { self.popen(); self.commasep_exprs(Inconsistent, exprs); if exprs.len() == 1 { - self.s.word(","); + self.word(","); } self.pclose() } @@ -1827,7 +1861,7 @@ impl<'a> State<'a> { fn print_expr_method_call(&mut self, segment: &ast::PathSegment, args: &[P]) { let base_args = &args[1..]; self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX); - self.s.word("."); + self.word("."); self.print_ident(segment.ident); if let Some(ref args) = segment.args { self.print_generic_args(args, true); @@ -1868,13 +1902,13 @@ impl<'a> State<'a> { }; self.print_expr_maybe_paren(lhs, left_prec); - self.s.space(); + self.space(); self.word_space(op.node.to_string()); self.print_expr_maybe_paren(rhs, right_prec) } fn print_expr_unary(&mut self, op: ast::UnOp, expr: &ast::Expr) { - self.s.word(ast::UnOp::to_string(op)); + self.word(ast::UnOp::to_string(op)); self.print_expr_maybe_paren(expr, parser::PREC_PREFIX) } @@ -1884,7 +1918,7 @@ impl<'a> State<'a> { mutability: ast::Mutability, expr: &ast::Expr, ) { - self.s.word("&"); + self.word("&"); match kind { ast::BorrowKind::Ref => self.print_mutability(mutability, false), ast::BorrowKind::Raw => { @@ -1932,10 +1966,10 @@ impl<'a> State<'a> { self.print_expr_tup(exprs); } ast::ExprKind::Call(ref func, ref args) => { - self.print_expr_call(func, &args[..]); + self.print_expr_call(func, &args); } ast::ExprKind::MethodCall(ref segment, ref args, _) => { - self.print_expr_method_call(segment, &args[..]); + self.print_expr_method_call(segment, &args); } ast::ExprKind::Binary(op, ref lhs, ref rhs) => { self.print_expr_binary(op, lhs, rhs); @@ -1952,7 +1986,7 @@ impl<'a> State<'a> { ast::ExprKind::Cast(ref expr, ref ty) => { let prec = AssocOp::As.precedence() as i8; self.print_expr_maybe_paren(expr, prec); - self.s.space(); + self.space(); self.word_space("as"); self.print_type(ty); } @@ -1975,7 +2009,7 @@ impl<'a> State<'a> { } self.head("while"); self.print_expr_as_cond(test); - self.s.space(); + self.space(); self.print_block_with_attrs(blk, attrs); } ast::ExprKind::ForLoop(ref pat, ref iter, ref blk, opt_label) => { @@ -1985,10 +2019,10 @@ impl<'a> State<'a> { } self.head("for"); self.print_pat(pat); - self.s.space(); + self.space(); self.word_space("in"); self.print_expr_as_cond(iter); - self.s.space(); + self.space(); self.print_block_with_attrs(blk, attrs); } ast::ExprKind::Loop(ref blk, opt_label) => { @@ -2004,13 +2038,14 @@ impl<'a> State<'a> { self.ibox(INDENT_UNIT); self.word_nbsp("match"); self.print_expr_as_cond(expr); - self.s.space(); + self.space(); self.bopen(); self.print_inner_attributes_no_trailing_hardbreak(attrs); for arm in arms { self.print_arm(arm); } - self.bclose(expr.span); + let empty = attrs.is_empty() && arms.is_empty(); + self.bclose(expr.span, empty); } ast::ExprKind::Closure( capture_clause, @@ -2025,7 +2060,7 @@ impl<'a> State<'a> { self.print_capture_clause(capture_clause); self.print_fn_params_and_ret(decl, true); - self.s.space(); + self.space(); self.print_expr(body); self.end(); // need to close a box @@ -2048,7 +2083,6 @@ impl<'a> State<'a> { ast::ExprKind::Async(capture_clause, _, ref blk) => { self.word_nbsp("async"); self.print_capture_clause(capture_clause); - self.s.space(); // cbox/ibox in analogy to the `ExprKind::Block` arm above self.cbox(INDENT_UNIT); self.ibox(0); @@ -2056,33 +2090,33 @@ impl<'a> State<'a> { } ast::ExprKind::Await(ref expr) => { self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX); - self.s.word(".await"); + self.word(".await"); } ast::ExprKind::Assign(ref lhs, ref rhs, _) => { let prec = AssocOp::Assign.precedence() as i8; self.print_expr_maybe_paren(lhs, prec + 1); - self.s.space(); + self.space(); self.word_space("="); self.print_expr_maybe_paren(rhs, prec); } ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => { let prec = AssocOp::Assign.precedence() as i8; self.print_expr_maybe_paren(lhs, prec + 1); - self.s.space(); - self.s.word(op.node.to_string()); + self.space(); + self.word(op.node.to_string()); self.word_space("="); self.print_expr_maybe_paren(rhs, prec); } ast::ExprKind::Field(ref expr, ident) => { self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX); - self.s.word("."); + self.word("."); self.print_ident(ident); } ast::ExprKind::Index(ref expr, ref index) => { self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX); - self.s.word("["); + self.word("["); self.print_expr(index); - self.s.word("]"); + self.word("]"); } ast::ExprKind::Range(ref start, ref end, limits) => { // Special case for `Range`. `AssocOp` claims that `Range` has higher precedence @@ -2094,41 +2128,39 @@ impl<'a> State<'a> { self.print_expr_maybe_paren(e, fake_prec); } if limits == ast::RangeLimits::HalfOpen { - self.s.word(".."); + self.word(".."); } else { - self.s.word("..="); + self.word("..="); } if let Some(ref e) = *end { self.print_expr_maybe_paren(e, fake_prec); } } - ast::ExprKind::Underscore => self.s.word("_"), + ast::ExprKind::Underscore => self.word("_"), ast::ExprKind::Path(None, ref path) => self.print_path(path, true, 0), ast::ExprKind::Path(Some(ref qself), ref path) => self.print_qpath(path, qself, true), ast::ExprKind::Break(opt_label, ref opt_expr) => { - self.s.word("break"); - self.s.space(); + self.word("break"); if let Some(label) = opt_label { + self.space(); self.print_ident(label.ident); - self.s.space(); } if let Some(ref expr) = *opt_expr { + self.space(); self.print_expr_maybe_paren(expr, parser::PREC_JUMP); - self.s.space(); } } ast::ExprKind::Continue(opt_label) => { - self.s.word("continue"); - self.s.space(); + self.word("continue"); if let Some(label) = opt_label { + self.space(); self.print_ident(label.ident); - self.s.space() } } ast::ExprKind::Ret(ref result) => { - self.s.word("return"); + self.word("return"); if let Some(ref expr) = *result { - self.s.word(" "); + self.word(" "); self.print_expr_maybe_paren(expr, parser::PREC_JUMP); } } @@ -2137,7 +2169,7 @@ impl<'a> State<'a> { self.print_inline_asm(a); } ast::ExprKind::LlvmInlineAsm(ref a) => { - self.s.word("llvm_asm!"); + self.word("llvm_asm!"); self.popen(); self.print_symbol(a.asm, a.asm_str_style); self.word_space(":"); @@ -2155,7 +2187,7 @@ impl<'a> State<'a> { s.print_expr(&out.expr); s.pclose(); }); - self.s.space(); + self.space(); self.word_space(":"); self.commasep(Inconsistent, &a.inputs, |s, &(co, ref o)| { @@ -2164,7 +2196,7 @@ impl<'a> State<'a> { s.print_expr(o); s.pclose(); }); - self.s.space(); + self.space(); self.word_space(":"); self.commasep(Inconsistent, &a.clobbers, |s, &co| { @@ -2183,7 +2215,7 @@ impl<'a> State<'a> { } if !options.is_empty() { - self.s.space(); + self.space(); self.word_space(":"); self.commasep(Inconsistent, &options, |s, &co| { s.print_string(co, ast::StrStyle::Cooked); @@ -2199,25 +2231,24 @@ impl<'a> State<'a> { self.pclose(); } ast::ExprKind::Yield(ref e) => { - self.s.word("yield"); + self.word("yield"); if let Some(ref expr) = *e { - self.s.space(); + self.space(); self.print_expr_maybe_paren(expr, parser::PREC_JUMP); } } ast::ExprKind::Try(ref e) => { self.print_expr_maybe_paren(e, parser::PREC_POSTFIX); - self.s.word("?") + self.word("?") } ast::ExprKind::TryBlock(ref blk) => { self.head("try"); - self.s.space(); self.print_block_with_attrs(blk, attrs) } ast::ExprKind::Err => { self.popen(); - self.s.word("/*ERROR*/"); + self.word("/*ERROR*/"); self.pclose() } } @@ -2338,6 +2369,9 @@ impl<'a> State<'a> { if opts.contains(InlineAsmOptions::RAW) { options.push("raw"); } + if opts.contains(InlineAsmOptions::MAY_UNWIND) { + options.push("may_unwind"); + } s.commasep(Inconsistent, &options, |s, &opt| { s.word(opt); }); @@ -2356,22 +2390,22 @@ impl<'a> State<'a> { } crate fn print_name(&mut self, name: Symbol) { - self.s.word(name.to_string()); + self.word(name.to_string()); self.ann.post(self, AnnNode::Name(&name)) } fn print_qpath(&mut self, path: &ast::Path, qself: &ast::QSelf, colons_before_params: bool) { - self.s.word("<"); + self.word("<"); self.print_type(&qself.ty); if qself.position > 0 { - self.s.space(); + self.space(); self.word_space("as"); let depth = path.segments.len() - qself.position; self.print_path(path, false, depth); } - self.s.word(">"); + self.word(">"); for item_segment in &path.segments[qself.position..] { - self.s.word("::"); + self.word("::"); self.print_ident(item_segment.ident); if let Some(ref args) = item_segment.args { self.print_generic_args(args, colons_before_params) @@ -2385,7 +2419,7 @@ impl<'a> State<'a> { /* Pat isn't normalized, but the beauty of it is that it doesn't matter */ match pat.kind { - PatKind::Wild => self.s.word("_"), + PatKind::Wild => self.word("_"), PatKind::Ident(binding_mode, ident, ref sub) => { match binding_mode { ast::BindingMode::ByRef(mutbl) => { @@ -2399,8 +2433,8 @@ impl<'a> State<'a> { } self.print_ident(ident); if let Some(ref p) = *sub { - self.s.space(); - self.s.word_space("@"); + self.space(); + self.word_space("@"); self.print_pat(p); } } @@ -2411,11 +2445,11 @@ impl<'a> State<'a> { self.print_path(path, true, 0); } self.popen(); - self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p)); + self.commasep(Inconsistent, &elts, |s, p| s.print_pat(p)); self.pclose(); } PatKind::Or(ref pats) => { - self.strsep("|", true, Inconsistent, &pats[..], |s, p| s.print_pat(p)); + self.strsep("|", true, Inconsistent, &pats, |s, p| s.print_pat(p)); } PatKind::Path(None, ref path) => { self.print_path(path, true, 0); @@ -2430,10 +2464,14 @@ impl<'a> State<'a> { self.print_path(path, true, 0); } self.nbsp(); - self.word_space("{"); + self.word("{"); + let empty = fields.is_empty() && !etc; + if !empty { + self.space(); + } self.commasep_cmnt( Consistent, - &fields[..], + &fields, |s, f| { s.cbox(INDENT_UNIT); if !f.is_shorthand { @@ -2449,27 +2487,29 @@ impl<'a> State<'a> { if !fields.is_empty() { self.word_space(","); } - self.s.word(".."); + self.word(".."); } - self.s.space(); - self.s.word("}"); + if !empty { + self.space(); + } + self.word("}"); } PatKind::Tuple(ref elts) => { self.popen(); - self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p)); + self.commasep(Inconsistent, &elts, |s, p| s.print_pat(p)); if elts.len() == 1 { - self.s.word(","); + self.word(","); } self.pclose(); } PatKind::Box(ref inner) => { - self.s.word("box "); + self.word("box "); self.print_pat(inner); } PatKind::Ref(ref inner, mutbl) => { - self.s.word("&"); + self.word("&"); if mutbl == ast::Mutability::Mut { - self.s.word("mut "); + self.word("mut "); } if let PatKind::Ident(ast::BindingMode::ByValue(ast::Mutability::Mut), ..) = inner.kind @@ -2485,23 +2525,22 @@ impl<'a> State<'a> { PatKind::Range(ref begin, ref end, Spanned { node: ref end_kind, .. }) => { if let Some(e) = begin { self.print_expr(e); - self.s.space(); } match *end_kind { - RangeEnd::Included(RangeSyntax::DotDotDot) => self.s.word("..."), - RangeEnd::Included(RangeSyntax::DotDotEq) => self.s.word("..="), - RangeEnd::Excluded => self.s.word(".."), + RangeEnd::Included(RangeSyntax::DotDotDot) => self.word("..."), + RangeEnd::Included(RangeSyntax::DotDotEq) => self.word("..="), + RangeEnd::Excluded => self.word(".."), } if let Some(e) = end { self.print_expr(e); } } PatKind::Slice(ref elts) => { - self.s.word("["); - self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(p)); - self.s.word("]"); + self.word("["); + self.commasep(Inconsistent, &elts, |s, p| s.print_pat(p)); + self.word("]"); } - PatKind::Rest => self.s.word(".."), + PatKind::Rest => self.word(".."), PatKind::Paren(ref inner) => { self.popen(); self.print_pat(inner); @@ -2515,18 +2554,18 @@ impl<'a> State<'a> { fn print_arm(&mut self, arm: &ast::Arm) { // Note, I have no idea why this check is necessary, but here it is. if arm.attrs.is_empty() { - self.s.space(); + self.space(); } self.cbox(INDENT_UNIT); self.ibox(0); self.maybe_print_comment(arm.pat.span.lo()); self.print_outer_attributes(&arm.attrs); self.print_pat(&arm.pat); - self.s.space(); + self.space(); if let Some(ref e) = arm.guard { self.word_space("if"); self.print_expr(e); - self.s.space(); + self.space(); } self.word_space("=>"); @@ -2542,13 +2581,13 @@ impl<'a> State<'a> { // If it is a user-provided unsafe block, print a comma after it. if let BlockCheckMode::Unsafe(ast::UserProvided) = blk.rules { - self.s.word(","); + self.word(","); } } _ => { self.end(); // Close the ibox for the pattern. self.print_expr(&arm.body); - self.s.word(","); + self.word(","); } } self.end(); // Close enclosing cbox. @@ -2558,17 +2597,17 @@ impl<'a> State<'a> { match explicit_self.node { SelfKind::Value(m) => { self.print_mutability(m, false); - self.s.word("self") + self.word("self") } SelfKind::Region(ref lt, m) => { - self.s.word("&"); + self.word("&"); self.print_opt_lifetime(lt); self.print_mutability(m, false); - self.s.word("self") + self.word("self") } SelfKind::Explicit(ref typ, m) => { self.print_mutability(m, false); - self.s.word("self"); + self.word("self"); self.word_space(":"); self.print_type(typ) } @@ -2595,7 +2634,7 @@ impl<'a> State<'a> { self.nbsp(); self.print_block_with_attrs(body, attrs); } else { - self.s.word(";"); + self.word(";"); } } @@ -2646,7 +2685,7 @@ impl<'a> State<'a> { pub fn print_type_bounds(&mut self, prefix: &'static str, bounds: &[ast::GenericBound]) { if !bounds.is_empty() { - self.s.word(prefix); + self.word(prefix); let mut first = true; for bound in bounds { if !(first && prefix.is_empty()) { @@ -2661,7 +2700,7 @@ impl<'a> State<'a> { match bound { GenericBound::Trait(tref, modifier) => { if modifier == &TraitBoundModifier::Maybe { - self.s.word("?"); + self.word("?"); } self.print_poly_trait_ref(tref); } @@ -2682,10 +2721,10 @@ impl<'a> State<'a> { ) { self.print_lifetime(lifetime); if !bounds.is_empty() { - self.s.word(": "); + self.word(": "); for (i, bound) in bounds.iter().enumerate() { if i != 0 { - self.s.word(" + "); + self.word(" + "); } match bound { ast::GenericBound::Outlives(lt) => self.print_lifetime(*lt), @@ -2700,7 +2739,7 @@ impl<'a> State<'a> { return; } - self.s.word("<"); + self.word("<"); self.commasep(Inconsistent, &generic_params, |s, param| { s.print_outer_attributes_inline(¶m.attrs); @@ -2714,7 +2753,7 @@ impl<'a> State<'a> { s.print_ident(param.ident); s.print_type_bounds(":", ¶m.bounds); if let Some(ref default) = default { - s.s.space(); + s.space(); s.word_space("="); s.print_type(default) } @@ -2722,12 +2761,12 @@ impl<'a> State<'a> { ast::GenericParamKind::Const { ref ty, kw_span: _, ref default } => { s.word_space("const"); s.print_ident(param.ident); - s.s.space(); + s.space(); s.word_space(":"); s.print_type(ty); s.print_type_bounds(":", ¶m.bounds); if let Some(ref default) = default { - s.s.space(); + s.space(); s.word_space("="); s.print_expr(&default.value); } @@ -2735,7 +2774,7 @@ impl<'a> State<'a> { } }); - self.s.word(">"); + self.word(">"); } crate fn print_where_clause(&mut self, where_clause: &ast::WhereClause) { @@ -2743,7 +2782,7 @@ impl<'a> State<'a> { return; } - self.s.space(); + self.space(); self.word_space("where"); for (i, predicate) in where_clause.predicates.iter().enumerate() { @@ -2751,34 +2790,34 @@ impl<'a> State<'a> { self.word_space(","); } - match *predicate { - ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { - ref bound_generic_params, - ref bounded_ty, - ref bounds, - .. - }) => { - self.print_formal_generic_params(bound_generic_params); - self.print_type(bounded_ty); - self.print_type_bounds(":", bounds); - } - ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { - ref lifetime, - ref bounds, - .. - }) => { - self.print_lifetime_bounds(*lifetime, bounds); - } - ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { - ref lhs_ty, - ref rhs_ty, - .. - }) => { - self.print_type(lhs_ty); - self.s.space(); - self.word_space("="); - self.print_type(rhs_ty); - } + self.print_where_predicate(predicate); + } + } + + pub fn print_where_predicate(&mut self, predicate: &ast::WherePredicate) { + match predicate { + ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { + bound_generic_params, + bounded_ty, + bounds, + .. + }) => { + self.print_formal_generic_params(bound_generic_params); + self.print_type(bounded_ty); + self.print_type_bounds(":", bounds); + } + ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { + lifetime, + bounds, + .. + }) => { + self.print_lifetime_bounds(*lifetime, bounds); + } + ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { lhs_ty, rhs_ty, .. }) => { + self.print_type(lhs_ty); + self.space(); + self.word_space("="); + self.print_type(rhs_ty); } } } @@ -2788,7 +2827,7 @@ impl<'a> State<'a> { ast::UseTreeKind::Simple(rename, ..) => { self.print_path(&tree.prefix, false, 0); if let Some(rename) = rename { - self.s.space(); + self.space(); self.word_space("as"); self.print_ident(rename); } @@ -2796,21 +2835,21 @@ impl<'a> State<'a> { ast::UseTreeKind::Glob => { if !tree.prefix.segments.is_empty() { self.print_path(&tree.prefix, false, 0); - self.s.word("::"); + self.word("::"); } - self.s.word("*"); + self.word("*"); } ast::UseTreeKind::Nested(ref items) => { if tree.prefix.segments.is_empty() { - self.s.word("{"); + self.word("{"); } else { self.print_path(&tree.prefix, false, 0); - self.s.word("::{"); + self.word("::{"); } - self.commasep(Inconsistent, &items[..], |this, &(ref tree, _)| { + self.commasep(Inconsistent, &items, |this, &(ref tree, _)| { this.print_use_tree(tree) }); - self.s.word("}"); + self.word("}"); } } } @@ -2849,8 +2888,8 @@ impl<'a> State<'a> { }; if !invalid { self.print_pat(&input.pat); - self.s.word(":"); - self.s.space(); + self.word(":"); + self.space(); } self.print_type(&input.ty); } @@ -2879,10 +2918,7 @@ impl<'a> State<'a> { generic_params: &[ast::GenericParam], ) { self.ibox(INDENT_UNIT); - if !generic_params.is_empty() { - self.s.word("for"); - self.print_generic_params(generic_params); - } + self.print_formal_generic_params(generic_params); let generics = ast::Generics { params: Vec::new(), where_clause: ast::WhereClause { @@ -2897,29 +2933,6 @@ impl<'a> State<'a> { self.end(); } - crate fn maybe_print_trailing_comment( - &mut self, - span: rustc_span::Span, - next_pos: Option, - ) { - if let Some(cmnts) = self.comments() { - if let Some(cmnt) = cmnts.trailing_comment(span, next_pos) { - self.print_comment(&cmnt); - } - } - } - - crate fn print_remaining_comments(&mut self) { - // If there aren't any remaining comments, then we need to manually - // make sure there is a line break at the end. - if self.next_comment().is_none() { - self.s.hardbreak(); - } - while let Some(ref cmnt) = self.next_comment() { - self.print_comment(cmnt); - } - } - crate fn print_fn_header_info(&mut self, header: ast::FnHeader) { self.print_constness(header.constness); self.print_asyncness(header.asyncness); @@ -2937,7 +2950,7 @@ impl<'a> State<'a> { } } - self.s.word("fn") + self.word("fn") } crate fn print_unsafety(&mut self, s: ast::Unsafe) { diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 719caaabbb..bab50df3dd 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -236,7 +236,7 @@ where // These unwraps are safe because `get` ensures the meta item // is a name/value pair string literal. - issue_num = match &*issue.unwrap().as_str() { + issue_num = match issue.unwrap().as_str() { "none" => None, issue => { let emit_diag = |msg: &str| { @@ -301,7 +301,7 @@ where match (feature, reason, issue) { (Some(feature), reason, Some(_)) => { - if !rustc_lexer::is_ident(&feature.as_str()) { + if !rustc_lexer::is_ident(feature.as_str()) { handle_errors( &sess.parse_sess, attr.span, @@ -519,8 +519,10 @@ pub fn eval_condition( [NestedMetaItem::Literal(Lit { kind: LitKind::Str(sym, ..), span, .. })] => { (sym, span) } - [NestedMetaItem::Literal(Lit { span, .. }) - | NestedMetaItem::MetaItem(MetaItem { span, .. })] => { + [ + NestedMetaItem::Literal(Lit { span, .. }) + | NestedMetaItem::MetaItem(MetaItem { span, .. }), + ] => { sess.span_diagnostic .struct_span_err(*span, "expected a version literal") .emit(); @@ -533,7 +535,7 @@ pub fn eval_condition( return false; } }; - let min_version = match parse_version(&min_version.as_str(), false) { + let min_version = match parse_version(min_version.as_str(), false) { Some(ver) => ver, None => { sess.span_diagnostic diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index 952e18c1e5..4a9904891e 100644 --- a/compiler/rustc_borrowck/src/borrow_set.rs +++ b/compiler/rustc_borrowck/src/borrow_set.rs @@ -84,7 +84,7 @@ pub enum LocalsStateAtExit { } impl LocalsStateAtExit { - fn build( + fn build<'tcx>( locals_are_invalidated_at_exit: bool, body: &Body<'tcx>, move_data: &MoveData<'tcx>, diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 7db8d4520d..15372ec153 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -5,7 +5,7 @@ use rustc_middle::ty::RegionVid; use rustc_middle::ty::TyCtxt; use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces}; use rustc_mir_dataflow::ResultsVisitable; -use rustc_mir_dataflow::{self, fmt::DebugWithContext, GenKill}; +use rustc_mir_dataflow::{self, fmt::DebugWithContext, CallReturnPlaces, GenKill}; use rustc_mir_dataflow::{Analysis, Direction, Results}; use std::fmt; use std::iter; @@ -434,9 +434,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> { &self, _trans: &mut impl GenKill, _block: mir::BasicBlock, - _func: &mir::Operand<'tcx>, - _args: &[mir::Operand<'tcx>], - _dest_place: mir::Place<'tcx>, + _return_places: CallReturnPlaces<'_, 'tcx>, ) { } } diff --git a/compiler/rustc_borrowck/src/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs index 689ec249a2..70acbc9ee2 100644 --- a/compiler/rustc_borrowck/src/def_use.rs +++ b/compiler/rustc_borrowck/src/def_use.rs @@ -17,7 +17,7 @@ pub fn categorize(context: PlaceContext) -> Option { PlaceContext::MutatingUse(MutatingUseContext::Store) | // This is potentially both a def and a use... - PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) | + PlaceContext::MutatingUse(MutatingUseContext::LlvmAsmOutput) | // We let Call define the result in both the success and // unwind cases. This is not really correct, however it @@ -26,6 +26,7 @@ pub fn categorize(context: PlaceContext) -> Option { // the def in call only to the input from the success // path and not the unwind path. -nmatsakis PlaceContext::MutatingUse(MutatingUseContext::Call) | + PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) | PlaceContext::MutatingUse(MutatingUseContext::Yield) | // Storage live and storage dead aren't proper defines, but we can ignore diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 1bc9f8cf3c..96326ef2d5 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -31,7 +31,7 @@ enum UniverseInfoInner<'tcx> { Other, } -impl UniverseInfo<'tcx> { +impl<'tcx> UniverseInfo<'tcx> { crate fn other() -> UniverseInfo<'tcx> { UniverseInfo(UniverseInfoInner::Other) } @@ -191,7 +191,7 @@ struct PredicateQuery<'tcx> { base_universe: ty::UniverseIndex, } -impl TypeOpInfo<'tcx> for PredicateQuery<'tcx> { +impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> { fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let mut err = tcx.sess.struct_span_err(span, "higher-ranked lifetime error"); err.note(&format!("could not prove {}", self.canonical_query.value.value.predicate)); @@ -231,7 +231,7 @@ struct NormalizeQuery<'tcx, T> { base_universe: ty::UniverseIndex, } -impl TypeOpInfo<'tcx> for NormalizeQuery<'tcx, T> +impl<'tcx, T> TypeOpInfo<'tcx> for NormalizeQuery<'tcx, T> where T: Copy + fmt::Display + TypeFoldable<'tcx> + 'tcx, { @@ -291,7 +291,7 @@ struct AscribeUserTypeQuery<'tcx> { base_universe: ty::UniverseIndex, } -impl TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> { +impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> { fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { // FIXME: This error message isn't great, but it doesn't show up in the existing UI tests, // and is only the fallback when the nice error fails. Consider improving this some more. @@ -368,6 +368,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>( error_region, cause.clone(), placeholder_region, + vec![], ), ), (Some(error_region), _) => NiceRegionError::new( diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 46a3c0fa10..a24b7cff9e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -15,16 +15,18 @@ use rustc_span::symbol::sym; use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP}; use rustc_trait_selection::infer::InferCtxtExt; +use crate::borrow_set::TwoPhaseActivation; use crate::borrowck_errors; +use crate::diagnostics::find_all_local_uses; use crate::{ borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf, InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind, }; use super::{ - explain_borrow::BorrowExplanation, FnSelfUseKind, IncludingDowncast, RegionName, - RegionNameSource, UseSpans, + explain_borrow::{BorrowExplanation, LaterUseKind}, + FnSelfUseKind, IncludingDowncast, RegionName, RegionNameSource, UseSpans, }; #[derive(Debug)] @@ -414,7 +416,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { tcx, generics, &mut err, - ¶m.name.as_str(), + param.name.as_str(), "Copy", None, ); @@ -768,9 +770,92 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Some((issued_span, span)), ); + self.suggest_using_local_if_applicable( + &mut err, + location, + (place, span), + gen_borrow_kind, + issued_borrow, + explanation, + ); + err } + #[instrument(level = "debug", skip(self, err))] + fn suggest_using_local_if_applicable( + &self, + err: &mut DiagnosticBuilder<'_>, + location: Location, + (place, span): (Place<'tcx>, Span), + gen_borrow_kind: BorrowKind, + issued_borrow: &BorrowData<'tcx>, + explanation: BorrowExplanation, + ) { + let used_in_call = + matches!(explanation, BorrowExplanation::UsedLater(LaterUseKind::Call, _call_span, _)); + if !used_in_call { + debug!("not later used in call"); + return; + } + + let outer_call_loc = + if let TwoPhaseActivation::ActivatedAt(loc) = issued_borrow.activation_location { + loc + } else { + issued_borrow.reserve_location + }; + let outer_call_stmt = self.body.stmt_at(outer_call_loc); + + let inner_param_location = location; + let Some(inner_param_stmt) = self.body.stmt_at(inner_param_location).left() else { + debug!("`inner_param_location` {:?} is not for a statement", inner_param_location); + return; + }; + let Some(&inner_param) = inner_param_stmt.kind.as_assign().map(|(p, _)| p) else { + debug!( + "`inner_param_location` {:?} is not for an assignment: {:?}", + inner_param_location, inner_param_stmt + ); + return; + }; + let inner_param_uses = find_all_local_uses::find(self.body, inner_param.local); + let Some((inner_call_loc,inner_call_term)) = inner_param_uses.into_iter().find_map(|loc| { + let Either::Right(term) = self.body.stmt_at(loc) else { + debug!("{:?} is a statement, so it can't be a call", loc); + return None; + }; + let TerminatorKind::Call { args, .. } = &term.kind else { + debug!("not a call: {:?}", term); + return None; + }; + debug!("checking call args for uses of inner_param: {:?}", args); + if args.contains(&Operand::Move(inner_param)) { + Some((loc,term)) + } else { + None + } + }) else { + debug!("no uses of inner_param found as a by-move call arg"); + return; + }; + debug!("===> outer_call_loc = {:?}, inner_call_loc = {:?}", outer_call_loc, inner_call_loc); + + let inner_call_span = inner_call_term.source_info.span; + let outer_call_span = outer_call_stmt.either(|s| s.source_info, |t| t.source_info).span; + if outer_call_span == inner_call_span || !outer_call_span.contains(inner_call_span) { + // FIXME: This stops the suggestion in some cases where it should be emitted. + // Fix the spans for those cases so it's emitted correctly. + debug!( + "outer span {:?} does not strictly contain inner span {:?}", + outer_call_span, inner_call_span + ); + return; + } + err.span_help(inner_call_span, "try adding a local storing this argument..."); + err.span_help(outer_call_span, "...and then using that local as the argument to this call"); + } + fn suggest_split_at_mut_if_applicable( &self, err: &mut DiagnosticBuilder<'_>, @@ -977,9 +1062,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Some(ref name), BorrowExplanation::MustBeValidFor { category: - category - @ - (ConstraintCategory::Return(_) + category @ (ConstraintCategory::Return(_) | ConstraintCategory::CallArgument | ConstraintCategory::OpaqueType), from_closure: false, @@ -1515,8 +1598,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { location: Location, mpi: MovePathIndex, ) -> (Vec, Vec) { - fn predecessor_locations( - body: &'a mir::Body<'tcx>, + fn predecessor_locations<'a>( + body: &'a mir::Body<'_>, location: Location, ) -> impl Iterator + 'a { if location.statement_index == 0 { diff --git a/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs b/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs new file mode 100644 index 0000000000..49d9caae71 --- /dev/null +++ b/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs @@ -0,0 +1,26 @@ +use std::collections::BTreeSet; + +use rustc_middle::mir::visit::{PlaceContext, Visitor}; +use rustc_middle::mir::{Body, Local, Location}; + +/// Find all uses of (including assignments to) a [`Local`]. +/// +/// Uses `BTreeSet` so output is deterministic. +pub(super) fn find<'tcx>(body: &Body<'tcx>, local: Local) -> BTreeSet { + let mut visitor = AllLocalUsesVisitor { for_local: local, uses: BTreeSet::default() }; + visitor.visit_body(body); + visitor.uses +} + +struct AllLocalUsesVisitor { + for_local: Local, + uses: BTreeSet, +} + +impl<'tcx> Visitor<'tcx> for AllLocalUsesVisitor { + fn visit_local(&mut self, local: &Local, _context: PlaceContext, location: Location) { + if *local == self.for_local { + self.uses.insert(location); + } + } +} diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 79623e26eb..e2eb125981 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -19,6 +19,7 @@ use rustc_target::abi::VariantIdx; use super::borrow_set::BorrowData; use super::MirBorrowckCtxt; +mod find_all_local_uses; mod find_use; mod outlives_suggestion; mod region_name; @@ -205,7 +206,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { { let local_info = &self.body.local_decls[local].local_info; if let Some(box LocalInfo::StaticRef { def_id, .. }) = *local_info { - buf.push_str(&self.infcx.tcx.item_name(def_id).as_str()); + buf.push_str(self.infcx.tcx.item_name(def_id).as_str()); } else { unreachable!(); } @@ -317,7 +318,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let decl = &self.body.local_decls[local]; match self.local_names[local] { Some(name) if !decl.from_compiler_desugaring() => { - buf.push_str(&name.as_str()); + buf.push_str(name.as_str()); Ok(()) } _ => Err(()), @@ -408,7 +409,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// Add a note that a type does not implement `Copy` pub(super) fn note_type_does_not_implement_copy( &self, - err: &mut DiagnosticBuilder<'a>, + err: &mut DiagnosticBuilder<'_>, place_desc: &str, ty: Ty<'tcx>, span: Option, @@ -732,21 +733,19 @@ pub(super) enum BorrowedContentSource<'tcx> { OverloadedIndex(Ty<'tcx>), } -impl BorrowedContentSource<'tcx> { +impl<'tcx> BorrowedContentSource<'tcx> { pub(super) fn describe_for_unnamed_place(&self, tcx: TyCtxt<'_>) -> String { match *self { BorrowedContentSource::DerefRawPointer => "a raw pointer".to_string(), BorrowedContentSource::DerefSharedRef => "a shared reference".to_string(), BorrowedContentSource::DerefMutableRef => "a mutable reference".to_string(), - BorrowedContentSource::OverloadedDeref(ty) => match ty.kind() { - ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Rc, def.did) => { - "an `Rc`".to_string() - } - ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Arc, def.did) => { - "an `Arc`".to_string() - } - _ => format!("dereference of `{}`", ty), - }, + BorrowedContentSource::OverloadedDeref(ty) => ty + .ty_adt_def() + .and_then(|adt| match tcx.get_diagnostic_name(adt.did)? { + name @ (sym::Rc | sym::Arc) => Some(format!("an `{}`", name)), + _ => None, + }) + .unwrap_or_else(|| format!("dereference of `{}`", ty)), BorrowedContentSource::OverloadedIndex(ty) => format!("index of `{}`", ty), } } @@ -770,15 +769,13 @@ impl BorrowedContentSource<'tcx> { BorrowedContentSource::DerefMutableRef => { bug!("describe_for_immutable_place: DerefMutableRef isn't immutable") } - BorrowedContentSource::OverloadedDeref(ty) => match ty.kind() { - ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Rc, def.did) => { - "an `Rc`".to_string() - } - ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Arc, def.did) => { - "an `Arc`".to_string() - } - _ => format!("a dereference of `{}`", ty), - }, + BorrowedContentSource::OverloadedDeref(ty) => ty + .ty_adt_def() + .and_then(|adt| match tcx.get_diagnostic_name(adt.did)? { + name @ (sym::Rc | sym::Arc) => Some(format!("an `{}`", name)), + _ => None, + }) + .unwrap_or_else(|| format!("dereference of `{}`", ty)), BorrowedContentSource::OverloadedIndex(ty) => format!("an index of `{}`", ty), } } @@ -960,8 +957,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { _ => None, }); let is_option_or_result = parent_self_ty.map_or(false, |def_id| { - tcx.is_diagnostic_item(sym::Option, def_id) - || tcx.is_diagnostic_item(sym::Result, def_id) + matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result)) }); FnSelfUseKind::Normal { self_arg, implicit_into_iter, is_option_or_result } }); diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index a0f8aabbe0..b5dad5ccde 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -165,10 +165,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { PlaceRef { local: _, projection: - [.., ProjectionElem::Index(_) - | ProjectionElem::ConstantIndex { .. } - | ProjectionElem::Subslice { .. } - | ProjectionElem::Downcast(..)], + [ + .., + ProjectionElem::Index(_) + | ProjectionElem::ConstantIndex { .. } + | ProjectionElem::Subslice { .. } + | ProjectionElem::Downcast(..), + ], } => bug!("Unexpected immutable place."), } @@ -217,19 +220,24 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { PlaceRef { local, projection: - [proj_base @ .., ProjectionElem::Deref, ProjectionElem::Field(field, _), ProjectionElem::Deref], + [ + proj_base @ .., + ProjectionElem::Deref, + ProjectionElem::Field(field, _), + ProjectionElem::Deref, + ], } => { err.span_label(span, format!("cannot {ACT}", ACT = act)); - if let Some((span, message)) = annotate_struct_field( + if let Some(span) = get_mut_span_in_struct_field( self.infcx.tcx, Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty, field, ) { - err.span_suggestion( + err.span_suggestion_verbose( span, "consider changing this to be mutable", - message, + " mut ".into(), Applicability::MaybeIncorrect, ); } @@ -739,7 +747,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { HirId, ImplItem, ImplItemKind, Item, ItemKind, }; - fn maybe_body_id_of_fn(hir_map: &Map<'tcx>, id: HirId) -> Option { + fn maybe_body_id_of_fn(hir_map: &Map<'_>, id: HirId) -> Option { match hir_map.find(id) { Some(Node::Item(Item { kind: ItemKind::Fn(_, _, body_id), .. })) | Some(Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(_, body_id), .. })) => { @@ -763,11 +771,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { kind: Call( _, - [Expr { - kind: MethodCall(path_segment, ..), - hir_id, - .. - }, ..], + [ + Expr { + kind: MethodCall(path_segment, ..), + hir_id, + .. + }, + .., + ], ), .. }, @@ -1048,18 +1059,18 @@ fn is_closure_or_generator(ty: Ty<'_>) -> bool { ty.is_closure() || ty.is_generator() } -/// Adds a suggestion to a struct definition given a field access to a local. -/// This function expects the local to be a reference to a struct in order to produce a suggestion. +/// Given a field that needs to be mutable, returns a span where the " mut " could go. +/// This function expects the local to be a reference to a struct in order to produce a span. /// /// ```text -/// LL | s: &'a String -/// | ---------- use `&'a mut String` here to make mutable +/// LL | s: &'a String +/// | ^^^ returns a span taking up the space here /// ``` -fn annotate_struct_field( +fn get_mut_span_in_struct_field<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, field: &mir::Field, -) -> Option<(Span, String)> { +) -> Option { // Expect our local to be a reference to a struct of some kind. if let ty::Ref(_, ty, _) = ty.kind() { if let ty::Adt(def, _) = ty.kind() { @@ -1070,25 +1081,10 @@ fn annotate_struct_field( // Now we're dealing with the actual struct that we're going to suggest a change to, // we can expect a field that is an immutable reference to a type. if let hir::Node::Field(field) = node { - if let hir::TyKind::Rptr( - lifetime, - hir::MutTy { mutbl: hir::Mutability::Not, ref ty }, - ) = field.ty.kind + if let hir::TyKind::Rptr(lifetime, hir::MutTy { mutbl: hir::Mutability::Not, ty }) = + field.ty.kind { - // Get the snippets in two parts - the named lifetime (if there is one) and - // type being referenced, that way we can reconstruct the snippet without loss - // of detail. - let type_snippet = tcx.sess.source_map().span_to_snippet(ty.span).ok()?; - let lifetime_snippet = if !lifetime.is_elided() { - format!("{} ", tcx.sess.source_map().span_to_snippet(lifetime.span).ok()?) - } else { - String::new() - }; - - return Some(( - field.ty.span, - format!("&{}mut {}", lifetime_snippet, &*type_snippet,), - )); + return Some(lifetime.span.between(ty.span)); } } } diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 11cdbe84ac..df23eaf24b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -6,7 +6,7 @@ use rustc_infer::infer::{ error_reporting::unexpected_hidden_region_diagnostic, NllRegionVariableOrigin, }; use rustc_middle::mir::{ConstraintCategory, ReturnConstraint}; -use rustc_middle::ty::subst::Subst; +use rustc_middle::ty::subst::{InternalSubsts, Subst}; use rustc_middle::ty::{self, RegionVid, Ty}; use rustc_span::symbol::{kw, sym}; use rustc_span::{BytePos, Span}; @@ -334,13 +334,43 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { match variance_info { ty::VarianceDiagInfo::None => {} - ty::VarianceDiagInfo::Mut { kind, ty } => { - let kind_name = match kind { - ty::VarianceDiagMutKind::Ref => "reference", - ty::VarianceDiagMutKind::RawPtr => "pointer", + ty::VarianceDiagInfo::Invariant { ty, param_index } => { + let (desc, note) = match ty.kind() { + ty::RawPtr(ty_mut) => { + assert_eq!(ty_mut.mutbl, rustc_hir::Mutability::Mut); + ( + format!("a mutable pointer to {}", ty_mut.ty), + "mutable pointers are invariant over their type parameter".to_string(), + ) + } + ty::Ref(_, inner_ty, mutbl) => { + assert_eq!(*mutbl, rustc_hir::Mutability::Mut); + ( + format!("a mutable reference to {}", inner_ty), + "mutable references are invariant over their type parameter" + .to_string(), + ) + } + ty::Adt(adt, substs) => { + let generic_arg = substs[param_index as usize]; + let identity_substs = + InternalSubsts::identity_for_item(self.infcx.tcx, adt.did); + let base_ty = self.infcx.tcx.mk_adt(adt, identity_substs); + let base_generic_arg = identity_substs[param_index as usize]; + let adt_desc = adt.descr(); + + let desc = format!( + "the type {ty}, which makes the generic argument {generic_arg} invariant" + ); + let note = format!( + "the {adt_desc} {base_ty} is invariant over the parameter {base_generic_arg}" + ); + (desc, note) + } + _ => panic!("Unexpected type {:?}", ty), }; - diag.note(&format!("requirement occurs because of a mutable {kind_name} to {ty}",)); - diag.note(&format!("mutable {kind_name}s are invariant over their type parameter")); + diag.note(&format!("requirement occurs because of {desc}",)); + diag.note(¬e); diag.help("see for more information about variance"); } } diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 5edb52b0b6..80f5f77a02 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -584,7 +584,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { Some(RegionNameHighlight::MatchedAdtAndSegment(lifetime_span)) } - hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Implicit => { + hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Implicit(_) => { // In this case, the user left off the lifetime; so // they wrote something like: // @@ -769,20 +769,24 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { let opaque_ty = hir.item(id); if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: - [hir::GenericBound::LangItemTrait( - hir::LangItem::Future, - _, - _, - hir::GenericArgs { - bindings: - [hir::TypeBinding { - ident: Ident { name: sym::Output, .. }, - kind: hir::TypeBindingKind::Equality { ty }, - .. - }], - .. - }, - )], + [ + hir::GenericBound::LangItemTrait( + hir::LangItem::Future, + _, + _, + hir::GenericArgs { + bindings: + [ + hir::TypeBinding { + ident: Ident { name: sym::Output, .. }, + kind: hir::TypeBindingKind::Equality { ty }, + .. + }, + ], + .. + }, + ), + ], .. }) = opaque_ty.kind { diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs index efd34f4e0a..c03e4d8a44 100644 --- a/compiler/rustc_borrowck/src/invalidation.rs +++ b/compiler/rustc_borrowck/src/invalidation.rs @@ -199,6 +199,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { options: _, line_spans: _, destination: _, + cleanup: _, } => { for op in operands { match *op { diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 76d3a83b48..fe34d6e7ca 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -3,9 +3,6 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(crate_visibility_modifier)] -#![cfg_attr(bootstrap, feature(format_args_capture))] -#![feature(in_band_lifetimes)] -#![feature(iter_zip)] #![feature(let_else)] #![feature(min_specialization)] #![feature(stmt_expr_attributes)] @@ -792,6 +789,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx options: _, line_spans: _, destination: _, + cleanup: _, } => { for op in operands { match *op { @@ -1396,10 +1394,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Rvalue::NullaryOp(_op, _ty) => { // nullary ops take no dynamic input; no borrowck effect. - // - // FIXME: is above actually true? Do we want to track - // the fact that uninitialized data can be created via - // `NullOp::Box`? } Rvalue::Aggregate(ref aggregate_kind, ref operands) => { diff --git a/compiler/rustc_borrowck/src/member_constraints.rs b/compiler/rustc_borrowck/src/member_constraints.rs index f22d355e61..0fe44328fd 100644 --- a/compiler/rustc_borrowck/src/member_constraints.rs +++ b/compiler/rustc_borrowck/src/member_constraints.rs @@ -53,7 +53,7 @@ rustc_index::newtype_index! { } } -impl Default for MemberConstraintSet<'tcx, ty::RegionVid> { +impl Default for MemberConstraintSet<'_, ty::RegionVid> { fn default() -> Self { Self { first_constraints: Default::default(), @@ -97,7 +97,7 @@ impl<'tcx> MemberConstraintSet<'tcx, ty::RegionVid> { } } -impl MemberConstraintSet<'tcx, R1> +impl<'tcx, R1> MemberConstraintSet<'tcx, R1> where R1: Copy + Hash + Eq, { @@ -140,7 +140,7 @@ where } } -impl MemberConstraintSet<'tcx, R> +impl MemberConstraintSet<'_, R> where R: Copy + Hash + Eq, { diff --git a/compiler/rustc_borrowck/src/path_utils.rs b/compiler/rustc_borrowck/src/path_utils.rs index d5d00b467e..b2c8dfc82c 100644 --- a/compiler/rustc_borrowck/src/path_utils.rs +++ b/compiler/rustc_borrowck/src/path_utils.rs @@ -141,7 +141,7 @@ pub(super) fn borrow_of_local_data(place: Place<'_>) -> bool { /// then returns the index of the field being projected. Note that this closure will always /// be `self` in the current MIR, because that is the only time we directly access the fields /// of a closure type. -pub(crate) fn is_upvar_field_projection( +pub(crate) fn is_upvar_field_projection<'tcx>( tcx: TyCtxt<'tcx>, upvars: &[Upvar<'tcx>], place_ref: PlaceRef<'tcx>, diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 4eb7be542e..76b3be7976 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -173,7 +173,7 @@ fn check_opaque_type_parameter_valid( // fn foo() -> foo::<'static..'static>::Foo<'l0..'lm>. // // which would error here on all of the `'static` args. - OpaqueTyOrigin::FnReturn | OpaqueTyOrigin::AsyncFn => return true, + OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return true, // Check these OpaqueTyOrigin::TyAlias => {} } diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index 100ac578f9..4a70535c63 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -1,5 +1,7 @@ use rustc_data_structures::fx::FxIndexSet; -use rustc_index::bit_set::{HybridBitSet, SparseBitMatrix}; +use rustc_index::bit_set::SparseBitMatrix; +use rustc_index::interval::IntervalSet; +use rustc_index::interval::SparseIntervalMatrix; use rustc_index::vec::Idx; use rustc_index::vec::IndexVec; use rustc_middle::mir::{BasicBlock, Body, Location}; @@ -110,11 +112,11 @@ crate enum RegionElement { PlaceholderRegion(ty::PlaceholderRegion), } -/// When we initially compute liveness, we use a bit matrix storing -/// points for each region-vid. +/// When we initially compute liveness, we use an interval matrix storing +/// liveness ranges for each region-vid. crate struct LivenessValues { elements: Rc, - points: SparseBitMatrix, + points: SparseIntervalMatrix, } impl LivenessValues { @@ -122,7 +124,7 @@ impl LivenessValues { /// Each of the regions in num_region_variables will be initialized with an /// empty set of points and no causal information. crate fn new(elements: Rc) -> Self { - Self { points: SparseBitMatrix::new(elements.num_points), elements } + Self { points: SparseIntervalMatrix::new(elements.num_points), elements } } /// Iterate through each region that has a value in this set. @@ -140,7 +142,7 @@ impl LivenessValues { /// Adds all the elements in the given bit array into the given /// region. Returns whether any of them are newly added. - crate fn add_elements(&mut self, row: N, locations: &HybridBitSet) -> bool { + crate fn add_elements(&mut self, row: N, locations: &IntervalSet) -> bool { debug!("LivenessValues::add_elements(row={:?}, locations={:?})", row, locations); self.points.union_row(row, locations) } @@ -153,7 +155,7 @@ impl LivenessValues { /// Returns `true` if the region `r` contains the given element. crate fn contains(&self, row: N, location: Location) -> bool { let index = self.elements.point_from_location(location); - self.points.contains(row, index) + self.points.row(row).map_or(false, |r| r.contains(index)) } /// Returns an iterator of all the elements contained by the region `r` @@ -221,7 +223,7 @@ impl PlaceholderIndices { crate struct RegionValues { elements: Rc, placeholder_indices: Rc, - points: SparseBitMatrix, + points: SparseIntervalMatrix, free_regions: SparseBitMatrix, /// Placeholders represent bound regions -- so something like `'a` @@ -241,7 +243,7 @@ impl RegionValues { let num_placeholders = placeholder_indices.len(); Self { elements: elements.clone(), - points: SparseBitMatrix::new(elements.num_points), + points: SparseIntervalMatrix::new(elements.num_points), placeholder_indices: placeholder_indices.clone(), free_regions: SparseBitMatrix::new(num_universal_regions), placeholders: SparseBitMatrix::new(num_placeholders), diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs index 20567610f6..4b6cab24cd 100644 --- a/compiler/rustc_borrowck/src/renumber.rs +++ b/compiler/rustc_borrowck/src/renumber.rs @@ -1,7 +1,7 @@ use rustc_index::vec::IndexVec; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin}; use rustc_middle::mir::visit::{MutVisitor, TyContext}; -use rustc_middle::mir::{Body, Location, PlaceElem, Promoted}; +use rustc_middle::mir::{Body, Location, Promoted}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -62,22 +62,6 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NllVisitor<'a, 'tcx> { debug!(?ty); } - fn process_projection_elem( - &mut self, - elem: PlaceElem<'tcx>, - _: Location, - ) -> Option> { - if let PlaceElem::Field(field, ty) = elem { - let new_ty = self.renumber_regions(ty); - - if new_ty != ty { - return Some(PlaceElem::Field(field, new_ty)); - } - } - - None - } - #[instrument(skip(self), level = "debug")] fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, location: Location) { *substs = self.renumber_regions(*substs); diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index ab1a7461b4..a3b39591f8 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -6,6 +6,7 @@ use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound}; use rustc_infer::infer::{self, InferCtxt, SubregionOrigin}; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::subst::GenericArgKind; +use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::DUMMY_SP; @@ -95,11 +96,23 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { self.add_outlives(r1_vid, r2_vid); } - GenericArgKind::Type(t1) => { + GenericArgKind::Type(mut t1) => { // we don't actually use this for anything, but // the `TypeOutlives` code needs an origin. let origin = infer::RelateParamBound(DUMMY_SP, t1, None); + // Placeholder regions need to be converted now because it may + // create new region variables, which can't be done later when + // verifying these bounds. + if t1.has_placeholders() { + t1 = tcx.fold_regions(&t1, &mut false, |r, _| match *r { + ty::RegionKind::RePlaceholder(placeholder) => { + self.constraints.placeholder_region(self.infcx, placeholder) + } + _ => r, + }); + } + TypeOutlives::new( &mut *self, tcx, diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index 8d97c3cbb0..fec6bdf314 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -58,7 +58,7 @@ crate struct CreateResult<'tcx> { crate normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>, } -crate fn create( +crate fn create<'tcx>( infcx: &InferCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, implicit_region_bound: Option>, @@ -81,7 +81,7 @@ crate fn create( .create() } -impl UniversalRegionRelations<'tcx> { +impl UniversalRegionRelations<'_> { /// Records in the `outlives_relation` (and /// `inverse_outlives_relation`) that `fr_a: fr_b`. Invoked by the /// builder below. @@ -110,7 +110,7 @@ impl UniversalRegionRelations<'tcx> { /// outlives `fr` and (b) is not local. /// /// (*) If there are multiple competing choices, we return all of them. - crate fn non_local_upper_bounds(&'a self, fr: &'a RegionVid) -> Vec<&'a RegionVid> { + crate fn non_local_upper_bounds<'a>(&'a self, fr: &'a RegionVid) -> Vec<&'a RegionVid> { debug!("non_local_upper_bound(fr={:?})", fr); let res = self.non_local_bounds(&self.inverse_outlives, fr); assert!(!res.is_empty(), "can't find an upper bound!?"); @@ -232,7 +232,7 @@ struct UniversalRegionRelationsBuilder<'this, 'tcx> { region_bound_pairs: RegionBoundPairs<'tcx>, } -impl UniversalRegionRelationsBuilder<'cx, 'tcx> { +impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { crate fn create(mut self) -> CreateResult<'tcx> { let unnormalized_input_output_tys = self .universal_regions diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index 92d2d04f23..bc740de515 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -117,9 +117,29 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } - assert!(body.yield_ty().is_some() == universal_regions.yield_ty.is_some()); - if let Some(mir_yield_ty) = body.yield_ty() { - let ur_yield_ty = universal_regions.yield_ty.unwrap(); + debug!( + "equate_inputs_and_outputs: body.yield_ty {:?}, universal_regions.yield_ty {:?}", + body.yield_ty(), + universal_regions.yield_ty + ); + + // We will not have a universal_regions.yield_ty if we yield (by accident) + // outside of a generator and return an `impl Trait`, so emit a delay_span_bug + // because we don't want to panic in an assert here if we've already got errors. + if body.yield_ty().is_some() != universal_regions.yield_ty.is_some() { + self.tcx().sess.delay_span_bug( + body.span, + &format!( + "Expected body to have yield_ty ({:?}) iff we have a UR yield_ty ({:?})", + body.yield_ty(), + universal_regions.yield_ty, + ), + ); + } + + if let (Some(mir_yield_ty), Some(ur_yield_ty)) = + (body.yield_ty(), universal_regions.yield_ty) + { let yield_span = body.local_decls[RETURN_PLACE].source_info.span; self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty, yield_span); } diff --git a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs index 8b74abd94c..dd23683fae 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs @@ -152,7 +152,7 @@ impl LocalUseMapBuild<'_> { } } -impl Visitor<'tcx> for LocalUseMapBuild<'_> { +impl Visitor<'_> for LocalUseMapBuild<'_> { fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) { if self.locals_with_use_data[local] { match def_use::categorize(context) { diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index 1e712354d6..f18fe1f43d 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -74,7 +74,7 @@ pub(super) fn generate<'mir, 'tcx>( // to compute whether a variable `X` is live if that variable contains // some region `R` in its type where `R` is not known to outlive a free // region (i.e., where `R` may be valid for just a subset of the fn body). -fn compute_live_locals( +fn compute_live_locals<'tcx>( tcx: TyCtxt<'tcx>, free_regions: &FxHashSet, body: &Body<'tcx>, @@ -104,7 +104,7 @@ fn compute_live_locals( /// regions. For these regions, we do not need to compute /// liveness, since the outlives constraints will ensure that they /// are live over the whole fn body anyhow. -fn regions_that_outlive_free_regions( +fn regions_that_outlive_free_regions<'tcx>( num_region_vars: usize, universal_regions: &UniversalRegions<'tcx>, constraint_set: &OutlivesConstraintSet<'tcx>, diff --git a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs index 79ab8b713f..ee067c4872 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs @@ -53,7 +53,7 @@ impl UseFactsExtractor<'_> { } } -impl Visitor<'tcx> for UseFactsExtractor<'_> { +impl Visitor<'_> for UseFactsExtractor<'_> { fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) { match def_use::categorize(context) { Some(DefUse::Def) => self.insert_def(local, location), @@ -63,7 +63,7 @@ impl Visitor<'tcx> for UseFactsExtractor<'_> { } } - fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) { + fn visit_place(&mut self, place: &Place<'_>, context: PlaceContext, location: Location) { self.super_place(place, context, location); match context { PlaceContext::NonMutatingUse(_) => { @@ -82,7 +82,7 @@ impl Visitor<'tcx> for UseFactsExtractor<'_> { } } -pub(super) fn populate_access_facts( +pub(super) fn populate_access_facts<'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, body: &Body<'tcx>, location_table: &LocationTable, @@ -123,7 +123,7 @@ pub(super) fn populate_access_facts( // For every potentially drop()-touched region `region` in `local`'s type // (`kind`), emit a Polonius `use_of_var_derefs_origin(local, origin)` fact. -pub(super) fn add_drop_of_var_derefs_origin( +pub(super) fn add_drop_of_var_derefs_origin<'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, local: Local, kind: &GenericArg<'tcx>, diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 73c284071d..094af20f52 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -1,5 +1,6 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_index::bit_set::HybridBitSet; +use rustc_index::interval::IntervalSet; use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location}; use rustc_middle::ty::{Ty, TypeFoldable}; @@ -34,7 +35,7 @@ use crate::{ /// DROP-LIVE set are to the liveness sets for regions found in the /// `dropck_outlives` result of the variable's type (in particular, /// this respects `#[may_dangle]` annotations). -pub(super) fn trace( +pub(super) fn trace<'mir, 'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, body: &Body<'tcx>, elements: &Rc, @@ -105,12 +106,12 @@ struct LivenessResults<'me, 'typeck, 'flow, 'tcx> { /// Points where the current variable is "use live" -- meaning /// that there is a future "full use" that may use its value. - use_live_at: HybridBitSet, + use_live_at: IntervalSet, /// Points where the current variable is "drop live" -- meaning /// that there is no future "full use" that may use its value, but /// there is a future drop. - drop_live_at: HybridBitSet, + drop_live_at: IntervalSet, /// Locations where drops may occur. drop_locations: Vec, @@ -119,14 +120,14 @@ struct LivenessResults<'me, 'typeck, 'flow, 'tcx> { stack: Vec, } -impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { +impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> { fn new(cx: LivenessContext<'me, 'typeck, 'flow, 'tcx>) -> Self { let num_points = cx.elements.num_points(); LivenessResults { cx, defs: HybridBitSet::new_empty(num_points), - use_live_at: HybridBitSet::new_empty(num_points), - drop_live_at: HybridBitSet::new_empty(num_points), + use_live_at: IntervalSet::new(num_points), + drop_live_at: IntervalSet::new(num_points), drop_locations: vec![], stack: vec![], } @@ -165,7 +166,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { drop_used: Vec<(Local, Location)>, live_locals: FxHashSet, ) { - let locations = HybridBitSet::new_empty(self.cx.elements.num_points()); + let locations = IntervalSet::new(self.cx.elements.num_points()); for (local, location) in drop_used { if !live_locals.contains(&local) { @@ -418,7 +419,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> { } } -impl LivenessContext<'_, '_, '_, 'tcx> { +impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { /// Returns `true` if the local variable (or some part of it) is initialized at the current /// cursor position. Callers should call one of the `seek` methods immediately before to point /// the cursor to the desired location. @@ -456,7 +457,7 @@ impl LivenessContext<'_, '_, '_, 'tcx> { fn add_use_live_facts_for( &mut self, value: impl TypeFoldable<'tcx>, - live_at: &HybridBitSet, + live_at: &IntervalSet, ) { debug!("add_use_live_facts_for(value={:?})", value); @@ -473,7 +474,7 @@ impl LivenessContext<'_, '_, '_, 'tcx> { dropped_local: Local, dropped_ty: Ty<'tcx>, drop_locations: &[Location], - live_at: &HybridBitSet, + live_at: &IntervalSet, ) { debug!( "add_drop_live_constraint(\ @@ -521,7 +522,7 @@ impl LivenessContext<'_, '_, '_, 'tcx> { elements: &RegionValueElements, typeck: &mut TypeChecker<'_, 'tcx>, value: impl TypeFoldable<'tcx>, - live_at: &HybridBitSet, + live_at: &IntervalSet, ) { debug!("make_all_regions_live(value={:?})", value); debug!( diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index da26d9c7b8..1f745f977d 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -31,7 +31,7 @@ use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts}; use rustc_middle::ty::{ self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, OpaqueTypeKey, RegionVid, - ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, WithConstness, + ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, }; use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::{Span, DUMMY_SP}; @@ -945,7 +945,7 @@ crate struct MirTypeckRegionConstraints<'tcx> { crate type_tests: Vec>, } -impl MirTypeckRegionConstraints<'tcx> { +impl<'tcx> MirTypeckRegionConstraints<'tcx> { fn placeholder_region( &mut self, infcx: &InferCtxt<'_, 'tcx>, @@ -1828,10 +1828,16 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.assert_iscleanup(body, block_data, unwind, true); } } - TerminatorKind::InlineAsm { destination, .. } => { + TerminatorKind::InlineAsm { destination, cleanup, .. } => { if let Some(target) = destination { self.assert_iscleanup(body, block_data, target, is_cleanup); } + if let Some(cleanup) = cleanup { + if is_cleanup { + span_mirbug!(self, block_data, "cleanup on cleanup block") + } + self.assert_iscleanup(body, block_data, cleanup, true); + } } } } @@ -1910,7 +1916,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let tcx = self.tcx(); match *ak { - AggregateKind::Adt(def, variant_index, substs, _, active_field_index) => { + AggregateKind::Adt(adt_did, variant_index, substs, _, active_field_index) => { + let def = tcx.adt_def(adt_did); let variant = &def.variants[variant_index]; let adj_field_index = active_field_index.unwrap_or(field_index); if let Some(field) = variant.fields.get(adj_field_index) { @@ -2615,8 +2622,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); let (def_id, instantiated_predicates) = match aggregate_kind { - AggregateKind::Adt(def, _, substs, _, _) => { - (def.did, tcx.predicates_of(def.did).instantiate(tcx, substs)) + AggregateKind::Adt(adt_did, _, substs, _, _) => { + (*adt_did, tcx.predicates_of(*adt_did).instantiate(tcx, substs)) } // For closures, we have some **extra requirements** we diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 415d1abaa8..cc3fe0a123 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -51,7 +51,7 @@ struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { universe_info: UniverseInfo<'tcx>, } -impl NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { +impl<'me, 'bccx, 'tcx> NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { fn new( type_checker: &'me mut TypeChecker<'bccx, 'tcx>, locations: Locations, @@ -62,7 +62,7 @@ impl NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { } } -impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { +impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { fn param_env(&self) -> ty::ParamEnv<'tcx> { self.type_checker.param_env } diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml index fd34f947f7..9031c3b2ec 100644 --- a/compiler/rustc_builtin_macros/Cargo.toml +++ b/compiler/rustc_builtin_macros/Cargo.toml @@ -15,6 +15,7 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } rustc_lexer = { path = "../rustc_lexer" } +rustc_lint_defs = { path = "../rustc_lint_defs" } rustc_parse = { path = "../rustc_parse" } rustc_target = { path = "../rustc_target" } rustc_session = { path = "../rustc_session" } diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 41662f46f1..1a93b9be99 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -8,13 +8,14 @@ use rustc_expand::base::{self, *}; use rustc_parse::parser::Parser; use rustc_parse_format as parse; use rustc_session::lint; +use rustc_session::parse::ParseSess; use rustc_span::symbol::Ident; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{InnerSpan, Span}; use rustc_target::asm::InlineAsmArch; use smallvec::smallvec; -struct AsmArgs { +pub struct AsmArgs { templates: Vec>, operands: Vec<(ast::InlineAsmOperand, Span)>, named_args: FxHashMap, @@ -31,30 +32,30 @@ fn parse_args<'a>( is_global_asm: bool, ) -> Result> { let mut p = ecx.new_parser_from_tts(tts); + let sess = &ecx.sess.parse_sess; + parse_asm_args(&mut p, sess, sp, is_global_asm) +} + +// Primarily public for rustfmt consumption. +// Internal consumers should continue to leverage `expand_asm`/`expand__global_asm` +pub fn parse_asm_args<'a>( + p: &mut Parser<'a>, + sess: &'a ParseSess, + sp: Span, + is_global_asm: bool, +) -> Result> { + let diag = &sess.span_diagnostic; if p.token == token::Eof { - return Err(ecx.struct_span_err(sp, "requires at least a template string argument")); + return Err(diag.struct_span_err(sp, "requires at least a template string argument")); } // Detect use of the legacy llvm_asm! syntax (which used to be called asm!) if !is_global_asm && p.look_ahead(1, |t| *t == token::Colon || *t == token::ModSep) { let mut err = - ecx.struct_span_err(sp, "the legacy LLVM-style asm! syntax is no longer supported"); + diag.struct_span_err(sp, "the legacy LLVM-style asm! syntax is no longer supported"); err.note("consider migrating to the new asm! syntax specified in RFC 2873"); err.note("alternatively, switch to llvm_asm! to keep your code working as it is"); - - // Find the span of the "asm!" so that we can offer an automatic suggestion - let asm_span = sp.from_inner(InnerSpan::new(0, 4)); - if let Ok(s) = ecx.source_map().span_to_snippet(asm_span) { - if s == "asm!" { - err.span_suggestion( - asm_span, - "replace with", - "llvm_asm!".into(), - Applicability::MachineApplicable, - ); - } - } return Err(err); } @@ -74,7 +75,7 @@ fn parse_args<'a>( if !p.eat(&token::Comma) { if allow_templates { // After a template string, we always expect *only* a comma... - let mut err = ecx.struct_span_err(p.token.span, "expected token: `,`"); + let mut err = diag.struct_span_err(p.token.span, "expected token: `,`"); err.span_label(p.token.span, "expected `,`"); p.maybe_annotate_with_ascription(&mut err, false); return Err(err); @@ -89,14 +90,14 @@ fn parse_args<'a>( // Parse clobber_abi if p.eat_keyword(sym::clobber_abi) { - parse_clobber_abi(&mut p, &mut args)?; + parse_clobber_abi(p, &mut args)?; allow_templates = false; continue; } // Parse options if p.eat_keyword(sym::options) { - parse_options(&mut p, &mut args, is_global_asm)?; + parse_options(p, &mut args, is_global_asm)?; allow_templates = false; continue; } @@ -116,25 +117,25 @@ fn parse_args<'a>( let mut explicit_reg = false; let op = if !is_global_asm && p.eat_keyword(kw::In) { - let reg = parse_reg(&mut p, &mut explicit_reg)?; + let reg = parse_reg(p, &mut explicit_reg)?; if p.eat_keyword(kw::Underscore) { - let err = ecx.struct_span_err(p.token.span, "_ cannot be used for input operands"); + let err = diag.struct_span_err(p.token.span, "_ cannot be used for input operands"); return Err(err); } let expr = p.parse_expr()?; ast::InlineAsmOperand::In { reg, expr } } else if !is_global_asm && p.eat_keyword(sym::out) { - let reg = parse_reg(&mut p, &mut explicit_reg)?; + let reg = parse_reg(p, &mut explicit_reg)?; let expr = if p.eat_keyword(kw::Underscore) { None } else { Some(p.parse_expr()?) }; ast::InlineAsmOperand::Out { reg, expr, late: false } } else if !is_global_asm && p.eat_keyword(sym::lateout) { - let reg = parse_reg(&mut p, &mut explicit_reg)?; + let reg = parse_reg(p, &mut explicit_reg)?; let expr = if p.eat_keyword(kw::Underscore) { None } else { Some(p.parse_expr()?) }; ast::InlineAsmOperand::Out { reg, expr, late: true } } else if !is_global_asm && p.eat_keyword(sym::inout) { - let reg = parse_reg(&mut p, &mut explicit_reg)?; + let reg = parse_reg(p, &mut explicit_reg)?; if p.eat_keyword(kw::Underscore) { - let err = ecx.struct_span_err(p.token.span, "_ cannot be used for input operands"); + let err = diag.struct_span_err(p.token.span, "_ cannot be used for input operands"); return Err(err); } let expr = p.parse_expr()?; @@ -146,9 +147,9 @@ fn parse_args<'a>( ast::InlineAsmOperand::InOut { reg, expr, late: false } } } else if !is_global_asm && p.eat_keyword(sym::inlateout) { - let reg = parse_reg(&mut p, &mut explicit_reg)?; + let reg = parse_reg(p, &mut explicit_reg)?; if p.eat_keyword(kw::Underscore) { - let err = ecx.struct_span_err(p.token.span, "_ cannot be used for input operands"); + let err = diag.struct_span_err(p.token.span, "_ cannot be used for input operands"); return Err(err); } let expr = p.parse_expr()?; @@ -167,7 +168,7 @@ fn parse_args<'a>( match expr.kind { ast::ExprKind::Path(..) => {} _ => { - let err = ecx + let err = diag .struct_span_err(expr.span, "argument to `sym` must be a path expression"); return Err(err); } @@ -186,7 +187,7 @@ fn parse_args<'a>( } else { "expected operand, clobber_abi, options, or additional template string" }; - let mut err = ecx.struct_span_err(template.span, errstr); + let mut err = diag.struct_span_err(template.span, errstr); err.span_label(template.span, errstr); return Err(err); } @@ -206,31 +207,31 @@ fn parse_args<'a>( // clobber_abi/options. We do this at the end once we have the full span // of the argument available. if !args.options_spans.is_empty() { - ecx.struct_span_err(span, "arguments are not allowed after options") + diag.struct_span_err(span, "arguments are not allowed after options") .span_labels(args.options_spans.clone(), "previous options") .span_label(span, "argument") .emit(); } else if let Some((_, abi_span)) = args.clobber_abis.last() { - ecx.struct_span_err(span, "arguments are not allowed after clobber_abi") + diag.struct_span_err(span, "arguments are not allowed after clobber_abi") .span_label(*abi_span, "clobber_abi") .span_label(span, "argument") .emit(); } if explicit_reg { if name.is_some() { - ecx.struct_span_err(span, "explicit register arguments cannot have names").emit(); + diag.struct_span_err(span, "explicit register arguments cannot have names").emit(); } args.reg_args.insert(slot); } else if let Some(name) = name { if let Some(&prev) = args.named_args.get(&name) { - ecx.struct_span_err(span, &format!("duplicate argument named `{}`", name)) + diag.struct_span_err(span, &format!("duplicate argument named `{}`", name)) .span_label(args.operands[prev].1, "previously here") .span_label(span, "duplicate argument") .emit(); continue; } if !args.reg_args.is_empty() { - let mut err = ecx.struct_span_err( + let mut err = diag.struct_span_err( span, "named arguments cannot follow explicit register arguments", ); @@ -243,7 +244,7 @@ fn parse_args<'a>( args.named_args.insert(name, slot); } else { if !args.named_args.is_empty() || !args.reg_args.is_empty() { - let mut err = ecx.struct_span_err( + let mut err = diag.struct_span_err( span, "positional arguments cannot follow named arguments \ or explicit register arguments", @@ -264,21 +265,21 @@ fn parse_args<'a>( && args.options.contains(ast::InlineAsmOptions::READONLY) { let spans = args.options_spans.clone(); - ecx.struct_span_err(spans, "the `nomem` and `readonly` options are mutually exclusive") + diag.struct_span_err(spans, "the `nomem` and `readonly` options are mutually exclusive") .emit(); } if args.options.contains(ast::InlineAsmOptions::PURE) && args.options.contains(ast::InlineAsmOptions::NORETURN) { let spans = args.options_spans.clone(); - ecx.struct_span_err(spans, "the `pure` and `noreturn` options are mutually exclusive") + diag.struct_span_err(spans, "the `pure` and `noreturn` options are mutually exclusive") .emit(); } if args.options.contains(ast::InlineAsmOptions::PURE) && !args.options.intersects(ast::InlineAsmOptions::NOMEM | ast::InlineAsmOptions::READONLY) { let spans = args.options_spans.clone(); - ecx.struct_span_err( + diag.struct_span_err( spans, "the `pure` option must be combined with either `nomem` or `readonly`", ) @@ -309,14 +310,14 @@ fn parse_args<'a>( } } if args.options.contains(ast::InlineAsmOptions::PURE) && !have_real_output { - ecx.struct_span_err( + diag.struct_span_err( args.options_spans.clone(), "asm with the `pure` option must have at least one output", ) .emit(); } if args.options.contains(ast::InlineAsmOptions::NORETURN) && !outputs_sp.is_empty() { - let err = ecx + let err = diag .struct_span_err(outputs_sp, "asm outputs are not allowed with the `noreturn` option"); // Bail out now since this is likely to confuse MIR @@ -325,7 +326,7 @@ fn parse_args<'a>( if args.clobber_abis.len() > 0 { if is_global_asm { - let err = ecx.struct_span_err( + let err = diag.struct_span_err( args.clobber_abis.iter().map(|(_, span)| *span).collect::>(), "`clobber_abi` cannot be used with `global_asm!`", ); @@ -334,7 +335,7 @@ fn parse_args<'a>( return Err(err); } if !regclass_outputs.is_empty() { - ecx.struct_span_err( + diag.struct_span_err( regclass_outputs.clone(), "asm with `clobber_abi` must specify explicit registers for outputs", ) @@ -420,6 +421,8 @@ fn parse_options<'a>( try_set_option(p, args, sym::att_syntax, ast::InlineAsmOptions::ATT_SYNTAX); } else if p.eat_keyword(kw::Raw) { try_set_option(p, args, kw::Raw, ast::InlineAsmOptions::RAW); + } else if p.eat_keyword(sym::may_unwind) { + try_set_option(p, args, kw::Raw, ast::InlineAsmOptions::MAY_UNWIND); } else { return p.unexpected(); } @@ -570,7 +573,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option Span { @@ -710,7 +713,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option Some(idx), None => { let msg = format!("there is no argument named `{}`", name); - ecx.struct_span_err(span, &msg[..]).emit(); + ecx.struct_span_err(span, &msg).emit(); None } }, @@ -806,7 +809,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option( +pub(super) fn expand_asm<'cx>( ecx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, @@ -833,7 +836,7 @@ pub fn expand_asm<'cx>( } } -pub fn expand_global_asm<'cx>( +pub(super) fn expand_global_asm<'cx>( ecx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs index 1e2646e4d3..9a45dec55f 100644 --- a/compiler/rustc_builtin_macros/src/assert.rs +++ b/compiler/rustc_builtin_macros/src/assert.rs @@ -1,4 +1,4 @@ -use crate::panic::use_panic_2021; +use crate::edition_panic::use_panic_2021; use rustc_ast::ptr::P; use rustc_ast::token; use rustc_ast::tokenstream::{DelimSpan, TokenStream}; diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index 307730f7f5..31086a2acf 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -1,4 +1,4 @@ -use crate::util::check_builtin_macro_attribute; +use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute}; use rustc_ast as ast; use rustc_ast::mut_visit::MutVisitor; @@ -11,7 +11,7 @@ use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_expand::config::StripUnconfigured; use rustc_expand::configure; use rustc_feature::Features; -use rustc_parse::parser::ForceCollect; +use rustc_parse::parser::{ForceCollect, Parser}; use rustc_session::utils::FlattenNonterminals; use rustc_session::Session; use rustc_span::symbol::sym; @@ -25,6 +25,7 @@ crate fn expand( annotatable: Annotatable, ) -> Vec { check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval); + warn_on_duplicate_attribute(&ecx, &annotatable, sym::cfg_eval); vec![cfg_eval(ecx.sess, ecx.ecfg.features, annotatable)] } @@ -77,6 +78,10 @@ fn flat_map_annotatable( Annotatable::Param(param) => vis.flat_map_param(param).pop().map(Annotatable::Param), Annotatable::FieldDef(sf) => vis.flat_map_field_def(sf).pop().map(Annotatable::FieldDef), Annotatable::Variant(v) => vis.flat_map_variant(v).pop().map(Annotatable::Variant), + Annotatable::Crate(mut krate) => { + vis.visit_crate(&mut krate); + Some(Annotatable::Crate(krate)) + } } } @@ -101,6 +106,7 @@ impl CfgFinder { Annotatable::Param(param) => finder.visit_param(¶m), Annotatable::FieldDef(field) => finder.visit_field_def(&field), Annotatable::Variant(variant) => finder.visit_variant(&variant), + Annotatable::Crate(krate) => finder.visit_crate(krate), }; finder.has_cfg_or_cfg_attr } @@ -138,8 +144,34 @@ impl CfgEval<'_, '_> { // the location of `#[cfg]` and `#[cfg_attr]` in the token stream. The tokenization // process is lossless, so this process is invisible to proc-macros. - // FIXME - get rid of this clone - let nt = annotatable.clone().into_nonterminal(); + let parse_annotatable_with: fn(&mut Parser<'_>) -> _ = match annotatable { + Annotatable::Item(_) => { + |parser| Annotatable::Item(parser.parse_item(ForceCollect::Yes).unwrap().unwrap()) + } + Annotatable::TraitItem(_) => |parser| { + Annotatable::TraitItem( + parser.parse_trait_item(ForceCollect::Yes).unwrap().unwrap().unwrap(), + ) + }, + Annotatable::ImplItem(_) => |parser| { + Annotatable::ImplItem( + parser.parse_impl_item(ForceCollect::Yes).unwrap().unwrap().unwrap(), + ) + }, + Annotatable::ForeignItem(_) => |parser| { + Annotatable::ForeignItem( + parser.parse_foreign_item(ForceCollect::Yes).unwrap().unwrap().unwrap(), + ) + }, + Annotatable::Stmt(_) => |parser| { + Annotatable::Stmt(P(parser.parse_stmt(ForceCollect::Yes).unwrap().unwrap())) + }, + Annotatable::Expr(_) => { + |parser| Annotatable::Expr(parser.parse_expr_force_collect().unwrap()) + } + _ => unreachable!(), + }; + let nt = annotatable.into_nonterminal(); let mut orig_tokens = rustc_parse::nt_to_tokenstream( &nt, @@ -173,25 +205,7 @@ impl CfgEval<'_, '_> { let mut parser = rustc_parse::stream_to_parser(&self.cfg.sess.parse_sess, orig_tokens, None); parser.capture_cfg = true; - annotatable = match annotatable { - Annotatable::Item(_) => { - Annotatable::Item(parser.parse_item(ForceCollect::Yes).unwrap().unwrap()) - } - Annotatable::TraitItem(_) => Annotatable::TraitItem( - parser.parse_trait_item(ForceCollect::Yes).unwrap().unwrap().unwrap(), - ), - Annotatable::ImplItem(_) => Annotatable::ImplItem( - parser.parse_impl_item(ForceCollect::Yes).unwrap().unwrap().unwrap(), - ), - Annotatable::ForeignItem(_) => Annotatable::ForeignItem( - parser.parse_foreign_item(ForceCollect::Yes).unwrap().unwrap().unwrap(), - ), - Annotatable::Stmt(_) => { - Annotatable::Stmt(P(parser.parse_stmt(ForceCollect::Yes).unwrap().unwrap())) - } - Annotatable::Expr(_) => Annotatable::Expr(parser.parse_expr_force_collect().unwrap()), - _ => unreachable!(), - }; + annotatable = parse_annotatable_with(&mut parser); // Now that we have our re-parsed `AttrAnnotatedTokenStream`, recursively configuring // our attribute target will correctly the tokens as well. diff --git a/compiler/rustc_builtin_macros/src/concat.rs b/compiler/rustc_builtin_macros/src/concat.rs index e5077d9367..59361510a6 100644 --- a/compiler/rustc_builtin_macros/src/concat.rs +++ b/compiler/rustc_builtin_macros/src/concat.rs @@ -21,7 +21,7 @@ pub fn expand_concat( match e.kind { ast::ExprKind::Lit(ref lit) => match lit.kind { ast::LitKind::Str(ref s, _) | ast::LitKind::Float(ref s, _) => { - accumulator.push_str(&s.as_str()); + accumulator.push_str(s.as_str()); } ast::LitKind::Char(c) => { accumulator.push(c); diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs new file mode 100644 index 0000000000..eb08170959 --- /dev/null +++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs @@ -0,0 +1,192 @@ +use rustc_ast as ast; +use rustc_ast::{ptr::P, tokenstream::TokenStream}; +use rustc_data_structures::sync::Lrc; +use rustc_errors::Applicability; +use rustc_expand::base::{self, DummyResult}; + +/// Emits errors for literal expressions that are invalid inside and outside of an array. +fn invalid_type_err(cx: &mut base::ExtCtxt<'_>, expr: &P, is_nested: bool) { + let lit = if let ast::ExprKind::Lit(lit) = &expr.kind { + lit + } else { + unreachable!(); + }; + match lit.kind { + ast::LitKind::Char(_) => { + let mut err = cx.struct_span_err(expr.span, "cannot concatenate character literals"); + if let Ok(snippet) = cx.sess.source_map().span_to_snippet(expr.span) { + err.span_suggestion( + expr.span, + "try using a byte character", + format!("b{}", snippet), + Applicability::MachineApplicable, + ) + .emit(); + } + } + ast::LitKind::Str(_, _) => { + let mut err = cx.struct_span_err(expr.span, "cannot concatenate string literals"); + // suggestion would be invalid if we are nested + if !is_nested { + if let Ok(snippet) = cx.sess.source_map().span_to_snippet(expr.span) { + err.span_suggestion( + expr.span, + "try using a byte string", + format!("b{}", snippet), + Applicability::MachineApplicable, + ); + } + } + err.emit(); + } + ast::LitKind::Float(_, _) => { + cx.span_err(expr.span, "cannot concatenate float literals"); + } + ast::LitKind::Bool(_) => { + cx.span_err(expr.span, "cannot concatenate boolean literals"); + } + ast::LitKind::Err(_) => {} + ast::LitKind::Int(_, _) if !is_nested => { + let mut err = cx.struct_span_err(expr.span, "cannot concatenate numeric literals"); + if let Ok(snippet) = cx.sess.source_map().span_to_snippet(expr.span) { + err.span_suggestion( + expr.span, + "try wrapping the number in an array", + format!("[{}]", snippet), + Applicability::MachineApplicable, + ); + } + err.emit(); + } + ast::LitKind::Int( + val, + ast::LitIntType::Unsuffixed | ast::LitIntType::Unsigned(ast::UintTy::U8), + ) => { + assert!(val > u8::MAX.into()); // must be an error + cx.span_err(expr.span, "numeric literal is out of bounds"); + } + ast::LitKind::Int(_, _) => { + cx.span_err(expr.span, "numeric literal is not a `u8`"); + } + _ => unreachable!(), + } +} + +fn handle_array_element( + cx: &mut base::ExtCtxt<'_>, + has_errors: &mut bool, + missing_literals: &mut Vec, + expr: &P, +) -> Option { + match expr.kind { + ast::ExprKind::Array(_) | ast::ExprKind::Repeat(_, _) => { + if !*has_errors { + cx.span_err(expr.span, "cannot concatenate doubly nested array"); + } + *has_errors = true; + None + } + ast::ExprKind::Lit(ref lit) => match lit.kind { + ast::LitKind::Int( + val, + ast::LitIntType::Unsuffixed | ast::LitIntType::Unsigned(ast::UintTy::U8), + ) if val <= u8::MAX.into() => Some(val as u8), + + ast::LitKind::Byte(val) => Some(val), + ast::LitKind::ByteStr(_) => { + if !*has_errors { + cx.struct_span_err(expr.span, "cannot concatenate doubly nested array") + .note("byte strings are treated as arrays of bytes") + .help("try flattening the array") + .emit(); + } + *has_errors = true; + None + } + _ => { + if !*has_errors { + invalid_type_err(cx, expr, true); + } + *has_errors = true; + None + } + }, + _ => { + missing_literals.push(expr.span); + None + } + } +} + +pub fn expand_concat_bytes( + cx: &mut base::ExtCtxt<'_>, + sp: rustc_span::Span, + tts: TokenStream, +) -> Box { + let es = match base::get_exprs_from_tts(cx, sp, tts) { + Some(e) => e, + None => return DummyResult::any(sp), + }; + let mut accumulator = Vec::new(); + let mut missing_literals = vec![]; + let mut has_errors = false; + for e in es { + match e.kind { + ast::ExprKind::Array(ref exprs) => { + for expr in exprs { + if let Some(elem) = + handle_array_element(cx, &mut has_errors, &mut missing_literals, expr) + { + accumulator.push(elem); + } + } + } + ast::ExprKind::Repeat(ref expr, ref count) => { + if let ast::ExprKind::Lit(ast::Lit { + kind: ast::LitKind::Int(count_val, _), .. + }) = count.value.kind + { + if let Some(elem) = + handle_array_element(cx, &mut has_errors, &mut missing_literals, expr) + { + for _ in 0..count_val { + accumulator.push(elem); + } + } + } else { + cx.span_err(count.value.span, "repeat count is not a positive number"); + } + } + ast::ExprKind::Lit(ref lit) => match lit.kind { + ast::LitKind::Byte(val) => { + accumulator.push(val); + } + ast::LitKind::ByteStr(ref bytes) => { + accumulator.extend_from_slice(&bytes); + } + _ => { + if !has_errors { + invalid_type_err(cx, &e, false); + } + has_errors = true; + } + }, + ast::ExprKind::Err => { + has_errors = true; + } + _ => { + missing_literals.push(e.span); + } + } + } + if !missing_literals.is_empty() { + let mut err = cx.struct_span_err(missing_literals.clone(), "expected a byte literal"); + err.note("only byte literals (like `b\"foo\"`, `b's'`, and `[3, 4, 5]`) can be passed to `concat_bytes!()`"); + err.emit(); + return base::MacEager::expr(DummyResult::raw_expr(sp, true)); + } else if has_errors { + return base::MacEager::expr(DummyResult::raw_expr(sp, true)); + } + let sp = cx.with_def_site_ctxt(sp); + base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(Lrc::from(accumulator)))) +} diff --git a/compiler/rustc_builtin_macros/src/concat_idents.rs b/compiler/rustc_builtin_macros/src/concat_idents.rs index 53a456b69a..239bafb266 100644 --- a/compiler/rustc_builtin_macros/src/concat_idents.rs +++ b/compiler/rustc_builtin_macros/src/concat_idents.rs @@ -29,7 +29,7 @@ pub fn expand_concat_idents<'cx>( } else { if let TokenTree::Token(token) = e { if let Some((ident, _)) = token.ident() { - res_str.push_str(&ident.name.as_str()); + res_str.push_str(ident.name.as_str()); continue; } } diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index 31a35b9b7b..47d7b6c259 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -121,7 +121,7 @@ fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool { fn report_unexpected_literal(sess: &Session, lit: &ast::Lit) { let help_msg = match lit.token.kind { - token::Str if rustc_lexer::is_ident(&lit.token.symbol.as_str()) => { + token::Str if rustc_lexer::is_ident(lit.token.symbol.as_str()) => { format!("try using `#[derive({})]`", lit.token.symbol) } _ => "for example, write `#[derive(Debug)]` for `Debug`".to_string(), diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 994a74a5a9..985c45e225 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -567,8 +567,11 @@ impl<'a> TraitDef<'a> { }) }); - let Generics { mut params, mut where_clause, span } = + let Generics { mut params, mut where_clause, .. } = self.generics.to_generics(cx, self.span, type_ident, generics); + where_clause.span = generics.where_clause.span; + let ctxt = self.span.ctxt(); + let span = generics.span.with_ctxt(ctxt); // Create the generic parameters params.extend(generics.params.iter().map(|param| match ¶m.kind { @@ -589,12 +592,12 @@ impl<'a> TraitDef<'a> { param.bounds.iter().cloned() ).collect(); - cx.typaram(self.span, param.ident, vec![], bounds, None) + cx.typaram(param.ident.span.with_ctxt(ctxt), param.ident, vec![], bounds, None) } GenericParamKind::Const { ty, kw_span, .. } => { let const_nodefault_kind = GenericParamKind::Const { ty: ty.clone(), - kw_span: *kw_span, + kw_span: kw_span.with_ctxt(ctxt), // We can't have default values inside impl block default: None, @@ -607,28 +610,27 @@ impl<'a> TraitDef<'a> { // and similarly for where clauses where_clause.predicates.extend(generics.where_clause.predicates.iter().map(|clause| { - match *clause { - ast::WherePredicate::BoundPredicate(ref wb) => { + match clause { + ast::WherePredicate::BoundPredicate(wb) => { + let span = wb.span.with_ctxt(ctxt); ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { - span: self.span, - bound_generic_params: wb.bound_generic_params.clone(), - bounded_ty: wb.bounded_ty.clone(), - bounds: wb.bounds.to_vec(), + span, + ..wb.clone() }) } - ast::WherePredicate::RegionPredicate(ref rb) => { + ast::WherePredicate::RegionPredicate(wr) => { + let span = wr.span.with_ctxt(ctxt); ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { - span: self.span, - lifetime: rb.lifetime, - bounds: rb.bounds.to_vec(), + span, + ..wr.clone() }) } - ast::WherePredicate::EqPredicate(ref we) => { + ast::WherePredicate::EqPredicate(we) => { + let span = we.span.with_ctxt(ctxt); ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { id: ast::DUMMY_NODE_ID, - span: self.span, - lhs_ty: we.lhs_ty.clone(), - rhs_ty: we.rhs_ty.clone(), + span, + ..we.clone() }) } } @@ -691,13 +693,13 @@ impl<'a> TraitDef<'a> { .iter() .map(|param| match param.kind { GenericParamKind::Lifetime { .. } => { - GenericArg::Lifetime(cx.lifetime(self.span, param.ident)) + GenericArg::Lifetime(cx.lifetime(param.ident.span.with_ctxt(ctxt), param.ident)) } GenericParamKind::Type { .. } => { - GenericArg::Type(cx.ty_ident(self.span, param.ident)) + GenericArg::Type(cx.ty_ident(param.ident.span.with_ctxt(ctxt), param.ident)) } GenericParamKind::Const { .. } => { - GenericArg::Const(cx.const_ident(self.span, param.ident)) + GenericArg::Const(cx.const_ident(param.ident.span.with_ctxt(ctxt), param.ident)) } }) .collect(); @@ -764,8 +766,8 @@ impl<'a> TraitDef<'a> { self, struct_def, type_ident, - &self_args[..], - &nonself_args[..], + &self_args, + &nonself_args, ) } else { method_def.expand_struct_method_body( @@ -773,8 +775,8 @@ impl<'a> TraitDef<'a> { self, struct_def, type_ident, - &self_args[..], - &nonself_args[..], + &self_args, + &nonself_args, use_temporaries, ) }; @@ -813,8 +815,8 @@ impl<'a> TraitDef<'a> { self, enum_def, type_ident, - &self_args[..], - &nonself_args[..], + &self_args, + &nonself_args, ) } else { method_def.expand_enum_method_body( @@ -823,7 +825,7 @@ impl<'a> TraitDef<'a> { enum_def, type_ident, self_args, - &nonself_args[..], + &nonself_args, ) }; @@ -845,16 +847,17 @@ impl<'a> MethodDef<'a> { nonself_args: &[P], fields: &SubstructureFields<'_>, ) -> P { + let span = trait_.span; let substructure = Substructure { type_ident, - method_ident: Ident::new(self.name, trait_.span), + method_ident: Ident::new(self.name, span), self_args, nonself_args, fields, }; let mut f = self.combine_substructure.borrow_mut(); let f: &mut CombineSubstructureFunc<'_> = &mut *f; - f(cx, trait_.span, &substructure) + f(cx, span, &substructure) } fn get_ret_ty( @@ -882,9 +885,10 @@ impl<'a> MethodDef<'a> { let mut nonself_args = Vec::new(); let mut arg_tys = Vec::new(); let mut nonstatic = false; + let span = trait_.span; let ast_explicit_self = self.explicit_self.as_ref().map(|self_ptr| { - let (self_expr, explicit_self) = ty::get_explicit_self(cx, trait_.span, self_ptr); + let (self_expr, explicit_self) = ty::get_explicit_self(cx, span, self_ptr); self_args.push(self_expr); nonstatic = true; @@ -893,11 +897,11 @@ impl<'a> MethodDef<'a> { }); for (ty, name) in self.args.iter() { - let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics); - let ident = Ident::new(*name, trait_.span); + let ast_ty = ty.to_ty(cx, span, type_ident, generics); + let ident = Ident::new(*name, span); arg_tys.push((ident, ast_ty)); - let arg_expr = cx.expr_ident(trait_.span, ident); + let arg_expr = cx.expr_ident(span, ident); match *ty { // for static methods, just treat any Self @@ -906,7 +910,7 @@ impl<'a> MethodDef<'a> { self_args.push(arg_expr); } Ptr(ref ty, _) if matches!(**ty, Self_) && nonstatic => { - self_args.push(cx.expr_deref(trait_.span, arg_expr)) + self_args.push(cx.expr_deref(span, arg_expr)) } _ => { nonself_args.push(arg_expr); @@ -927,33 +931,33 @@ impl<'a> MethodDef<'a> { arg_types: Vec<(Ident, P)>, body: P, ) -> P { + let span = trait_.span; // Create the generics that aren't for `Self`. - let fn_generics = self.generics.to_generics(cx, trait_.span, type_ident, generics); + let fn_generics = self.generics.to_generics(cx, span, type_ident, generics); let args = { let self_args = explicit_self.map(|explicit_self| { - let ident = Ident::with_dummy_span(kw::SelfLower).with_span_pos(trait_.span); + let ident = Ident::with_dummy_span(kw::SelfLower).with_span_pos(span); ast::Param::from_self(ast::AttrVec::default(), explicit_self, ident) }); - let nonself_args = - arg_types.into_iter().map(|(name, ty)| cx.param(trait_.span, name, ty)); + let nonself_args = arg_types.into_iter().map(|(name, ty)| cx.param(span, name, ty)); self_args.into_iter().chain(nonself_args).collect() }; let ret_type = self.get_ret_ty(cx, trait_, generics, type_ident); - let method_ident = Ident::new(self.name, trait_.span); + let method_ident = Ident::new(self.name, span); let fn_decl = cx.fn_decl(args, ast::FnRetTy::Ty(ret_type)); let body_block = cx.block_expr(body); - let unsafety = if self.is_unsafe { ast::Unsafe::Yes(trait_.span) } else { ast::Unsafe::No }; + let unsafety = if self.is_unsafe { ast::Unsafe::Yes(span) } else { ast::Unsafe::No }; - let trait_lo_sp = trait_.span.shrink_to_lo(); + let trait_lo_sp = span.shrink_to_lo(); let sig = ast::FnSig { header: ast::FnHeader { unsafety, ext: ast::Extern::None, ..ast::FnHeader::default() }, decl: fn_decl, - span: trait_.span, + span, }; let defaultness = ast::Defaultness::Final; @@ -961,7 +965,7 @@ impl<'a> MethodDef<'a> { P(ast::AssocItem { id: ast::DUMMY_NODE_ID, attrs: self.attributes.clone(), - span: trait_.span, + span, vis: ast::Visibility { span: trait_lo_sp, kind: ast::VisibilityKind::Inherited, @@ -1024,11 +1028,11 @@ impl<'a> MethodDef<'a> { nonself_args: &[P], use_temporaries: bool, ) -> P { - let mut raw_fields = Vec::new(); // Vec<[fields of self], - // [fields of next Self arg], [etc]> + let mut raw_fields = Vec::new(); // Vec<[fields of self], [fields of next Self arg], [etc]> + let span = trait_.span; let mut patterns = Vec::new(); for i in 0..self_args.len() { - let struct_path = cx.path(trait_.span, vec![type_ident]); + let struct_path = cx.path(span, vec![type_ident]); let (pat, ident_expr) = trait_.create_struct_pattern( cx, struct_path, @@ -1048,7 +1052,7 @@ impl<'a> MethodDef<'a> { let mut other_fields: Vec> = raw_fields.collect(); first_field .map(|(span, opt_id, field, attrs)| FieldInfo { - span, + span: span.with_ctxt(trait_.span.ctxt()), name: opt_id, self_: field, other: other_fields @@ -1062,7 +1066,7 @@ impl<'a> MethodDef<'a> { }) .collect() } else { - cx.span_bug(trait_.span, "no `self` parameter for method in generic `derive`") + cx.span_bug(span, "no `self` parameter for method in generic `derive`") }; // body of the inner most destructuring match @@ -1079,11 +1083,7 @@ impl<'a> MethodDef<'a> { // structs. This is actually right-to-left, but it shouldn't // matter. for (arg_expr, pat) in iter::zip(self_args, patterns) { - body = cx.expr_match( - trait_.span, - arg_expr.clone(), - vec![cx.arm(trait_.span, pat.clone(), body)], - ) + body = cx.expr_match(span, arg_expr.clone(), vec![cx.arm(span, pat.clone(), body)]) } body @@ -1193,7 +1193,7 @@ impl<'a> MethodDef<'a> { mut self_args: Vec>, nonself_args: &[P], ) -> P { - let sp = trait_.span; + let span = trait_.span; let variants = &enum_def.variants; let self_arg_names = iter::once("__self".to_string()) @@ -1208,7 +1208,7 @@ impl<'a> MethodDef<'a> { let self_arg_idents = self_arg_names .iter() - .map(|name| Ident::from_str_and_span(name, sp)) + .map(|name| Ident::from_str_and_span(name, span)) .collect::>(); // The `vi_idents` will be bound, solely in the catch-all, to @@ -1217,8 +1217,8 @@ impl<'a> MethodDef<'a> { let vi_idents = self_arg_names .iter() .map(|name| { - let vi_suffix = format!("{}_vi", &name[..]); - Ident::from_str_and_span(&vi_suffix, trait_.span) + let vi_suffix = format!("{}_vi", name); + Ident::from_str_and_span(&vi_suffix, span) }) .collect::>(); @@ -1226,7 +1226,7 @@ impl<'a> MethodDef<'a> { // delegated expression that handles the catch-all case, // using `__variants_tuple` to drive logic if necessary. let catch_all_substructure = - EnumNonMatchingCollapsed(self_arg_idents, &variants[..], &vi_idents[..]); + EnumNonMatchingCollapsed(self_arg_idents, &variants, &vi_idents); let first_fieldless = variants.iter().find(|v| v.data.fields().is_empty()); @@ -1248,7 +1248,7 @@ impl<'a> MethodDef<'a> { self_arg_name, ast::Mutability::Not, ); - (cx.pat(sp, PatKind::Ref(p, ast::Mutability::Not)), idents) + (cx.pat(span, PatKind::Ref(p, ast::Mutability::Not)), idents) }; // A single arm has form (&VariantK, &VariantK, ...) => BodyK @@ -1261,13 +1261,13 @@ impl<'a> MethodDef<'a> { idents }; for self_arg_name in &self_arg_names[1..] { - let (p, idents) = mk_self_pat(cx, &self_arg_name[..]); + let (p, idents) = mk_self_pat(cx, &self_arg_name); subpats.push(p); self_pats_idents.push(idents); } // Here is the pat = `(&VariantK, &VariantK, ...)` - let single_pat = cx.pat_tuple(sp, subpats); + let single_pat = cx.pat_tuple(span, subpats); // For the BodyK, we need to delegate to our caller, // passing it an EnumMatching to indicate which case @@ -1284,7 +1284,7 @@ impl<'a> MethodDef<'a> { .into_iter() .enumerate() // For each arg field of self, pull out its getter expr ... - .map(|(field_index, (sp, opt_ident, self_getter_expr, attrs))| { + .map(|(field_index, (span, opt_ident, self_getter_expr, attrs))| { // ... but FieldInfo also wants getter expr // for matching other arguments of Self type; // so walk across the *other* self_pats_idents @@ -1307,7 +1307,7 @@ impl<'a> MethodDef<'a> { .collect::>>(); FieldInfo { - span: sp, + span, name: opt_ident, self_: self_getter_expr, other: others, @@ -1330,7 +1330,7 @@ impl<'a> MethodDef<'a> { &substructure, ); - cx.arm(sp, single_pat, arm_expr) + cx.arm(span, single_pat, arm_expr) }) .collect(); @@ -1353,12 +1353,12 @@ impl<'a> MethodDef<'a> { // Since we know that all the arguments will match if we reach // the match expression we add the unreachable intrinsics as the // result of the catch all which should help llvm in optimizing it - Some(deriving::call_unreachable(cx, sp)) + Some(deriving::call_unreachable(cx, span)) } _ => None, }; if let Some(arm) = default { - match_arms.push(cx.arm(sp, cx.pat_wild(sp), arm)); + match_arms.push(cx.arm(span, cx.pat_wild(span), arm)); } // We will usually need the catch-all after matching the @@ -1392,23 +1392,23 @@ impl<'a> MethodDef<'a> { // We also build an expression which checks whether all discriminants are equal // discriminant_test = __self0_vi == __self1_vi && __self0_vi == __self2_vi && ... - let mut discriminant_test = cx.expr_bool(sp, true); + let mut discriminant_test = cx.expr_bool(span, true); let mut first_ident = None; for (&ident, self_arg) in iter::zip(&vi_idents, &self_args) { - let self_addr = cx.expr_addr_of(sp, self_arg.clone()); + let self_addr = cx.expr_addr_of(span, self_arg.clone()); let variant_value = - deriving::call_intrinsic(cx, sp, sym::discriminant_value, vec![self_addr]); - let let_stmt = cx.stmt_let(sp, false, ident, variant_value); + deriving::call_intrinsic(cx, span, sym::discriminant_value, vec![self_addr]); + let let_stmt = cx.stmt_let(span, false, ident, variant_value); index_let_stmts.push(let_stmt); match first_ident { Some(first) => { - let first_expr = cx.expr_ident(sp, first); - let id = cx.expr_ident(sp, ident); - let test = cx.expr_binary(sp, BinOpKind::Eq, first_expr, id); + let first_expr = cx.expr_ident(span, first); + let id = cx.expr_ident(span, ident); + let test = cx.expr_binary(span, BinOpKind::Eq, first_expr, id); discriminant_test = - cx.expr_binary(sp, BinOpKind::And, discriminant_test, test) + cx.expr_binary(span, BinOpKind::And, discriminant_test, test) } None => { first_ident = Some(ident); @@ -1430,8 +1430,8 @@ impl<'a> MethodDef<'a> { // them when they are fed as r-values into a tuple // expression; here add a layer of borrowing, turning // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`. - self_args.map_in_place(|self_arg| cx.expr_addr_of(sp, self_arg)); - let match_arg = cx.expr(sp, ast::ExprKind::Tup(self_args)); + self_args.map_in_place(|self_arg| cx.expr_addr_of(span, self_arg)); + let match_arg = cx.expr(span, ast::ExprKind::Tup(self_args)); // Lastly we create an expression which branches on all discriminants being equal // if discriminant_test { @@ -1445,10 +1445,10 @@ impl<'a> MethodDef<'a> { // else { // // } - let all_match = cx.expr_match(sp, match_arg, match_arms); - let arm_expr = cx.expr_if(sp, discriminant_test, all_match, Some(arm_expr)); + let all_match = cx.expr_match(span, match_arg, match_arms); + let arm_expr = cx.expr_if(span, discriminant_test, all_match, Some(arm_expr)); index_let_stmts.push(cx.stmt_expr(arm_expr)); - cx.expr_block(cx.block(sp, index_let_stmts)) + cx.expr_block(cx.block(span, index_let_stmts)) } else if variants.is_empty() { // As an additional wrinkle, For a zero-variant enum A, // currently the compiler @@ -1499,16 +1499,16 @@ impl<'a> MethodDef<'a> { // derive Debug on such a type could here generate code // that needs the feature gate enabled.) - deriving::call_unreachable(cx, sp) + deriving::call_unreachable(cx, span) } else { // Final wrinkle: the self_args are expressions that deref // down to desired places, but we cannot actually deref // them when they are fed as r-values into a tuple // expression; here add a layer of borrowing, turning // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`. - self_args.map_in_place(|self_arg| cx.expr_addr_of(sp, self_arg)); - let match_arg = cx.expr(sp, ast::ExprKind::Tup(self_args)); - cx.expr_match(sp, match_arg, match_arms) + self_args.map_in_place(|self_arg| cx.expr_addr_of(span, self_arg)); + let match_arg = cx.expr(span, ast::ExprKind::Tup(self_args)); + cx.expr_match(span, match_arg, match_arms) } } @@ -1556,11 +1556,9 @@ impl<'a> TraitDef<'a> { let is_tuple = matches!(struct_def, ast::VariantData::Tuple(..)); match (just_spans.is_empty(), named_idents.is_empty()) { - (false, false) => cx.span_bug( - self.span, - "a struct with named and unnamed \ - fields in generic `derive`", - ), + (false, false) => { + cx.span_bug(self.span, "a struct with named and unnamed fields in generic `derive`") + } // named fields (_, false) => Named(named_idents), // unnamed fields diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs index 00d75be439..7a41800325 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs @@ -211,14 +211,6 @@ fn mk_ty_param( cx.typaram(span, Ident::new(name, span), attrs.to_owned(), bounds, None) } -fn mk_generics(params: Vec, span: Span) -> Generics { - Generics { - params, - where_clause: ast::WhereClause { has_where_token: false, predicates: Vec::new(), span }, - span, - } -} - /// Bounds on type parameters. #[derive(Clone)] pub struct Bounds { @@ -236,7 +228,7 @@ impl Bounds { self_ty: Ident, self_generics: &Generics, ) -> Generics { - let generic_params = self + let params = self .bounds .iter() .map(|t| { @@ -245,7 +237,11 @@ impl Bounds { }) .collect(); - mk_generics(generic_params, span) + Generics { + params, + where_clause: ast::WhereClause { has_where_token: false, predicates: Vec::new(), span }, + span, + } } } diff --git a/compiler/rustc_builtin_macros/src/panic.rs b/compiler/rustc_builtin_macros/src/edition_panic.rs similarity index 73% rename from compiler/rustc_builtin_macros/src/panic.rs rename to compiler/rustc_builtin_macros/src/edition_panic.rs index 54ab596bf3..518b88dec6 100644 --- a/compiler/rustc_builtin_macros/src/panic.rs +++ b/compiler/rustc_builtin_macros/src/edition_panic.rs @@ -20,8 +20,29 @@ pub fn expand_panic<'cx>( sp: Span, tts: TokenStream, ) -> Box { - let panic = if use_panic_2021(sp) { sym::panic_2021 } else { sym::panic_2015 }; + let mac = if use_panic_2021(sp) { sym::panic_2021 } else { sym::panic_2015 }; + expand(mac, cx, sp, tts) +} +// This expands to either +// - `$crate::panic::unreachable_2015!(...)` or +// - `$crate::panic::unreachable_2021!(...)` +// depending on the edition. +pub fn expand_unreachable<'cx>( + cx: &'cx mut ExtCtxt<'_>, + sp: Span, + tts: TokenStream, +) -> Box { + let mac = if use_panic_2021(sp) { sym::unreachable_2021 } else { sym::unreachable_2015 }; + expand(mac, cx, sp, tts) +} + +fn expand<'cx>( + mac: rustc_span::Symbol, + cx: &'cx mut ExtCtxt<'_>, + sp: Span, + tts: TokenStream, +) -> Box { let sp = cx.with_call_site_ctxt(sp); MacEager::expr( @@ -31,7 +52,7 @@ pub fn expand_panic<'cx>( path: Path { span: sp, segments: cx - .std_path(&[sym::panic, panic]) + .std_path(&[sym::panic, mac]) .into_iter() .map(|ident| PathSegment::from_ident(ident)) .collect(), diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs index 6de12acfb9..285027fc63 100644 --- a/compiler/rustc_builtin_macros/src/env.rs +++ b/compiler/rustc_builtin_macros/src/env.rs @@ -80,11 +80,11 @@ pub fn expand_env<'cx>( } let sp = cx.with_def_site_ctxt(sp); - let value = env::var(&*var.as_str()).ok().as_deref().map(Symbol::intern); + let value = env::var(var.as_str()).ok().as_deref().map(Symbol::intern); cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value)); let e = match value { None => { - cx.span_err(sp, &msg.as_str()); + cx.span_err(sp, msg.as_str()); return DummyResult::any(sp); } Some(value) => cx.expr_str(sp, value), diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 097eaddb87..154c51b2c7 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -23,6 +23,7 @@ enum ArgumentType { enum Position { Exact(usize), + Capture(usize), Named(Symbol), } @@ -47,6 +48,8 @@ struct Context<'a, 'b> { /// * `arg_unique_types` (in simplified JSON): `[["o", "x"], ["o", "x"], ["o", "x"]]` /// * `names` (in JSON): `{"foo": 2}` args: Vec>, + /// The number of arguments that were added by implicit capturing. + num_captured_args: usize, /// Placeholder slot numbers indexed by argument. arg_types: Vec>, /// Unique format specs seen for each argument. @@ -88,8 +91,8 @@ struct Context<'a, 'b> { /// * Implicit argument resolution: `"{1:.0$} {2:.foo$} {1:.3$} {4:.0$}"` /// * Name resolution: `"{1:.0$} {2:.5$} {1:.3$} {4:.0$}"` /// * `count_positions` (in JSON): `{0: 0, 5: 1, 3: 2}` - /// * `count_args`: `vec![Exact(0), Exact(5), Exact(3)]` - count_args: Vec, + /// * `count_args`: `vec![0, 5, 3]` + count_args: Vec, /// Relative slot numbers for count arguments. count_positions: FxHashMap, /// Number of count slots assigned. @@ -229,6 +232,11 @@ fn parse_args<'a>( } impl<'a, 'b> Context<'a, 'b> { + /// The number of arguments that were explicitly given. + fn num_args(&self) -> usize { + self.args.len() - self.num_captured_args + } + fn resolve_name_inplace(&self, p: &mut parse::Piece<'_>) { // NOTE: the `unwrap_or` branch is needed in case of invalid format // arguments, e.g., `format_args!("{foo}")`. @@ -343,7 +351,7 @@ impl<'a, 'b> Context<'a, 'b> { } fn describe_num_args(&self) -> Cow<'_, str> { - match self.args.len() { + match self.num_args() { 0 => "no arguments were given".into(), 1 => "there is 1 argument".into(), x => format!("there are {} arguments", x).into(), @@ -369,7 +377,7 @@ impl<'a, 'b> Context<'a, 'b> { let count = self.pieces.len() + self.arg_with_formatting.iter().filter(|fmt| fmt.precision_span.is_some()).count(); - if self.names.is_empty() && !numbered_position_args && count != self.args.len() { + if self.names.is_empty() && !numbered_position_args && count != self.num_args() { e = self.ecx.struct_span_err( sp, &format!( @@ -417,7 +425,7 @@ impl<'a, 'b> Context<'a, 'b> { if let Some(span) = fmt.precision_span { let span = self.fmtsp.from_inner(span); match fmt.precision { - parse::CountIsParam(pos) if pos > self.args.len() => { + parse::CountIsParam(pos) if pos > self.num_args() => { e.span_label( span, &format!( @@ -460,7 +468,7 @@ impl<'a, 'b> Context<'a, 'b> { if let Some(span) = fmt.width_span { let span = self.fmtsp.from_inner(span); match fmt.width { - parse::CountIsParam(pos) if pos > self.args.len() => { + parse::CountIsParam(pos) if pos > self.num_args() => { e.span_label( span, &format!( @@ -492,12 +500,15 @@ impl<'a, 'b> Context<'a, 'b> { /// Actually verifies and tracks a given format placeholder /// (a.k.a. argument). fn verify_arg_type(&mut self, arg: Position, ty: ArgumentType) { + if let Exact(arg) = arg { + if arg >= self.num_args() { + self.invalid_refs.push((arg, self.curpiece)); + return; + } + } + match arg { - Exact(arg) => { - if self.args.len() <= arg { - self.invalid_refs.push((arg, self.curpiece)); - return; - } + Exact(arg) | Capture(arg) => { match ty { Placeholder(_) => { // record every (position, type) combination only once @@ -513,7 +524,7 @@ impl<'a, 'b> Context<'a, 'b> { if let Entry::Vacant(e) = self.count_positions.entry(arg) { let i = self.count_positions_count; e.insert(i); - self.count_args.push(Exact(arg)); + self.count_args.push(arg); self.count_positions_count += 1; } } @@ -524,7 +535,7 @@ impl<'a, 'b> Context<'a, 'b> { match self.names.get(&name) { Some(&idx) => { // Treat as positional arg. - self.verify_arg_type(Exact(idx), ty) + self.verify_arg_type(Capture(idx), ty) } None => { // For the moment capturing variables from format strings expanded from macros is @@ -539,9 +550,10 @@ impl<'a, 'b> Context<'a, 'b> { } else { self.fmtsp }; + self.num_captured_args += 1; self.args.push(self.ecx.expr_ident(span, Ident::new(name, span))); self.names.insert(name, idx); - self.verify_arg_type(Exact(idx), ty) + self.verify_arg_type(Capture(idx), ty) } else { let msg = format!("there is no argument named `{}`", name); let sp = if self.is_literal { @@ -549,7 +561,7 @@ impl<'a, 'b> Context<'a, 'b> { } else { self.fmtsp }; - let mut err = self.ecx.struct_span_err(sp, &msg[..]); + let mut err = self.ecx.struct_span_err(sp, &msg); err.note(&format!( "did you intend to capture a variable `{}` from \ @@ -769,13 +781,12 @@ impl<'a, 'b> Context<'a, 'b> { for arg_ty in self.arg_unique_types[i].iter() { args.push(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty, i)); } - heads.push(self.ecx.expr_addr_of(e.span, e)); + // use the arg span for `&arg` so that borrowck errors + // point to the specific expression passed to the macro + // (the span is otherwise unavailable in MIR) + heads.push(self.ecx.expr_addr_of(e.span.with_ctxt(self.macsp.ctxt()), e)); } - for pos in self.count_args { - let index = match pos { - Exact(i) => i, - _ => panic!("should never happen"), - }; + for index in self.count_args { let span = spans_pos[index]; args.push(Context::format_arg(self.ecx, self.macsp, span, &Count, index)); } @@ -956,7 +967,7 @@ pub fn expand_preparsed_format_args( ast::StrStyle::Raw(raw) => Some(raw as usize), }; - let fmt_str = &fmt_str.as_str(); // for the suggestions below + let fmt_str = fmt_str.as_str(); // for the suggestions below let fmt_snippet = ecx.source_map().span_to_snippet(fmt_sp).ok(); let mut parser = parse::Parser::new( fmt_str, @@ -996,8 +1007,9 @@ pub fn expand_preparsed_format_args( e.note(¬e); } if let Some((label, span)) = err.secondary_label { - let sp = fmt_span.from_inner(span); - e.span_label(sp, label); + if efmt_kind_is_lit { + e.span_label(fmt_span.from_inner(span), label); + } } e.emit(); return DummyResult::raw_expr(sp, true); @@ -1010,6 +1022,7 @@ pub fn expand_preparsed_format_args( let mut cx = Context { ecx, args, + num_captured_args: 0, arg_types, arg_unique_types, names, diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs index bfddd7073f..ecd16736e7 100644 --- a/compiler/rustc_builtin_macros/src/format_foreign.rs +++ b/compiler/rustc_builtin_macros/src/format_foreign.rs @@ -7,28 +7,29 @@ pub(crate) mod printf { pub enum Substitution<'a> { /// A formatted output substitution with its internal byte offset. Format(Format<'a>), - /// A literal `%%` escape. - Escape, + /// A literal `%%` escape, with its start and end indices. + Escape((usize, usize)), } impl<'a> Substitution<'a> { pub fn as_str(&self) -> &str { match *self { Substitution::Format(ref fmt) => fmt.span, - Substitution::Escape => "%%", + Substitution::Escape(_) => "%%", } } pub fn position(&self) -> Option { match *self { Substitution::Format(ref fmt) => Some(fmt.position), - _ => None, + Substitution::Escape((start, end)) => Some(InnerSpan::new(start, end)), } } pub fn set_position(&mut self, start: usize, end: usize) { - if let Substitution::Format(ref mut fmt) = self { - fmt.position = InnerSpan::new(start, end); + match self { + Substitution::Format(ref mut fmt) => fmt.position = InnerSpan::new(start, end), + Substitution::Escape(ref mut pos) => *pos = (start, end), } } @@ -39,7 +40,7 @@ pub(crate) mod printf { pub fn translate(&self) -> Result> { match *self { Substitution::Format(ref fmt) => fmt.translate(), - Substitution::Escape => Err(None), + Substitution::Escape(_) => Err(None), } } } @@ -304,14 +305,9 @@ pub(crate) mod printf { fn next(&mut self) -> Option { let (mut sub, tail) = parse_next_substitution(self.s)?; self.s = tail; - match sub { - Substitution::Format(_) => { - if let Some(inner_span) = sub.position() { - sub.set_position(inner_span.start + self.pos, inner_span.end + self.pos); - self.pos += inner_span.end; - } - } - Substitution::Escape => self.pos += 2, + if let Some(InnerSpan { start, end }) = sub.position() { + sub.set_position(start + self.pos, end + self.pos); + self.pos += end; } Some(sub) } @@ -340,7 +336,7 @@ pub(crate) mod printf { let at = { let start = s.find('%')?; if let '%' = s[start + 1..].chars().next()? { - return Some((Substitution::Escape, &s[start + 2..])); + return Some((Substitution::Escape((start, start + 2)), &s[start + 2..])); } Cur::new_at(s, start) diff --git a/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs b/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs index 1336aab731..fc7442470a 100644 --- a/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs +++ b/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs @@ -13,9 +13,9 @@ macro_rules! assert_eq_pnsat { fn test_escape() { assert_eq!(pns("has no escapes"), None); assert_eq!(pns("has no escapes, either %"), None); - assert_eq!(pns("*so* has a %% escape"), Some((S::Escape, " escape"))); - assert_eq!(pns("%% leading escape"), Some((S::Escape, " leading escape"))); - assert_eq!(pns("trailing escape %%"), Some((S::Escape, ""))); + assert_eq!(pns("*so* has a %% escape"), Some((S::Escape((11, 13)), " escape"))); + assert_eq!(pns("%% leading escape"), Some((S::Escape((0, 2)), " leading escape"))); + assert_eq!(pns("trailing escape %%"), Some((S::Escape((16, 18)), ""))); } #[test] diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index d1d276930b..e43cece4f1 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -6,7 +6,6 @@ #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] #![feature(decl_macro)] -#![feature(iter_zip)] #![feature(nll)] #![feature(proc_macro_internals)] #![feature(proc_macro_quote)] @@ -20,28 +19,29 @@ use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind}; use rustc_expand::proc_macro::BangProcMacro; use rustc_span::symbol::sym; -mod asm; mod assert; mod cfg; mod cfg_accessible; mod cfg_eval; mod compile_error; mod concat; +mod concat_bytes; mod concat_idents; mod derive; mod deriving; +mod edition_panic; mod env; mod format; mod format_foreign; mod global_allocator; mod llvm_asm; mod log_syntax; -mod panic; mod source_util; mod test; mod trace_macros; mod util; +pub mod asm; pub mod cmdline_attrs; pub mod proc_macro_harness; pub mod standard_library_imports; @@ -65,6 +65,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { cfg: cfg::expand_cfg, column: source_util::expand_column, compile_error: compile_error::expand_compile_error, + concat_bytes: concat_bytes::expand_concat_bytes, concat_idents: concat_idents::expand_concat_idents, concat: concat::expand_concat, env: env::expand_env, @@ -81,8 +82,9 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { log_syntax: log_syntax::expand_log_syntax, module_path: source_util::expand_mod, option_env: env::expand_option_env, - core_panic: panic::expand_panic, - std_panic: panic::expand_panic, + core_panic: edition_panic::expand_panic, + std_panic: edition_panic::expand_panic, + unreachable: edition_panic::expand_unreachable, stringify: source_util::expand_stringify, trace_macros: trace_macros::expand_trace_macros, } diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index d2629926b5..c08b141b55 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -1,6 +1,6 @@ /// The expansion from a test function to the appropriate test struct for libtest /// Ideally, this code would be in libtest but for efficiency and error messages it lives here. -use crate::util::check_builtin_macro_attribute; +use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute}; use rustc_ast as ast; use rustc_ast::attr; @@ -27,6 +27,7 @@ pub fn expand_test_case( anno_item: Annotatable, ) -> Vec { check_builtin_macro_attribute(ecx, meta_item, sym::test_case); + warn_on_duplicate_attribute(&ecx, &anno_item, sym::test_case); if !ecx.ecfg.should_test { return vec![]; @@ -55,6 +56,7 @@ pub fn expand_test( item: Annotatable, ) -> Vec { check_builtin_macro_attribute(cx, meta_item, sym::test); + warn_on_duplicate_attribute(&cx, &item, sym::test); expand_test_or_bench(cx, attr_sp, item, false) } @@ -65,6 +67,7 @@ pub fn expand_bench( item: Annotatable, ) -> Vec { check_builtin_macro_attribute(cx, meta_item, sym::bench); + warn_on_duplicate_attribute(&cx, &item, sym::bench); expand_test_or_bench(cx, attr_sp, item, true) } diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 64ccd4331e..418729e784 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -84,9 +84,35 @@ struct TestHarnessGenerator<'a> { tests: Vec, } +impl TestHarnessGenerator<'_> { + fn add_test_cases(&mut self, node_id: ast::NodeId, span: Span, prev_tests: Vec) { + let mut tests = mem::replace(&mut self.tests, prev_tests); + + if !tests.is_empty() { + // Create an identifier that will hygienically resolve the test + // case name, even in another module. + let expn_id = self.cx.ext_cx.resolver.expansion_for_ast_pass( + span, + AstPass::TestHarness, + &[], + Some(node_id), + ); + for test in &mut tests { + // See the comment on `mk_main` for why we're using + // `apply_mark` directly. + test.ident.span = + test.ident.span.apply_mark(expn_id.to_expn_id(), Transparency::Opaque); + } + self.cx.test_cases.extend(tests); + } + } +} + impl<'a> MutVisitor for TestHarnessGenerator<'a> { fn visit_crate(&mut self, c: &mut ast::Crate) { + let prev_tests = mem::take(&mut self.tests); noop_visit_crate(c, self); + self.add_test_cases(ast::CRATE_NODE_ID, c.span, prev_tests); // Create a main function to run our tests c.items.push(mk_main(&mut self.cx)); @@ -103,34 +129,10 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> { // We don't want to recurse into anything other than mods, since // mods or tests inside of functions will break things - if let ast::ItemKind::Mod(..) = item.kind { - let tests = mem::take(&mut self.tests); + if let ast::ItemKind::Mod(_, ModKind::Loaded(.., span)) = item.kind { + let prev_tests = mem::take(&mut self.tests); noop_visit_item_kind(&mut item.kind, self); - let mut tests = mem::replace(&mut self.tests, tests); - - if !tests.is_empty() { - let parent = - if item.id == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { item.id }; - // Create an identifier that will hygienically resolve the test - // case name, even in another module. - let inner_span = match item.kind { - ast::ItemKind::Mod(_, ModKind::Loaded(.., span)) => span, - _ => unreachable!(), - }; - let expn_id = self.cx.ext_cx.resolver.expansion_for_ast_pass( - inner_span, - AstPass::TestHarness, - &[], - Some(parent), - ); - for test in &mut tests { - // See the comment on `mk_main` for why we're using - // `apply_mark` directly. - test.ident.span = - test.ident.span.apply_mark(expn_id.to_expn_id(), Transparency::Opaque); - } - self.cx.test_cases.extend(tests); - } + self.add_test_cases(item.id, span, prev_tests); } smallvec![P(item)] } @@ -146,7 +148,7 @@ fn entry_point_type(sess: &Session, item: &ast::Item, depth: usize) -> EntryPoin } else if sess.contains_name(&item.attrs, sym::rustc_main) { EntryPointType::MainAttr } else if item.ident.name == sym::main { - if depth == 1 { + if depth == 0 { // This is a top-level function so can be 'main' EntryPointType::MainNamed } else { diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs index 01ea80c4c8..527fe50eff 100644 --- a/compiler/rustc_builtin_macros/src/util.rs +++ b/compiler/rustc_builtin_macros/src/util.rs @@ -1,6 +1,7 @@ -use rustc_ast::MetaItem; -use rustc_expand::base::ExtCtxt; +use rustc_ast::{Attribute, MetaItem}; +use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_feature::AttributeTemplate; +use rustc_lint_defs::builtin::DUPLICATE_MACRO_ATTRIBUTES; use rustc_parse::validate_attr; use rustc_span::Symbol; @@ -10,3 +11,33 @@ pub fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, na let attr = ecx.attribute(meta_item.clone()); validate_attr::check_builtin_attribute(&ecx.sess.parse_sess, &attr, name, template); } + +/// Emit a warning if the item is annotated with the given attribute. This is used to diagnose when +/// an attribute may have been mistakenly duplicated. +pub fn warn_on_duplicate_attribute(ecx: &ExtCtxt<'_>, item: &Annotatable, name: Symbol) { + let attrs: Option<&[Attribute]> = match item { + Annotatable::Item(item) => Some(&item.attrs), + Annotatable::TraitItem(item) => Some(&item.attrs), + Annotatable::ImplItem(item) => Some(&item.attrs), + Annotatable::ForeignItem(item) => Some(&item.attrs), + Annotatable::Expr(expr) => Some(&expr.attrs), + Annotatable::Arm(arm) => Some(&arm.attrs), + Annotatable::ExprField(field) => Some(&field.attrs), + Annotatable::PatField(field) => Some(&field.attrs), + Annotatable::GenericParam(param) => Some(¶m.attrs), + Annotatable::Param(param) => Some(¶m.attrs), + Annotatable::FieldDef(def) => Some(&def.attrs), + Annotatable::Variant(variant) => Some(&variant.attrs), + _ => None, + }; + if let Some(attrs) = attrs { + if let Some(attr) = ecx.sess.find_by_name(attrs, name) { + ecx.parse_sess().buffer_lint( + DUPLICATE_MACRO_ATTRIBUTES, + attr.span, + ecx.current_expansion.lint_node_id, + "duplicated attribute", + ); + } + } +} diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml index f524b42c5e..3aba528abf 100644 --- a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml +++ b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml @@ -5,6 +5,21 @@ on: - pull_request jobs: + rustfmt: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + + - name: Install rustfmt + run: | + rustup component add rustfmt + + - name: Rustfmt + run: | + cargo fmt --check + build: runs-on: ${{ matrix.os }} timeout-minutes: 60 @@ -65,6 +80,12 @@ jobs: git config --global user.name "User" ./y.rs prepare + - name: Build without unstable features + env: + TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }} + # This is the config rust-lang/rust uses for builds + run: ./y.rs build --no-unstable-features + - name: Build run: ./y.rs build --sysroot none @@ -152,11 +173,12 @@ jobs: ./y.exe build - #- name: Package prebuilt cg_clif - # run: tar cvfJ cg_clif.tar.xz build + - name: Package prebuilt cg_clif + # don't use compression as xzip isn't supported by tar on windows and bzip2 hangs + run: tar cvf cg_clif.tar build - #- name: Upload prebuilt cg_clif - # uses: actions/upload-artifact@v2 - # with: - # name: cg_clif-${{ runner.os }} - # path: cg_clif.tar.xz + - name: Upload prebuilt cg_clif + uses: actions/upload-artifact@v2 + with: + name: cg_clif-${{ runner.os }} + path: cg_clif.tar diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/nightly-cranelift.yml b/compiler/rustc_codegen_cranelift/.github/workflows/nightly-cranelift.yml new file mode 100644 index 0000000000..a019793edd --- /dev/null +++ b/compiler/rustc_codegen_cranelift/.github/workflows/nightly-cranelift.yml @@ -0,0 +1,59 @@ +name: Test nightly Cranelift + +on: + push: + schedule: + - cron: '17 1 * * *' # At 01:17 UTC every day. + +jobs: + build: + runs-on: ubuntu-latest + timeout-minutes: 60 + + steps: + - uses: actions/checkout@v2 + + - name: Cache cargo installed crates + uses: actions/cache@v2 + with: + path: ~/.cargo/bin + key: ubuntu-latest-cargo-installed-crates + + - name: Prepare dependencies + run: | + git config --global user.email "user@example.com" + git config --global user.name "User" + ./y.rs prepare + + - name: Patch Cranelift + run: | + sed -i 's/cranelift-codegen = { version = "\w*.\w*.\w*", features = \["unwind", "all-arch"\] }/cranelift-codegen = { git = "https:\/\/github.com\/bytecodealliance\/wasmtime.git", features = ["unwind", "all-arch"] }/' Cargo.toml + sed -i 's/cranelift-frontend = "\w*.\w*.\w*"/cranelift-frontend = { git = "https:\/\/github.com\/bytecodealliance\/wasmtime.git" }/' Cargo.toml + sed -i 's/cranelift-module = "\w*.\w*.\w*"/cranelift-module = { git = "https:\/\/github.com\/bytecodealliance\/wasmtime.git" }/' Cargo.toml + sed -i 's/cranelift-native = "\w*.\w*.\w*"/cranelift-native = { git = "https:\/\/github.com\/bytecodealliance\/wasmtime.git" }/' Cargo.toml + sed -i 's/cranelift-jit = { version = "\w*.\w*.\w*", optional = true }/cranelift-jit = { git = "https:\/\/github.com\/bytecodealliance\/wasmtime.git", optional = true }/' Cargo.toml + sed -i 's/cranelift-object = "\w*.\w*.\w*"/cranelift-object = { git = "https:\/\/github.com\/bytecodealliance\/wasmtime.git" }/' Cargo.toml + + sed -i 's/gimli = { version = "0.25.0", default-features = false, features = \["write"\]}/gimli = { version = "0.26.1", default-features = false, features = ["write"] }/' Cargo.toml + + cat Cargo.toml + + - name: Build without unstable features + # This is the config rust-lang/rust uses for builds + run: ./y.rs build --no-unstable-features + + - name: Build + run: ./y.rs build --sysroot none + - name: Test + run: | + # Enable backtraces for easier debugging + export RUST_BACKTRACE=1 + + # Reduce amount of benchmark runs as they are slow + export COMPILE_RUNS=2 + export RUN_RUNS=2 + + # Enable extra checks + export CG_CLIF_ENABLE_VERIFIER=1 + + ./test.sh diff --git a/compiler/rustc_codegen_cranelift/.vscode/settings.json b/compiler/rustc_codegen_cranelift/.vscode/settings.json index f62e59cefc..74fde9c27c 100644 --- a/compiler/rustc_codegen_cranelift/.vscode/settings.json +++ b/compiler/rustc_codegen_cranelift/.vscode/settings.json @@ -5,6 +5,7 @@ "rust-analyzer.assist.importEnforceGranularity": true, "rust-analyzer.assist.importPrefix": "crate", "rust-analyzer.cargo.runBuildScripts": true, + "rust-analyzer.cargo.features": ["unstable-features"] "rust-analyzer.linkedProjects": [ "./Cargo.toml", //"./build_sysroot/sysroot_src/src/libstd/Cargo.toml", diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock index 4afddf7686..65e142a00f 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "anyhow" -version = "1.0.42" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486" +checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203" [[package]] name = "ar" @@ -21,9 +21,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "bitflags" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "cfg-if" @@ -33,16 +33,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.76.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" +version = "0.78.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc0cb7df82c8cf8f2e6a8dd394a0932a71369c160cc9b027dca414fced242513" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.76.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" +version = "0.78.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe4463c15fa42eee909e61e5eac4866b7c6d22d0d8c621e57a0c5380753bfa8c" dependencies = [ "cranelift-bforest", "cranelift-codegen-meta", @@ -57,8 +59,9 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.76.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" +version = "0.78.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793f6a94a053a55404ea16e1700202a88101672b8cd6b4df63e13cde950852bf" dependencies = [ "cranelift-codegen-shared", "cranelift-entity", @@ -66,18 +69,21 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.76.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" +version = "0.78.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44aa1846df275bce5eb30379d65964c7afc63c05a117076e62a119c25fe174be" [[package]] name = "cranelift-entity" -version = "0.76.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" +version = "0.78.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3a45d8d6318bf8fc518154d9298eab2a8154ec068a8885ff113f6db8d69bb3a" [[package]] name = "cranelift-frontend" -version = "0.76.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" +version = "0.78.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e07339bd461766deb7605169de039e01954768ff730fa1254e149001884a8525" dependencies = [ "cranelift-codegen", "log", @@ -87,8 +93,9 @@ dependencies = [ [[package]] name = "cranelift-jit" -version = "0.76.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" +version = "0.78.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e8f0d60fb5d67f7a1e5c49db38ba96d1c846921faef02085fc5590b74781747" dependencies = [ "anyhow", "cranelift-codegen", @@ -104,8 +111,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.76.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" +version = "0.78.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "825ac7e0959cbe7ddc9cc21209f0319e611a57f9fcb2b723861fe7ef2017e651" dependencies = [ "anyhow", "cranelift-codegen", @@ -115,8 +123,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.76.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" +version = "0.78.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03e2fca76ff57e0532936a71e3fc267eae6a19a86656716479c66e7f912e3d7b" dependencies = [ "cranelift-codegen", "libc", @@ -125,8 +134,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.76.0" -source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" +version = "0.78.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55500d0fc9bb05c0944fc4506649249d28f55bd4fe95b87f0e55bf41058f0e6d" dependencies = [ "anyhow", "cranelift-codegen", @@ -138,9 +148,9 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +checksum = "738c290dfaea84fc1ca15ad9c168d083b05a714e1efddd8edaab678dc28d2836" dependencies = [ "cfg-if", ] @@ -172,9 +182,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.98" +version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" +checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" [[package]] name = "libloading" @@ -206,15 +216,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "object" -version = "0.26.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55827317fb4c08822499848a14237d2874d6f139828893017237e7ab93eb386" +checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" dependencies = [ "crc32fast", "indexmap", @@ -223,9 +233,9 @@ dependencies = [ [[package]] name = "regalloc" -version = "0.0.31" +version = "0.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "571f7f397d61c4755285cd37853fe8e03271c243424a907415909379659381c5" +checksum = "a6304468554ed921da3d32c355ea107b8d13d7b8996c3adfb7aab48d3bc321f4" dependencies = [ "log", "rustc-hash", @@ -271,15 +281,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" [[package]] name = "target-lexicon" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0652da4c4121005e9ed22b79f6c5f2d9e2752906b53a33e9490489ba421a6fb" +checksum = "d9bffcddbc2458fa3e6058414599e3c838a022abae82e5c67b4f7f80298d5bff" [[package]] name = "winapi" diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml index 61d40702a3..3be4250296 100644 --- a/compiler/rustc_codegen_cranelift/Cargo.toml +++ b/compiler/rustc_codegen_cranelift/Cargo.toml @@ -8,23 +8,23 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", features = ["unwind", "all-arch"] } -cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git" } -cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git" } -cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git" } -cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", optional = true } -cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git" } +cranelift-codegen = { version = "0.78.0", features = ["unwind", "all-arch"] } +cranelift-frontend = "0.78.0" +cranelift-module = "0.78.0" +cranelift-native = "0.78.0" +cranelift-jit = { version = "0.78.0", optional = true } +cranelift-object = "0.78.0" target-lexicon = "0.12.0" gimli = { version = "0.25.0", default-features = false, features = ["write"]} -object = { version = "0.26.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } +object = { version = "0.27.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "do_not_remove_cg_clif_ranlib" } indexmap = "1.0.2" libloading = { version = "0.6.0", optional = true } smallvec = "1.6.1" +[patch.crates-io] # Uncomment to use local checkout of cranelift -#[patch."https://github.com/bytecodealliance/wasmtime.git"] #cranelift-codegen = { path = "../wasmtime/cranelift/codegen" } #cranelift-frontend = { path = "../wasmtime/cranelift/frontend" } #cranelift-module = { path = "../wasmtime/cranelift/module" } @@ -32,7 +32,6 @@ smallvec = "1.6.1" #cranelift-jit = { path = "../wasmtime/cranelift/jit" } #cranelift-object = { path = "../wasmtime/cranelift/object" } -#[patch.crates-io] #gimli = { path = "../" } [features] @@ -41,31 +40,12 @@ unstable-features = ["jit", "inline_asm"] jit = ["cranelift-jit", "libloading"] inline_asm = [] -[profile.dev] -# By compiling dependencies with optimizations, performing tests gets much faster. -opt-level = 3 - -[profile.dev.package.rustc_codegen_cranelift] -# Disabling optimizations for cg_clif itself makes compilation after a change faster. -opt-level = 0 - -[profile.release.package.rustc_codegen_cranelift] -incremental = true - # Disable optimizations and debuginfo of build scripts and some of the heavy build deps, as the # execution time of build scripts is so fast that optimizing them slows down the total build time. -[profile.dev.build-override] -opt-level = 0 -debug = false - [profile.release.build-override] opt-level = 0 debug = false -[profile.dev.package.cranelift-codegen-meta] -opt-level = 0 -debug = false - [profile.release.package.cranelift-codegen-meta] opt-level = 0 debug = false diff --git a/compiler/rustc_codegen_cranelift/Readme.md b/compiler/rustc_codegen_cranelift/Readme.md index dad8ed90b5..8a2db5a43e 100644 --- a/compiler/rustc_codegen_cranelift/Readme.md +++ b/compiler/rustc_codegen_cranelift/Readme.md @@ -37,7 +37,7 @@ Assuming `$cg_clif_dir` is the directory you cloned this repo into and you follo In the directory with your project (where you can do the usual `cargo build`), run: ```bash -$ $cg_clif_dir/build/cargo build +$ $cg_clif_dir/build/cargo-clif build ``` This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend. diff --git a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock index 22be21cb8d..dd09656248 100644 --- a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock +++ b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock @@ -40,9 +40,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "cc" -version = "1.0.70" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0" +checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" [[package]] name = "cfg-if" @@ -56,7 +56,7 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.50" +version = "0.1.66" dependencies = [ "rustc-std-workspace-core", ] @@ -67,9 +67,9 @@ version = "0.0.0" [[package]] name = "dlmalloc" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332570860c2edf2d57914987bf9e24835425f75825086b6ba7d1e6a3e4f1f254" +checksum = "a6fe28e0bf9357092740362502f5cc7955d8dc125ebda71dec72336c2e15c62e" dependencies = [ "compiler_builtins", "libc", @@ -132,9 +132,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.102" +version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103" +checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" dependencies = [ "rustc-std-workspace-core", ] diff --git a/compiler/rustc_codegen_cranelift/build_system/build_backend.rs b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs index 150b6d01a6..1382c7e537 100644 --- a/compiler/rustc_codegen_cranelift/build_system/build_backend.rs +++ b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs @@ -2,9 +2,29 @@ use std::env; use std::path::{Path, PathBuf}; use std::process::Command; -pub(crate) fn build_backend(channel: &str, host_triple: &str) -> PathBuf { +pub(crate) fn build_backend( + channel: &str, + host_triple: &str, + use_unstable_features: bool, +) -> PathBuf { let mut cmd = Command::new("cargo"); - cmd.arg("build").arg("--target").arg(host_triple).arg("--features").arg("unstable-features"); + cmd.arg("build").arg("--target").arg(host_triple); + + cmd.env("CARGO_BUILD_INCREMENTAL", "true"); // Force incr comp even in release mode + + let mut rustflags = env::var("RUSTFLAGS").unwrap_or_default(); + + if env::var("CI").as_ref().map(|val| &**val) == Ok("true") { + // Deny warnings on CI + rustflags += " -Dwarnings"; + + // Disabling incr comp reduces cache size and incr comp doesn't save as much on CI anyway + cmd.env("CARGO_BUILD_INCREMENTAL", "false"); + } + + if use_unstable_features { + cmd.arg("--features").arg("unstable-features"); + } match channel { "debug" => {} @@ -14,25 +34,20 @@ pub(crate) fn build_backend(channel: &str, host_triple: &str) -> PathBuf { _ => unreachable!(), } + // Set the rpath to make the cg_clif executable find librustc_codegen_cranelift without changing + // LD_LIBRARY_PATH if cfg!(unix) { if cfg!(target_os = "macos") { - cmd.env( - "RUSTFLAGS", - "-Csplit-debuginfo=unpacked \ + rustflags += " -Csplit-debuginfo=unpacked \ -Clink-arg=-Wl,-rpath,@loader_path/../lib \ - -Zosx-rpath-install-name" - .to_string() - + env::var("RUSTFLAGS").as_deref().unwrap_or(""), - ); + -Zosx-rpath-install-name"; } else { - cmd.env( - "RUSTFLAGS", - "-Clink-arg=-Wl,-rpath=$ORIGIN/../lib ".to_string() - + env::var("RUSTFLAGS").as_deref().unwrap_or(""), - ); + rustflags += " -Clink-arg=-Wl,-rpath=$ORIGIN/../lib "; } } + cmd.env("RUSTFLAGS", rustflags); + eprintln!("[BUILD] rustc_codegen_cranelift"); crate::utils::spawn_and_wait(cmd); diff --git a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs index 642abc41f4..2956fb698e 100644 --- a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs +++ b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs @@ -46,9 +46,9 @@ pub(crate) fn build_sysroot( // Build and copy cargo wrapper let mut build_cargo_wrapper_cmd = Command::new("rustc"); build_cargo_wrapper_cmd - .arg("scripts/cargo.rs") + .arg("scripts/cargo-clif.rs") .arg("-o") - .arg(target_dir.join("cargo")) + .arg(target_dir.join("cargo-clif")) .arg("-g"); spawn_and_wait(build_cargo_wrapper_cmd); @@ -193,8 +193,7 @@ fn build_clif_sysroot_for_triple( "RUSTC", env::current_dir().unwrap().join(target_dir).join("bin").join("cg_clif_build_sysroot"), ); - // FIXME Enable incremental again once rust-lang/rust#74946 is fixed - build_cmd.env("CARGO_INCREMENTAL", "0").env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif"); + build_cmd.env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif"); spawn_and_wait(build_cmd); // Copy all relevant files to the sysroot diff --git a/compiler/rustc_codegen_cranelift/build_system/prepare.rs b/compiler/rustc_codegen_cranelift/build_system/prepare.rs index ae9a35048b..561e2ed7b0 100644 --- a/compiler/rustc_codegen_cranelift/build_system/prepare.rs +++ b/compiler/rustc_codegen_cranelift/build_system/prepare.rs @@ -30,7 +30,7 @@ pub(crate) fn prepare() { clone_repo( "portable-simd", "https://github.com/rust-lang/portable-simd", - "8cf7a62e5d2552961df51e5200aaa5b7c890a4bf", + "b8d6b6844602f80af79cd96401339ec594d472d8", ); apply_patches("portable-simd", Path::new("portable-simd")); @@ -92,7 +92,7 @@ fn prepare_sysroot() { clone_repo( "build_sysroot/compiler-builtins", "https://github.com/rust-lang/compiler-builtins.git", - "0.1.50", + "0.1.66", ); apply_patches("compiler-builtins", Path::new("build_sysroot/compiler-builtins")); } diff --git a/compiler/rustc_codegen_cranelift/docs/usage.md b/compiler/rustc_codegen_cranelift/docs/usage.md index bcc5745d9d..785c738378 100644 --- a/compiler/rustc_codegen_cranelift/docs/usage.md +++ b/compiler/rustc_codegen_cranelift/docs/usage.md @@ -9,7 +9,7 @@ Assuming `$cg_clif_dir` is the directory you cloned this repo into and you follo In the directory with your project (where you can do the usual `cargo build`), run: ```bash -$ $cg_clif_dir/build/cargo build +$ $cg_clif_dir/build/cargo-clif build ``` This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend. @@ -32,7 +32,7 @@ In jit mode cg_clif will immediately execute your code without creating an execu > The jit mode will probably need cargo integration to make this possible. ```bash -$ $cg_clif_dir/build/cargo jit +$ $cg_clif_dir/build/cargo-clif jit ``` or @@ -45,7 +45,7 @@ There is also an experimental lazy jit mode. In this mode functions are only com first called. ```bash -$ $cg_clif_dir/build/cargo lazy-jit +$ $cg_clif_dir/build/cargo-clif lazy-jit ``` ## Shell diff --git a/compiler/rustc_codegen_cranelift/example/issue-91827-extern-types.rs b/compiler/rustc_codegen_cranelift/example/issue-91827-extern-types.rs new file mode 100644 index 0000000000..cf8fada532 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/example/issue-91827-extern-types.rs @@ -0,0 +1,60 @@ +// Copied from rustc ui test suite + +// run-pass +// +// Test that we can handle unsized types with an extern type tail part. +// Regression test for issue #91827. + +#![feature(const_ptr_offset_from)] +#![feature(const_slice_from_raw_parts)] +#![feature(extern_types)] + +use std::ptr::addr_of; + +extern "C" { + type Opaque; +} + +unsafe impl Sync for Opaque {} + +#[repr(C)] +pub struct List { + len: usize, + data: [T; 0], + tail: Opaque, +} + +#[repr(C)] +pub struct ListImpl { + len: usize, + data: [T; N], +} + +impl List { + const fn as_slice(&self) -> &[T] { + unsafe { std::slice::from_raw_parts(self.data.as_ptr(), self.len) } + } +} + +impl ListImpl { + const fn as_list(&self) -> &List { + unsafe { std::mem::transmute(self) } + } +} + +pub static A: ListImpl = ListImpl { + len: 3, + data: [5, 6, 7], +}; +pub static A_REF: &'static List = A.as_list(); +pub static A_TAIL_OFFSET: isize = tail_offset(A.as_list()); + +const fn tail_offset(list: &List) -> isize { + unsafe { (addr_of!(list.tail) as *const u8).offset_from(list as *const List as *const u8) } +} + +fn main() { + assert_eq!(A_REF.as_slice(), &[5, 6, 7]); + // Check that interpreter and code generation agree about the position of the tail field. + assert_eq!(A_TAIL_OFFSET, tail_offset(A_REF)); +} diff --git a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs index cbfdb3c44f..ef3b575d39 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs @@ -129,6 +129,7 @@ fn call_return_u128_pair() { return_u128_pair(); } +#[allow(unreachable_code)] // FIXME false positive fn main() { take_unique(Unique { pointer: 0 as *const (), diff --git a/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch b/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch index 2e68369466..c132590869 100644 --- a/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch +++ b/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch @@ -1,41 +1,20 @@ -From 6bfce5dc2cbf834c74dbccb7538adc08c6eb57e7 Mon Sep 17 00:00:00 2001 +From 97c473937382a5b5858d9cce3c947855d23b2dc5 Mon Sep 17 00:00:00 2001 From: bjorn3 -Date: Sun, 25 Jul 2021 18:39:31 +0200 +Date: Thu, 18 Nov 2021 19:28:40 +0100 Subject: [PATCH] Disable unsupported tests --- - crates/core_simd/src/vector.rs | 2 ++ - crates/core_simd/src/math.rs | 4 ++++ - crates/core_simd/tests/masks.rs | 12 ------------ - crates/core_simd/tests/ops_macros.rs | 6 ++++++ - crates/core_simd/tests/round.rs | 2 ++ - 6 files changed, 15 insertions(+), 13 deletions(-) + crates/core_simd/src/math.rs | 6 ++++++ + crates/core_simd/src/vector.rs | 2 ++ + crates/core_simd/tests/masks.rs | 2 ++ + crates/core_simd/tests/ops_macros.rs | 4 ++++ + 4 files changed, 14 insertions(+) -diff --git a/crates/core_simd/src/vector.rs b/crates/core_simd/src/vector.rs -index 25c5309..2b3d819 100644 ---- a/crates/core_simd/src/vector.rs -+++ b/crates/core_simd/src/vector.rs -@@ -22,6 +22,7 @@ where - self.0 - } - -+ /* - /// SIMD gather: construct a SIMD vector by reading from a slice, using potentially discontiguous indices. - /// If an index is out of bounds, that lane instead selects the value from the "or" vector. - /// ``` -@@ -150,6 +151,7 @@ where - // Cleared ☢️ *mut T Zone - } - } -+ */ - } - - impl Copy for Simd diff --git a/crates/core_simd/src/math.rs b/crates/core_simd/src/math.rs -index 7290a28..e394730 100644 +index 2bae414..2f87499 100644 --- a/crates/core_simd/src/math.rs +++ b/crates/core_simd/src/math.rs -@@ -2,6 +2,7 @@ macro_rules! impl_uint_arith { +@@ -5,6 +5,7 @@ macro_rules! impl_uint_arith { ($($ty:ty),+) => { $( impl Simd<$ty, LANES> where LaneCount: SupportedLaneCount { @@ -43,15 +22,15 @@ index 7290a28..e394730 100644 /// Lanewise saturating add. /// /// # Examples -@@ -38,6 +39,7 @@ macro_rules! impl_uint_arith { +@@ -43,6 +44,7 @@ macro_rules! impl_uint_arith { pub fn saturating_sub(self, second: Self) -> Self { - unsafe { crate::intrinsics::simd_saturating_sub(self, second) } + unsafe { simd_saturating_sub(self, second) } } + */ })+ } } -@@ -46,6 +48,7 @@ macro_rules! impl_int_arith { +@@ -51,6 +53,7 @@ macro_rules! impl_int_arith { ($($ty:ty),+) => { $( impl Simd<$ty, LANES> where LaneCount: SupportedLaneCount { @@ -59,7 +38,23 @@ index 7290a28..e394730 100644 /// Lanewise saturating add. /// /// # Examples -@@ -141,6 +144,7 @@ macro_rules! impl_int_arith { +@@ -89,6 +92,7 @@ macro_rules! impl_int_arith { + pub fn saturating_sub(self, second: Self) -> Self { + unsafe { simd_saturating_sub(self, second) } + } ++ */ + + /// Lanewise absolute value, implemented in Rust. + /// Every lane becomes its absolute value. +@@ -109,6 +113,7 @@ macro_rules! impl_int_arith { + (self^m) - m + } + ++ /* + /// Lanewise saturating absolute value, implemented in Rust. + /// As abs(), except the MIN value becomes MAX instead of itself. + /// +@@ -151,6 +156,7 @@ macro_rules! impl_int_arith { pub fn saturating_neg(self) -> Self { Self::splat(0).saturating_sub(self) } @@ -67,51 +62,51 @@ index 7290a28..e394730 100644 })+ } } +diff --git a/crates/core_simd/src/vector.rs b/crates/core_simd/src/vector.rs +index 7c5ec2b..c8631e8 100644 +--- a/crates/core_simd/src/vector.rs ++++ b/crates/core_simd/src/vector.rs +@@ -75,6 +75,7 @@ where + Self(array) + } + ++ /* + /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector. + /// If an index is out-of-bounds, the lane is instead selected from the `or` vector. + /// +@@ -297,6 +298,7 @@ where + // Cleared ☢️ *mut T Zone + } + } ++ */ + } + + impl Copy for Simd diff --git a/crates/core_simd/tests/masks.rs b/crates/core_simd/tests/masks.rs -index 61d8e44..2bccae2 100644 +index 6a8ecd3..68fcb49 100644 --- a/crates/core_simd/tests/masks.rs +++ b/crates/core_simd/tests/masks.rs -@@ -67,19 +67,6 @@ macro_rules! test_mask_api { - assert_eq!(int.to_array(), [-1, 0, 0, -1, 0, 0, -1, 0]); +@@ -68,6 +68,7 @@ macro_rules! test_mask_api { assert_eq!(core_simd::Mask::<$type, 8>::from_int(int), mask); } -- -- #[cfg(feature = "generic_const_exprs")] -- #[test] -- fn roundtrip_bitmask_conversion() { -- let values = [ -- true, false, false, true, false, false, true, false, -- true, true, false, false, false, false, false, true, -- ]; -- let mask = core_simd::Mask::<$type, 16>::from_array(values); -- let bitmask = mask.to_bitmask(); -- assert_eq!(bitmask, [0b01001001, 0b10000011]); -- assert_eq!(core_simd::Mask::<$type, 16>::from_bitmask(bitmask), mask); -- } + ++ /* + #[cfg(feature = "generic_const_exprs")] + #[test] + fn roundtrip_bitmask_conversion() { +@@ -80,6 +81,7 @@ macro_rules! test_mask_api { + assert_eq!(bitmask, [0b01001001, 0b10000011]); + assert_eq!(core_simd::Mask::<$type, 16>::from_bitmask(bitmask), mask); + } ++ */ } } } diff --git a/crates/core_simd/tests/ops_macros.rs b/crates/core_simd/tests/ops_macros.rs -index cb39e73..fc0ebe1 100644 +index 31b7ee2..bd04b3c 100644 --- a/crates/core_simd/tests/ops_macros.rs +++ b/crates/core_simd/tests/ops_macros.rs -@@ -435,6 +435,7 @@ macro_rules! impl_float_tests { - ) - } - -+ /* - fn mul_add() { - test_helpers::test_ternary_elementwise( - &Vector::::mul_add, -@@ -442,6 +443,7 @@ macro_rules! impl_float_tests { - &|_, _, _| true, - ) - } -+ */ - - fn recip() { - test_helpers::test_unary_elementwise( -@@ -581,6 +585,7 @@ macro_rules! impl_float_tests { +@@ -567,6 +567,7 @@ macro_rules! impl_float_tests { }); } @@ -119,7 +114,7 @@ index cb39e73..fc0ebe1 100644 fn horizontal_max() { test_helpers::test_1(&|x| { let vmax = Vector::::from_array(x).horizontal_max(); -@@ -604,6 +609,7 @@ macro_rules! impl_float_tests { +@@ -590,6 +591,7 @@ macro_rules! impl_float_tests { Ok(()) }); } @@ -127,26 +122,22 @@ index cb39e73..fc0ebe1 100644 } #[cfg(feature = "std")] -diff --git a/crates/core_simd/tests/round.rs b/crates/core_simd/tests/round.rs -index 37044a7..4cdc6b7 100644 ---- a/crates/core_simd/tests/round.rs -+++ b/crates/core_simd/tests/round.rs -@@ -25,6 +25,7 @@ macro_rules! float_rounding_test { - ) - } +@@ -604,6 +606,7 @@ macro_rules! impl_float_tests { + ) + } -+ /* - fn round() { - test_helpers::test_unary_elementwise( - &Vector::::round, -@@ -32,6 +33,7 @@ macro_rules! float_rounding_test { - &|_| true, - ) ++ /* + fn mul_add() { + test_helpers::test_ternary_elementwise( + &Vector::::mul_add, +@@ -611,6 +614,7 @@ macro_rules! impl_float_tests { + &|_, _, _| true, + ) + } ++ */ } -+ */ - - fn trunc() { - test_helpers::test_unary_elementwise( + } + } -- 2.26.2.7.g19db9cfb68 diff --git a/compiler/rustc_codegen_cranelift/patches/0027-sysroot-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0027-sysroot-128bit-atomic-operations.patch index e2d07bd126..ffee641457 100644 --- a/compiler/rustc_codegen_cranelift/patches/0027-sysroot-128bit-atomic-operations.patch +++ b/compiler/rustc_codegen_cranelift/patches/0027-sysroot-128bit-atomic-operations.patch @@ -107,7 +107,7 @@ index fa96b7a..2854f9c 100644 inner::monotonize(raw) } --#[cfg(all(target_has_atomic = "64", not(target_has_atomic = "128")))] +-#[cfg(any(all(target_has_atomic = "64", not(target_has_atomic = "128")), target_arch = "aarch64"))] +#[cfg(target_has_atomic = "64")] pub mod inner { use crate::sync::atomic::AtomicU64; @@ -117,7 +117,7 @@ index fa96b7a..2854f9c 100644 } +/* - #[cfg(target_has_atomic = "128")] + #[cfg(all(target_has_atomic = "128", not(target_arch = "aarch64")))] pub mod inner { use crate::sync::atomic::AtomicU128; @@ -94,8 +95,9 @@ pub mod inner { diff --git a/compiler/rustc_codegen_cranelift/patches/0028-sysroot-Disable-long-running-tests.patch b/compiler/rustc_codegen_cranelift/patches/0028-sysroot-Disable-long-running-tests.patch new file mode 100644 index 0000000000..bf74a74c7c --- /dev/null +++ b/compiler/rustc_codegen_cranelift/patches/0028-sysroot-Disable-long-running-tests.patch @@ -0,0 +1,30 @@ +From 0ffdd8eda8df364391c8ac6e1ce92c73ba9254d4 Mon Sep 17 00:00:00 2001 +From: bjorn3 +Date: Fri, 3 Dec 2021 12:16:30 +0100 +Subject: [PATCH] Disable long running tests + +--- + library/core/tests/slice.rs | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs +index 2c8f00a..44847ee 100644 +--- a/library/core/tests/slice.rs ++++ b/library/core/tests/slice.rs +@@ -2332,7 +2332,8 @@ macro_rules! empty_max_mut { + }; + } + ++/* + #[cfg(not(miri))] // Comparing usize::MAX many elements takes forever in Miri (and in rustc without optimizations) + take_tests! { + slice: &[(); usize::MAX], method: take, + (take_in_bounds_max_range_to, (..usize::MAX), Some(EMPTY_MAX), &[(); 0]), +@@ -2345,3 +2347,4 @@ take_tests! { + (take_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()), + (take_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()), + } ++*/ +-- +2.26.2.7.g19db9cfb68 + diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain index 360570b3ae..cab94c0b8c 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain +++ b/compiler/rustc_codegen_cranelift/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2021-09-19" +channel = "nightly-2021-12-30" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/compiler/rustc_codegen_cranelift/scripts/cargo.rs b/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs similarity index 95% rename from compiler/rustc_codegen_cranelift/scripts/cargo.rs rename to compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs index 89ec8da77d..41d82b581c 100644 --- a/compiler/rustc_codegen_cranelift/scripts/cargo.rs +++ b/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs @@ -42,7 +42,7 @@ fn main() { "RUSTFLAGS", env::var("RUSTFLAGS").unwrap_or(String::new()) + " -Cprefer-dynamic", ); - std::array::IntoIter::new(["rustc".to_string()]) + IntoIterator::into_iter(["rustc".to_string()]) .chain(env::args().skip(2)) .chain([ "--".to_string(), @@ -56,7 +56,7 @@ fn main() { "RUSTFLAGS", env::var("RUSTFLAGS").unwrap_or(String::new()) + " -Cprefer-dynamic", ); - std::array::IntoIter::new(["rustc".to_string()]) + IntoIterator::into_iter(["rustc".to_string()]) .chain(env::args().skip(2)) .chain([ "--".to_string(), diff --git a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh index ca83e7096b..73600faa1e 100644 --- a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh +++ b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh @@ -1,7 +1,7 @@ #!/bin/bash set -e -./y.rs build +./y.rs build --no-unstable-features source scripts/config.sh echo "[SETUP] Rust fork" @@ -33,7 +33,7 @@ index d95b5b7f17f..00b6f0e3635 100644 [dependencies] core = { path = "../core" } -compiler_builtins = { version = "0.1.40", features = ['rustc-dep-of-std'] } -+compiler_builtins = { version = "0.1.46", features = ['rustc-dep-of-std', 'no-asm'] } ++compiler_builtins = { version = "0.1.66", features = ['rustc-dep-of-std', 'no-asm'] } [dev-dependencies] rand = "0.7" @@ -53,5 +53,6 @@ local-rebuild = true [rust] codegen-backends = ["cranelift"] deny-warnings = false +verbose-tests = false EOF popd diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh index b714d47fec..6bcc3049ec 100755 --- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh +++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh @@ -10,7 +10,7 @@ pushd rust cargo install ripgrep -rm -r src/test/ui/{extern/,panics/,unsized-locals/,thinlto/,simd*,*lto*.rs,linkage*,unwind-*.rs} || true +rm -r src/test/ui/{extern/,panics/,unsized-locals/,lto/,simd*,linkage*,unwind-*.rs} || true for test in $(rg --files-with-matches "asm!|catch_unwind|should_panic|lto|// needs-asm-support" src/test/ui); do rm $test done @@ -30,22 +30,25 @@ rm src/test/ui/cleanup-rvalue-temp-during-incomplete-alloc.rs rm src/test/ui/issues/issue-26655.rs rm src/test/ui/issues/issue-29485.rs rm src/test/ui/issues/issue-30018-panic.rs -rm src/test/ui/multi-panic.rs +rm src/test/ui/process/multi-panic.rs rm src/test/ui/sepcomp/sepcomp-unwind.rs rm src/test/ui/structs-enums/unit-like-struct-drop-run.rs -rm src/test/ui/terminate-in-initializer.rs +rm src/test/ui/drop/terminate-in-initializer.rs rm src/test/ui/threads-sendsync/task-stderr.rs rm src/test/ui/numbers-arithmetic/int-abs-overflow.rs rm src/test/ui/drop/drop-trait-enum.rs rm src/test/ui/numbers-arithmetic/issue-8460.rs -rm src/test/ui/rt-explody-panic-payloads.rs +rm src/test/ui/runtime/rt-explody-panic-payloads.rs rm src/test/incremental/change_crate_dep_kind.rs +rm src/test/ui/threads-sendsync/unwind-resource.rs rm src/test/ui/issues/issue-28950.rs # depends on stack size optimizations -rm src/test/ui/init-large-type.rs # same +rm src/test/ui/codegen/init-large-type.rs # same rm src/test/ui/sse2.rs # cpuid not supported, so sse2 not detected rm src/test/ui/issues/issue-33992.rs # unsupported linkages rm src/test/ui/issues/issue-51947.rs # same +rm src/test/incremental/hashes/function_interfaces.rs # same +rm src/test/incremental/hashes/statics.rs # same rm src/test/ui/numbers-arithmetic/saturating-float-casts.rs # intrinsic gives different but valid result rm src/test/ui/mir/mir_misc_casts.rs # depends on deduplication of constants rm src/test/ui/mir/mir_raw_fat_ptr.rs # same @@ -59,22 +62,22 @@ rm src/test/ui/intrinsics/intrinsic-nearby.rs # unimplemented nearbyintf32 and n rm src/test/incremental/hashes/inline_asm.rs # inline asm rm src/test/incremental/issue-72386.rs # same -rm src/test/incremental/issue-49482.rs # same -rm src/test/incremental/issue-54059.rs # same rm src/test/incremental/lto.rs # requires lto +rm src/test/incremental/dirty_clean.rs # TODO rm -r src/test/run-make/emit-shared-files # requires the rustdoc executable in build/bin/ rm -r src/test/run-make/unstable-flag-required # same +rm -r src/test/run-make/rustdoc-* # same rm -r src/test/run-make/emit-named-files # requires full --emit support -rm src/test/pretty/asm.rs # inline asm -rm src/test/pretty/raw-str-nonexpr.rs # same - rm -r src/test/run-pass-valgrind/unsized-locals rm src/test/ui/json-bom-plus-crlf-multifile.rs # differing warning rm src/test/ui/json-bom-plus-crlf.rs # same +rm src/test/ui/intrinsics/const-eval-select-x86_64.rs # same rm src/test/ui/match/issue-82392.rs # differing error +rm src/test/ui/consts/min_const_fn/address_of_const.rs # same +rm src/test/ui/consts/issue-miri-1910.rs # same rm src/test/ui/type-alias-impl-trait/cross_crate_ice*.rs # requires removed aux dep rm src/test/ui/allocator/no_std-alloc-error-handler-default.rs # missing rust_oom definition @@ -88,6 +91,16 @@ rm -r src/test/run-make/fmt-write-bloat/ # tests an optimization rm src/test/ui/abi/mir/mir_codegen_calls_variadic.rs # requires float varargs rm src/test/ui/abi/variadic-ffi.rs # requires callee side vararg support +rm src/test/ui/command/command-current-dir.rs # can't find libstd.so + +rm src/test/ui/abi/stack-protector.rs # requires stack protector support + +rm src/test/incremental/issue-80691-bad-eval-cache.rs # wrong exit code +rm src/test/incremental/spike-neg1.rs # errors out for some reason +rm src/test/incremental/spike-neg2.rs # same + +rm src/test/incremental/thinlto/cgu_invalidated_when_import_{added,removed}.rs # requires LLVM + echo "[TEST] rustc test suite" -RUST_TEST_NOCAPTURE=1 COMPILETEST_FORCE_STAGE0=1 ./x.py test --stage 0 src/test/{codegen-units,run-make,run-pass-valgrind,ui} +RUST_TEST_NOCAPTURE=1 COMPILETEST_FORCE_STAGE0=1 ./x.py test --stage 0 src/test/{codegen-units,run-make,run-pass-valgrind,ui,incremental} popd diff --git a/compiler/rustc_codegen_cranelift/scripts/tests.sh b/compiler/rustc_codegen_cranelift/scripts/tests.sh index 28a7980d66..bdb3de0936 100755 --- a/compiler/rustc_codegen_cranelift/scripts/tests.sh +++ b/compiler/rustc_codegen_cranelift/scripts/tests.sh @@ -35,6 +35,10 @@ function base_sysroot_tests() { $MY_RUSTC example/arbitrary_self_types_pointers_and_wrappers.rs --crate-name arbitrary_self_types_pointers_and_wrappers --crate-type bin --target "$TARGET_TRIPLE" $RUN_WRAPPER ./target/out/arbitrary_self_types_pointers_and_wrappers + echo "[AOT] issue_91827_extern_types" + $MY_RUSTC example/issue-91827-extern-types.rs --crate-name issue_91827_extern_types --crate-type bin --target "$TARGET_TRIPLE" + $RUN_WRAPPER ./target/out/issue_91827_extern_types + echo "[AOT] alloc_system" $MY_RUSTC example/alloc_system.rs --crate-type lib --target "$TARGET_TRIPLE" @@ -76,73 +80,73 @@ function base_sysroot_tests() { function extended_sysroot_tests() { pushd rand - ../build/cargo clean + ../build/cargo-clif clean if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then echo "[TEST] rust-random/rand" - ../build/cargo test --workspace + ../build/cargo-clif test --workspace else echo "[AOT] rust-random/rand" - ../build/cargo build --workspace --target $TARGET_TRIPLE --tests + ../build/cargo-clif build --workspace --target $TARGET_TRIPLE --tests fi popd pushd simple-raytracer if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then echo "[BENCH COMPILE] ebobby/simple-raytracer" - hyperfine --runs "${RUN_RUNS:-10}" --warmup 1 --prepare "../build/cargo clean" \ + hyperfine --runs "${RUN_RUNS:-10}" --warmup 1 --prepare "../build/cargo-clif clean" \ "RUSTC=rustc RUSTFLAGS='' cargo build" \ - "../build/cargo build" + "../build/cargo-clif build" echo "[BENCH RUN] ebobby/simple-raytracer" cp ./target/debug/main ./raytracer_cg_clif hyperfine --runs "${RUN_RUNS:-10}" ./raytracer_cg_llvm ./raytracer_cg_clif else - ../build/cargo clean + ../build/cargo-clif clean echo "[BENCH COMPILE] ebobby/simple-raytracer (skipped)" echo "[COMPILE] ebobby/simple-raytracer" - ../build/cargo build --target $TARGET_TRIPLE + ../build/cargo-clif build --target $TARGET_TRIPLE echo "[BENCH RUN] ebobby/simple-raytracer (skipped)" fi popd pushd build_sysroot/sysroot_src/library/core/tests echo "[TEST] libcore" - ../../../../../build/cargo clean + ../../../../../build/cargo-clif clean if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then - ../../../../../build/cargo test + ../../../../../build/cargo-clif test else - ../../../../../build/cargo build --target $TARGET_TRIPLE --tests + ../../../../../build/cargo-clif build --target $TARGET_TRIPLE --tests fi popd pushd regex echo "[TEST] rust-lang/regex example shootout-regex-dna" - ../build/cargo clean + ../build/cargo-clif clean export RUSTFLAGS="$RUSTFLAGS --cap-lints warn" # newer aho_corasick versions throw a deprecation warning # Make sure `[codegen mono items] start` doesn't poison the diff - ../build/cargo build --example shootout-regex-dna --target $TARGET_TRIPLE + ../build/cargo-clif build --example shootout-regex-dna --target $TARGET_TRIPLE if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then cat examples/regexdna-input.txt \ - | ../build/cargo run --example shootout-regex-dna --target $TARGET_TRIPLE \ + | ../build/cargo-clif run --example shootout-regex-dna --target $TARGET_TRIPLE \ | grep -v "Spawned thread" > res.txt diff -u res.txt examples/regexdna-output.txt fi if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then echo "[TEST] rust-lang/regex tests" - ../build/cargo test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options -q + ../build/cargo-clif test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options -q else echo "[AOT] rust-lang/regex tests" - ../build/cargo build --tests --target $TARGET_TRIPLE + ../build/cargo-clif build --tests --target $TARGET_TRIPLE fi popd pushd portable-simd echo "[TEST] rust-lang/portable-simd" - ../build/cargo clean - ../build/cargo build --all-targets --target $TARGET_TRIPLE + ../build/cargo-clif clean + ../build/cargo-clif build --all-targets --target $TARGET_TRIPLE if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then - ../build/cargo test -q + ../build/cargo-clif test -q fi popd } diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 78fdf9c02d..72ebc84c1a 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -18,11 +18,11 @@ pub(crate) use self::returning::codegen_return; fn clif_sig_from_fn_abi<'tcx>( tcx: TyCtxt<'tcx>, - triple: &target_lexicon::Triple, + default_call_conv: CallConv, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, ) -> Signature { let call_conv = match fn_abi.conv { - Conv::Rust | Conv::C => CallConv::triple_default(triple), + Conv::Rust | Conv::C => default_call_conv, Conv::X86_64SysV => CallConv::SystemV, Conv::X86_64Win64 => CallConv::WindowsFastcall, Conv::ArmAapcs @@ -55,7 +55,7 @@ pub(crate) fn get_function_sig<'tcx>( assert!(!inst.substs.needs_infer()); clif_sig_from_fn_abi( tcx, - triple, + CallConv::triple_default(triple), &RevealAllLayoutCx(tcx).fn_abi_of_instance(inst, ty::List::empty()), ) } @@ -91,7 +91,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { returns: Vec, args: &[Value], ) -> &[Value] { - let sig = Signature { params, returns, call_conv: CallConv::triple_default(self.triple()) }; + let sig = Signature { params, returns, call_conv: self.target_config.default_call_conv }; let func_id = self.module.declare_function(name, Linkage::Import, &sig).unwrap(); let func_ref = self.module.declare_func_in_func(func_id, &mut self.bcx.func); let call_inst = self.bcx.ins().call(func_ref, args); @@ -420,7 +420,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( } let (ptr, method) = crate::vtable::get_ptr_and_method_ref(fx, args[0].value, idx); - let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi); + let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi); let sig = fx.bcx.import_signature(sig); (CallTarget::Indirect(sig, method), Some(ptr)) @@ -440,7 +440,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( } let func = codegen_operand(fx, func).load_scalar(fx); - let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi); + let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi); let sig = fx.bcx.import_signature(sig); (CallTarget::Indirect(sig, func), None) @@ -531,7 +531,7 @@ pub(crate) fn codegen_drop<'tcx>( let fn_abi = RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(virtual_drop, ty::List::empty()); - let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi); + let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi); let sig = fx.bcx.import_signature(sig); fx.bcx.ins().call_indirect(sig, drop_fn, &[ptr]); } diff --git a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs index 2144e7ed67..9f0bd31e95 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs @@ -71,7 +71,7 @@ fn cast_target_to_abi_params(cast: CastTarget) -> SmallVec<[AbiParam; 2]> { .prefix .iter() .flatten() - .map(|&kind| reg_to_abi_param(Reg { kind, size: cast.prefix_chunk_size })) + .map(|®| reg_to_abi_param(reg)) .chain((0..rest_count).map(|_| reg_to_abi_param(cast.rest.unit))) .collect::>(); @@ -117,7 +117,9 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> { PassMode::Cast(cast) => cast_target_to_abi_params(cast), PassMode::Indirect { attrs, extra_attrs: None, on_stack } => { if on_stack { - let size = u32::try_from(self.layout.size.bytes()).unwrap(); + // Abi requires aligning struct size to pointer size + let size = self.layout.size.align_to(tcx.data_layout.pointer_align.abi); + let size = u32::try_from(size.bytes()).unwrap(); smallvec![apply_arg_attrs_to_abi_param( AbiParam::special(pointer_ty(tcx), ArgumentPurpose::StructArgument(size),), attrs @@ -204,7 +206,6 @@ pub(super) fn from_casted_value<'tcx>( // It may also be smaller for example when the type is a wrapper around an integer with a // larger alignment than the integer. size: (std::cmp::max(abi_param_size, layout_size) + 15) / 16 * 16, - offset: None, }); let ptr = Pointer::new(fx.bcx.ins().stack_addr(pointer_ty(fx.tcx), stack_slot, 0)); let mut offset = 0; diff --git a/compiler/rustc_codegen_cranelift/src/archive.rs b/compiler/rustc_codegen_cranelift/src/archive.rs index 71f510c037..b0eb3864d8 100644 --- a/compiler/rustc_codegen_cranelift/src/archive.rs +++ b/compiler/rustc_codegen_cranelift/src/archive.rs @@ -1,7 +1,6 @@ //! Creation of ar archives like for the lib and staticlib crate type use std::collections::BTreeMap; -use std::convert::TryFrom; use std::fs::File; use std::io::{self, Read, Seek}; use std::path::{Path, PathBuf}; @@ -10,7 +9,7 @@ use rustc_codegen_ssa::back::archive::ArchiveBuilder; use rustc_session::Session; use object::read::archive::ArchiveFile; -use object::{Object, ObjectSymbol, ReadCache, SymbolKind}; +use object::{Object, ObjectSymbol, ReadCache}; #[derive(Debug)] enum ArchiveEntry { @@ -150,12 +149,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { object .symbols() .filter_map(|symbol| { - if symbol.is_undefined() - || symbol.is_local() - || symbol.kind() != SymbolKind::Data - && symbol.kind() != SymbolKind::Text - && symbol.kind() != SymbolKind::Tls - { + if symbol.is_undefined() || symbol.is_local() { None } else { symbol.name().map(|name| name.as_bytes().to_vec()).ok() diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 1b30edd293..b16f5af66f 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -1,6 +1,7 @@ //! Codegen of a single function use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink}; +use rustc_ast::InlineAsmOptions; use rustc_index::vec::IndexVec; use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::layout::FnAbiOf; @@ -48,13 +49,15 @@ pub(crate) fn codegen_fn<'tcx>( (0..mir.basic_blocks().len()).map(|_| bcx.create_block()).collect(); // Make FunctionCx - let pointer_type = module.target_config().pointer_type(); + let target_config = module.target_config(); + let pointer_type = target_config.pointer_type(); let clif_comments = crate::pretty_clif::CommentWriter::new(tcx, instance); let mut fx = FunctionCx { cx, module, tcx, + target_config, pointer_type, constants_cx: ConstantCx::new(), @@ -71,8 +74,6 @@ pub(crate) fn codegen_fn<'tcx>( clif_comments, source_info_set: indexmap::IndexSet::new(), next_ssa_var: 0, - - inline_asm_index: 0, }; let arg_uninhabited = fx @@ -203,7 +204,6 @@ pub(crate) fn verify_func( tcx.sess.err(&format!("{:?}", err)); let pretty_error = cranelift_codegen::print_errors::pretty_verifier_error( &func, - None, Some(Box::new(writer)), err, ); @@ -239,7 +239,8 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) { fx.add_comment(inst, terminator_head); } - fx.set_debug_loc(bb_data.terminator().source_info); + let source_info = bb_data.terminator().source_info; + fx.set_debug_loc(source_info); match &bb_data.terminator().kind { TerminatorKind::Goto { target } => { @@ -294,20 +295,18 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) { AssertKind::BoundsCheck { ref len, ref index } => { let len = codegen_operand(fx, len).load_scalar(fx); let index = codegen_operand(fx, index).load_scalar(fx); - let location = fx - .get_caller_location(bb_data.terminator().source_info.span) - .load_scalar(fx); + let location = fx.get_caller_location(source_info.span).load_scalar(fx); codegen_panic_inner( fx, rustc_hir::LangItem::PanicBoundsCheck, &[index, len, location], - bb_data.terminator().source_info.span, + source_info.span, ); } _ => { let msg_str = msg.description(); - codegen_panic(fx, msg_str, bb_data.terminator().source_info.span); + codegen_panic(fx, msg_str, source_info.span); } } } @@ -378,10 +377,18 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) { options, destination, line_spans: _, + cleanup: _, } => { + if options.contains(InlineAsmOptions::MAY_UNWIND) { + fx.tcx.sess.span_fatal( + source_info.span, + "cranelift doesn't support unwinding from inline assembly.", + ); + } + crate::inline_asm::codegen_inline_asm( fx, - bb_data.terminator().source_info.span, + source_info.span, template, operands, *options, @@ -415,7 +422,7 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) { } TerminatorKind::Drop { place, target, unwind: _ } => { let drop_place = codegen_place(fx, *place); - crate::abi::codegen_drop(fx, bb_data.terminator().source_info.span, drop_place); + crate::abi::codegen_drop(fx, source_info.span, drop_place); let target_block = fx.get_block(*target); fx.bcx.ins().jump(target_block, &[]); @@ -671,7 +678,7 @@ fn codegen_stmt<'tcx>( // FIXME use emit_small_memset where possible let addr = lval.to_ptr().get_addr(fx); let val = operand.load_scalar(fx); - fx.bcx.call_memset(fx.module.target_config(), addr, val, times); + fx.bcx.call_memset(fx.target_config, addr, val, times); } else { let loop_block = fx.bcx.create_block(); let loop_block2 = fx.bcx.create_block(); @@ -708,30 +715,6 @@ fn codegen_stmt<'tcx>( let operand = operand.load_scalar(fx); lval.write_cvalue(fx, CValue::by_val(operand, box_layout)); } - Rvalue::NullaryOp(NullOp::Box, content_ty) => { - let usize_type = fx.clif_type(fx.tcx.types.usize).unwrap(); - let content_ty = fx.monomorphize(content_ty); - let layout = fx.layout_of(content_ty); - let llsize = fx.bcx.ins().iconst(usize_type, layout.size.bytes() as i64); - let llalign = fx.bcx.ins().iconst(usize_type, layout.align.abi.bytes() as i64); - let box_layout = fx.layout_of(fx.tcx.mk_box(content_ty)); - - // Allocate space: - let def_id = - match fx.tcx.lang_items().require(rustc_hir::LangItem::ExchangeMalloc) { - Ok(id) => id, - Err(s) => { - fx.tcx - .sess - .fatal(&format!("allocation of `{}` {}", box_layout.ty, s)); - } - }; - let instance = ty::Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx); - let func_ref = fx.get_function_ref(instance); - let call = fx.bcx.ins().call(func_ref, &[llsize, llalign]); - let ptr = fx.bcx.inst_results(call)[0]; - lval.write_cvalue(fx, CValue::by_val(ptr, box_layout)); - } Rvalue::NullaryOp(null_op, ty) => { assert!( lval.layout() @@ -742,10 +725,8 @@ fn codegen_stmt<'tcx>( let val = match null_op { NullOp::SizeOf => layout.size.bytes(), NullOp::AlignOf => layout.align.abi.bytes(), - NullOp::Box => unreachable!(), }; - let val = - CValue::const_val(fx, fx.layout_of(fx.tcx.types.usize), val.into()); + let val = CValue::const_val(fx, fx.layout_of(fx.tcx.types.usize), val.into()); lval.write_cvalue(fx, val); } Rvalue::Aggregate(ref kind, ref operands) => match kind.as_ref() { @@ -793,7 +774,7 @@ fn codegen_stmt<'tcx>( let elem_size: u64 = pointee.size.bytes(); let bytes = if elem_size != 1 { fx.bcx.ins().imul_imm(count, elem_size as i64) } else { count }; - fx.bcx.call_memcpy(fx.module.target_config(), dst, src, bytes); + fx.bcx.call_memcpy(fx.target_config, dst, src, bytes); } } } diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 0e84681d9a..3b6025c73d 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -1,3 +1,4 @@ +use cranelift_codegen::isa::TargetFrontendConfig; use rustc_index::vec::IndexVec; use rustc_middle::ty::layout::{ FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, @@ -235,7 +236,8 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> { pub(crate) cx: &'clif mut crate::CodegenCx<'tcx>, pub(crate) module: &'m mut dyn Module, pub(crate) tcx: TyCtxt<'tcx>, - pub(crate) pointer_type: Type, // Cached from module + pub(crate) target_config: TargetFrontendConfig, // Cached from module + pub(crate) pointer_type: Type, // Cached from module pub(crate) constants_cx: ConstantCx, pub(crate) instance: Instance<'tcx>, @@ -255,8 +257,6 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> { /// This should only be accessed by `CPlace::new_var`. pub(crate) next_ssa_var: u32, - - pub(crate) inline_asm_index: u32, } impl<'tcx> LayoutOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> { @@ -359,10 +359,6 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { crate::constant::codegen_const_value(self, const_loc, self.tcx.caller_location_ty()) } - pub(crate) fn triple(&self) -> &target_lexicon::Triple { - self.module.isa().triple() - } - pub(crate) fn anonymous_str(&mut self, msg: &str) -> Value { let mut data_ctx = DataContext::new(); data_ctx.define(msg.as_bytes().to_vec().into_boxed_slice()); diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 5c4991f1fb..9a6c45ae98 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -369,7 +369,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant TodoItem::Static(def_id) => { //println!("static {:?}", def_id); - let section_name = tcx.codegen_fn_attrs(def_id).link_section.map(|s| s.as_str()); + let section_name = tcx.codegen_fn_attrs(def_id).link_section; let alloc = tcx.eval_static_initializer(def_id).unwrap(); @@ -388,6 +388,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant if let Some(section_name) = section_name { let (segment_name, section_name) = if tcx.sess.target.is_like_osx { + let section_name = section_name.as_str(); if let Some(names) = section_name.split_once(',') { names } else { @@ -397,7 +398,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant )); } } else { - ("", &*section_name) + ("", section_name.as_str()) }; data_ctx.set_segment_section(segment_name, section_name); } diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs index c8c2d50b03..589910ede9 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/emit.rs @@ -67,10 +67,8 @@ impl WriterRelocate { } /// Perform the collected relocations to be usable for JIT usage. - #[cfg(feature = "jit")] + #[cfg(all(feature = "jit", not(windows)))] pub(super) fn relocate_for_jit(mut self, jit_module: &cranelift_jit::JITModule) -> Vec { - use std::convert::TryInto; - for reloc in self.relocs.drain(..) { match reloc.name { super::DebugRelocName::Section(_) => unreachable!(), diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs index 6d172817cb..638b025be2 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs @@ -10,7 +10,7 @@ use crate::prelude::*; use rustc_index::vec::IndexVec; use cranelift_codegen::entity::EntityRef; -use cranelift_codegen::ir::{LabelValueLoc, StackSlots, ValueLabel, ValueLoc}; +use cranelift_codegen::ir::{Endianness, LabelValueLoc, ValueLabel}; use cranelift_codegen::isa::TargetIsa; use cranelift_codegen::ValueLocRange; @@ -23,15 +23,6 @@ use gimli::{Encoding, Format, LineEncoding, RunTimeEndian, X86_64}; pub(crate) use emit::{DebugReloc, DebugRelocName}; pub(crate) use unwind::UnwindContext; -fn target_endian(tcx: TyCtxt<'_>) -> RunTimeEndian { - use rustc_target::abi::Endian; - - match tcx.data_layout.endian { - Endian::Big => RunTimeEndian::Big, - Endian::Little => RunTimeEndian::Little, - } -} - pub(crate) struct DebugContext<'tcx> { tcx: TyCtxt<'tcx>, @@ -60,6 +51,11 @@ impl<'tcx> DebugContext<'tcx> { address_size: isa.frontend_config().pointer_bytes(), }; + let endian = match isa.endianness() { + Endianness::Little => RunTimeEndian::Little, + Endianness::Big => RunTimeEndian::Big, + }; + let mut dwarf = DwarfUnit::new(encoding); let producer = format!( @@ -67,7 +63,12 @@ impl<'tcx> DebugContext<'tcx> { rustc_interface::util::version_str().unwrap_or("unknown version"), cranelift_codegen::VERSION, ); - let comp_dir = tcx.sess.opts.working_dir.to_string_lossy(FileNameDisplayPreference::Remapped).into_owned(); + let comp_dir = tcx + .sess + .opts + .working_dir + .to_string_lossy(FileNameDisplayPreference::Remapped) + .into_owned(); let (name, file_info) = match tcx.sess.local_crate_source_file.clone() { Some(path) => { let name = path.to_string_lossy().into_owned(); @@ -103,7 +104,7 @@ impl<'tcx> DebugContext<'tcx> { DebugContext { tcx, - endian: target_endian(tcx), + endian, dwarf, unit_range_list: RangeList(Vec::new()), @@ -250,7 +251,7 @@ impl<'tcx> DebugContext<'tcx> { // FIXME make it more reliable and implement scopes before re-enabling this. if false { - let value_labels_ranges = context.build_value_labels_ranges(isa).unwrap(); + let value_labels_ranges = std::collections::HashMap::new(); // FIXME for (local, _local_decl) in mir.local_decls.iter_enumerated() { let ty = self.tcx.subst_and_normalize_erasing_regions( @@ -264,7 +265,6 @@ impl<'tcx> DebugContext<'tcx> { self, isa, symbol, - context, &local_map, &value_labels_ranges, Place { local, projection: ty::List::empty() }, @@ -283,7 +283,6 @@ fn place_location<'tcx>( debug_context: &mut DebugContext<'tcx>, isa: &dyn TargetIsa, symbol: usize, - context: &Context, local_map: &IndexVec>, #[allow(rustc::default_hash_types)] value_labels_ranges: &std::collections::HashMap< ValueLabel, @@ -306,12 +305,7 @@ fn place_location<'tcx>( addend: i64::from(value_loc_range.start), }, end: Address::Symbol { symbol, addend: i64::from(value_loc_range.end) }, - data: translate_loc( - isa, - value_loc_range.loc, - &context.func.stack_slots, - ) - .unwrap(), + data: translate_loc(isa, value_loc_range.loc).unwrap(), }) .collect(), ); @@ -340,34 +334,14 @@ fn place_location<'tcx>( AttributeValue::Exprloc(Expression::new()) // For PointerBase::Stack: - //AttributeValue::Exprloc(translate_loc(ValueLoc::Stack(*stack_slot), &context.func.stack_slots).unwrap()) + //AttributeValue::Exprloc(translate_loc(ValueLoc::Stack(*stack_slot)).unwrap()) } } } // Adapted from https://github.com/CraneStation/wasmtime/blob/5a1845b4caf7a5dba8eda1fef05213a532ed4259/crates/debug/src/transform/expression.rs#L59-L137 -fn translate_loc( - isa: &dyn TargetIsa, - loc: LabelValueLoc, - stack_slots: &StackSlots, -) -> Option { +fn translate_loc(isa: &dyn TargetIsa, loc: LabelValueLoc) -> Option { match loc { - LabelValueLoc::ValueLoc(ValueLoc::Reg(reg)) => { - let machine_reg = isa.map_dwarf_register(reg).unwrap(); - let mut expr = Expression::new(); - expr.op_reg(gimli::Register(machine_reg)); - Some(expr) - } - LabelValueLoc::ValueLoc(ValueLoc::Stack(ss)) => { - if let Some(ss_offset) = stack_slots[ss].offset { - let mut expr = Expression::new(); - expr.op_breg(X86_64::RBP, i64::from(ss_offset) + 16); - Some(expr) - } else { - None - } - } - LabelValueLoc::ValueLoc(ValueLoc::Unassigned) => unreachable!(), LabelValueLoc::Reg(reg) => { let machine_reg = isa.map_regalloc_reg_to_dwarf(reg).unwrap(); let mut expr = Expression::new(); diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs index 9984dc92c4..9dc9b2cf9f 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/object.rs @@ -1,5 +1,3 @@ -use std::convert::{TryFrom, TryInto}; - use rustc_data_structures::fx::FxHashMap; use cranelift_module::FuncId; diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs index f0896ea0e1..e4f2833809 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs @@ -2,6 +2,7 @@ use crate::prelude::*; +use cranelift_codegen::ir::Endianness; use cranelift_codegen::isa::{unwind::UnwindInfo, TargetIsa}; use cranelift_object::ObjectProduct; @@ -17,8 +18,11 @@ pub(crate) struct UnwindContext { } impl UnwindContext { - pub(crate) fn new(tcx: TyCtxt<'_>, isa: &dyn TargetIsa, pic_eh_frame: bool) -> Self { - let endian = super::target_endian(tcx); + pub(crate) fn new(isa: &dyn TargetIsa, pic_eh_frame: bool) -> Self { + let endian = match isa.endianness() { + Endianness::Little => RunTimeEndian::Little, + Endianness::Big => RunTimeEndian::Big, + }; let mut frame_table = FrameTable::default(); let cie_id = if let Some(mut cie) = isa.create_systemv_cie() { diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 0a8d6122aa..046e4393a6 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -4,6 +4,7 @@ use std::path::PathBuf; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; +use rustc_codegen_ssa::back::metadata::create_compressed_metadata_file; use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_metadata::EncodedMetadata; @@ -84,7 +85,7 @@ fn reuse_workproduct_for_cgu( let work_product = cgu.work_product(tcx); if let Some(saved_file) = &work_product.saved_file { let obj_out = - tcx.output_filenames(()).temp_path(OutputType::Object, Some(&cgu.name().as_str())); + tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu.name().as_str())); object = Some(obj_out.clone()); let source_file = rustc_incremental::in_incr_comp_dir_sess(&tcx.sess, &saved_file); if let Err(err) = rustc_fs_util::link_or_copy(&source_file, &obj_out) { @@ -123,6 +124,7 @@ fn module_codegen( backend_config.clone(), module.isa(), tcx.sess.opts.debuginfo != DebugInfo::None, + cgu_name, ); super::predefine_mono_items(tcx, &mut module, &mono_items); for (mono_item, _) in mono_items { @@ -176,7 +178,7 @@ fn module_codegen( ) }); - codegen_global_asm(tcx, &cgu.name().as_str(), &cx.global_asm); + codegen_global_asm(tcx, cgu.name().as_str(), &cx.global_asm); codegen_result } @@ -207,7 +209,7 @@ pub(crate) fn run_aot( cgus.iter() .map(|cgu| { let cgu_reuse = determine_cgu_reuse(tcx, cgu); - tcx.sess.cgu_reuse_tracker.set_actual_reuse(&cgu.name().as_str(), cgu_reuse); + tcx.sess.cgu_reuse_tracker.set_actual_reuse(cgu.name().as_str(), cgu_reuse); match cgu_reuse { _ if backend_config.disable_incr_cache => {} @@ -241,7 +243,7 @@ pub(crate) fn run_aot( let isa = crate::build_isa(tcx.sess, &backend_config); let mut allocator_module = make_module(tcx.sess, isa, "allocator_shim".to_string()); assert_eq!(pointer_ty(tcx), allocator_module.target_config().pointer_type()); - let mut allocator_unwind_context = UnwindContext::new(tcx, allocator_module.isa(), true); + let mut allocator_unwind_context = UnwindContext::new(allocator_module.isa(), true); let created_alloc_shim = crate::allocator::codegen(tcx, &mut allocator_module, &mut allocator_unwind_context); @@ -277,7 +279,8 @@ pub(crate) fn run_aot( let tmp_file = tcx.output_filenames(()).temp_path(OutputType::Metadata, Some(&metadata_cgu_name)); - let obj = crate::metadata::new_metadata_object(tcx, &metadata_cgu_name, &metadata); + let symbol_name = rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx); + let obj = create_compressed_metadata_file(tcx.sess, &metadata, &symbol_name); if let Err(err) = std::fs::write(&tmp_file, obj) { tcx.sess.fatal(&format!("error writing metadata object file: {}", err)); diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs index 76fbc9ad51..309d27090b 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs @@ -3,7 +3,7 @@ use std::cell::RefCell; use std::ffi::CString; -use std::lazy::{Lazy, SyncOnceCell}; +use std::lazy::SyncOnceCell; use std::os::raw::{c_char, c_int}; use std::sync::{mpsc, Mutex}; @@ -11,6 +11,7 @@ use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink}; use rustc_codegen_ssa::CrateInfo; use rustc_middle::mir::mono::MonoItem; use rustc_session::Session; +use rustc_span::Symbol; use cranelift_jit::{JITBuilder, JITModule}; @@ -23,7 +24,7 @@ struct JitState { } thread_local! { - static LAZY_JIT_STATE: RefCell> = RefCell::new(None); + static LAZY_JIT_STATE: RefCell> = const { RefCell::new(None) }; } /// The Sender owned by the rustc thread @@ -50,12 +51,11 @@ impl UnsafeMessage { fn send(self) -> Result<(), mpsc::SendError> { thread_local! { /// The Sender owned by the local thread - static LOCAL_MESSAGE_SENDER: Lazy> = Lazy::new(|| + static LOCAL_MESSAGE_SENDER: mpsc::Sender = GLOBAL_MESSAGE_SENDER .get().unwrap() .lock().unwrap() - .clone() - ); + .clone(); } LOCAL_MESSAGE_SENDER.with(|sender| sender.send(self)) } @@ -76,7 +76,13 @@ fn create_jit_module<'tcx>( jit_builder.symbols(imported_symbols); let mut jit_module = JITModule::new(jit_builder); - let mut cx = crate::CodegenCx::new(tcx, backend_config.clone(), jit_module.isa(), false); + let mut cx = crate::CodegenCx::new( + tcx, + backend_config.clone(), + jit_module.isa(), + false, + Symbol::intern("dummy_cgu_name"), + ); crate::allocator::codegen(tcx, &mut jit_module, &mut cx.unwind_context); crate::main_shim::maybe_create_entry_wrapper( @@ -246,7 +252,13 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) -> jit_module.prepare_for_function_redefine(func_id).unwrap(); - let mut cx = crate::CodegenCx::new(tcx, backend_config, jit_module.isa(), false); + let mut cx = crate::CodegenCx::new( + tcx, + backend_config, + jit_module.isa(), + false, + Symbol::intern("dummy_cgu_name"), + ); tcx.sess.time("codegen fn", || crate::base::codegen_fn(&mut cx, jit_module, instance)); assert!(cx.global_asm.is_empty()); diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs index 09c5e6031c..93384bc551 100644 --- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs @@ -1,4 +1,4 @@ -//! Codegen of [`asm!`] invocations. +//! Codegen of `asm!` invocations. use crate::prelude::*; @@ -6,6 +6,7 @@ use std::fmt::Write; use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_middle::mir::InlineAsmOperand; +use rustc_span::Symbol; use rustc_target::asm::*; pub(crate) fn codegen_inline_asm<'tcx>( @@ -17,10 +18,7 @@ pub(crate) fn codegen_inline_asm<'tcx>( ) { // FIXME add .eh_frame unwind info directives - if template.is_empty() { - // Black box - return; - } else if template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) { + if template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) { let true_ = fx.bcx.ins().iconst(types::I32, 1); fx.bcx.ins().trapnz(true_, TrapCode::User(1)); return; @@ -41,8 +39,10 @@ pub(crate) fn codegen_inline_asm<'tcx>( assert_eq!(operands.len(), 4); let (leaf, eax_place) = match operands[1] { InlineAsmOperand::InOut { reg, late: true, ref in_value, out_place } => { - let reg = expect_reg(reg); - assert_eq!(reg, InlineAsmReg::X86(X86InlineAsmReg::ax)); + assert_eq!( + reg, + InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)) + ); ( crate::base::codegen_operand(fx, in_value).load_scalar(fx), crate::base::codegen_place(fx, out_place.unwrap()), @@ -64,8 +64,10 @@ pub(crate) fn codegen_inline_asm<'tcx>( }; let (sub_leaf, ecx_place) = match operands[2] { InlineAsmOperand::InOut { reg, late: true, ref in_value, out_place } => { - let reg = expect_reg(reg); - assert_eq!(reg, InlineAsmReg::X86(X86InlineAsmReg::cx)); + assert_eq!( + reg, + InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)) + ); ( crate::base::codegen_operand(fx, in_value).load_scalar(fx), crate::base::codegen_place(fx, out_place.unwrap()), @@ -75,8 +77,10 @@ pub(crate) fn codegen_inline_asm<'tcx>( }; let edx_place = match operands[3] { InlineAsmOperand::Out { reg, late: true, place } => { - let reg = expect_reg(reg); - assert_eq!(reg, InlineAsmReg::X86(X86InlineAsmReg::dx)); + assert_eq!( + reg, + InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)) + ); crate::base::codegen_place(fx, place.unwrap()) } _ => unreachable!(), @@ -96,60 +100,59 @@ pub(crate) fn codegen_inline_asm<'tcx>( crate::trap::trap_unimplemented(fx, "Alloca is not supported"); } - let mut slot_size = Size::from_bytes(0); - let mut clobbered_regs = Vec::new(); let mut inputs = Vec::new(); let mut outputs = Vec::new(); - let mut new_slot = |reg_class: InlineAsmRegClass| { - let reg_size = reg_class - .supported_types(InlineAsmArch::X86_64) - .iter() - .map(|(ty, _)| ty.size()) - .max() - .unwrap(); - let align = rustc_target::abi::Align::from_bytes(reg_size.bytes()).unwrap(); - slot_size = slot_size.align_to(align); - let offset = slot_size; - slot_size += reg_size; - offset + let mut asm_gen = InlineAssemblyGenerator { + tcx: fx.tcx, + arch: fx.tcx.sess.asm_arch.unwrap(), + template, + operands, + options, + registers: Vec::new(), + stack_slots_clobber: Vec::new(), + stack_slots_input: Vec::new(), + stack_slots_output: Vec::new(), + stack_slot_size: Size::from_bytes(0), }; + asm_gen.allocate_registers(); + asm_gen.allocate_stack_slots(); - // FIXME overlap input and output slots to save stack space - for operand in operands { + let inline_asm_index = fx.cx.inline_asm_index.get(); + fx.cx.inline_asm_index.set(inline_asm_index + 1); + let asm_name = format!( + "__inline_asm_{}_n{}", + fx.cx.cgu_name.as_str().replace('.', "__").replace('-', "_"), + inline_asm_index + ); + + let generated_asm = asm_gen.generate_asm_wrapper(&asm_name); + fx.cx.global_asm.push_str(&generated_asm); + + for (i, operand) in operands.iter().enumerate() { match *operand { - InlineAsmOperand::In { reg, ref value } => { - let reg = expect_reg(reg); - clobbered_regs.push((reg, new_slot(reg.reg_class()))); + InlineAsmOperand::In { reg: _, ref value } => { inputs.push(( - reg, - new_slot(reg.reg_class()), + asm_gen.stack_slots_input[i].unwrap(), crate::base::codegen_operand(fx, value).load_scalar(fx), )); } - InlineAsmOperand::Out { reg, late: _, place } => { - let reg = expect_reg(reg); - clobbered_regs.push((reg, new_slot(reg.reg_class()))); + InlineAsmOperand::Out { reg: _, late: _, place } => { if let Some(place) = place { outputs.push(( - reg, - new_slot(reg.reg_class()), + asm_gen.stack_slots_output[i].unwrap(), crate::base::codegen_place(fx, place), )); } } - InlineAsmOperand::InOut { reg, late: _, ref in_value, out_place } => { - let reg = expect_reg(reg); - clobbered_regs.push((reg, new_slot(reg.reg_class()))); + InlineAsmOperand::InOut { reg: _, late: _, ref in_value, out_place } => { inputs.push(( - reg, - new_slot(reg.reg_class()), + asm_gen.stack_slots_input[i].unwrap(), crate::base::codegen_operand(fx, in_value).load_scalar(fx), )); if let Some(out_place) = out_place { outputs.push(( - reg, - new_slot(reg.reg_class()), + asm_gen.stack_slots_output[i].unwrap(), crate::base::codegen_place(fx, out_place), )); } @@ -160,110 +163,474 @@ pub(crate) fn codegen_inline_asm<'tcx>( } } - let inline_asm_index = fx.inline_asm_index; - fx.inline_asm_index += 1; - let asm_name = format!("{}__inline_asm_{}", fx.symbol_name, inline_asm_index); - - let generated_asm = generate_asm_wrapper( - &asm_name, - InlineAsmArch::X86_64, - options, - template, - clobbered_regs, - &inputs, - &outputs, - ); - fx.cx.global_asm.push_str(&generated_asm); - - call_inline_asm(fx, &asm_name, slot_size, inputs, outputs); + call_inline_asm(fx, &asm_name, asm_gen.stack_slot_size, inputs, outputs); } -fn generate_asm_wrapper( - asm_name: &str, +struct InlineAssemblyGenerator<'a, 'tcx> { + tcx: TyCtxt<'tcx>, arch: InlineAsmArch, + template: &'a [InlineAsmTemplatePiece], + operands: &'a [InlineAsmOperand<'tcx>], options: InlineAsmOptions, - template: &[InlineAsmTemplatePiece], - clobbered_regs: Vec<(InlineAsmReg, Size)>, - inputs: &[(InlineAsmReg, Size, Value)], - outputs: &[(InlineAsmReg, Size, CPlace<'_>)], -) -> String { - let mut generated_asm = String::new(); - writeln!(generated_asm, ".globl {}", asm_name).unwrap(); - writeln!(generated_asm, ".type {},@function", asm_name).unwrap(); - writeln!(generated_asm, ".section .text.{},\"ax\",@progbits", asm_name).unwrap(); - writeln!(generated_asm, "{}:", asm_name).unwrap(); + registers: Vec>, + stack_slots_clobber: Vec>, + stack_slots_input: Vec>, + stack_slots_output: Vec>, + stack_slot_size: Size, +} - generated_asm.push_str(".intel_syntax noprefix\n"); - generated_asm.push_str(" push rbp\n"); - generated_asm.push_str(" mov rbp,rdi\n"); +impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { + fn allocate_registers(&mut self) { + let sess = self.tcx.sess; + let map = allocatable_registers( + self.arch, + |feature| sess.target_features.contains(&Symbol::intern(feature)), + &sess.target, + ); + let mut allocated = FxHashMap::<_, (bool, bool)>::default(); + let mut regs = vec![None; self.operands.len()]; - // Save clobbered registers - if !options.contains(InlineAsmOptions::NORETURN) { - // FIXME skip registers saved by the calling convention - for &(reg, offset) in &clobbered_regs { - save_register(&mut generated_asm, arch, reg, offset); - } - } - - // Write input registers - for &(reg, offset, _value) in inputs { - restore_register(&mut generated_asm, arch, reg, offset); - } - - if options.contains(InlineAsmOptions::ATT_SYNTAX) { - generated_asm.push_str(".att_syntax\n"); - } - - // The actual inline asm - for piece in template { - match piece { - InlineAsmTemplatePiece::String(s) => { - generated_asm.push_str(s); + // Add explicit registers to the allocated set. + for (i, operand) in self.operands.iter().enumerate() { + match *operand { + InlineAsmOperand::In { reg: InlineAsmRegOrRegClass::Reg(reg), .. } => { + regs[i] = Some(reg); + allocated.entry(reg).or_default().0 = true; + } + InlineAsmOperand::Out { + reg: InlineAsmRegOrRegClass::Reg(reg), late: true, .. + } => { + regs[i] = Some(reg); + allocated.entry(reg).or_default().1 = true; + } + InlineAsmOperand::Out { reg: InlineAsmRegOrRegClass::Reg(reg), .. } + | InlineAsmOperand::InOut { reg: InlineAsmRegOrRegClass::Reg(reg), .. } => { + regs[i] = Some(reg); + allocated.insert(reg, (true, true)); + } + _ => (), } - InlineAsmTemplatePiece::Placeholder { operand_idx: _, modifier: _, span: _ } => todo!(), - } - } - generated_asm.push('\n'); - - if options.contains(InlineAsmOptions::ATT_SYNTAX) { - generated_asm.push_str(".intel_syntax noprefix\n"); - } - - if !options.contains(InlineAsmOptions::NORETURN) { - // Read output registers - for &(reg, offset, _place) in outputs { - save_register(&mut generated_asm, arch, reg, offset); } - // Restore clobbered registers - for &(reg, offset) in clobbered_regs.iter().rev() { - restore_register(&mut generated_asm, arch, reg, offset); + // Allocate out/inout/inlateout registers first because they are more constrained. + for (i, operand) in self.operands.iter().enumerate() { + match *operand { + InlineAsmOperand::Out { + reg: InlineAsmRegOrRegClass::RegClass(class), + late: false, + .. + } + | InlineAsmOperand::InOut { + reg: InlineAsmRegOrRegClass::RegClass(class), .. + } => { + let mut alloc_reg = None; + for ® in &map[&class] { + let mut used = false; + reg.overlapping_regs(|r| { + if allocated.contains_key(&r) { + used = true; + } + }); + + if !used { + alloc_reg = Some(reg); + break; + } + } + + let reg = alloc_reg.expect("cannot allocate registers"); + regs[i] = Some(reg); + allocated.insert(reg, (true, true)); + } + _ => (), + } } - generated_asm.push_str(" pop rbp\n"); - generated_asm.push_str(" ret\n"); - } else { - generated_asm.push_str(" ud2\n"); + // Allocate in/lateout. + for (i, operand) in self.operands.iter().enumerate() { + match *operand { + InlineAsmOperand::In { reg: InlineAsmRegOrRegClass::RegClass(class), .. } => { + let mut alloc_reg = None; + for ® in &map[&class] { + let mut used = false; + reg.overlapping_regs(|r| { + if allocated.get(&r).copied().unwrap_or_default().0 { + used = true; + } + }); + + if !used { + alloc_reg = Some(reg); + break; + } + } + + let reg = alloc_reg.expect("cannot allocate registers"); + regs[i] = Some(reg); + allocated.entry(reg).or_default().0 = true; + } + InlineAsmOperand::Out { + reg: InlineAsmRegOrRegClass::RegClass(class), + late: true, + .. + } => { + let mut alloc_reg = None; + for ® in &map[&class] { + let mut used = false; + reg.overlapping_regs(|r| { + if allocated.get(&r).copied().unwrap_or_default().1 { + used = true; + } + }); + + if !used { + alloc_reg = Some(reg); + break; + } + } + + let reg = alloc_reg.expect("cannot allocate registers"); + regs[i] = Some(reg); + allocated.entry(reg).or_default().1 = true; + } + _ => (), + } + } + + self.registers = regs; } - generated_asm.push_str(".att_syntax\n"); - writeln!(generated_asm, ".size {name}, .-{name}", name = asm_name).unwrap(); - generated_asm.push_str(".text\n"); - generated_asm.push_str("\n\n"); + fn allocate_stack_slots(&mut self) { + let mut slot_size = Size::from_bytes(0); + let mut slots_clobber = vec![None; self.operands.len()]; + let mut slots_input = vec![None; self.operands.len()]; + let mut slots_output = vec![None; self.operands.len()]; - generated_asm + let new_slot_fn = |slot_size: &mut Size, reg_class: InlineAsmRegClass| { + let reg_size = + reg_class.supported_types(self.arch).iter().map(|(ty, _)| ty.size()).max().unwrap(); + let align = rustc_target::abi::Align::from_bytes(reg_size.bytes()).unwrap(); + let offset = slot_size.align_to(align); + *slot_size = offset + reg_size; + offset + }; + let mut new_slot = |x| new_slot_fn(&mut slot_size, x); + + // Allocate stack slots for saving clobbered registers + let abi_clobber = InlineAsmClobberAbi::parse( + self.arch, + |feature| self.tcx.sess.target_features.contains(&Symbol::intern(feature)), + &self.tcx.sess.target, + Symbol::intern("C"), + ) + .unwrap() + .clobbered_regs(); + for (i, reg) in self.registers.iter().enumerate().filter_map(|(i, r)| r.map(|r| (i, r))) { + let mut need_save = true; + // If the register overlaps with a register clobbered by function call, then + // we don't need to save it. + for r in abi_clobber { + r.overlapping_regs(|r| { + if r == reg { + need_save = false; + } + }); + + if !need_save { + break; + } + } + + if need_save { + slots_clobber[i] = Some(new_slot(reg.reg_class())); + } + } + + // Allocate stack slots for inout + for (i, operand) in self.operands.iter().enumerate() { + match *operand { + InlineAsmOperand::InOut { reg, out_place: Some(_), .. } => { + let slot = new_slot(reg.reg_class()); + slots_input[i] = Some(slot); + slots_output[i] = Some(slot); + } + _ => (), + } + } + + let slot_size_before_input = slot_size; + let mut new_slot = |x| new_slot_fn(&mut slot_size, x); + + // Allocate stack slots for input + for (i, operand) in self.operands.iter().enumerate() { + match *operand { + InlineAsmOperand::In { reg, .. } + | InlineAsmOperand::InOut { reg, out_place: None, .. } => { + slots_input[i] = Some(new_slot(reg.reg_class())); + } + _ => (), + } + } + + // Reset slot size to before input so that input and output operands can overlap + // and save some memory. + let slot_size_after_input = slot_size; + slot_size = slot_size_before_input; + let mut new_slot = |x| new_slot_fn(&mut slot_size, x); + + // Allocate stack slots for output + for (i, operand) in self.operands.iter().enumerate() { + match *operand { + InlineAsmOperand::Out { reg, place: Some(_), .. } => { + slots_output[i] = Some(new_slot(reg.reg_class())); + } + _ => (), + } + } + + slot_size = slot_size.max(slot_size_after_input); + + self.stack_slots_clobber = slots_clobber; + self.stack_slots_input = slots_input; + self.stack_slots_output = slots_output; + self.stack_slot_size = slot_size; + } + + fn generate_asm_wrapper(&self, asm_name: &str) -> String { + let mut generated_asm = String::new(); + writeln!(generated_asm, ".globl {}", asm_name).unwrap(); + writeln!(generated_asm, ".type {},@function", asm_name).unwrap(); + writeln!(generated_asm, ".section .text.{},\"ax\",@progbits", asm_name).unwrap(); + writeln!(generated_asm, "{}:", asm_name).unwrap(); + + let is_x86 = matches!(self.arch, InlineAsmArch::X86 | InlineAsmArch::X86_64); + + if is_x86 { + generated_asm.push_str(".intel_syntax noprefix\n"); + } + Self::prologue(&mut generated_asm, self.arch); + + // Save clobbered registers + if !self.options.contains(InlineAsmOptions::NORETURN) { + for (reg, slot) in self + .registers + .iter() + .zip(self.stack_slots_clobber.iter().copied()) + .filter_map(|(r, s)| r.zip(s)) + { + Self::save_register(&mut generated_asm, self.arch, reg, slot); + } + } + + // Write input registers + for (reg, slot) in self + .registers + .iter() + .zip(self.stack_slots_input.iter().copied()) + .filter_map(|(r, s)| r.zip(s)) + { + Self::restore_register(&mut generated_asm, self.arch, reg, slot); + } + + if is_x86 && self.options.contains(InlineAsmOptions::ATT_SYNTAX) { + generated_asm.push_str(".att_syntax\n"); + } + + // The actual inline asm + for piece in self.template { + match piece { + InlineAsmTemplatePiece::String(s) => { + generated_asm.push_str(s); + } + InlineAsmTemplatePiece::Placeholder { operand_idx, modifier, span: _ } => { + if self.options.contains(InlineAsmOptions::ATT_SYNTAX) { + generated_asm.push('%'); + } + self.registers[*operand_idx] + .unwrap() + .emit(&mut generated_asm, self.arch, *modifier) + .unwrap(); + } + } + } + generated_asm.push('\n'); + + if is_x86 && self.options.contains(InlineAsmOptions::ATT_SYNTAX) { + generated_asm.push_str(".intel_syntax noprefix\n"); + } + + if !self.options.contains(InlineAsmOptions::NORETURN) { + // Read output registers + for (reg, slot) in self + .registers + .iter() + .zip(self.stack_slots_output.iter().copied()) + .filter_map(|(r, s)| r.zip(s)) + { + Self::save_register(&mut generated_asm, self.arch, reg, slot); + } + + // Restore clobbered registers + for (reg, slot) in self + .registers + .iter() + .zip(self.stack_slots_clobber.iter().copied()) + .filter_map(|(r, s)| r.zip(s)) + { + Self::restore_register(&mut generated_asm, self.arch, reg, slot); + } + + Self::epilogue(&mut generated_asm, self.arch); + } else { + Self::epilogue_noreturn(&mut generated_asm, self.arch); + } + + if is_x86 { + generated_asm.push_str(".att_syntax\n"); + } + writeln!(generated_asm, ".size {name}, .-{name}", name = asm_name).unwrap(); + generated_asm.push_str(".text\n"); + generated_asm.push_str("\n\n"); + + generated_asm + } + + fn prologue(generated_asm: &mut String, arch: InlineAsmArch) { + match arch { + InlineAsmArch::X86 => { + generated_asm.push_str(" push ebp\n"); + generated_asm.push_str(" mov ebp,[esp+8]\n"); + } + InlineAsmArch::X86_64 => { + generated_asm.push_str(" push rbp\n"); + generated_asm.push_str(" mov rbp,rdi\n"); + } + InlineAsmArch::RiscV32 => { + generated_asm.push_str(" addi sp, sp, -8\n"); + generated_asm.push_str(" sw ra, 4(sp)\n"); + generated_asm.push_str(" sw s0, 0(sp)\n"); + generated_asm.push_str(" mv s0, a0\n"); + } + InlineAsmArch::RiscV64 => { + generated_asm.push_str(" addi sp, sp, -16\n"); + generated_asm.push_str(" sd ra, 8(sp)\n"); + generated_asm.push_str(" sd s0, 0(sp)\n"); + generated_asm.push_str(" mv s0, a0\n"); + } + _ => unimplemented!("prologue for {:?}", arch), + } + } + + fn epilogue(generated_asm: &mut String, arch: InlineAsmArch) { + match arch { + InlineAsmArch::X86 => { + generated_asm.push_str(" pop ebp\n"); + generated_asm.push_str(" ret\n"); + } + InlineAsmArch::X86_64 => { + generated_asm.push_str(" pop rbp\n"); + generated_asm.push_str(" ret\n"); + } + InlineAsmArch::RiscV32 => { + generated_asm.push_str(" lw s0, 0(sp)\n"); + generated_asm.push_str(" lw ra, 4(sp)\n"); + generated_asm.push_str(" addi sp, sp, 8\n"); + generated_asm.push_str(" ret\n"); + } + InlineAsmArch::RiscV64 => { + generated_asm.push_str(" ld s0, 0(sp)\n"); + generated_asm.push_str(" ld ra, 8(sp)\n"); + generated_asm.push_str(" addi sp, sp, 16\n"); + generated_asm.push_str(" ret\n"); + } + _ => unimplemented!("epilogue for {:?}", arch), + } + } + + fn epilogue_noreturn(generated_asm: &mut String, arch: InlineAsmArch) { + match arch { + InlineAsmArch::X86 | InlineAsmArch::X86_64 => { + generated_asm.push_str(" ud2\n"); + } + InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => { + generated_asm.push_str(" ebreak\n"); + } + _ => unimplemented!("epilogue_noreturn for {:?}", arch), + } + } + + fn save_register( + generated_asm: &mut String, + arch: InlineAsmArch, + reg: InlineAsmReg, + offset: Size, + ) { + match arch { + InlineAsmArch::X86 => { + write!(generated_asm, " mov [ebp+0x{:x}], ", offset.bytes()).unwrap(); + reg.emit(generated_asm, InlineAsmArch::X86, None).unwrap(); + generated_asm.push('\n'); + } + InlineAsmArch::X86_64 => { + write!(generated_asm, " mov [rbp+0x{:x}], ", offset.bytes()).unwrap(); + reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap(); + generated_asm.push('\n'); + } + InlineAsmArch::RiscV32 => { + generated_asm.push_str(" sw "); + reg.emit(generated_asm, InlineAsmArch::RiscV32, None).unwrap(); + writeln!(generated_asm, ", 0x{:x}(s0)", offset.bytes()).unwrap(); + } + InlineAsmArch::RiscV64 => { + generated_asm.push_str(" sd "); + reg.emit(generated_asm, InlineAsmArch::RiscV64, None).unwrap(); + writeln!(generated_asm, ", 0x{:x}(s0)", offset.bytes()).unwrap(); + } + _ => unimplemented!("save_register for {:?}", arch), + } + } + + fn restore_register( + generated_asm: &mut String, + arch: InlineAsmArch, + reg: InlineAsmReg, + offset: Size, + ) { + match arch { + InlineAsmArch::X86 => { + generated_asm.push_str(" mov "); + reg.emit(generated_asm, InlineAsmArch::X86, None).unwrap(); + writeln!(generated_asm, ", [ebp+0x{:x}]", offset.bytes()).unwrap(); + } + InlineAsmArch::X86_64 => { + generated_asm.push_str(" mov "); + reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap(); + writeln!(generated_asm, ", [rbp+0x{:x}]", offset.bytes()).unwrap(); + } + InlineAsmArch::RiscV32 => { + generated_asm.push_str(" lw "); + reg.emit(generated_asm, InlineAsmArch::RiscV32, None).unwrap(); + writeln!(generated_asm, ", 0x{:x}(s0)", offset.bytes()).unwrap(); + } + InlineAsmArch::RiscV64 => { + generated_asm.push_str(" ld "); + reg.emit(generated_asm, InlineAsmArch::RiscV64, None).unwrap(); + writeln!(generated_asm, ", 0x{:x}(s0)", offset.bytes()).unwrap(); + } + _ => unimplemented!("restore_register for {:?}", arch), + } + } } fn call_inline_asm<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, asm_name: &str, slot_size: Size, - inputs: Vec<(InlineAsmReg, Size, Value)>, - outputs: Vec<(InlineAsmReg, Size, CPlace<'tcx>)>, + inputs: Vec<(Size, Value)>, + outputs: Vec<(Size, CPlace<'tcx>)>, ) { let stack_slot = fx.bcx.func.create_stack_slot(StackSlotData { kind: StackSlotKind::ExplicitSlot, - offset: None, size: u32::try_from(slot_size.bytes()).unwrap(), }); if fx.clif_comments.enabled() { @@ -287,50 +654,16 @@ fn call_inline_asm<'tcx>( fx.add_comment(inline_asm_func, asm_name); } - for (_reg, offset, value) in inputs { + for (offset, value) in inputs { fx.bcx.ins().stack_store(value, stack_slot, i32::try_from(offset.bytes()).unwrap()); } let stack_slot_addr = fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0); fx.bcx.ins().call(inline_asm_func, &[stack_slot_addr]); - for (_reg, offset, place) in outputs { + for (offset, place) in outputs { let ty = fx.clif_type(place.layout().ty).unwrap(); let value = fx.bcx.ins().stack_load(ty, stack_slot, i32::try_from(offset.bytes()).unwrap()); place.write_cvalue(fx, CValue::by_val(value, place.layout())); } } - -fn expect_reg(reg_or_class: InlineAsmRegOrRegClass) -> InlineAsmReg { - match reg_or_class { - InlineAsmRegOrRegClass::Reg(reg) => reg, - InlineAsmRegOrRegClass::RegClass(class) => unimplemented!("{:?}", class), - } -} - -fn save_register(generated_asm: &mut String, arch: InlineAsmArch, reg: InlineAsmReg, offset: Size) { - match arch { - InlineAsmArch::X86_64 => { - write!(generated_asm, " mov [rbp+0x{:x}], ", offset.bytes()).unwrap(); - reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap(); - generated_asm.push('\n'); - } - _ => unimplemented!("save_register for {:?}", arch), - } -} - -fn restore_register( - generated_asm: &mut String, - arch: InlineAsmArch, - reg: InlineAsmReg, - offset: Size, -) { - match arch { - InlineAsmArch::X86_64 => { - generated_asm.push_str(" mov "); - reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap(); - writeln!(generated_asm, ", [rbp+0x{:x}]", offset.bytes()).unwrap(); - } - _ => unimplemented!("restore_register for {:?}", arch), - } -} diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 313b62c577..f4703b22ec 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -503,10 +503,10 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( if intrinsic == sym::copy_nonoverlapping { // FIXME emit_small_memcpy - fx.bcx.call_memcpy(fx.module.target_config(), dst, src, byte_amount); + fx.bcx.call_memcpy(fx.target_config, dst, src, byte_amount); } else { // FIXME emit_small_memmove - fx.bcx.call_memmove(fx.module.target_config(), dst, src, byte_amount); + fx.bcx.call_memmove(fx.target_config, dst, src, byte_amount); } }; // NOTE: the volatile variants have src and dst swapped @@ -522,10 +522,10 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( // FIXME make the copy actually volatile when using emit_small_mem{cpy,move} if intrinsic == sym::volatile_copy_nonoverlapping_memory { // FIXME emit_small_memcpy - fx.bcx.call_memcpy(fx.module.target_config(), dst, src, byte_amount); + fx.bcx.call_memcpy(fx.target_config, dst, src, byte_amount); } else { // FIXME emit_small_memmove - fx.bcx.call_memmove(fx.module.target_config(), dst, src, byte_amount); + fx.bcx.call_memmove(fx.target_config, dst, src, byte_amount); } }; size_of_val, (c ptr) { @@ -673,7 +673,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( let dst_ptr = dst.load_scalar(fx); // FIXME make the memset actually volatile when switching to emit_small_memset // FIXME use emit_small_memset - fx.bcx.call_memset(fx.module.target_config(), dst_ptr, val, count); + fx.bcx.call_memset(fx.target_config, dst_ptr, val, count); }; ctlz | ctlz_nonzero, (v arg) { // FIXME trap on `ctlz_nonzero` with zero arg. @@ -1067,7 +1067,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( kw.Try, (v f, v data, v _catch_fn) { // FIXME once unwinding is supported, change this to actually catch panics let f_sig = fx.bcx.func.import_signature(Signature { - call_conv: CallConv::triple_default(fx.triple()), + call_conv: fx.target_config.default_call_conv, params: vec![AbiParam::new(fx.bcx.func.dfg.value_type(data))], returns: vec![], }); diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index 43e68b4afa..6c0631d9ec 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -67,7 +67,34 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( _ if intrinsic.as_str().starts_with("simd_shuffle"), (c x, c y, o idx) { validate_simd_type!(fx, intrinsic, span, x.layout().ty); - let n: u16 = intrinsic.as_str()["simd_shuffle".len()..].parse().unwrap(); + // If this intrinsic is the older "simd_shuffleN" form, simply parse the integer. + // If there is no suffix, use the index array length. + let n: u16 = if intrinsic == sym::simd_shuffle { + // Make sure this is actually an array, since typeck only checks the length-suffixed + // version of this intrinsic. + let idx_ty = fx.monomorphize(idx.ty(fx.mir, fx.tcx)); + match idx_ty.kind() { + ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => { + len.try_eval_usize(fx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(|| { + span_bug!(span, "could not evaluate shuffle index array length") + }).try_into().unwrap() + } + _ => { + fx.tcx.sess.span_err( + span, + &format!( + "simd_shuffle index must be an array of `u32`, got `{}`", + idx_ty, + ), + ); + // Prevent verifier error + crate::trap::trap_unreachable(fx, "compilation should not have succeeded"); + return; + } + } + } else { + intrinsic.as_str()["simd_shuffle".len()..].parse().unwrap() + }; assert_eq!(x.layout(), y.layout()); let layout = x.layout(); @@ -378,27 +405,27 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( }; simd_reduce_min, (c v) { - // FIXME support floats validate_simd_type!(fx, intrinsic, span, v.layout().ty); simd_reduce(fx, v, None, ret, |fx, layout, a, b| { - let lt = fx.bcx.ins().icmp(if layout.ty.is_signed() { - IntCC::SignedLessThan - } else { - IntCC::UnsignedLessThan - }, a, b); + let lt = match layout.ty.kind() { + ty::Int(_) => fx.bcx.ins().icmp(IntCC::SignedLessThan, a, b), + ty::Uint(_) => fx.bcx.ins().icmp(IntCC::UnsignedLessThan, a, b), + ty::Float(_) => fx.bcx.ins().fcmp(FloatCC::LessThan, a, b), + _ => unreachable!(), + }; fx.bcx.ins().select(lt, a, b) }); }; simd_reduce_max, (c v) { - // FIXME support floats validate_simd_type!(fx, intrinsic, span, v.layout().ty); simd_reduce(fx, v, None, ret, |fx, layout, a, b| { - let gt = fx.bcx.ins().icmp(if layout.ty.is_signed() { - IntCC::SignedGreaterThan - } else { - IntCC::UnsignedGreaterThan - }, a, b); + let gt = match layout.ty.kind() { + ty::Int(_) => fx.bcx.ins().icmp(IntCC::SignedGreaterThan, a, b), + ty::Uint(_) => fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, a, b), + ty::Float(_) => fx.bcx.ins().fcmp(FloatCC::GreaterThan, a, b), + _ => unreachable!(), + }; fx.bcx.ins().select(gt, a, b) }); }; diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index beb97edf09..cb18f42f74 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -4,7 +4,6 @@ #![warn(unused_lifetimes)] #![warn(unreachable_pub)] -extern crate snap; #[macro_use] extern crate rustc_middle; extern crate rustc_ast; @@ -26,6 +25,7 @@ extern crate rustc_target; extern crate rustc_driver; use std::any::Any; +use std::cell::Cell; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::CodegenResults; @@ -34,6 +34,7 @@ use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_session::config::OutputFilenames; use rustc_session::Session; +use rustc_span::Symbol; use cranelift_codegen::isa::TargetIsa; use cranelift_codegen::settings::{self, Configurable}; @@ -59,7 +60,6 @@ mod inline_asm; mod intrinsics; mod linkage; mod main_shim; -mod metadata; mod num; mod optimize; mod pointer; @@ -71,9 +71,7 @@ mod value_and_place; mod vtable; mod prelude { - pub(crate) use std::convert::{TryFrom, TryInto}; - - pub(crate) use rustc_span::{Span, FileNameDisplayPreference}; + pub(crate) use rustc_span::{FileNameDisplayPreference, Span}; pub(crate) use rustc_hir::def_id::{DefId, LOCAL_CRATE}; pub(crate) use rustc_middle::bug; @@ -125,9 +123,11 @@ impl String> Drop for PrintOnPanic { struct CodegenCx<'tcx> { tcx: TyCtxt<'tcx>, global_asm: String, + inline_asm_index: Cell, cached_context: Context, debug_context: Option>, unwind_context: UnwindContext, + cgu_name: Symbol, } impl<'tcx> CodegenCx<'tcx> { @@ -136,18 +136,21 @@ impl<'tcx> CodegenCx<'tcx> { backend_config: BackendConfig, isa: &dyn TargetIsa, debug_info: bool, + cgu_name: Symbol, ) -> Self { assert_eq!(pointer_ty(tcx), isa.pointer_type()); let unwind_context = - UnwindContext::new(tcx, isa, matches!(backend_config.codegen_mode, CodegenMode::Aot)); + UnwindContext::new(isa, matches!(backend_config.codegen_mode, CodegenMode::Aot)); let debug_context = if debug_info { Some(DebugContext::new(tcx, isa)) } else { None }; CodegenCx { tcx, global_asm: String::new(), + inline_asm_index: Cell::new(0), cached_context: Context::new(), debug_context, unwind_context, + cgu_name, } } } @@ -205,6 +208,7 @@ impl CodegenBackend for CraneliftCodegenBackend { &self, ongoing_codegen: Box, _sess: &Session, + _outputs: &OutputFilenames, ) -> Result<(CodegenResults, FxHashMap), ErrorReported> { Ok(*ongoing_codegen .downcast::<(CodegenResults, FxHashMap)>() @@ -268,19 +272,16 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box { - let builder = cranelift_native::builder_with_options(variant, true).unwrap(); + let builder = cranelift_native::builder_with_options(true).unwrap(); builder } Some(value) => { let mut builder = - cranelift_codegen::isa::lookup_variant(target_triple.clone(), variant) - .unwrap_or_else(|err| { - sess.fatal(&format!("can't compile for {}: {}", target_triple, err)); - }); + cranelift_codegen::isa::lookup(target_triple.clone()).unwrap_or_else(|err| { + sess.fatal(&format!("can't compile for {}: {}", target_triple, err)); + }); if let Err(_) = builder.enable(value) { sess.fatal("the specified target cpu isn't currently supported by Cranelift."); } @@ -288,10 +289,9 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box { let mut builder = - cranelift_codegen::isa::lookup_variant(target_triple.clone(), variant) - .unwrap_or_else(|err| { - sess.fatal(&format!("can't compile for {}: {}", target_triple, err)); - }); + cranelift_codegen::isa::lookup(target_triple.clone()).unwrap_or_else(|err| { + sess.fatal(&format!("can't compile for {}: {}", target_triple, err)); + }); if target_triple.architecture == target_lexicon::Architecture::X86_64 { // Don't use "haswell" as the default, as it implies `has_lzcnt`. // macOS CI is still at Ivy Bridge EP, so `lzcnt` is interpreted as `bsr`. diff --git a/compiler/rustc_codegen_cranelift/src/metadata.rs b/compiler/rustc_codegen_cranelift/src/metadata.rs deleted file mode 100644 index 1c8fd0b01d..0000000000 --- a/compiler/rustc_codegen_cranelift/src/metadata.rs +++ /dev/null @@ -1,76 +0,0 @@ -//! Writing of the rustc metadata for dylibs - -use object::write::{Object, StandardSegment, Symbol, SymbolSection}; -use object::{SectionKind, SymbolFlags, SymbolKind, SymbolScope}; - -use rustc_metadata::EncodedMetadata; -use rustc_middle::ty::TyCtxt; - -// Adapted from https://github.com/rust-lang/rust/blob/da573206f87b5510de4b0ee1a9c044127e409bd3/src/librustc_codegen_llvm/base.rs#L47-L112 -pub(crate) fn new_metadata_object( - tcx: TyCtxt<'_>, - cgu_name: &str, - metadata: &EncodedMetadata, -) -> Vec { - use snap::write::FrameEncoder; - use std::io::Write; - - let mut compressed = rustc_metadata::METADATA_HEADER.to_vec(); - FrameEncoder::new(&mut compressed).write_all(metadata.raw_data()).unwrap(); - - let triple = crate::target_triple(tcx.sess); - - let binary_format = match triple.binary_format { - target_lexicon::BinaryFormat::Elf => object::BinaryFormat::Elf, - target_lexicon::BinaryFormat::Coff => object::BinaryFormat::Coff, - target_lexicon::BinaryFormat::Macho => object::BinaryFormat::MachO, - binary_format => tcx.sess.fatal(&format!("binary format {} is unsupported", binary_format)), - }; - let architecture = match triple.architecture { - target_lexicon::Architecture::Aarch64(_) => object::Architecture::Aarch64, - target_lexicon::Architecture::Arm(_) => object::Architecture::Arm, - target_lexicon::Architecture::Avr => object::Architecture::Avr, - target_lexicon::Architecture::Hexagon => object::Architecture::Hexagon, - target_lexicon::Architecture::Mips32(_) => object::Architecture::Mips, - target_lexicon::Architecture::Mips64(_) => object::Architecture::Mips64, - target_lexicon::Architecture::Msp430 => object::Architecture::Msp430, - target_lexicon::Architecture::Powerpc => object::Architecture::PowerPc, - target_lexicon::Architecture::Powerpc64 => object::Architecture::PowerPc64, - target_lexicon::Architecture::Powerpc64le => todo!(), - target_lexicon::Architecture::Riscv32(_) => object::Architecture::Riscv32, - target_lexicon::Architecture::Riscv64(_) => object::Architecture::Riscv64, - target_lexicon::Architecture::S390x => object::Architecture::S390x, - target_lexicon::Architecture::Sparc64 => object::Architecture::Sparc64, - target_lexicon::Architecture::Sparcv9 => object::Architecture::Sparc64, - target_lexicon::Architecture::X86_32(_) => object::Architecture::I386, - target_lexicon::Architecture::X86_64 => object::Architecture::X86_64, - architecture => { - tcx.sess.fatal(&format!("target architecture {:?} is unsupported", architecture,)) - } - }; - let endian = match triple.endianness().unwrap() { - target_lexicon::Endianness::Little => object::Endianness::Little, - target_lexicon::Endianness::Big => object::Endianness::Big, - }; - - let mut object = Object::new(binary_format, architecture, endian); - object.add_file_symbol(cgu_name.as_bytes().to_vec()); - - let segment = object.segment_name(StandardSegment::Data).to_vec(); - let section_id = object.add_section(segment, b".rustc".to_vec(), SectionKind::Data); - let offset = object.append_section_data(section_id, &compressed, 1); - // For MachO and probably PE this is necessary to prevent the linker from throwing away the - // .rustc section. For ELF this isn't necessary, but it also doesn't harm. - object.add_symbol(Symbol { - name: rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx).into_bytes(), - value: offset, - size: compressed.len() as u64, - kind: SymbolKind::Data, - scope: SymbolScope::Dynamic, - weak: false, - section: SymbolSection::Section(section_id), - flags: SymbolFlags::None, - }); - - object.write().unwrap() -} diff --git a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs index ec846d7196..4dffb89e10 100644 --- a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs +++ b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs @@ -57,7 +57,7 @@ use std::io::Write; use cranelift_codegen::{ entity::SecondaryMap, - ir::{entities::AnyEntity, function::DisplayFunctionAnnotations}, + ir::entities::AnyEntity, write::{FuncWriter, PlainWriter}, }; @@ -129,7 +129,6 @@ impl FuncWriter for &'_ CommentWriter { &mut self, w: &mut dyn fmt::Write, func: &Function, - reg_info: Option<&isa::RegInfo>, ) -> Result { for comment in &self.global_comments { if !comment.is_empty() { @@ -142,7 +141,7 @@ impl FuncWriter for &'_ CommentWriter { writeln!(w)?; } - self.super_preamble(w, func, reg_info) + self.super_preamble(w, func) } fn write_entity_definition( @@ -165,11 +164,10 @@ impl FuncWriter for &'_ CommentWriter { &mut self, w: &mut dyn fmt::Write, func: &Function, - isa: Option<&dyn isa::TargetIsa>, block: Block, indent: usize, ) -> fmt::Result { - PlainWriter.write_block_header(w, func, isa, block, indent) + PlainWriter.write_block_header(w, func, block, indent) } fn write_instruction( @@ -177,11 +175,10 @@ impl FuncWriter for &'_ CommentWriter { w: &mut dyn fmt::Write, func: &Function, aliases: &SecondaryMap>, - isa: Option<&dyn isa::TargetIsa>, inst: Inst, indent: usize, ) -> fmt::Result { - PlainWriter.write_instruction(w, func, aliases, isa, inst, indent)?; + PlainWriter.write_instruction(w, func, aliases, inst, indent)?; if let Some(comment) = self.entity_comments.get(&inst.into()) { writeln!(w, "; {}", comment.replace('\n', "\n; "))?; } @@ -249,7 +246,6 @@ pub(crate) fn write_clif_file<'tcx>( &mut clif_comments, &mut clif, &context.func, - &DisplayFunctionAnnotations { isa: Some(isa), value_ranges: None }, ) .unwrap(); @@ -278,7 +274,6 @@ impl fmt::Debug for FunctionCx<'_, '_, '_> { &mut &self.clif_comments, &mut clif, &self.bcx.func, - &DisplayFunctionAnnotations::default(), ) .unwrap(); writeln!(f, "\n{}", clif) diff --git a/compiler/rustc_codegen_cranelift/src/trap.rs b/compiler/rustc_codegen_cranelift/src/trap.rs index fe8d20fa39..99b5366e34 100644 --- a/compiler/rustc_codegen_cranelift/src/trap.rs +++ b/compiler/rustc_codegen_cranelift/src/trap.rs @@ -9,7 +9,7 @@ fn codegen_print(fx: &mut FunctionCx<'_, '_, '_>, msg: &str) { "puts", Linkage::Import, &Signature { - call_conv: CallConv::triple_default(fx.triple()), + call_conv: fx.target_config.default_call_conv, params: vec![AbiParam::new(fx.pointer_type)], returns: vec![AbiParam::new(types::I32)], }, diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index 30d5340935..f29d13ccab 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -329,7 +329,6 @@ impl<'tcx> CPlace<'tcx> { // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to // specify stack slot alignment. size: (u32::try_from(layout.size.bytes()).unwrap() + 15) / 16 * 16, - offset: None, }); CPlace { inner: CPlaceInner::Addr(Pointer::stack_slot(stack_slot), None), layout } } @@ -472,7 +471,6 @@ impl<'tcx> CPlace<'tcx> { // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to // specify stack slot alignment. size: (src_ty.bytes() + 15) / 16 * 16, - offset: None, }); let ptr = Pointer::stack_slot(stack_slot); ptr.store(fx, data, MemFlags::trusted()); @@ -512,6 +510,26 @@ impl<'tcx> CPlace<'tcx> { let dst_layout = self.layout(); let to_ptr = match self.inner { CPlaceInner::Var(_local, var) => { + if let ty::Array(element, len) = dst_layout.ty.kind() { + // Can only happen for vector types + let len = + u16::try_from(len.eval_usize(fx.tcx, ParamEnv::reveal_all())).unwrap(); + let vector_ty = fx.clif_type(element).unwrap().by(len).unwrap(); + + let data = match from.0 { + CValueInner::ByRef(ptr, None) => { + let mut flags = MemFlags::new(); + flags.set_notrap(); + ptr.load(fx, vector_ty, flags) + } + CValueInner::ByVal(_) + | CValueInner::ByValPair(_, _) + | CValueInner::ByRef(_, Some(_)) => bug!("array should be ByRef"), + }; + + fx.bcx.def_var(var, data); + return; + } let data = CValue(from.0, dst_layout).load_scalar(fx); let dst_ty = fx.clif_type(self.layout().ty).unwrap(); transmute_value(fx, var, data, dst_ty); @@ -583,7 +601,7 @@ impl<'tcx> CPlace<'tcx> { let src_align = src_layout.align.abi.bytes() as u8; let dst_align = dst_layout.align.abi.bytes() as u8; fx.bcx.emit_small_memory_copy( - fx.module.target_config(), + fx.target_config, to_addr, from_addr, size, @@ -605,14 +623,39 @@ impl<'tcx> CPlace<'tcx> { let layout = self.layout(); match self.inner { - CPlaceInner::Var(local, var) => { - if let Abi::Vector { .. } = layout.abi { + CPlaceInner::Var(local, var) => match layout.ty.kind() { + ty::Array(_, _) => { + // Can only happen for vector types return CPlace { inner: CPlaceInner::VarLane(local, var, field.as_u32().try_into().unwrap()), layout: layout.field(fx, field.as_u32().try_into().unwrap()), }; } - } + ty::Adt(adt_def, substs) if layout.ty.is_simd() => { + let f0_ty = adt_def.non_enum_variant().fields[0].ty(fx.tcx, substs); + + match f0_ty.kind() { + ty::Array(_, _) => { + assert_eq!(field.as_u32(), 0); + return CPlace { + inner: CPlaceInner::Var(local, var), + layout: layout.field(fx, field.as_u32().try_into().unwrap()), + }; + } + _ => { + return CPlace { + inner: CPlaceInner::VarLane( + local, + var, + field.as_u32().try_into().unwrap(), + ), + layout: layout.field(fx, field.as_u32().try_into().unwrap()), + }; + } + } + } + _ => {} + }, CPlaceInner::VarPair(local, var1, var2) => { let layout = layout.field(&*fx, field.index()); @@ -629,7 +672,12 @@ impl<'tcx> CPlace<'tcx> { let (field_ptr, field_layout) = codegen_field(fx, base, extra, layout, field); if field_layout.is_unsized() { - CPlace::for_ptr_with_extra(field_ptr, extra.unwrap(), field_layout) + if let ty::Foreign(_) = field_layout.ty.kind() { + assert!(extra.is_none()); + CPlace::for_ptr(field_ptr, field_layout) + } else { + CPlace::for_ptr_with_extra(field_ptr, extra.unwrap(), field_layout) + } } else { CPlace::for_ptr(field_ptr, field_layout) } diff --git a/compiler/rustc_codegen_cranelift/y.rs b/compiler/rustc_codegen_cranelift/y.rs index 26605003c4..98b114de91 100755 --- a/compiler/rustc_codegen_cranelift/y.rs +++ b/compiler/rustc_codegen_cranelift/y.rs @@ -43,7 +43,9 @@ mod utils; fn usage() { eprintln!("Usage:"); eprintln!(" ./y.rs prepare"); - eprintln!(" ./y.rs build [--debug] [--sysroot none|clif|llvm] [--target-dir DIR]"); + eprintln!( + " ./y.rs build [--debug] [--sysroot none|clif|llvm] [--target-dir DIR] [--no-unstable-features]" + ); } macro_rules! arg_error { @@ -92,6 +94,7 @@ fn main() { let mut target_dir = PathBuf::from("build"); let mut channel = "release"; let mut sysroot_kind = SysrootKind::Clif; + let mut use_unstable_features = true; while let Some(arg) = args.next().as_deref() { match arg { "--target-dir" => { @@ -109,6 +112,7 @@ fn main() { None => arg_error!("--sysroot requires argument"), } } + "--no-unstable-features" => use_unstable_features = false, flag if flag.starts_with("-") => arg_error!("Unknown flag {}", flag), arg => arg_error!("Unexpected argument {}", arg), } @@ -141,7 +145,8 @@ fn main() { process::exit(1); } - let cg_clif_build_dir = build_backend::build_backend(channel, &host_triple); + let cg_clif_build_dir = + build_backend::build_backend(channel, &host_triple, use_unstable_features); build_sysroot::build_sysroot( channel, sysroot_kind, diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock index 60a2101c68..47925f72c2 100644 --- a/compiler/rustc_codegen_gcc/Cargo.lock +++ b/compiler/rustc_codegen_gcc/Cargo.lock @@ -17,12 +17,6 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "450575f58f7bee32816abbff470cbc47797397c2a81e0eaced4b98436daf52e1" -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - [[package]] name = "bitflags" version = "1.3.2" @@ -35,15 +29,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "crc32fast" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" -dependencies = [ - "cfg-if", -] - [[package]] name = "fm" version = "0.1.4" @@ -56,7 +41,7 @@ dependencies = [ [[package]] name = "gccjit" version = "1.0.0" -source = "git+https://github.com/antoyo/gccjit.rs#2d4fea7319f80531b2e5d264fca9f1c498a3a62e" +source = "git+https://github.com/antoyo/gccjit.rs#0672b78d162d65b6f36ea4062947253affe9fdef" dependencies = [ "gccjit_sys", ] @@ -64,7 +49,7 @@ dependencies = [ [[package]] name = "gccjit_sys" version = "0.0.1" -source = "git+https://github.com/antoyo/gccjit.rs#2d4fea7319f80531b2e5d264fca9f1c498a3a62e" +source = "git+https://github.com/antoyo/gccjit.rs#0672b78d162d65b6f36ea4062947253affe9fdef" dependencies = [ "libc 0.1.12", ] @@ -85,33 +70,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ "cfg-if", - "libc 0.2.102", + "libc 0.2.112", "wasi", ] -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" - [[package]] name = "hermit-abi" version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ - "libc 0.2.102", -] - -[[package]] -name = "indexmap" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" -dependencies = [ - "autocfg", - "hashbrown", + "libc 0.2.112", ] [[package]] @@ -122,7 +91,7 @@ checksum = "96bd995a092cac79868250589869b5a5d656b02a02bd74c8ebdc566dc7203090" dependencies = [ "fm", "getopts", - "libc 0.2.102", + "libc 0.2.112", "num_cpus", "termcolor", "threadpool", @@ -138,9 +107,9 @@ checksum = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122" [[package]] name = "libc" -version = "0.2.102" +version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103" +checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" [[package]] name = "memchr" @@ -155,25 +124,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" dependencies = [ "hermit-abi", - "libc 0.2.102", -] - -[[package]] -name = "object" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a38f2be3697a57b4060074ff41b44c16870d916ad7877c17696e063257482bc7" -dependencies = [ - "crc32fast", - "indexmap", - "memchr", + "libc 0.2.112", ] [[package]] name = "ppv-lite86" -version = "0.2.10" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" [[package]] name = "rand" @@ -181,7 +139,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" dependencies = [ - "libc 0.2.102", + "libc 0.2.112", "rand_chacha", "rand_core", "rand_hc", @@ -257,7 +215,6 @@ dependencies = [ "ar", "gccjit", "lang_tester", - "object", "target-lexicon", "tempfile", ] @@ -284,7 +241,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" dependencies = [ "cfg-if", - "libc 0.2.102", + "libc 0.2.112", "rand", "redox_syscall", "remove_dir_all", @@ -321,7 +278,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" dependencies = [ - "libc 0.2.102", + "libc 0.2.112", ] [[package]] diff --git a/compiler/rustc_codegen_gcc/Cargo.toml b/compiler/rustc_codegen_gcc/Cargo.toml index 9e8c195c15..21f0bfbf69 100644 --- a/compiler/rustc_codegen_gcc/Cargo.toml +++ b/compiler/rustc_codegen_gcc/Cargo.toml @@ -23,11 +23,6 @@ target-lexicon = "0.10.0" ar = "0.8.0" -[dependencies.object] -version = "0.25.0" -default-features = false -features = ["read", "std", "write"] # We don't need WASM support. - [dev-dependencies] lang_tester = "0.3.9" tempfile = "3.1.0" diff --git a/compiler/rustc_codegen_gcc/Readme.md b/compiler/rustc_codegen_gcc/Readme.md index 709d93c6ed..1fcfb5f6e2 100644 --- a/compiler/rustc_codegen_gcc/Readme.md +++ b/compiler/rustc_codegen_gcc/Readme.md @@ -111,6 +111,8 @@ Or add a breakpoint to `add_error` in gdb and print the line number using: p loc->m_line ``` +To get the `rustc` command to run in `gdb`, add the `--verbose` flag to `cargo build`. + ### How to use a custom-build rustc * Build the stage2 compiler (`rustup toolchain link debug-current build/x86_64-unknown-linux-gnu/stage2`). diff --git a/compiler/rustc_codegen_gcc/config.sh b/compiler/rustc_codegen_gcc/config.sh index 87df2f2102..a932c1c837 100644 --- a/compiler/rustc_codegen_gcc/config.sh +++ b/compiler/rustc_codegen_gcc/config.sh @@ -38,7 +38,7 @@ if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then fi fi -export RUSTFLAGS="$linker -Cpanic=abort -Zsymbol-mangling-version=v0 -Cdebuginfo=2 -Clto=off -Zpanic-abort-tests -Zcodegen-backend=$(pwd)/target/${CHANNEL:-debug}/librustc_codegen_gcc.$dylib_ext --sysroot $(pwd)/build_sysroot/sysroot" +export RUSTFLAGS="$linker -Cpanic=abort -Csymbol-mangling-version=v0 -Cdebuginfo=2 -Clto=off -Zpanic-abort-tests -Zcodegen-backend=$(pwd)/target/${CHANNEL:-debug}/librustc_codegen_gcc.$dylib_ext --sysroot $(pwd)/build_sysroot/sysroot" # FIXME(antoyo): remove once the atomic shim is gone if [[ `uname` == 'Darwin' ]]; then diff --git a/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch b/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch index ee5ba449fb..73e9c858ca 100644 --- a/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch +++ b/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch @@ -46,4 +46,24 @@ index 4bc44e9..8e3c7a4 100644 #[test] fn cell_allows_array_cycle() { +diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs +index 3e00e0a..8e5663b 100644 +--- a/library/core/tests/slice.rs ++++ b/library/core/tests/slice.rs +@@ -2108,6 +2108,7 @@ fn test_copy_within_panics_src_out_of_bounds() { + bytes.copy_within(usize::MAX..=usize::MAX, 0); + } + ++/* + #[test] + fn test_is_sorted() { + let empty: [i32; 0] = []; +@@ -2122,6 +2123,7 @@ fn test_is_sorted() { + assert!(!["c", "bb", "aaa"].is_sorted()); + assert!(["c", "bb", "aaa"].is_sorted_by_key(|s| s.len())); + } ++*/ + + #[test] + fn test_slice_run_destructors() { -- 2.21.0 (Apple Git-122) diff --git a/compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch b/compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch new file mode 100644 index 0000000000..8954f91021 --- /dev/null +++ b/compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch @@ -0,0 +1,24 @@ +From b1ae000f6da1abd3b8e9b80c40bc11c89b8ae93c Mon Sep 17 00:00:00 2001 +From: bjorn3 +Date: Thu, 30 Dec 2021 16:54:40 +0100 +Subject: [PATCH] [core] Disable portable-simd test + +--- + library/core/tests/lib.rs | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs +index ec70034..7cd9e21 100644 +--- a/library/core/tests/lib.rs ++++ b/library/core/tests/lib.rs +@@ -121,7 +121,6 @@ mod pattern; + mod pin; + mod ptr; + mod result; +-mod simd; + mod slice; + mod str; + mod str_lossy; +-- +2.26.2.7.g19db9cfb68 + diff --git a/compiler/rustc_codegen_gcc/patches/0028-core-Disable-long-running-tests.patch b/compiler/rustc_codegen_gcc/patches/0028-core-Disable-long-running-tests.patch new file mode 100644 index 0000000000..bf74a74c7c --- /dev/null +++ b/compiler/rustc_codegen_gcc/patches/0028-core-Disable-long-running-tests.patch @@ -0,0 +1,30 @@ +From 0ffdd8eda8df364391c8ac6e1ce92c73ba9254d4 Mon Sep 17 00:00:00 2001 +From: bjorn3 +Date: Fri, 3 Dec 2021 12:16:30 +0100 +Subject: [PATCH] Disable long running tests + +--- + library/core/tests/slice.rs | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs +index 2c8f00a..44847ee 100644 +--- a/library/core/tests/slice.rs ++++ b/library/core/tests/slice.rs +@@ -2332,7 +2332,8 @@ macro_rules! empty_max_mut { + }; + } + ++/* + #[cfg(not(miri))] // Comparing usize::MAX many elements takes forever in Miri (and in rustc without optimizations) + take_tests! { + slice: &[(); usize::MAX], method: take, + (take_in_bounds_max_range_to, (..usize::MAX), Some(EMPTY_MAX), &[(); 0]), +@@ -2345,3 +2347,4 @@ take_tests! { + (take_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()), + (take_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()), + } ++*/ +-- +2.26.2.7.g19db9cfb68 + diff --git a/compiler/rustc_codegen_gcc/rust-toolchain b/compiler/rustc_codegen_gcc/rust-toolchain index d311a33f80..ee0822f6c3 100644 --- a/compiler/rustc_codegen_gcc/rust-toolchain +++ b/compiler/rustc_codegen_gcc/rust-toolchain @@ -1 +1 @@ -nightly-2021-09-28 +nightly-2021-12-30 diff --git a/compiler/rustc_codegen_gcc/src/abi.rs b/compiler/rustc_codegen_gcc/src/abi.rs index 2bbb199c89..a8b1e70e2b 100644 --- a/compiler/rustc_codegen_gcc/src/abi.rs +++ b/compiler/rustc_codegen_gcc/src/abi.rs @@ -48,8 +48,8 @@ impl GccType for CastTarget { let mut args: Vec<_> = self .prefix .iter() - .flat_map(|option_kind| { - option_kind.map(|kind| Reg { kind, size: self.prefix_chunk_size }.gcc_type(cx)) + .flat_map(|option_reg| { + option_reg.map(|reg| reg.gcc_type(cx)) }) .chain((0..rest_count).map(|_| rest_gcc_unit)) .collect(); diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index 7c3ed3c5ee..453bcd601d 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -18,30 +18,30 @@ use crate::type_of::LayoutGccExt; // Rust asm! and GCC Extended Asm semantics differ substantially. // -// 1. Rust asm operands go along as one list of operands. Operands themselves indicate -// if they're "in" or "out". "In" and "out" operands can interleave. One operand can be +// 1. Rust asm operands go along as one list of operands. Operands themselves indicate +// if they're "in" or "out". "In" and "out" operands can interleave. One operand can be // both "in" and "out" (`inout(reg)`). // -// GCC asm has two different lists for "in" and "out" operands. In terms of gccjit, -// this means that all "out" operands must go before "in" operands. "In" and "out" operands +// GCC asm has two different lists for "in" and "out" operands. In terms of gccjit, +// this means that all "out" operands must go before "in" operands. "In" and "out" operands // cannot interleave. // -// 2. Operand lists in both Rust and GCC are indexed. Index starts from 0. Indexes are important +// 2. Operand lists in both Rust and GCC are indexed. Index starts from 0. Indexes are important // because the asm template refers to operands by index. // // Mapping from Rust to GCC index would be 1-1 if it wasn't for... // -// 3. Clobbers. GCC has a separate list of clobbers, and clobbers don't have indexes. -// Contrary, Rust expresses clobbers through "out" operands that aren't tied to +// 3. Clobbers. GCC has a separate list of clobbers, and clobbers don't have indexes. +// Contrary, Rust expresses clobbers through "out" operands that aren't tied to // a variable (`_`), and such "clobbers" do have index. // -// 4. Furthermore, GCC Extended Asm does not support explicit register constraints -// (like `out("eax")`) directly, offering so-called "local register variables" -// as a workaround. These variables need to be declared and initialized *before* -// the Extended Asm block but *after* normal local variables +// 4. Furthermore, GCC Extended Asm does not support explicit register constraints +// (like `out("eax")`) directly, offering so-called "local register variables" +// as a workaround. These variables need to be declared and initialized *before* +// the Extended Asm block but *after* normal local variables // (see comment in `codegen_inline_asm` for explanation). // -// With that in mind, let's see how we translate Rust syntax to GCC +// With that in mind, let's see how we translate Rust syntax to GCC // (from now on, `CC` stands for "constraint code"): // // * `out(reg_class) var` -> translated to output operand: `"=CC"(var)` @@ -52,18 +52,17 @@ use crate::type_of::LayoutGccExt; // // * `out("explicit register") _` -> not translated to any operands, register is simply added to clobbers list // -// * `inout(reg_class) in_var => out_var` -> translated to two operands: +// * `inout(reg_class) in_var => out_var` -> translated to two operands: // output: `"=CC"(in_var)` -// input: `"num"(out_var)` where num is the GCC index +// input: `"num"(out_var)` where num is the GCC index // of the corresponding output operand // -// * `inout(reg_class) in_var => _` -> same as `inout(reg_class) in_var => tmp`, +// * `inout(reg_class) in_var => _` -> same as `inout(reg_class) in_var => tmp`, // where "tmp" is a temporary unused variable // -// * `out/in/inout("explicit register") var` -> translated to one or two operands as described above -// with `"r"(var)` constraint, +// * `out/in/inout("explicit register") var` -> translated to one or two operands as described above +// with `"r"(var)` constraint, // and one register variable assigned to the desired register. -// const ATT_SYNTAX_INS: &str = ".att_syntax noprefix\n\t"; const INTEL_SYNTAX_INS: &str = "\n\t.intel_syntax noprefix"; @@ -118,13 +117,20 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { true } - fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, _span: &[Span], _instance: Instance<'_>) { + fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, span: &[Span], _instance: Instance<'_>, _dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>) { + if options.contains(InlineAsmOptions::MAY_UNWIND) { + self.sess() + .struct_span_err(span[0], "GCC backend does not support unwinding from inline asm") + .emit(); + return; + } + let asm_arch = self.tcx.sess.asm_arch.unwrap(); let is_x86 = matches!(asm_arch, InlineAsmArch::X86 | InlineAsmArch::X86_64); let att_dialect = is_x86 && options.contains(InlineAsmOptions::ATT_SYNTAX); let intel_dialect = is_x86 && !options.contains(InlineAsmOptions::ATT_SYNTAX); - // GCC index of an output operand equals its position in the array + // GCC index of an output operand equals its position in the array let mut outputs = vec![]; // GCC index of an input operand equals its position in the array @@ -138,9 +144,9 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { let mut constants_len = 0; // There are rules we must adhere to if we want GCC to do the right thing: - // + // // * Every local variable that the asm block uses as an output must be declared *before* - // the asm block. + // the asm block. // * There must be no instructions whatsoever between the register variables and the asm. // // Therefore, the backend must generate the instructions strictly in this order: @@ -152,7 +158,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { // We also must make sure that no input operands are emitted before output operands. // // This is why we work in passes, first emitting local vars, then local register vars. - // Also, we don't emit any asm operands immediately; we save them to + // Also, we don't emit any asm operands immediately; we save them to // the one of the buffers to be emitted later. // 1. Normal variables (and saving operands to buffers). @@ -165,7 +171,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { (Constraint(constraint), Some(place)) => (constraint, place.layout.gcc_type(self.cx, false)), // When `reg` is a class and not an explicit register but the out place is not specified, // we need to create an unused output variable to assign the output to. This var - // needs to be of a type that's "compatible" with the register class, but specific type + // needs to be of a type that's "compatible" with the register class, but specific type // doesn't matter. (Constraint(constraint), None) => (constraint, dummy_output_type(self.cx, reg.reg_class())), (Register(_), Some(_)) => { @@ -193,7 +199,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { let tmp_var = self.current_func().new_local(None, ty, "output_register"); outputs.push(AsmOutOperand { - constraint, + constraint, rust_idx, late, readwrite: false, @@ -204,12 +210,12 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { InlineAsmOperandRef::In { reg, value } => { if let ConstraintOrRegister::Constraint(constraint) = reg_to_gcc(reg) { - inputs.push(AsmInOperand { - constraint: Cow::Borrowed(constraint), - rust_idx, + inputs.push(AsmInOperand { + constraint: Cow::Borrowed(constraint), + rust_idx, val: value.immediate() }); - } + } else { // left for the next pass continue @@ -219,7 +225,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { InlineAsmOperandRef::InOut { reg, late, in_value, out_place } => { let constraint = if let ConstraintOrRegister::Constraint(constraint) = reg_to_gcc(reg) { constraint - } + } else { // left for the next pass continue @@ -228,22 +234,22 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { // Rustc frontend guarantees that input and output types are "compatible", // so we can just use input var's type for the output variable. // - // This decision is also backed by the fact that LLVM needs in and out - // values to be of *exactly the same type*, not just "compatible". + // This decision is also backed by the fact that LLVM needs in and out + // values to be of *exactly the same type*, not just "compatible". // I'm not sure if GCC is so picky too, but better safe than sorry. let ty = in_value.layout.gcc_type(self.cx, false); let tmp_var = self.current_func().new_local(None, ty, "output_register"); // If the out_place is None (i.e `inout(reg) _` syntax was used), we translate - // it to one "readwrite (+) output variable", otherwise we translate it to two + // it to one "readwrite (+) output variable", otherwise we translate it to two // "out and tied in" vars as described above. let readwrite = out_place.is_none(); outputs.push(AsmOutOperand { - constraint, + constraint, rust_idx, late, readwrite, - tmp_var, + tmp_var, out_place, }); @@ -252,8 +258,8 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { let constraint = Cow::Owned(out_gcc_idx.to_string()); inputs.push(AsmInOperand { - constraint, - rust_idx, + constraint, + rust_idx, val: in_value.immediate() }); } @@ -280,7 +286,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { if let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg) { let out_place = if let Some(place) = place { place - } + } else { // processed in the previous pass continue @@ -291,7 +297,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { tmp_var.set_register_name(reg_name); outputs.push(AsmOutOperand { - constraint: "r".into(), + constraint: "r".into(), rust_idx, late, readwrite: false, @@ -311,9 +317,9 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { reg_var.set_register_name(reg_name); self.llbb().add_assignment(None, reg_var, value.immediate()); - inputs.push(AsmInOperand { - constraint: "r".into(), - rust_idx, + inputs.push(AsmInOperand { + constraint: "r".into(), + rust_idx, val: reg_var.to_rvalue() }); } @@ -324,31 +330,23 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { // `inout("explicit register") in_var => out_var` InlineAsmOperandRef::InOut { reg, late, in_value, out_place } => { if let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg) { - let out_place = if let Some(place) = out_place { - place - } - else { - // processed in the previous pass - continue - }; - // See explanation in the first pass. let ty = in_value.layout.gcc_type(self.cx, false); let tmp_var = self.current_func().new_local(None, ty, "output_register"); tmp_var.set_register_name(reg_name); outputs.push(AsmOutOperand { - constraint: "r".into(), + constraint: "r".into(), rust_idx, late, readwrite: false, tmp_var, - out_place: Some(out_place) + out_place, }); let constraint = Cow::Owned((outputs.len() - 1).to_string()); - inputs.push(AsmInOperand { - constraint, + inputs.push(AsmInOperand { + constraint, rust_idx, val: in_value.immediate() }); @@ -357,8 +355,8 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { // processed in the previous pass } - InlineAsmOperandRef::Const { .. } - | InlineAsmOperandRef::SymFn { .. } + InlineAsmOperandRef::Const { .. } + | InlineAsmOperandRef::SymFn { .. } | InlineAsmOperandRef::SymStatic { .. } => { // processed in the previous pass } @@ -453,7 +451,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { if !intel_dialect { template_str.push_str(INTEL_SYNTAX_INS); } - + // 4. Generate Extended Asm block let block = self.llbb(); @@ -472,7 +470,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { } if !options.contains(InlineAsmOptions::PRESERVES_FLAGS) { - // TODO(@Commeownist): I'm not 100% sure this one clobber is sufficient + // TODO(@Commeownist): I'm not 100% sure this one clobber is sufficient // on all architectures. For instance, what about FP stack? extended_asm.add_clobber("cc"); } @@ -491,10 +489,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { self.call(self.type_void(), builtin_unreachable, &[], None); } - // Write results to outputs. + // Write results to outputs. // // We need to do this because: - // 1. Turning `PlaceRef` into `RValue` is error-prone and has nasty edge cases + // 1. Turning `PlaceRef` into `RValue` is error-prone and has nasty edge cases // (especially with current `rustc_backend_ssa` API). // 2. Not every output operand has an `out_place`, and it's required by `add_output_operand`. // @@ -502,7 +500,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { // generates `out_place = tmp_var;` assignments if out_place exists. for op in &outputs { if let Some(place) = op.out_place { - OperandValue::Immediate(op.tmp_var.to_rvalue()).store(self, place); + OperandValue::Immediate(op.tmp_var.to_rvalue()).store(self, place); } } @@ -561,7 +559,6 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => unimplemented!(), InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => unimplemented!(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => unimplemented!(), - InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => unimplemented!(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8) => unimplemented!(), @@ -570,6 +567,7 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => unimplemented!(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => unimplemented!(), + InlineAsmRegClass::Avr(_) => unimplemented!(), InlineAsmRegClass::Bpf(_) => unimplemented!(), InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => unimplemented!(), InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => unimplemented!(), @@ -620,8 +618,7 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => { unimplemented!() } - InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => cx.type_i32(), + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg)=> cx.type_i32(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => cx.type_f32(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg) @@ -632,6 +629,7 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => { unimplemented!() } + InlineAsmRegClass::Avr(_) => unimplemented!(), InlineAsmRegClass::Bpf(_) => unimplemented!(), InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(), @@ -728,8 +726,7 @@ fn modifier_to_gcc(arch: InlineAsmArch, reg: InlineAsmRegClass, modifier: Option | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => { unimplemented!() } - InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => unimplemented!(), + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => unimplemented!(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => unimplemented!(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg) @@ -740,6 +737,7 @@ fn modifier_to_gcc(arch: InlineAsmArch, reg: InlineAsmRegClass, modifier: Option | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => { unimplemented!() } + InlineAsmRegClass::Avr(_) => unimplemented!(), InlineAsmRegClass::Bpf(_) => unimplemented!(), InlineAsmRegClass::Hexagon(_) => unimplemented!(), InlineAsmRegClass::Mips(_) => unimplemented!(), diff --git a/compiler/rustc_codegen_gcc/src/back/write.rs b/compiler/rustc_codegen_gcc/src/back/write.rs index c3e3847823..334ef32f1d 100644 --- a/compiler/rustc_codegen_gcc/src/back/write.rs +++ b/compiler/rustc_codegen_gcc/src/back/write.rs @@ -1,4 +1,4 @@ -use std::fs; +use std::{env, fs}; use gccjit::OutputKind; use rustc_codegen_ssa::{CompiledModule, ModuleCodegen}; @@ -32,7 +32,7 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext, _diag_han if config.emit_asm { let _timer = cgcx .prof - .generic_activity_with_arg("LLVM_module_codegen_emit_asm", &module.name[..]); + .generic_activity_with_arg("LLVM_module_codegen_emit_asm", &*module.name); let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); context.compile_to_file(OutputKind::Assembler, path.to_str().expect("path to str")); } @@ -41,18 +41,18 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext, _diag_han EmitObj::ObjectCode(_) => { let _timer = cgcx .prof - .generic_activity_with_arg("LLVM_module_codegen_emit_obj", &module.name[..]); - match &*module.name { - "std_example.7rcbfp3g-cgu.15" => { - println!("Dumping reproducer {}", module.name); - let _ = fs::create_dir("/tmp/reproducers"); - // FIXME(antoyo): segfault in dump_reproducer_to_file() might be caused by - // transmuting an rvalue to an lvalue. - // Segfault is actually in gcc::jit::reproducer::get_identifier_as_lvalue - context.dump_reproducer_to_file(&format!("/tmp/reproducers/{}.c", module.name)); - println!("Dumped reproducer {}", module.name); - }, - _ => (), + .generic_activity_with_arg("LLVM_module_codegen_emit_obj", &*module.name); + if env::var("CG_GCCJIT_DUMP_MODULE_NAMES").as_deref() == Ok("1") { + println!("Module {}", module.name); + } + if env::var("CG_GCCJIT_DUMP_MODULE").as_deref() == Ok(&module.name) { + println!("Dumping reproducer {}", module.name); + let _ = fs::create_dir("/tmp/reproducers"); + // FIXME(antoyo): segfault in dump_reproducer_to_file() might be caused by + // transmuting an rvalue to an lvalue. + // Segfault is actually in gcc::jit::reproducer::get_identifier_as_lvalue + context.dump_reproducer_to_file(&format!("/tmp/reproducers/{}.c", module.name)); + println!("Dumped reproducer {}", module.name); } context.compile_to_file(OutputKind::ObjectFile, obj_out.to_str().expect("path to str")); } diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs index a3b8d32838..8b23e96066 100644 --- a/compiler/rustc_codegen_gcc/src/base.rs +++ b/compiler/rustc_codegen_gcc/src/base.rs @@ -7,14 +7,12 @@ use gccjit::{ GlobalKind, }; use rustc_middle::dep_graph; -use rustc_middle::middle::exported_symbols; use rustc_middle::ty::TyCtxt; use rustc_middle::mir::mono::Linkage; use rustc_codegen_ssa::{ModuleCodegen, ModuleKind}; use rustc_codegen_ssa::base::maybe_create_entry_wrapper; use rustc_codegen_ssa::mono_item::MonoItemExt; use rustc_codegen_ssa::traits::DebugInfoMethods; -use rustc_metadata::EncodedMetadata; use rustc_session::config::DebugInfo; use rustc_span::Symbol; @@ -83,7 +81,10 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (Modul for arg in &tcx.sess.opts.cg.llvm_args { context.add_command_line_option(arg); } + // NOTE: an optimization (https://github.com/rust-lang/rustc_codegen_gcc/issues/53). context.add_command_line_option("-fno-semantic-interposition"); + // NOTE: Rust relies on LLVM not doing TBAA (https://github.com/rust-lang/unsafe-code-guidelines/issues/292). + context.add_command_line_option("-fno-strict-aliasing"); if env::var("CG_GCCJIT_DUMP_CODE").as_deref() == Ok("1") { context.set_dump_code_on_compile(true); } @@ -132,40 +133,3 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (Modul (module, cost) } - -pub fn write_compressed_metadata<'tcx>(tcx: TyCtxt<'tcx>, metadata: &EncodedMetadata, gcc_module: &mut GccContext) { - use snap::write::FrameEncoder; - use std::io::Write; - - // Historical note: - // - // When using link.exe it was seen that the section name `.note.rustc` - // was getting shortened to `.note.ru`, and according to the PE and COFF - // specification: - // - // > Executable images do not use a string table and do not support - // > section names longer than 8 characters - // - // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format - // - // As a result, we choose a slightly shorter name! As to why - // `.note.rustc` works on MinGW, see - // https://github.com/llvm/llvm-project/blob/llvmorg-12.0.0/lld/COFF/Writer.cpp#L1190-L1197 - let section_name = if tcx.sess.target.is_like_osx { "__DATA,.rustc" } else { ".rustc" }; - - let context = &gcc_module.context; - let mut compressed = rustc_metadata::METADATA_HEADER.to_vec(); - FrameEncoder::new(&mut compressed).write_all(&metadata.raw_data()).unwrap(); - - let name = exported_symbols::metadata_symbol_name(tcx); - let typ = context.new_array_type(None, context.new_type::(), compressed.len() as i32); - let global = context.new_global(None, GlobalKind::Exported, typ, name); - global.global_set_initializer(&compressed); - global.set_link_section(section_name); - - // Also generate a .section directive to force no - // flags, at least for ELF outputs, so that the - // metadata doesn't get loaded into memory. - let directive = format!(".section {}", section_name); - context.add_top_level_asm(None, &directive); -} diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index fff2aa6df7..379c88bbd4 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -200,7 +200,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { fn check_ptr_call<'b>(&mut self, _typ: &str, func_ptr: RValue<'gcc>, args: &'b [RValue<'gcc>]) -> Cow<'b, [RValue<'gcc>]> { let mut all_args_match = true; let mut param_types = vec![]; - let gcc_func = func_ptr.get_type().is_function_ptr_type().expect("function ptr"); + let gcc_func = func_ptr.get_type().dyncast_function_ptr_type().expect("function ptr"); for (index, arg) in args.iter().enumerate().take(gcc_func.get_param_count()) { let param = gcc_func.get_param_type(index); if param != arg.get_type() { @@ -277,7 +277,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // gccjit requires to use the result of functions, even when it's not used. // That's why we assign the result to a local or call add_eval(). - let gcc_func = func_ptr.get_type().is_function_ptr_type().expect("function ptr"); + let gcc_func = func_ptr.get_type().dyncast_function_ptr_type().expect("function ptr"); let mut return_type = gcc_func.get_return_type(); let current_block = self.current_block.borrow().expect("block"); let void_type = self.context.new_type::<()>(); @@ -605,22 +605,17 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn and(&mut self, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> { - // FIXME(antoyo): hack by putting the result in a variable to workaround this bug: - // https://gcc.gnu.org/bugzilla//show_bug.cgi?id=95498 if a.get_type() != b.get_type() { b = self.context.new_cast(None, b, a.get_type()); } - let res = self.current_func().new_local(None, b.get_type(), "andResult"); - self.llbb().add_assignment(None, res, a & b); - res.to_rvalue() + a & b } - fn or(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - // FIXME(antoyo): hack by putting the result in a variable to workaround this bug: - // https://gcc.gnu.org/bugzilla//show_bug.cgi?id=95498 - let res = self.current_func().new_local(None, b.get_type(), "orResult"); - self.llbb().add_assignment(None, res, a | b); - res.to_rvalue() + fn or(&mut self, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> { + if a.get_type() != b.get_type() { + b = self.context.new_cast(None, b, a.get_type()); + } + a | b } fn xor(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { @@ -628,8 +623,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn neg(&mut self, a: RValue<'gcc>) -> RValue<'gcc> { - // TODO(antoyo): use new_unary_op()? - self.cx.context.new_rvalue_from_long(a.get_type(), 0) - a + self.cx.context.new_unary_op(None, UnaryOp::Minus, a.get_type(), a) } fn fneg(&mut self, a: RValue<'gcc>) -> RValue<'gcc> { @@ -816,7 +810,10 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let atomic_load = self.context.get_builtin_function(&format!("__atomic_load_{}", size.bytes())); let ordering = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc()); - let volatile_const_void_ptr_type = self.context.new_type::<*mut ()>().make_const().make_volatile(); + let volatile_const_void_ptr_type = self.context.new_type::<()>() + .make_const() + .make_volatile() + .make_pointer(); let ptr = self.context.new_cast(None, ptr, volatile_const_void_ptr_type); self.context.new_call(None, atomic_load, &[ptr, ordering]) } @@ -941,7 +938,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // TODO(antoyo): handle alignment. let atomic_store = self.context.get_builtin_function(&format!("__atomic_store_{}", size.bytes())); let ordering = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc()); - let volatile_const_void_ptr_type = self.context.new_type::<*mut ()>().make_const().make_volatile(); + let volatile_const_void_ptr_type = self.context.new_type::<()>() + .make_volatile() + .make_pointer(); let ptr = self.context.new_cast(None, ptr, volatile_const_void_ptr_type); // FIXME(antoyo): fix libgccjit to allow comparing an integer type with an aligned integer type because @@ -981,12 +980,12 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { assert_eq!(idx as usize as u64, idx); let value = ptr.dereference(None).to_rvalue(); - if value_type.is_array().is_some() { + if value_type.dyncast_array().is_some() { let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from")); let element = self.context.new_array_access(None, value, index); element.get_address(None) } - else if let Some(vector_type) = value_type.is_vector() { + else if let Some(vector_type) = value_type.dyncast_vector() { let array_type = vector_type.get_element_type().make_pointer(); let array = self.bitcast(ptr, array_type); let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from")); @@ -1009,7 +1008,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn sext(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { // TODO(antoyo): check that it indeed sign extend the value. - if dest_ty.is_vector().is_some() { + if dest_ty.dyncast_vector().is_some() { // TODO(antoyo): nothing to do as it is only for LLVM? return value; } @@ -1081,7 +1080,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let right_type = rhs.get_type(); if left_type != right_type { // NOTE: because libgccjit cannot compare function pointers. - if left_type.is_function_ptr_type().is_some() && right_type.is_function_ptr_type().is_some() { + if left_type.dyncast_function_ptr_type().is_some() && right_type.dyncast_function_ptr_type().is_some() { lhs = self.context.new_cast(None, lhs, self.usize_type.make_pointer()); rhs = self.context.new_cast(None, rhs, self.usize_type.make_pointer()); } @@ -1189,12 +1188,12 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { assert_eq!(idx as usize as u64, idx); let value_type = aggregate_value.get_type(); - if value_type.is_array().is_some() { + if value_type.dyncast_array().is_some() { let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from")); let element = self.context.new_array_access(None, aggregate_value, index); element.get_address(None) } - else if value_type.is_vector().is_some() { + else if value_type.dyncast_vector().is_some() { panic!(); } else if let Some(pointer_type) = value_type.get_pointee() { @@ -1221,11 +1220,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let value_type = aggregate_value.get_type(); let lvalue = - if value_type.is_array().is_some() { + if value_type.dyncast_array().is_some() { let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from")); self.context.new_array_access(None, aggregate_value, index) } - else if value_type.is_vector().is_some() { + else if value_type.dyncast_vector().is_some() { panic!(); } else if let Some(pointer_type) = value_type.get_pointee() { @@ -1404,7 +1403,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { self.cx } - fn do_not_inline(&mut self, _llret: RValue<'gcc>) { + fn apply_attrs_to_cleanup_callsite(&mut self, _llret: RValue<'gcc>) { unimplemented!(); } diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs index bda08b653f..5851826147 100644 --- a/compiler/rustc_codegen_gcc/src/common.rs +++ b/compiler/rustc_codegen_gcc/src/common.rs @@ -1,5 +1,4 @@ use std::convert::TryFrom; -use std::convert::TryInto; use gccjit::LValue; use gccjit::{Block, CType, RValue, Type, ToRValue}; @@ -33,7 +32,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { return value; } - let global = self.global_string(&*symbol.as_str()); + let global = self.global_string(symbol.as_str()); self.const_cstr_cache.borrow_mut().insert(symbol, global); global @@ -44,7 +43,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { let string = self.context.new_string_literal(&*string); let sym = self.generate_local_symbol_name("str"); let global = self.declare_private_global(&sym, self.val_ty(string)); - global.global_set_initializer_value(string); + global.global_set_initializer_rvalue(string); global // TODO(antoyo): set linkage. } @@ -79,7 +78,7 @@ pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> bytes.iter() .map(|&byte| context.new_rvalue_from_int(byte_type, byte as i32)) .collect(); - context.new_rvalue_from_array(None, typ, &elements) + context.new_array_constructor(None, typ, &elements) } pub fn type_is_pointer<'gcc>(typ: Type<'gcc>) -> bool { @@ -120,13 +119,6 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } fn const_uint_big(&self, typ: Type<'gcc>, num: u128) -> RValue<'gcc> { - let num64: Result = num.try_into(); - if let Ok(num) = num64 { - // FIXME(antoyo): workaround for a bug where libgccjit is expecting a constant. - // The operations >> 64 and | low are making the normal case a non-constant. - return self.context.new_rvalue_from_long(typ, num as i64); - } - if num >> 64 != 0 { // FIXME(antoyo): use a new function new_rvalue_from_unsigned_long()? let low = self.context.new_rvalue_from_long(self.u64_type, num as u64 as i64); @@ -193,7 +185,7 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { // TODO(antoyo): cache the type? It's anonymous, so probably not. let typ = self.type_struct(&fields, packed); let struct_type = typ.is_struct().expect("struct type"); - self.context.new_rvalue_from_struct(None, struct_type, values) + self.context.new_struct_constructor(None, struct_type.as_type(), None, values) } fn const_to_opt_uint(&self, _v: RValue<'gcc>) -> Option { diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index 205498acc3..ba4589bd81 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -20,7 +20,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { pub fn const_bitcast(&self, value: RValue<'gcc>, typ: Type<'gcc>) -> RValue<'gcc> { if value.get_type() == self.bool_type.make_pointer() { if let Some(pointee) = typ.get_pointee() { - if pointee.is_vector().is_some() { + if pointee.dyncast_vector().is_some() { panic!() } } @@ -31,9 +31,13 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> { fn static_addr_of(&self, cv: RValue<'gcc>, align: Align, kind: Option<&str>) -> RValue<'gcc> { - if let Some(global_value) = self.const_globals.borrow().get(&cv) { - // TODO(antoyo): upgrade alignment. - return *global_value; + // TODO(antoyo): implement a proper rvalue comparison in libgccjit instead of doing the + // following: + for (value, variable) in &*self.const_globals.borrow() { + if format!("{:?}", value) == format!("{:?}", cv) { + // TODO(antoyo): upgrade alignment. + return *variable; + } } let global_value = self.static_addr_of_mut(cv, align, kind); // TODO(antoyo): set global constant. @@ -77,7 +81,7 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> { else { value }; - global.global_set_initializer_value(value); + global.global_set_initializer_rvalue(value); // As an optimization, all shared statics which do not have interior // mutability are placed into read-only memory. @@ -176,7 +180,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { }; // FIXME(antoyo): I think the name coming from generate_local_symbol_name() above cannot be used // globally. - global.global_set_initializer_value(cv); + global.global_set_initializer_rvalue(cv); // TODO(antoyo): set unnamed address. global.get_address(None) } @@ -371,7 +375,7 @@ fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &Codeg real_name.push_str(&sym); let global2 = cx.define_global(&real_name, llty, is_tls, attrs.link_section); // TODO(antoyo): set linkage. - global2.global_set_initializer_value(global1.get_address(None)); + global2.global_set_initializer_rvalue(global1.get_address(None)); // TODO(antoyo): use global_set_initializer() when it will work. global2 } diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index 7677ade731..dfcd1b6231 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -1,16 +1,6 @@ use std::cell::{Cell, RefCell}; -use gccjit::{ - Block, - Context, - CType, - Function, - FunctionType, - LValue, - RValue, - Struct, - Type, -}; +use gccjit::{Block, CType, Context, Function, FunctionType, LValue, RValue, Struct, Type}; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::traits::{ BackendTypes, diff --git a/compiler/rustc_codegen_gcc/src/declare.rs b/compiler/rustc_codegen_gcc/src/declare.rs index b79a50d1ee..dbee505a49 100644 --- a/compiler/rustc_codegen_gcc/src/declare.rs +++ b/compiler/rustc_codegen_gcc/src/declare.rs @@ -17,7 +17,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { global.set_tls_model(self.tls_model); } if let Some(link_section) = link_section { - global.set_link_section(&link_section.as_str()); + global.set_link_section(link_section.as_str()); } global } @@ -53,7 +53,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { global.set_tls_model(self.tls_model); } if let Some(link_section) = link_section { - global.set_link_section(&link_section.as_str()); + global.set_link_section(link_section.as_str()); } let global_address = global.get_address(None); self.globals.borrow_mut().insert(name.to_string(), global_address); diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index f3a2382ef3..572ac559d0 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -88,7 +88,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { let arg_tys = sig.inputs(); let ret_ty = sig.output(); let name = tcx.item_name(def_id); - let name_str = &*name.as_str(); + let name_str = name.as_str(); let llret_ty = self.layout_of(ret_ty).gcc_type(self, true); let result = PlaceRef::new_sized(llresult, fn_abi.ret.layout); @@ -526,7 +526,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let value = if result_type.is_signed(self.cx) { - self.context.new_bitcast(None, value, typ) + self.context.new_cast(None, value, typ) } else { value @@ -690,7 +690,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { }, }; - self.context.new_bitcast(None, result, result_type) + self.context.new_cast(None, result, result_type) } fn count_leading_zeroes(&self, width: u64, arg: RValue<'gcc>) -> RValue<'gcc> { @@ -741,6 +741,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let not_low = self.context.new_unary_op(None, UnaryOp::LogicalNegate, self.u64_type, low); let not_low_and_not_high = not_low & not_high; let index = not_high + not_low_and_not_high; + // NOTE: the following cast is necessary to avoid a GIMPLE verification failure in + // gcc. + // TODO(antoyo): do the correct verification in libgccjit to avoid an error at the + // compilation stage. + let index = self.context.new_cast(None, index, self.i32_type); let res = self.context.new_array_access(None, result, index); @@ -764,7 +769,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let arg = if result_type.is_signed(self.cx) { let new_type = result_type.to_unsigned(self.cx); - self.context.new_bitcast(None, arg, new_type) + self.context.new_cast(None, arg, new_type) } else { arg @@ -816,10 +821,15 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let not_high = self.context.new_unary_op(None, UnaryOp::LogicalNegate, self.u64_type, high); let not_low_and_not_high = not_low & not_high; let index = not_low + not_low_and_not_high; + // NOTE: the following cast is necessary to avoid a GIMPLE verification failure in + // gcc. + // TODO(antoyo): do the correct verification in libgccjit to avoid an error at the + // compilation stage. + let index = self.context.new_cast(None, index, self.i32_type); let res = self.context.new_array_access(None, result, index); - return self.context.new_bitcast(None, res, result_type); + return self.context.new_cast(None, res, result_type); } else { unimplemented!("count_trailing_zeroes for {:?}", arg_type); @@ -833,7 +843,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { arg }; let res = self.context.new_call(None, count_trailing_zeroes, &[arg]); - self.context.new_bitcast(None, res, result_type) + self.context.new_cast(None, res, result_type) } fn int_width(&self, typ: Type<'gcc>) -> i64 { @@ -847,7 +857,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let value = if result_type.is_signed(self.cx) { - self.context.new_bitcast(None, value, value_type) + self.context.new_cast(None, value, value_type) } else { value @@ -863,7 +873,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let low = self.context.new_cast(None, value, self.cx.ulonglong_type); let low = self.context.new_call(None, popcount, &[low]); let res = high + low; - return self.context.new_bitcast(None, res, result_type); + return self.context.new_cast(None, res, result_type); } // First step. @@ -888,7 +898,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let value = left + right; if value_type.is_u8(&self.cx) { - return self.context.new_bitcast(None, value, result_type); + return self.context.new_cast(None, value, result_type); } // Fourth step. @@ -899,7 +909,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let value = left + right; if value_type.is_u16(&self.cx) { - return self.context.new_bitcast(None, value, result_type); + return self.context.new_cast(None, value, result_type); } // Fifth step. @@ -910,7 +920,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let value = left + right; if value_type.is_u32(&self.cx) { - return self.context.new_bitcast(None, value, result_type); + return self.context.new_cast(None, value, result_type); } // Sixth step. @@ -920,7 +930,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let right = shifted & mask; let value = left + right; - self.context.new_bitcast(None, value, result_type) + self.context.new_cast(None, value, result_type) } // Algorithm from: https://blog.regehr.org/archives/1063 diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index 26a42217e4..aff27f71d9 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -52,7 +52,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), callee_ty.fn_sig(tcx)); let arg_tys = sig.inputs(); - let name_str = &*name.as_str(); + let name_str = name.as_str(); // every intrinsic below takes a SIMD vector as its first argument require_simd!(arg_tys[0], "input"); diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 629003d798..20347f1878 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -20,9 +20,7 @@ extern crate rustc_metadata; extern crate rustc_middle; extern crate rustc_session; extern crate rustc_span; -extern crate rustc_symbol_mangling; extern crate rustc_target; -extern crate snap; // This prevents duplicating functions and statics that are already part of the host rustc process. #[allow(unused_extern_crates)] @@ -92,12 +90,10 @@ impl CodegenBackend for GccCodegenBackend { let target_cpu = target_cpu(tcx.sess); let res = codegen_crate(self.clone(), tcx, target_cpu.to_string(), metadata, need_metadata_module); - rustc_symbol_mangling::test::report_symbol_names(tcx); - Box::new(res) } - fn join_codegen(&self, ongoing_codegen: Box, sess: &Session) -> Result<(CodegenResults, FxHashMap), ErrorReported> { + fn join_codegen(&self, ongoing_codegen: Box, sess: &Session, _outputs: &OutputFilenames) -> Result<(CodegenResults, FxHashMap), ErrorReported> { let (codegen_results, work_products) = ongoing_codegen .downcast::>() .expect("Expected GccCodegenBackend's OngoingCodegen, found Box") @@ -128,10 +124,6 @@ impl ExtraBackendMethods for GccCodegenBackend { } } - fn write_compressed_metadata<'tcx>(&self, tcx: TyCtxt<'tcx>, metadata: &EncodedMetadata, gcc_module: &mut Self::Module) { - base::write_compressed_metadata(tcx, metadata, gcc_module) - } - fn codegen_allocator<'tcx>(&self, tcx: TyCtxt<'tcx>, mods: &mut Self::Module, module_name: &str, kind: AllocatorKind, has_alloc_error_handler: bool) { unsafe { allocator::codegen(tcx, mods, module_name, kind, has_alloc_error_handler) } } diff --git a/compiler/rustc_codegen_gcc/src/type_.rs b/compiler/rustc_codegen_gcc/src/type_.rs index 3545e1b628..28e2adc492 100644 --- a/compiler/rustc_codegen_gcc/src/type_.rs +++ b/compiler/rustc_codegen_gcc/src/type_.rs @@ -122,7 +122,7 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { if typ.is_integral() { TypeKind::Integer } - else if typ.is_vector().is_some() { + else if typ.dyncast_vector().is_some() { TypeKind::Vector } else { @@ -141,10 +141,10 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } fn element_type(&self, ty: Type<'gcc>) -> Type<'gcc> { - if let Some(typ) = ty.is_array() { + if let Some(typ) = ty.dyncast_array() { typ } - else if let Some(vector_type) = ty.is_vector() { + else if let Some(vector_type) = ty.dyncast_vector() { vector_type.get_element_type() } else if let Some(typ) = ty.get_pointee() { diff --git a/compiler/rustc_codegen_gcc/test.sh b/compiler/rustc_codegen_gcc/test.sh index 944d0ce516..b9aeee7955 100755 --- a/compiler/rustc_codegen_gcc/test.sh +++ b/compiler/rustc_codegen_gcc/test.sh @@ -183,7 +183,7 @@ EOF git checkout src/test/ui/type-alias-impl-trait/auxiliary/cross_crate_ice2.rs rm src/test/ui/llvm-asm/llvm-asm-in-out-operand.rs || true # TODO(antoyo): Enable back this test if I ever implement the llvm_asm! macro. - RUSTC_ARGS="-Zpanic-abort-tests -Zsymbol-mangling-version=v0 -Zcodegen-backend="$(pwd)"/../target/"$CHANNEL"/librustc_codegen_gcc."$dylib_ext" --sysroot "$(pwd)"/../build_sysroot/sysroot -Cpanic=abort" + RUSTC_ARGS="-Zpanic-abort-tests -Csymbol-mangling-version=v0 -Zcodegen-backend="$(pwd)"/../target/"$CHANNEL"/librustc_codegen_gcc."$dylib_ext" --sysroot "$(pwd)"/../build_sysroot/sysroot -Cpanic=abort" echo "[TEST] rustc test suite" COMPILETEST_FORCE_STAGE0=1 ./x.py test --run always --stage 0 src/test/ui/ --rustc-args "$RUSTC_ARGS" diff --git a/compiler/rustc_codegen_gcc/tests/run/asm.rs b/compiler/rustc_codegen_gcc/tests/run/asm.rs index 9c0055b0b6..46abbb553b 100644 --- a/compiler/rustc_codegen_gcc/tests/run/asm.rs +++ b/compiler/rustc_codegen_gcc/tests/run/asm.rs @@ -3,7 +3,9 @@ // Run-time: // status: 0 -#![feature(asm, global_asm)] +#![feature(asm_const, asm_sym)] + +use std::arch::{asm, global_asm}; global_asm!(" .global add_asm @@ -17,6 +19,16 @@ extern "C" { fn add_asm(a: i64, b: i64) -> i64; } +pub unsafe fn mem_cpy(dst: *mut u8, src: *const u8, len: usize) { + asm!( + "rep movsb", + inout("rdi") dst => _, + inout("rsi") src => _, + inout("rcx") len => _, + options(preserves_flags, nostack) + ); +} + fn main() { unsafe { asm!("nop"); @@ -62,11 +74,11 @@ fn main() { } assert_eq!(x, 43); - // check inout(reg_class) x + // check inout(reg_class) x let mut x: u64 = 42; unsafe { asm!("add {0}, {0}", - inout(reg) x + inout(reg) x ); } assert_eq!(x, 84); @@ -75,7 +87,7 @@ fn main() { let mut x: u64 = 42; unsafe { asm!("add r11, r11", - inout("r11") x + inout("r11") x ); } assert_eq!(x, 84); @@ -98,12 +110,12 @@ fn main() { assert_eq!(res, 7); assert_eq!(rem, 2); - // check const + // check const let mut x: u64 = 42; unsafe { asm!("add {}, {}", inout(reg) x, - const 1 + const 1 ); } assert_eq!(x, 43); @@ -150,4 +162,11 @@ fn main() { assert_eq!(x, 42); assert_eq!(unsafe { add_asm(40, 2) }, 42); + + let array1 = [1u8, 2, 3]; + let mut array2 = [0u8, 0, 0]; + unsafe { + mem_cpy(array2.as_mut_ptr(), array1.as_ptr(), 3); + } + assert_eq!(array1, array2); } diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index 5f3f533447..3b410c2cb4 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -11,8 +11,8 @@ doctest = false bitflags = "1.0" cstr = "0.2" libc = "0.2" +libloading = "0.7.1" measureme = "10.0.0" -snap = "1" tracing = "0.1" rustc_middle = { path = "../rustc_middle" } rustc-demangle = "0.1.21" diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 07adfff090..e9b66b54c5 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -136,11 +136,11 @@ impl ArgAttributesExt for ArgAttributes { } pub trait LlvmType { - fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type; + fn llvm_type<'ll>(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type; } impl LlvmType for Reg { - fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type { + fn llvm_type<'ll>(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type { match self.kind { RegKind::Integer => cx.type_ix(self.size.bits()), RegKind::Float => match self.size.bits() { @@ -154,7 +154,7 @@ impl LlvmType for Reg { } impl LlvmType for CastTarget { - fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type { + fn llvm_type<'ll>(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type { let rest_ll_unit = self.rest.unit.llvm_type(cx); let (rest_count, rem_bytes) = if self.rest.unit.size.bytes() == 0 { (0, 0) @@ -181,9 +181,7 @@ impl LlvmType for CastTarget { let mut args: Vec<_> = self .prefix .iter() - .flat_map(|option_kind| { - option_kind.map(|kind| Reg { kind, size: self.prefix_chunk_size }.llvm_type(cx)) - }) + .flat_map(|option_reg| option_reg.map(|reg| reg.llvm_type(cx))) .chain((0..rest_count).map(|_| rest_ll_unit)) .collect(); @@ -214,7 +212,7 @@ pub trait ArgAbiExt<'ll, 'tcx> { ); } -impl ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { +impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { /// Gets the LLVM type for a place of the original Rust type of /// this argument/return, i.e., the result of `type_of::type_of`. fn memory_ty(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type { @@ -289,7 +287,7 @@ impl ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { fn store_fn_arg( &self, - bx: &mut Builder<'a, 'll, 'tcx>, + bx: &mut Builder<'_, 'll, 'tcx>, idx: &mut usize, dst: PlaceRef<'tcx, &'ll Value>, ) { @@ -316,7 +314,7 @@ impl ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { } } -impl ArgAbiMethods<'tcx> for Builder<'a, 'll, 'tcx> { +impl<'ll, 'tcx> ArgAbiMethods<'tcx> for Builder<'_, 'll, 'tcx> { fn store_fn_arg( &mut self, arg_abi: &ArgAbi<'tcx, Ty<'tcx>>, @@ -338,15 +336,15 @@ impl ArgAbiMethods<'tcx> for Builder<'a, 'll, 'tcx> { } } -pub trait FnAbiLlvmExt<'tcx> { +pub trait FnAbiLlvmExt<'ll, 'tcx> { fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type; fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type; fn llvm_cconv(&self) -> llvm::CallConv; fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value); - fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value); + fn apply_attrs_callsite(&self, bx: &mut Builder<'_, 'll, 'tcx>, callsite: &'ll Value); } -impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { +impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type { // Ignore "extra" args from the call site for C variadic functions. // Only the "fixed" args are part of the LLVM function signature. @@ -466,6 +464,9 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { ); } } + PassMode::Cast(cast) => { + cast.attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, cx, llfn); + } _ => {} } for arg in &self.args { @@ -497,14 +498,14 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { apply(a); apply(b); } - PassMode::Cast(_) => { - apply(&ArgAttributes::new()); + PassMode::Cast(cast) => { + apply(&cast.attrs); } } } } - fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value) { + fn apply_attrs_callsite(&self, bx: &mut Builder<'_, 'll, 'tcx>, callsite: &'ll Value) { if self.ret.layout.abi.is_uninhabited() { llvm::Attribute::NoReturn.apply_callsite(llvm::AttributePlace::Function, callsite); } @@ -533,6 +534,13 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { ); } } + PassMode::Cast(cast) => { + cast.attrs.apply_attrs_to_callsite( + llvm::AttributePlace::ReturnValue, + &bx.cx, + callsite, + ); + } _ => {} } if let abi::Abi::Scalar(scalar) = self.ret.layout.abi { @@ -577,8 +585,8 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { apply(bx.cx, a); apply(bx.cx, b); } - PassMode::Cast(_) => { - apply(bx.cx, &ArgAttributes::new()); + PassMode::Cast(cast) => { + apply(bx.cx, &cast.attrs); } } } @@ -602,7 +610,7 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { } } -impl AbiBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { +impl<'tcx> AbiBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { fn apply_attrs_callsite(&mut self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, callsite: Self::Value) { fn_abi.apply_attrs_callsite(self, callsite) } diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 02096f4abf..caf16c1939 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -1,6 +1,8 @@ use crate::builder::Builder; +use crate::common::Funclet; use crate::context::CodegenCx; use crate::llvm; +use crate::llvm_util; use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; @@ -21,7 +23,7 @@ use rustc_target::asm::*; use libc::{c_char, c_uint}; use tracing::debug; -impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { +impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { fn codegen_llvm_inline_asm( &mut self, ia: &hir::LlvmInlineAsmInner, @@ -98,6 +100,8 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { ia.alignstack, ia.dialect, &[span], + false, + None, ); if r.is_none() { return false; @@ -121,6 +125,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { options: InlineAsmOptions, line_spans: &[Span], instance: Instance<'_>, + dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>, ) { let asm_arch = self.tcx.sess.asm_arch.unwrap(); @@ -314,6 +319,9 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { "~{vxrm}".to_string(), ]); } + InlineAsmArch::Avr => { + constraints.push("~{sreg}".to_string()); + } InlineAsmArch::Nvptx64 => {} InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {} InlineAsmArch::Hexagon => {} @@ -355,6 +363,8 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { alignstack, dialect, line_spans, + options.contains(InlineAsmOptions::MAY_UNWIND), + dest_catch_funclet, ) .unwrap_or_else(|| span_bug!(line_spans[0], "LLVM asm constraint validation failed")); @@ -389,7 +399,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { } } -impl AsmMethods for CodegenCx<'ll, 'tcx> { +impl AsmMethods for CodegenCx<'_, '_> { fn codegen_global_asm( &self, template: &[InlineAsmTemplatePiece], @@ -437,8 +447,8 @@ impl AsmMethods for CodegenCx<'ll, 'tcx> { } } -pub(crate) fn inline_asm_call( - bx: &mut Builder<'a, 'll, 'tcx>, +pub(crate) fn inline_asm_call<'ll>( + bx: &mut Builder<'_, 'll, '_>, asm: &str, cons: &str, inputs: &[&'ll Value], @@ -447,9 +457,16 @@ pub(crate) fn inline_asm_call( alignstack: bool, dia: LlvmAsmDialect, line_spans: &[Span], + unwind: bool, + dest_catch_funclet: Option<( + &'ll llvm::BasicBlock, + &'ll llvm::BasicBlock, + Option<&Funclet<'ll>>, + )>, ) -> Option<&'ll Value> { let volatile = if volatile { llvm::True } else { llvm::False }; let alignstack = if alignstack { llvm::True } else { llvm::False }; + let can_throw = if unwind { llvm::True } else { llvm::False }; let argtys = inputs .iter() @@ -460,12 +477,19 @@ pub(crate) fn inline_asm_call( .collect::>(); debug!("Asm Output Type: {:?}", output); - let fty = bx.cx.type_func(&argtys[..], output); + let fty = bx.cx.type_func(&argtys, output); unsafe { // Ask LLVM to verify that the constraints are well-formed. let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons.as_ptr().cast(), cons.len()); debug!("constraint verification result: {:?}", constraints_ok); if constraints_ok { + if unwind && llvm_util::get_version() < (13, 0, 0) { + bx.cx.sess().span_fatal( + line_spans[0], + "unwinding from inline assembly is only supported on llvm >= 13.", + ); + } + let v = llvm::LLVMRustInlineAsm( fty, asm.as_ptr().cast(), @@ -475,8 +499,14 @@ pub(crate) fn inline_asm_call( volatile, alignstack, llvm::AsmDialect::from_generic(dia), + can_throw, ); - let call = bx.call(fty, v, inputs, None); + + let call = if let Some((dest, catch, funclet)) = dest_catch_funclet { + bx.invoke(fty, v, inputs, dest, catch, funclet) + } else { + bx.call(fty, v, inputs, None) + }; // Store mark in a metadata node so we can map LLVM errors // back to source locations. See #17552. @@ -553,7 +583,7 @@ fn a64_vreg_index(reg: InlineAsmReg) -> Option { } /// Converts a register class to an LLVM constraint code. -fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>) -> String { +fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> String { match reg { // For vector registers LLVM wants the register name to match the type size. InlineAsmRegOrRegClass::Reg(reg) => { @@ -602,7 +632,6 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>) unreachable!("clobber-only") } InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => "l", InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8) => "t", @@ -642,6 +671,11 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>) InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r", InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r", InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w", + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_upper) => "d", + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) => "r", + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) => "w", + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => "e", InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r", InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f", InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { @@ -668,8 +702,7 @@ fn modifier_to_llvm( InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { unreachable!("clobber-only") } - InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => None, + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => None, InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => None, InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg) @@ -722,6 +755,14 @@ fn modifier_to_llvm( } InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => None, InlineAsmRegClass::Bpf(_) => None, + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) + | InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) + | InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => match modifier { + Some('h') => Some('B'), + Some('l') => Some('A'), + _ => None, + }, + InlineAsmRegClass::Avr(_) => None, InlineAsmRegClass::S390x(_) => None, InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { bug!("LLVM backend does not support SPIR-V") @@ -732,7 +773,7 @@ fn modifier_to_llvm( /// Type to use for outputs that are discarded. It doesn't really matter what /// the type is, as long as it is valid for the constraint code. -fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll Type { +fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &'ll Type { match reg { InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) @@ -742,8 +783,7 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { unreachable!("clobber-only") } - InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) - | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => cx.type_i32(), + InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => cx.type_f32(), InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg) @@ -785,6 +825,11 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(), InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => cx.type_i64(), InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => cx.type_i32(), + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg) => cx.type_i8(), + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_upper) => cx.type_i8(), + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) => cx.type_i16(), + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) => cx.type_i16(), + InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => cx.type_i16(), InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(), InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { @@ -796,7 +841,7 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll /// Helper function to get the LLVM type for a Scalar. Pointers are returned as /// the equivalent integer type. -fn llvm_asm_scalar_type(cx: &CodegenCx<'ll, 'tcx>, scalar: Scalar) -> &'ll Type { +fn llvm_asm_scalar_type<'ll>(cx: &CodegenCx<'ll, '_>, scalar: Scalar) -> &'ll Type { match scalar.value { Primitive::Int(Integer::I8, _) => cx.type_i8(), Primitive::Int(Integer::I16, _) => cx.type_i16(), @@ -810,8 +855,8 @@ fn llvm_asm_scalar_type(cx: &CodegenCx<'ll, 'tcx>, scalar: Scalar) -> &'ll Type } /// Fix up an input value to work around LLVM bugs. -fn llvm_fixup_input( - bx: &mut Builder<'a, 'll, 'tcx>, +fn llvm_fixup_input<'ll, 'tcx>( + bx: &mut Builder<'_, 'll, 'tcx>, mut value: &'ll Value, reg: InlineAsmRegClass, layout: &TyAndLayout<'tcx>, @@ -888,8 +933,8 @@ fn llvm_fixup_input( } /// Fix up an output value to work around LLVM bugs. -fn llvm_fixup_output( - bx: &mut Builder<'a, 'll, 'tcx>, +fn llvm_fixup_output<'ll, 'tcx>( + bx: &mut Builder<'_, 'll, 'tcx>, mut value: &'ll Value, reg: InlineAsmRegClass, layout: &TyAndLayout<'tcx>, @@ -964,7 +1009,7 @@ fn llvm_fixup_output( } /// Output type to use for llvm_fixup_output. -fn llvm_fixup_output_type( +fn llvm_fixup_output_type<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass, layout: &TyAndLayout<'tcx>, diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 8e6329a997..7f82ce307d 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -25,7 +25,7 @@ use crate::value::Value; /// Mark LLVM function to use provided inline heuristic. #[inline] -fn inline(cx: &CodegenCx<'ll, '_>, val: &'ll Value, inline: InlineAttr) { +fn inline<'ll>(cx: &CodegenCx<'ll, '_>, val: &'ll Value, inline: InlineAttr) { use self::InlineAttr::*; match inline { Hint => Attribute::InlineHint.apply_llfn(Function, val), @@ -41,7 +41,7 @@ fn inline(cx: &CodegenCx<'ll, '_>, val: &'ll Value, inline: InlineAttr) { /// Apply LLVM sanitize attributes. #[inline] -pub fn sanitize(cx: &CodegenCx<'ll, '_>, no_sanitize: SanitizerSet, llfn: &'ll Value) { +pub fn sanitize<'ll>(cx: &CodegenCx<'ll, '_>, no_sanitize: SanitizerSet, llfn: &'ll Value) { let enabled = cx.tcx.sess.opts.debugging_opts.sanitizer - no_sanitize; if enabled.contains(SanitizerSet::ADDRESS) { llvm::Attribute::SanitizeAddress.apply_llfn(Function, llfn); @@ -59,17 +59,17 @@ pub fn sanitize(cx: &CodegenCx<'ll, '_>, no_sanitize: SanitizerSet, llfn: &'ll V /// Tell LLVM to emit or not emit the information necessary to unwind the stack for the function. #[inline] -pub fn emit_uwtable(val: &'ll Value, emit: bool) { +pub fn emit_uwtable(val: &Value, emit: bool) { Attribute::UWTable.toggle_llfn(Function, val, emit); } /// Tell LLVM if this function should be 'naked', i.e., skip the epilogue and prologue. #[inline] -fn naked(val: &'ll Value, is_naked: bool) { +fn naked(val: &Value, is_naked: bool) { Attribute::Naked.toggle_llfn(Function, val, is_naked); } -pub fn set_frame_pointer_type(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { +pub fn set_frame_pointer_type<'ll>(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { let mut fp = cx.sess().target.frame_pointer; // "mcount" function relies on stack pointer. // See . @@ -92,7 +92,7 @@ pub fn set_frame_pointer_type(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { /// Tell LLVM what instrument function to insert. #[inline] -fn set_instrument_function(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { +fn set_instrument_function<'ll>(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { if cx.sess().instrument_mcount() { // Similar to `clang -pg` behavior. Handled by the // `post-inline-ee-instrument` LLVM pass. @@ -110,7 +110,7 @@ fn set_instrument_function(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { } } -fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { +fn set_probestack<'ll>(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { // Currently stack probes seem somewhat incompatible with the address // sanitizer and thread sanitizer. With asan we're already protected from // stack overflow anyway so we don't really need stack probes regardless. @@ -161,7 +161,7 @@ fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { } } -fn set_stackprotector(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { +fn set_stackprotector<'ll>(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { let sspattr = match cx.sess().stack_protector() { StackProtector::None => return, StackProtector::All => Attribute::StackProtectReq, @@ -172,7 +172,7 @@ fn set_stackprotector(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { sspattr.apply_llfn(Function, llfn) } -pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { +pub fn apply_target_cpu_attr<'ll>(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { let target_cpu = SmallCStr::new(llvm_util::target_cpu(cx.tcx.sess)); llvm::AddFunctionAttrStringValue( llfn, @@ -182,7 +182,7 @@ pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { ); } -pub fn apply_tune_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { +pub fn apply_tune_cpu_attr<'ll>(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { if let Some(tune) = llvm_util::tune_cpu(cx.tcx.sess) { let tune_cpu = SmallCStr::new(tune); llvm::AddFunctionAttrStringValue( @@ -196,14 +196,14 @@ pub fn apply_tune_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { /// Sets the `NonLazyBind` LLVM attribute on a given function, /// assuming the codegen options allow skipping the PLT. -pub fn non_lazy_bind(sess: &Session, llfn: &'ll Value) { +pub fn non_lazy_bind<'ll>(sess: &Session, llfn: &'ll Value) { // Don't generate calls through PLT if it's not necessary if !sess.needs_plt() { Attribute::NonLazyBind.apply_llfn(Function, llfn); } } -pub(crate) fn default_optimisation_attrs(sess: &Session, llfn: &'ll Value) { +pub(crate) fn default_optimisation_attrs<'ll>(sess: &Session, llfn: &'ll Value) { match sess.opts.optimize { OptLevel::Size => { llvm::Attribute::MinSize.unapply_llfn(Function, llfn); @@ -226,7 +226,11 @@ pub(crate) fn default_optimisation_attrs(sess: &Session, llfn: &'ll Value) { /// Composite function which sets LLVM attributes for function depending on its AST (`#[attribute]`) /// attributes. -pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::Instance<'tcx>) { +pub fn from_fn_attrs<'ll, 'tcx>( + cx: &CodegenCx<'ll, 'tcx>, + llfn: &'ll Value, + instance: ty::Instance<'tcx>, +) { let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(instance.def_id()); match codegen_fn_attrs.optimize { @@ -322,7 +326,7 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty:: .target_features .iter() .flat_map(|f| { - let feature = &f.as_str(); + let feature = f.as_str(); llvm_util::to_llvm_feature(cx.tcx.sess, feature) .into_iter() .map(|f| format!("+{}", f)) @@ -347,7 +351,7 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty:: let name = codegen_fn_attrs.link_name.unwrap_or_else(|| cx.tcx.item_name(instance.def_id())); - let name = CString::new(&name.as_str()[..]).unwrap(); + let name = CString::new(name.as_str()).unwrap(); llvm::AddFunctionAttrStringValue( llfn, llvm::AttributePlace::Function, diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 97780de9ba..ddba43cd1f 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -3,7 +3,7 @@ use crate::back::write::{ }; use crate::llvm::archive_ro::ArchiveRO; use crate::llvm::{self, build_string, False, True}; -use crate::{LlvmCodegenBackend, ModuleLlvm}; +use crate::{llvm_util, LlvmCodegenBackend, ModuleLlvm}; use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared}; use rustc_codegen_ssa::back::symbol_export; use rustc_codegen_ssa::back::write::{ @@ -363,7 +363,7 @@ fn fat_lto( crate struct Linker<'a>(&'a mut llvm::Linker<'a>); -impl Linker<'a> { +impl<'a> Linker<'a> { crate fn new(llmod: &'a llvm::Module) -> Self { unsafe { Linker(llvm::LLVMRustLinkerNew(llmod)) } } @@ -383,7 +383,7 @@ impl Linker<'a> { } } -impl Drop for Linker<'a> { +impl Drop for Linker<'_> { fn drop(&mut self) { unsafe { llvm::LLVMRustLinkerFree(&mut *(self.0 as *mut _)); @@ -587,7 +587,7 @@ pub(crate) fn run_pass_manager( config: &ModuleConfig, thin: bool, ) -> Result<(), FatalError> { - let _timer = cgcx.prof.extra_verbose_generic_activity("LLVM_lto_optimize", &module.name[..]); + let _timer = cgcx.prof.extra_verbose_generic_activity("LLVM_lto_optimize", &*module.name); // Now we have one massive module inside of llmod. Time to run the // LTO-specific optimization passes that LLVM provides. @@ -596,7 +596,10 @@ pub(crate) fn run_pass_manager( // tools/lto/LTOCodeGenerator.cpp debug!("running the pass manager"); unsafe { - if write::should_use_new_llvm_pass_manager(cgcx, config) { + if llvm_util::should_use_new_llvm_pass_manager( + &config.new_llvm_pass_manager, + &cgcx.target_arch, + ) { let opt_stage = if thin { llvm::OptStage::ThinLTO } else { llvm::OptStage::FatLTO }; let opt_level = config.opt_level.unwrap_or(config::OptLevel::No); write::optimize_with_new_llvm_pass_manager( diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 6d2ad70af2..384596dfff 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -23,7 +23,7 @@ use rustc_errors::{FatalError, Handler, Level}; use rustc_fs_util::{link_or_copy, path_to_c_string}; use rustc_middle::bug; use rustc_middle::ty::TyCtxt; -use rustc_session::config::{self, Lto, OutputType, Passes, SwitchWithOptPath}; +use rustc_session::config::{self, Lto, OutputType, Passes, SplitDwarfKind, SwitchWithOptPath}; use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::InnerSpan; @@ -46,7 +46,7 @@ pub fn llvm_err(handler: &rustc_errors::Handler, msg: &str) -> FatalError { } } -pub fn write_output_file( +pub fn write_output_file<'ll>( handler: &rustc_errors::Handler, target: &'ll llvm::TargetMachine, pm: &llvm::PassManager<'ll>, @@ -106,7 +106,11 @@ pub fn create_informational_target_machine(sess: &Session) -> &'static mut llvm: pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> &'static mut llvm::TargetMachine { let split_dwarf_file = if tcx.sess.target_can_use_split_dwarf() { - tcx.output_filenames(()).split_dwarf_path(tcx.sess.split_debuginfo(), Some(mod_name)) + tcx.output_filenames(()).split_dwarf_path( + tcx.sess.split_debuginfo(), + tcx.sess.opts.debugging_opts.split_dwarf_kind, + Some(mod_name), + ) } else { None }; @@ -205,8 +209,11 @@ pub fn target_machine_factory( let use_init_array = !sess.opts.debugging_opts.use_ctors_section.unwrap_or(sess.target.use_ctors_section); + let path_mapping = sess.source_map().path_mapping().clone(); + Arc::new(move |config: TargetMachineFactoryConfig| { - let split_dwarf_file = config.split_dwarf_file.unwrap_or_default(); + let split_dwarf_file = + path_mapping.map_prefix(config.split_dwarf_file.unwrap_or_default()).0; let split_dwarf_file = CString::new(split_dwarf_file.to_str().unwrap()).unwrap(); let tm = unsafe { @@ -259,6 +266,7 @@ pub(crate) fn save_temp_bitcode( pub struct DiagnosticHandlers<'a> { data: *mut (&'a CodegenContext, &'a Handler), llcx: &'a llvm::Context, + old_handler: Option<&'a llvm::DiagnosticHandler>, } impl<'a> DiagnosticHandlers<'a> { @@ -267,12 +275,35 @@ impl<'a> DiagnosticHandlers<'a> { handler: &'a Handler, llcx: &'a llvm::Context, ) -> Self { + let remark_passes_all: bool; + let remark_passes: Vec; + match &cgcx.remark { + Passes::All => { + remark_passes_all = true; + remark_passes = Vec::new(); + } + Passes::Some(passes) => { + remark_passes_all = false; + remark_passes = + passes.iter().map(|name| CString::new(name.as_str()).unwrap()).collect(); + } + }; + let remark_passes: Vec<*const c_char> = + remark_passes.iter().map(|name: &CString| name.as_ptr()).collect(); let data = Box::into_raw(Box::new((cgcx, handler))); unsafe { + let old_handler = llvm::LLVMRustContextGetDiagnosticHandler(llcx); + llvm::LLVMRustContextConfigureDiagnosticHandler( + llcx, + diagnostic_handler, + data.cast(), + remark_passes_all, + remark_passes.as_ptr(), + remark_passes.len(), + ); llvm::LLVMRustSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, data.cast()); - llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, data.cast()); + DiagnosticHandlers { data, llcx, old_handler } } - DiagnosticHandlers { data, llcx } } } @@ -281,7 +312,7 @@ impl<'a> Drop for DiagnosticHandlers<'a> { use std::ptr::null_mut; unsafe { llvm::LLVMRustSetInlineAsmDiagnosticHandler(self.llcx, inline_asm_handler, null_mut()); - llvm::LLVMContextSetDiagnosticHandler(self.llcx, diagnostic_handler, null_mut()); + llvm::LLVMRustContextSetDiagnosticHandler(self.llcx, self.old_handler); drop(Box::from_raw(self.data)); } } @@ -337,13 +368,8 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void if enabled { diag_handler.note_without_error(&format!( - "optimization {} for {} at {}:{}:{}: {}", - opt.kind.describe(), - opt.pass_name, - opt.filename, - opt.line, - opt.column, - opt.message + "{}:{}:{}: {}: {}", + opt.filename, opt.line, opt.column, opt.pass_name, opt.message, )); } } @@ -394,17 +420,6 @@ fn get_pgo_sample_use_path(config: &ModuleConfig) -> Option { .map(|path_buf| CString::new(path_buf.to_string_lossy().as_bytes()).unwrap()) } -pub(crate) fn should_use_new_llvm_pass_manager( - _cgcx: &CodegenContext, - config: &ModuleConfig, -) -> bool { - // The new pass manager is causing significant performance issues such as #91128, and is - // therefore disabled in stable versions of rustc by default. - config - .new_llvm_pass_manager - .unwrap_or(false) -} - pub(crate) unsafe fn optimize_with_new_llvm_pass_manager( cgcx: &CodegenContext, diag_handler: &Handler, @@ -447,6 +462,8 @@ pub(crate) unsafe fn optimize_with_new_llvm_pass_manager( let extra_passes = config.passes.join(","); + let llvm_plugins = config.llvm_plugins.join(","); + // FIXME: NewPM doesn't provide a facility to pass custom InlineParams. // We would have to add upstream support for this first, before we can support // config.inline_threshold and our more aggressive default thresholds. @@ -476,6 +493,8 @@ pub(crate) unsafe fn optimize_with_new_llvm_pass_manager( selfprofile_after_pass_callback, extra_passes.as_ptr().cast(), extra_passes.len(), + llvm_plugins.as_ptr().cast(), + llvm_plugins.len(), ); result.into_result().map_err(|()| llvm_err(diag_handler, "failed to run LLVM passes")) } @@ -487,7 +506,7 @@ pub(crate) unsafe fn optimize( module: &ModuleCodegen, config: &ModuleConfig, ) -> Result<(), FatalError> { - let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_optimize", &module.name[..]); + let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_optimize", &*module.name); let llmod = module.module_llvm.llmod(); let llcx = &*module.module_llvm.llcx; @@ -504,7 +523,10 @@ pub(crate) unsafe fn optimize( } if let Some(opt_level) = config.opt_level { - if should_use_new_llvm_pass_manager(cgcx, config) { + if llvm_util::should_use_new_llvm_pass_manager( + &config.new_llvm_pass_manager, + &cgcx.target_arch, + ) { let opt_stage = match cgcx.lto { Lto::Fat => llvm::OptStage::PreLinkFatLTO, Lto::Thin | Lto::ThinLocal => llvm::OptStage::PreLinkThinLTO, @@ -640,14 +662,14 @@ pub(crate) unsafe fn optimize( { let _timer = cgcx.prof.extra_verbose_generic_activity( "LLVM_module_optimize_function_passes", - &module.name[..], + &*module.name, ); llvm::LLVMRustRunFunctionPassManager(fpm, llmod); } { let _timer = cgcx.prof.extra_verbose_generic_activity( "LLVM_module_optimize_module_passes", - &module.name[..], + &*module.name, ); llvm::LLVMRunPassManager(mpm, llmod); } @@ -710,7 +732,7 @@ pub(crate) unsafe fn codegen( module: ModuleCodegen, config: &ModuleConfig, ) -> Result { - let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_codegen", &module.name[..]); + let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_codegen", &*module.name); { let llmod = module.module_llvm.llmod(); let llcx = &*module.module_llvm.llcx; @@ -759,7 +781,7 @@ pub(crate) unsafe fn codegen( if config.bitcode_needed() { let _timer = cgcx .prof - .generic_activity_with_arg("LLVM_module_codegen_make_bitcode", &module.name[..]); + .generic_activity_with_arg("LLVM_module_codegen_make_bitcode", &*module.name); let thin = ThinBuffer::new(llmod); let data = thin.data(); @@ -772,10 +794,9 @@ pub(crate) unsafe fn codegen( } if config.emit_bc || config.emit_obj == EmitObj::Bitcode { - let _timer = cgcx.prof.generic_activity_with_arg( - "LLVM_module_codegen_emit_bitcode", - &module.name[..], - ); + let _timer = cgcx + .prof + .generic_activity_with_arg("LLVM_module_codegen_emit_bitcode", &*module.name); if let Err(e) = fs::write(&bc_out, data) { let msg = format!("failed to write bytecode to {}: {}", bc_out.display(), e); diag_handler.err(&msg); @@ -783,18 +804,16 @@ pub(crate) unsafe fn codegen( } if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) { - let _timer = cgcx.prof.generic_activity_with_arg( - "LLVM_module_codegen_embed_bitcode", - &module.name[..], - ); + let _timer = cgcx + .prof + .generic_activity_with_arg("LLVM_module_codegen_embed_bitcode", &*module.name); embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data); } } if config.emit_ir { - let _timer = cgcx - .prof - .generic_activity_with_arg("LLVM_module_codegen_emit_ir", &module.name[..]); + let _timer = + cgcx.prof.generic_activity_with_arg("LLVM_module_codegen_emit_ir", &*module.name); let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name); let out_c = path_to_c_string(&out); @@ -843,9 +862,8 @@ pub(crate) unsafe fn codegen( } if config.emit_asm { - let _timer = cgcx - .prof - .generic_activity_with_arg("LLVM_module_codegen_emit_asm", &module.name[..]); + let _timer = + cgcx.prof.generic_activity_with_arg("LLVM_module_codegen_emit_asm", &*module.name); let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); // We can't use the same module for asm and object code output, @@ -875,20 +893,21 @@ pub(crate) unsafe fn codegen( EmitObj::ObjectCode(_) => { let _timer = cgcx .prof - .generic_activity_with_arg("LLVM_module_codegen_emit_obj", &module.name[..]); + .generic_activity_with_arg("LLVM_module_codegen_emit_obj", &*module.name); let dwo_out = cgcx.output_filenames.temp_path_dwo(module_name); - let dwo_out = match cgcx.split_debuginfo { - // Don't change how DWARF is emitted in single mode (or when disabled). - SplitDebuginfo::Off | SplitDebuginfo::Packed => None, - // Emit (a subset of the) DWARF into a separate file in split mode. - SplitDebuginfo::Unpacked => { - if cgcx.target_can_use_split_dwarf { - Some(dwo_out.as_path()) - } else { - None - } - } + let dwo_out = match (cgcx.split_debuginfo, cgcx.split_dwarf_kind) { + // Don't change how DWARF is emitted when disabled. + (SplitDebuginfo::Off, _) => None, + // Don't provide a DWARF object path if split debuginfo is enabled but this is + // a platform that doesn't support Split DWARF. + _ if !cgcx.target_can_use_split_dwarf => None, + // Don't provide a DWARF object path in single mode, sections will be written + // into the object as normal but ignored by linker. + (_, SplitDwarfKind::Single) => None, + // Emit (a subset of the) DWARF into a separate dwarf object file in split + // mode. + (_, SplitDwarfKind::Split) => Some(dwo_out.as_path()), }; with_codegen(tm, llmod, config.no_builtins, |cpm| { @@ -925,12 +944,37 @@ pub(crate) unsafe fn codegen( Ok(module.into_compiled_module( config.emit_obj != EmitObj::None, - cgcx.target_can_use_split_dwarf && cgcx.split_debuginfo == SplitDebuginfo::Unpacked, + cgcx.target_can_use_split_dwarf + && cgcx.split_debuginfo != SplitDebuginfo::Off + && cgcx.split_dwarf_kind == SplitDwarfKind::Split, config.emit_bc, &cgcx.output_filenames, )) } +fn create_section_with_flags_asm(section_name: &str, section_flags: &str, data: &[u8]) -> Vec { + let mut asm = format!(".section {},\"{}\"\n", section_name, section_flags).into_bytes(); + asm.extend_from_slice(b".ascii \""); + asm.reserve(data.len()); + for &byte in data { + if byte == b'\\' || byte == b'"' { + asm.push(b'\\'); + asm.push(byte); + } else if byte < 0x20 || byte >= 0x80 { + // Avoid non UTF-8 inline assembly. Use octal escape sequence, because it is fixed + // width, while hex escapes will consume following characters. + asm.push(b'\\'); + asm.push(b'0' + ((byte >> 6) & 0x7)); + asm.push(b'0' + ((byte >> 3) & 0x7)); + asm.push(b'0' + ((byte >> 0) & 0x7)); + } else { + asm.push(byte); + } + } + asm.extend_from_slice(b"\"\n"); + asm +} + /// Embed the bitcode of an LLVM module in the LLVM module itself. /// /// This is done primarily for iOS where it appears to be standard to compile C @@ -956,34 +1000,6 @@ unsafe fn embed_bitcode( cmdline: &str, bitcode: &[u8], ) { - let llconst = common::bytes_in_context(llcx, bitcode); - let llglobal = llvm::LLVMAddGlobal( - llmod, - common::val_ty(llconst), - "rustc.embedded.module\0".as_ptr().cast(), - ); - llvm::LLVMSetInitializer(llglobal, llconst); - - let is_apple = cgcx.opts.target_triple.triple().contains("-ios") - || cgcx.opts.target_triple.triple().contains("-darwin") - || cgcx.opts.target_triple.triple().contains("-tvos"); - - let section = if is_apple { "__LLVM,__bitcode\0" } else { ".llvmbc\0" }; - llvm::LLVMSetSection(llglobal, section.as_ptr().cast()); - llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); - llvm::LLVMSetGlobalConstant(llglobal, llvm::True); - - let llconst = common::bytes_in_context(llcx, cmdline.as_bytes()); - let llglobal = llvm::LLVMAddGlobal( - llmod, - common::val_ty(llconst), - "rustc.embedded.cmdline\0".as_ptr().cast(), - ); - llvm::LLVMSetInitializer(llglobal, llconst); - let section = if is_apple { "__LLVM,__cmdline\0" } else { ".llvmcmd\0" }; - llvm::LLVMSetSection(llglobal, section.as_ptr().cast()); - llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); - // We're adding custom sections to the output object file, but we definitely // do not want these custom sections to make their way into the final linked // executable. The purpose of these custom sections is for tooling @@ -1005,31 +1021,54 @@ unsafe fn embed_bitcode( // * COFF - if we don't do anything the linker will by default copy all // these sections to the output artifact, not what we want! To subvert // this we want to flag the sections we inserted here as - // `IMAGE_SCN_LNK_REMOVE`. Unfortunately though LLVM has no native way to - // do this. Thankfully though we can do this with some inline assembly, - // which is easy enough to add via module-level global inline asm. + // `IMAGE_SCN_LNK_REMOVE`. // // * ELF - this is very similar to COFF above. One difference is that these // sections are removed from the output linked artifact when // `--gc-sections` is passed, which we pass by default. If that flag isn't // passed though then these sections will show up in the final output. // Additionally the flag that we need to set here is `SHF_EXCLUDE`. + // + // Unfortunately, LLVM provides no way to set custom section flags. For ELF + // and COFF we emit the sections using module level inline assembly for that + // reason (see issue #90326 for historical background). + let is_apple = cgcx.opts.target_triple.triple().contains("-ios") + || cgcx.opts.target_triple.triple().contains("-darwin") + || cgcx.opts.target_triple.triple().contains("-tvos"); if is_apple || cgcx.opts.target_triple.triple().starts_with("wasm") || cgcx.opts.target_triple.triple().starts_with("asmjs") { - // nothing to do here - } else if cgcx.is_pe_coff { - let asm = " - .section .llvmbc,\"n\" - .section .llvmcmd,\"n\" - "; - llvm::LLVMRustAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len()); + // We don't need custom section flags, create LLVM globals. + let llconst = common::bytes_in_context(llcx, bitcode); + let llglobal = llvm::LLVMAddGlobal( + llmod, + common::val_ty(llconst), + "rustc.embedded.module\0".as_ptr().cast(), + ); + llvm::LLVMSetInitializer(llglobal, llconst); + + let section = if is_apple { "__LLVM,__bitcode\0" } else { ".llvmbc\0" }; + llvm::LLVMSetSection(llglobal, section.as_ptr().cast()); + llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); + llvm::LLVMSetGlobalConstant(llglobal, llvm::True); + + let llconst = common::bytes_in_context(llcx, cmdline.as_bytes()); + let llglobal = llvm::LLVMAddGlobal( + llmod, + common::val_ty(llconst), + "rustc.embedded.cmdline\0".as_ptr().cast(), + ); + llvm::LLVMSetInitializer(llglobal, llconst); + let section = if is_apple { "__LLVM,__cmdline\0" } else { ".llvmcmd\0" }; + llvm::LLVMSetSection(llglobal, section.as_ptr().cast()); + llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); } else { - let asm = " - .section .llvmbc,\"e\" - .section .llvmcmd,\"e\" - "; + // We need custom section flags, so emit module-level inline assembly. + let section_flags = if cgcx.is_pe_coff { "n" } else { "e" }; + let asm = create_section_with_flags_asm(".llvmbc", section_flags, bitcode); + llvm::LLVMRustAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len()); + let asm = create_section_with_flags_asm(".llvmcmd", section_flags, cmdline.as_bytes()); llvm::LLVMRustAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len()); } } diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index 8766caef6e..7b6ce5ea89 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -9,13 +9,12 @@ //! int)` and `rec(x=int, y=int, z=int)` will have the same [`llvm::Type`]. //! //! [`Ty`]: rustc_middle::ty::Ty -//! [`val_ty`]: common::val_ty +//! [`val_ty`]: crate::common::val_ty use super::ModuleLlvm; use crate::attributes; use crate::builder::Builder; -use crate::common; use crate::context::CodegenCx; use crate::llvm; use crate::value::Value; @@ -25,72 +24,22 @@ use rustc_codegen_ssa::mono_item::MonoItemExt; use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{ModuleCodegen, ModuleKind}; use rustc_data_structures::small_c_str::SmallCStr; -use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; -use rustc_middle::middle::exported_symbols; use rustc_middle::mir::mono::{Linkage, Visibility}; use rustc_middle::ty::TyCtxt; use rustc_session::config::DebugInfo; use rustc_span::symbol::Symbol; use rustc_target::spec::SanitizerSet; -use std::ffi::CString; use std::time::Instant; -pub fn write_compressed_metadata<'tcx>( - tcx: TyCtxt<'tcx>, - metadata: &EncodedMetadata, - llvm_module: &mut ModuleLlvm, -) { - use snap::write::FrameEncoder; - use std::io::Write; - - // Historical note: - // - // When using link.exe it was seen that the section name `.note.rustc` - // was getting shortened to `.note.ru`, and according to the PE and COFF - // specification: - // - // > Executable images do not use a string table and do not support - // > section names longer than 8 characters - // - // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format - // - // As a result, we choose a slightly shorter name! As to why - // `.note.rustc` works on MinGW, see - // https://github.com/llvm/llvm-project/blob/llvmorg-12.0.0/lld/COFF/Writer.cpp#L1190-L1197 - let section_name = if tcx.sess.target.is_like_osx { "__DATA,.rustc" } else { ".rustc" }; - - let (metadata_llcx, metadata_llmod) = (&*llvm_module.llcx, llvm_module.llmod()); - let mut compressed = rustc_metadata::METADATA_HEADER.to_vec(); - FrameEncoder::new(&mut compressed).write_all(metadata.raw_data()).unwrap(); - - let llmeta = common::bytes_in_context(metadata_llcx, &compressed); - let llconst = common::struct_in_context(metadata_llcx, &[llmeta], false); - let name = exported_symbols::metadata_symbol_name(tcx); - let buf = CString::new(name).unwrap(); - let llglobal = - unsafe { llvm::LLVMAddGlobal(metadata_llmod, common::val_ty(llconst), buf.as_ptr()) }; - unsafe { - llvm::LLVMSetInitializer(llglobal, llconst); - let name = SmallCStr::new(section_name); - llvm::LLVMSetSection(llglobal, name.as_ptr()); - - // Also generate a .section directive to force no - // flags, at least for ELF outputs, so that the - // metadata doesn't get loaded into memory. - let directive = format!(".section {}", section_name); - llvm::LLVMSetModuleInlineAsm2(metadata_llmod, directive.as_ptr().cast(), directive.len()) - } -} - pub struct ValueIter<'ll> { cur: Option<&'ll Value>, step: unsafe extern "C" fn(&'ll Value) -> Option<&'ll Value>, } -impl Iterator for ValueIter<'ll> { +impl<'ll> Iterator for ValueIter<'ll> { type Item = &'ll Value; fn next(&mut self) -> Option<&'ll Value> { @@ -102,14 +51,11 @@ impl Iterator for ValueIter<'ll> { } } -pub fn iter_globals(llmod: &'ll llvm::Module) -> ValueIter<'ll> { +pub fn iter_globals(llmod: &llvm::Module) -> ValueIter<'_> { unsafe { ValueIter { cur: llvm::LLVMGetFirstGlobal(llmod), step: llvm::LLVMGetNextGlobal } } } -pub fn compile_codegen_unit( - tcx: TyCtxt<'tcx>, - cgu_name: Symbol, -) -> (ModuleCodegen, u64) { +pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen, u64) { let start_time = Instant::now(); let dep_node = tcx.codegen_unit(cgu_name).codegen_dep_node(tcx); @@ -133,7 +79,7 @@ pub fn compile_codegen_unit( &[cgu_name.to_string(), cgu.size_estimate().to_string()], ); // Instantiate monomorphizations without filling out definitions yet... - let llvm_module = ModuleLlvm::new(tcx, &cgu_name.as_str()); + let llvm_module = ModuleLlvm::new(tcx, cgu_name.as_str()); { let cx = CodegenCx::new(tcx, cgu, &llvm_module); let mono_items = cx.codegen_unit.items_in_deterministic_order(cx.tcx); @@ -197,7 +143,7 @@ pub fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) { None => return, }; unsafe { - let buf = SmallCStr::new(§.as_str()); + let buf = SmallCStr::new(sect.as_str()); llvm::LLVMSetSection(llval, buf.as_ptr()); } } diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index ff88302bf7..5217fa2758 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -36,7 +36,7 @@ pub struct Builder<'a, 'll, 'tcx> { pub cx: &'a CodegenCx<'ll, 'tcx>, } -impl Drop for Builder<'a, 'll, 'tcx> { +impl Drop for Builder<'_, '_, '_> { fn drop(&mut self) { unsafe { llvm::LLVMDisposeBuilder(&mut *(self.llbuilder as *mut _)); @@ -52,7 +52,7 @@ const EMPTY_C_STR: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"\0") } // FIXME(eddyb) pass `&CStr` directly to FFI once it's a thin pointer. const UNNAMED: *const c_char = EMPTY_C_STR.as_ptr(); -impl BackendTypes for Builder<'_, 'll, 'tcx> { +impl<'ll, 'tcx> BackendTypes for Builder<'_, 'll, 'tcx> { type Value = as BackendTypes>::Value; type Function = as BackendTypes>::Function; type BasicBlock = as BackendTypes>::BasicBlock; @@ -70,27 +70,27 @@ impl abi::HasDataLayout for Builder<'_, '_, '_> { } } -impl ty::layout::HasTyCtxt<'tcx> for Builder<'_, '_, 'tcx> { +impl<'tcx> ty::layout::HasTyCtxt<'tcx> for Builder<'_, '_, 'tcx> { #[inline] fn tcx(&self) -> TyCtxt<'tcx> { self.cx.tcx } } -impl ty::layout::HasParamEnv<'tcx> for Builder<'_, '_, 'tcx> { +impl<'tcx> ty::layout::HasParamEnv<'tcx> for Builder<'_, '_, 'tcx> { fn param_env(&self) -> ty::ParamEnv<'tcx> { self.cx.param_env() } } -impl HasTargetSpec for Builder<'_, '_, 'tcx> { +impl HasTargetSpec for Builder<'_, '_, '_> { #[inline] fn target_spec(&self) -> &Target { self.cx.target_spec() } } -impl LayoutOfHelpers<'tcx> for Builder<'_, '_, 'tcx> { +impl<'tcx> LayoutOfHelpers<'tcx> for Builder<'_, '_, 'tcx> { type LayoutOfResult = TyAndLayout<'tcx>; #[inline] @@ -99,7 +99,7 @@ impl LayoutOfHelpers<'tcx> for Builder<'_, '_, 'tcx> { } } -impl FnAbiOfHelpers<'tcx> for Builder<'_, '_, 'tcx> { +impl<'tcx> FnAbiOfHelpers<'tcx> for Builder<'_, '_, 'tcx> { type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>; #[inline] @@ -113,7 +113,7 @@ impl FnAbiOfHelpers<'tcx> for Builder<'_, '_, 'tcx> { } } -impl Deref for Builder<'_, 'll, 'tcx> { +impl<'ll, 'tcx> Deref for Builder<'_, 'll, 'tcx> { type Target = CodegenCx<'ll, 'tcx>; #[inline] @@ -122,7 +122,7 @@ impl Deref for Builder<'_, 'll, 'tcx> { } } -impl HasCodegen<'tcx> for Builder<'_, 'll, 'tcx> { +impl<'ll, 'tcx> HasCodegen<'tcx> for Builder<'_, 'll, 'tcx> { type CodegenCx = CodegenCx<'ll, 'tcx>; } @@ -136,7 +136,7 @@ macro_rules! builder_methods_for_value_instructions { } } -impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { +impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn build(cx: &'a CodegenCx<'ll, 'tcx>, llbb: &'ll BasicBlock) -> Self { let bx = Builder::with_cx(cx); unsafe { @@ -1201,19 +1201,26 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { unsafe { llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, UNNAMED) } } - fn do_not_inline(&mut self, llret: &'ll Value) { - llvm::Attribute::NoInline.apply_callsite(llvm::AttributePlace::Function, llret); + fn apply_attrs_to_cleanup_callsite(&mut self, llret: &'ll Value) { + // Cleanup is always the cold path. + llvm::Attribute::Cold.apply_callsite(llvm::AttributePlace::Function, llret); + + // In LLVM versions with deferred inlining (currently, system LLVM < 14), + // inlining drop glue can lead to exponential size blowup, see #41696 and #92110. + if !llvm_util::is_rust_llvm() && llvm_util::get_version() < (14, 0, 0) { + llvm::Attribute::NoInline.apply_callsite(llvm::AttributePlace::Function, llret); + } } } -impl StaticBuilderMethods for Builder<'a, 'll, 'tcx> { +impl<'ll> StaticBuilderMethods for Builder<'_, 'll, '_> { fn get_static(&mut self, def_id: DefId) -> &'ll Value { // Forward to the `get_static` method of `CodegenCx` self.cx().get_static(def_id) } } -impl Builder<'a, 'll, 'tcx> { +impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { fn with_cx(cx: &'a CodegenCx<'ll, 'tcx>) -> Self { // Create a fresh builder from the crate context. let llbuilder = unsafe { llvm::LLVMCreateBuilderInContext(cx.llcx) }; diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index 1bc924d3b9..ac423a2270 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -22,7 +22,7 @@ use rustc_middle::ty::{self, Instance, TypeFoldable}; /// /// - `cx`: the crate context /// - `instance`: the instance to be instantiated -pub fn get_fn(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value { +pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value { let tcx = cx.tcx(); debug!("get_fn(instance={:?})", instance); diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 73a8d46443..9d34734f4e 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -65,7 +65,7 @@ pub struct Funclet<'ll> { operand: OperandBundleDef<'ll>, } -impl Funclet<'ll> { +impl<'ll> Funclet<'ll> { pub fn new(cleanuppad: &'ll Value) -> Self { Funclet { cleanuppad, operand: OperandBundleDef::new("funclet", &[cleanuppad]) } } @@ -79,7 +79,7 @@ impl Funclet<'ll> { } } -impl BackendTypes for CodegenCx<'ll, 'tcx> { +impl<'ll> BackendTypes for CodegenCx<'ll, '_> { type Value = &'ll Value; // FIXME(eddyb) replace this with a `Function` "subclass" of `Value`. type Function = &'ll Value; @@ -93,7 +93,7 @@ impl BackendTypes for CodegenCx<'ll, 'tcx> { type DIVariable = &'ll llvm::debuginfo::DIVariable; } -impl CodegenCx<'ll, 'tcx> { +impl<'ll> CodegenCx<'ll, '_> { pub fn const_array(&self, ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value { unsafe { llvm::LLVMConstArray(ty, elts.as_ptr(), elts.len() as c_uint) } } @@ -120,7 +120,7 @@ impl CodegenCx<'ll, 'tcx> { !null_terminated as Bool, ); let sym = self.generate_local_symbol_name("str"); - let g = self.define_global(&sym[..], self.val_ty(sc)).unwrap_or_else(|| { + let g = self.define_global(&sym, self.val_ty(sc)).unwrap_or_else(|| { bug!("symbol `{}` is already defined", sym); }); llvm::LLVMSetInitializer(g, sc); @@ -145,7 +145,7 @@ impl CodegenCx<'ll, 'tcx> { } } -impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { +impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn const_null(&self, t: &'ll Type) -> &'ll Value { unsafe { llvm::LLVMConstNull(t) } } @@ -327,14 +327,18 @@ pub fn val_ty(v: &Value) -> &Type { unsafe { llvm::LLVMTypeOf(v) } } -pub fn bytes_in_context(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value { +pub fn bytes_in_context<'ll>(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value { unsafe { let ptr = bytes.as_ptr() as *const c_char; llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True) } } -pub fn struct_in_context(llcx: &'a llvm::Context, elts: &[&'a Value], packed: bool) -> &'a Value { +pub fn struct_in_context<'ll>( + llcx: &'ll llvm::Context, + elts: &[&'ll Value], + packed: bool, +) -> &'ll Value { unsafe { llvm::LLVMConstStructInContext(llcx, elts.as_ptr(), elts.len() as c_uint, packed as Bool) } diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index b154ced42f..d43c7c6065 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -24,7 +24,7 @@ use rustc_target::abi::{ use std::ops::Range; use tracing::debug; -pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value { +pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value { let mut llvals = Vec::with_capacity(alloc.relocations().len() + 1); let dl = cx.data_layout(); let pointer_size = dl.pointer_size.bytes() as usize; @@ -127,7 +127,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll cx.const_struct(&llvals, true) } -pub fn codegen_static_initializer( +pub fn codegen_static_initializer<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, def_id: DefId, ) -> Result<(&'ll Value, &'tcx Allocation), ErrorHandled> { @@ -135,7 +135,7 @@ pub fn codegen_static_initializer( Ok((const_alloc_to_llvm(cx, alloc), alloc)) } -fn set_global_alignment(cx: &CodegenCx<'ll, '_>, gv: &'ll Value, mut align: Align) { +fn set_global_alignment<'ll>(cx: &CodegenCx<'ll, '_>, gv: &'ll Value, mut align: Align) { // The target may require greater alignment for globals than the type does. // Note: GCC and Clang also allow `__attribute__((aligned))` on variables, // which can force it to be smaller. Rust doesn't support this yet. @@ -152,7 +152,7 @@ fn set_global_alignment(cx: &CodegenCx<'ll, '_>, gv: &'ll Value, mut align: Alig } } -fn check_and_apply_linkage( +fn check_and_apply_linkage<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, @@ -206,11 +206,11 @@ fn check_and_apply_linkage( } } -pub fn ptrcast(val: &'ll Value, ty: &'ll Type) -> &'ll Value { +pub fn ptrcast<'ll>(val: &'ll Value, ty: &'ll Type) -> &'ll Value { unsafe { llvm::LLVMConstPointerCast(val, ty) } } -impl CodegenCx<'ll, 'tcx> { +impl<'ll> CodegenCx<'ll, '_> { crate fn const_bitcast(&self, val: &'ll Value, ty: &'ll Type) -> &'ll Value { unsafe { llvm::LLVMConstBitCast(val, ty) } } @@ -225,7 +225,7 @@ impl CodegenCx<'ll, 'tcx> { let gv = match kind { Some(kind) if !self.tcx.sess.fewer_names() => { let name = self.generate_local_symbol_name(kind); - let gv = self.define_global(&name[..], self.val_ty(cv)).unwrap_or_else(|| { + let gv = self.define_global(&name, self.val_ty(cv)).unwrap_or_else(|| { bug!("symbol `{}` is already defined", name); }); llvm::LLVMRustSetLinkage(gv, llvm::Linkage::PrivateLinkage); @@ -344,7 +344,7 @@ impl CodegenCx<'ll, 'tcx> { } } -impl StaticMethods for CodegenCx<'ll, 'tcx> { +impl<'ll> StaticMethods for CodegenCx<'ll, '_> { fn static_addr_of(&self, cv: &'ll Value, align: Align, kind: Option<&str>) -> &'ll Value { if let Some(&gv) = self.const_globals.borrow().get(&cv) { unsafe { diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 613a8df891..9f24a95482 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -124,7 +124,7 @@ fn to_llvm_tls_model(tls_model: TlsModel) -> llvm::ThreadLocalMode { } } -pub unsafe fn create_module( +pub unsafe fn create_module<'ll>( tcx: TyCtxt<'_>, llcx: &'ll llvm::Context, mod_name: &str, @@ -320,7 +320,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { let dbg_cx = if tcx.sess.opts.debuginfo != DebugInfo::None { let dctx = debuginfo::CrateDebugContext::new(llmod); - debuginfo::metadata::compile_unit_metadata(tcx, &codegen_unit.name().as_str(), &dctx); + debuginfo::metadata::compile_unit_metadata(tcx, codegen_unit.name().as_str(), &dctx); Some(dctx) } else { None @@ -363,7 +363,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { } #[inline] - pub fn coverage_context(&'a self) -> Option<&'a coverageinfo::CrateCoverageContext<'ll, 'tcx>> { + pub fn coverage_context(&self) -> Option<&coverageinfo::CrateCoverageContext<'ll, 'tcx>> { self.coverage_cx.as_ref() } @@ -380,7 +380,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { } } -impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { +impl<'ll, 'tcx> MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn vtables( &self, ) -> &RefCell, Option>), &'ll Value>> @@ -504,8 +504,8 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { } } -impl CodegenCx<'b, 'tcx> { - crate fn get_intrinsic(&self, key: &str) -> (&'b Type, &'b Value) { +impl<'ll> CodegenCx<'ll, '_> { + crate fn get_intrinsic(&self, key: &str) -> (&'ll Type, &'ll Value) { if let Some(v) = self.intrinsics.borrow().get(key).cloned() { return v; } @@ -516,9 +516,9 @@ impl CodegenCx<'b, 'tcx> { fn insert_intrinsic( &self, name: &'static str, - args: Option<&[&'b llvm::Type]>, - ret: &'b llvm::Type, - ) -> (&'b llvm::Type, &'b llvm::Value) { + args: Option<&[&'ll llvm::Type]>, + ret: &'ll llvm::Type, + ) -> (&'ll llvm::Type, &'ll llvm::Value) { let fn_ty = if let Some(args) = args { self.type_func(args, ret) } else { @@ -529,7 +529,7 @@ impl CodegenCx<'b, 'tcx> { (fn_ty, f) } - fn declare_intrinsic(&self, key: &str) -> Option<(&'b Type, &'b Value)> { + fn declare_intrinsic(&self, key: &str) -> Option<(&'ll Type, &'ll Value)> { macro_rules! ifn { ($name:expr, fn() -> $ret:expr) => ( if key == $name { @@ -793,7 +793,7 @@ impl CodegenCx<'b, 'tcx> { None } - crate fn eh_catch_typeinfo(&self) -> &'b Value { + crate fn eh_catch_typeinfo(&self) -> &'ll Value { if let Some(eh_catch_typeinfo) = self.eh_catch_typeinfo.get() { return eh_catch_typeinfo; } @@ -813,7 +813,7 @@ impl CodegenCx<'b, 'tcx> { } } -impl<'b, 'tcx> CodegenCx<'b, 'tcx> { +impl CodegenCx<'_, '_> { /// Generates a new symbol name with the given prefix. This symbol name must /// only be used for definitions with `internal` or `private` linkage. pub fn generate_local_symbol_name(&self, prefix: &str) -> String { @@ -829,21 +829,21 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> { } } -impl HasDataLayout for CodegenCx<'ll, 'tcx> { +impl HasDataLayout for CodegenCx<'_, '_> { #[inline] fn data_layout(&self) -> &TargetDataLayout { &self.tcx.data_layout } } -impl HasTargetSpec for CodegenCx<'ll, 'tcx> { +impl HasTargetSpec for CodegenCx<'_, '_> { #[inline] fn target_spec(&self) -> &Target { &self.tcx.sess.target } } -impl ty::layout::HasTyCtxt<'tcx> for CodegenCx<'ll, 'tcx> { +impl<'tcx> ty::layout::HasTyCtxt<'tcx> for CodegenCx<'_, 'tcx> { #[inline] fn tcx(&self) -> TyCtxt<'tcx> { self.tcx @@ -856,7 +856,7 @@ impl<'tcx, 'll> HasParamEnv<'tcx> for CodegenCx<'ll, 'tcx> { } } -impl LayoutOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> { +impl<'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'_, 'tcx> { type LayoutOfResult = TyAndLayout<'tcx>; #[inline] @@ -869,7 +869,7 @@ impl LayoutOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> { } } -impl FnAbiOfHelpers<'tcx> for CodegenCx<'ll, 'tcx> { +impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'_, 'tcx> { type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>; #[inline] diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 6830864ba0..e0af565375 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -9,6 +9,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_hir::def_id::{DefId, DefIdSet}; use rustc_llvm::RustString; use rustc_middle::mir::coverage::CodeRegion; +use rustc_middle::ty::TyCtxt; use rustc_span::Symbol; use std::ffi::CString; @@ -17,10 +18,11 @@ use tracing::debug; /// Generates and exports the Coverage Map. /// -/// This Coverage Map complies with Coverage Mapping Format version 4 (zero-based encoded as 3), -/// as defined at [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format) -/// and published in Rust's November 2020 fork of LLVM. This version is supported by the LLVM -/// coverage tools (`llvm-profdata` and `llvm-cov`) bundled with Rust's fork of LLVM. +/// Rust Coverage Map generation supports LLVM Coverage Mapping Format versions +/// 5 (LLVM 12, only) and 6 (zero-based encoded as 4 and 5, respectively), as defined at +/// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format). +/// These versions are supported by the LLVM coverage tools (`llvm-profdata` and `llvm-cov`) +/// bundled with Rust's fork of LLVM. /// /// Consequently, Rust's bundled version of Clang also generates Coverage Maps compliant with /// the same version. Clang's implementation of Coverage Map generation was referenced when @@ -30,11 +32,12 @@ use tracing::debug; pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) { let tcx = cx.tcx; - // Ensure LLVM supports Coverage Map Version 4 (encoded as a zero-based value: 3). - // If not, the LLVM Version must be less than 11. + // Ensure the installed version of LLVM supports at least Coverage Map + // Version 5 (encoded as a zero-based value: 4), which was introduced with + // LLVM 12. let version = coverageinfo::mapping_version(); - if version != 3 { - tcx.sess.fatal("rustc option `-Z instrument-coverage` requires LLVM 11 or higher."); + if version < 4 { + tcx.sess.fatal("rustc option `-Z instrument-coverage` requires LLVM 12 or higher."); } debug!("Generating coverage map for CodegenUnit: `{}`", cx.codegen_unit.name()); @@ -57,7 +60,7 @@ pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) { return; } - let mut mapgen = CoverageMapGenerator::new(); + let mut mapgen = CoverageMapGenerator::new(tcx, version); // Encode coverage mappings and generate function records let mut function_data = Vec::new(); @@ -86,7 +89,7 @@ pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) { }); let filenames_size = filenames_buffer.len(); - let filenames_val = cx.const_bytes(&filenames_buffer[..]); + let filenames_val = cx.const_bytes(&filenames_buffer); let filenames_ref = coverageinfo::hash_bytes(filenames_buffer); // Generate the LLVM IR representation of the coverage map and store it in a well-known global @@ -112,15 +115,33 @@ struct CoverageMapGenerator { } impl CoverageMapGenerator { - fn new() -> Self { - Self { filenames: FxIndexSet::default() } + fn new(tcx: TyCtxt<'_>, version: u32) -> Self { + let mut filenames = FxIndexSet::default(); + if version >= 5 { + // LLVM Coverage Mapping Format version 6 (zero-based encoded as 5) + // requires setting the first filename to the compilation directory. + // Since rustc generates coverage maps with relative paths, the + // compilation directory can be combined with the the relative paths + // to get absolute paths, if needed. + let working_dir = tcx + .sess + .opts + .working_dir + .remapped_path_if_available() + .to_string_lossy() + .to_string(); + let c_filename = + CString::new(working_dir).expect("null error converting filename to C string"); + filenames.insert(c_filename); + } + Self { filenames } } /// Using the `expressions` and `counter_regions` collected for the current function, generate /// the `mapping_regions` and `virtual_file_mapping`, and capture any new filenames. Then use /// LLVM APIs to encode the `virtual_file_mapping`, `expressions`, and `mapping_regions` into /// the given `coverage_mapping` byte buffer, compliant with the LLVM Coverage Mapping format. - fn write_coverage_mapping( + fn write_coverage_mapping<'a>( &mut self, expressions: Vec, counter_regions: impl Iterator, @@ -179,9 +200,9 @@ impl CoverageMapGenerator { /// Construct coverage map header and the array of function records, and combine them into the /// coverage map. Save the coverage map data into the LLVM IR as a static global using a /// specific, well-known section and name. - fn generate_coverage_map( + fn generate_coverage_map<'ll>( self, - cx: &CodegenCx<'ll, 'tcx>, + cx: &CodegenCx<'ll, '_>, version: u32, filenames_size: usize, filenames_val: &'ll llvm::Value, @@ -208,7 +229,7 @@ impl CoverageMapGenerator { /// Save the function record into the LLVM IR as a static global using a /// specific, well-known section and name. fn save_function_record( - cx: &CodegenCx<'ll, 'tcx>, + cx: &CodegenCx<'_, '_>, mangled_function_name: String, source_hash: u64, filenames_ref: u64, @@ -217,7 +238,7 @@ fn save_function_record( ) { // Concatenate the encoded coverage mappings let coverage_mapping_size = coverage_mapping_buffer.len(); - let coverage_mapping_val = cx.const_bytes(&coverage_mapping_buffer[..]); + let coverage_mapping_val = cx.const_bytes(&coverage_mapping_buffer); let func_name_hash = coverageinfo::hash_str(&mangled_function_name); let func_name_hash_val = cx.const_u64(func_name_hash); diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index ef11e2972e..b2879ef4ae 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -56,7 +56,7 @@ impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> { } } -impl CoverageInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { +impl<'ll, 'tcx> CoverageInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn coverageinfo_finalize(&self) { mapgen::finalize(self) } @@ -96,7 +96,7 @@ impl CoverageInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { } } -impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { +impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { fn set_function_source_hash( &mut self, instance: Instance<'tcx>, @@ -184,7 +184,7 @@ impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { } } -fn declare_unused_fn(cx: &CodegenCx<'ll, 'tcx>, def_id: &DefId) -> Instance<'tcx> { +fn declare_unused_fn<'tcx>(cx: &CodegenCx<'_, 'tcx>, def_id: &DefId) -> Instance<'tcx> { let tcx = cx.tcx; let instance = Instance::new( @@ -212,15 +212,15 @@ fn declare_unused_fn(cx: &CodegenCx<'ll, 'tcx>, def_id: &DefId) -> Instance<'tcx ), ); - llvm::set_linkage(llfn, llvm::Linkage::WeakAnyLinkage); - llvm::set_visibility(llfn, llvm::Visibility::Hidden); + llvm::set_linkage(llfn, llvm::Linkage::PrivateLinkage); + llvm::set_visibility(llfn, llvm::Visibility::Default); assert!(cx.instances.borrow_mut().insert(instance, llfn).is_none()); instance } -fn codegen_unused_fn_and_counter(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) { +fn codegen_unused_fn_and_counter<'tcx>(cx: &CodegenCx<'_, 'tcx>, instance: Instance<'tcx>) { let llfn = cx.get_fn(instance); let llbb = Builder::append_block(cx, llfn, "unused_function"); let mut bx = Builder::build(cx, llbb); @@ -237,8 +237,8 @@ fn codegen_unused_fn_and_counter(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<' bx.ret_void(); } -fn add_unused_function_coverage( - cx: &CodegenCx<'ll, 'tcx>, +fn add_unused_function_coverage<'tcx>( + cx: &CodegenCx<'_, 'tcx>, instance: Instance<'tcx>, def_id: DefId, ) { @@ -268,7 +268,7 @@ fn add_unused_function_coverage( /// required by LLVM InstrProf source-based coverage instrumentation. Use /// `bx.get_pgo_func_name_var()` to ensure the variable is only created once per /// `Instance`. -fn create_pgo_func_name_var( +fn create_pgo_func_name_var<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>, ) -> &'ll llvm::Value { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs index 58f8573a2a..39f53235e2 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs @@ -16,7 +16,7 @@ use rustc_index::vec::Idx; /// Produces DIScope DIEs for each MIR Scope which has variables defined in it. // FIXME(eddyb) almost all of this should be in `rustc_codegen_ssa::mir::debuginfo`. -pub fn compute_mir_scopes( +pub fn compute_mir_scopes<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>, mir: &Body<'tcx>, @@ -45,7 +45,7 @@ pub fn compute_mir_scopes( } } -fn make_mir_scope( +fn make_mir_scope<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>, mir: &Body<'tcx>, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs index ae1f83d944..31a09242c5 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs @@ -28,7 +28,7 @@ pub fn insert_reference_to_gdb_debug_scripts_section_global(bx: &mut Builder<'_, /// Allocates the global variable responsible for the .debug_gdb_scripts binary /// section. -pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx<'ll, '_>) -> &'ll Value { +pub fn get_or_insert_gdb_debug_scripts_section_global<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll Value { let c_section_var_name = "__rustc_debug_gdb_scripts_section__\0"; let section_var_name = &c_section_var_name[..c_section_var_name.len() - 1]; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index cd29f2af01..60ff18af0a 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -18,6 +18,7 @@ use crate::llvm::debuginfo::{ use crate::value::Value; use cstr::cstr; +use rustc_codegen_ssa::debuginfo::type_names::cpp_like_debuginfo; use rustc_codegen_ssa::traits::*; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; @@ -155,7 +156,7 @@ pub struct TypeMap<'ll, 'tcx> { type_to_unique_id: FxHashMap, UniqueTypeId>, } -impl TypeMap<'ll, 'tcx> { +impl<'ll, 'tcx> TypeMap<'ll, 'tcx> { /// Adds a Ty to metadata mapping to the TypeMap. The method will fail if /// the mapping already exists. fn register_type_with_metadata(&mut self, type_: Ty<'tcx>, metadata: &'ll DIType) { @@ -291,7 +292,7 @@ enum RecursiveTypeDescription<'ll, 'tcx> { FinalMetadata(&'ll DICompositeType), } -fn create_and_register_recursive_type_forward_declaration( +fn create_and_register_recursive_type_forward_declaration<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, unfinished_type: Ty<'tcx>, unique_type_id: UniqueTypeId, @@ -313,7 +314,7 @@ fn create_and_register_recursive_type_forward_declaration( } } -impl RecursiveTypeDescription<'ll, 'tcx> { +impl<'ll, 'tcx> RecursiveTypeDescription<'ll, 'tcx> { /// Finishes up the description of the type in question (mostly by providing /// descriptions of the fields of the given type) and returns the final type /// metadata. @@ -375,7 +376,7 @@ macro_rules! return_if_metadata_created_in_meantime { }; } -fn fixed_vec_metadata( +fn fixed_vec_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, unique_type_id: UniqueTypeId, array_or_slice_type: Ty<'tcx>, @@ -410,7 +411,7 @@ fn fixed_vec_metadata( MetadataCreationResult::new(metadata, false) } -fn vec_slice_metadata( +fn vec_slice_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, slice_ptr_type: Ty<'tcx>, element_type: Ty<'tcx>, @@ -456,7 +457,7 @@ fn vec_slice_metadata( let metadata = composite_type_metadata( cx, slice_ptr_type, - &slice_type_name[..], + &slice_type_name, unique_type_id, member_descriptions, NO_SCOPE_METADATA, @@ -466,7 +467,7 @@ fn vec_slice_metadata( MetadataCreationResult::new(metadata, false) } -fn subroutine_type_metadata( +fn subroutine_type_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, unique_type_id: UniqueTypeId, signature: ty::PolyFnSig<'tcx>, @@ -507,7 +508,7 @@ fn subroutine_type_metadata( // `trait_type` should be the actual trait (e.g., `Trait`). Where the trait is part // of a DST struct, there is no `trait_object_type` and the results of this // function will be a little bit weird. -fn trait_pointer_metadata( +fn trait_pointer_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, trait_type: Ty<'tcx>, trait_object_type: Option>, @@ -579,7 +580,7 @@ fn trait_pointer_metadata( composite_type_metadata( cx, trait_object_type.unwrap_or(trait_type), - &trait_type_name[..], + &trait_type_name, unique_type_id, member_descriptions, containing_scope, @@ -588,7 +589,11 @@ fn trait_pointer_metadata( ) } -pub fn type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>, usage_site_span: Span) -> &'ll DIType { +pub fn type_metadata<'ll, 'tcx>( + cx: &CodegenCx<'ll, 'tcx>, + t: Ty<'tcx>, + usage_site_span: Span, +) -> &'ll DIType { // Get the unique type ID of this type. let unique_type_id = { let mut type_map = debug_context(cx).type_map.borrow_mut(); @@ -812,7 +817,7 @@ fn hex_encode(data: &[u8]) -> String { hex_string } -pub fn file_metadata(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) -> &'ll DIFile { +pub fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) -> &'ll DIFile { debug!("file_metadata: file_name: {:?}", source_file.name); let hash = Some(&source_file.src_hash); @@ -833,11 +838,11 @@ pub fn file_metadata(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) -> &'ll file_metadata_raw(cx, file_name, directory, hash) } -pub fn unknown_file_metadata(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile { +pub fn unknown_file_metadata<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile { file_metadata_raw(cx, None, None, None) } -fn file_metadata_raw( +fn file_metadata_raw<'ll>( cx: &CodegenCx<'ll, '_>, file_name: Option, directory: Option, @@ -924,21 +929,21 @@ impl MsvcBasicName for ty::FloatTy { } } -fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { +fn basic_type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { debug!("basic_type_metadata: {:?}", t); // When targeting MSVC, emit MSVC style type names for compatibility with // .natvis visualizers (and perhaps other existing native debuggers?) - let msvc_like_names = cx.tcx.sess.target.is_like_msvc; + let cpp_like_debuginfo = cpp_like_debuginfo(cx.tcx); let (name, encoding) = match t.kind() { ty::Never => ("!", DW_ATE_unsigned), ty::Tuple(elements) if elements.is_empty() => ("()", DW_ATE_unsigned), ty::Bool => ("bool", DW_ATE_boolean), ty::Char => ("char", DW_ATE_unsigned_char), - ty::Int(int_ty) if msvc_like_names => (int_ty.msvc_basic_name(), DW_ATE_signed), - ty::Uint(uint_ty) if msvc_like_names => (uint_ty.msvc_basic_name(), DW_ATE_unsigned), - ty::Float(float_ty) if msvc_like_names => (float_ty.msvc_basic_name(), DW_ATE_float), + ty::Int(int_ty) if cpp_like_debuginfo => (int_ty.msvc_basic_name(), DW_ATE_signed), + ty::Uint(uint_ty) if cpp_like_debuginfo => (uint_ty.msvc_basic_name(), DW_ATE_unsigned), + ty::Float(float_ty) if cpp_like_debuginfo => (float_ty.msvc_basic_name(), DW_ATE_float), ty::Int(int_ty) => (int_ty.name_str(), DW_ATE_signed), ty::Uint(uint_ty) => (uint_ty.name_str(), DW_ATE_unsigned), ty::Float(float_ty) => (float_ty.name_str(), DW_ATE_float), @@ -955,7 +960,7 @@ fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { ) }; - if !msvc_like_names { + if !cpp_like_debuginfo { return ty_metadata; } @@ -981,7 +986,7 @@ fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { typedef_metadata } -fn foreign_type_metadata( +fn foreign_type_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>, unique_type_id: UniqueTypeId, @@ -992,7 +997,7 @@ fn foreign_type_metadata( create_struct_stub(cx, t, &name, unique_type_id, NO_SCOPE_METADATA, DIFlags::FlagZero) } -fn pointer_type_metadata( +fn pointer_type_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, pointer_type: Ty<'tcx>, pointee_type_metadata: &'ll DIType, @@ -1012,7 +1017,7 @@ fn pointer_type_metadata( } } -fn param_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { +fn param_type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { debug!("param_type_metadata: {:?}", t); let name = format!("{:?}", t); unsafe { @@ -1026,24 +1031,35 @@ fn param_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { } } -pub fn compile_unit_metadata( - tcx: TyCtxt<'_>, +pub fn compile_unit_metadata<'ll, 'tcx>( + tcx: TyCtxt<'tcx>, codegen_unit_name: &str, - debug_context: &CrateDebugContext<'ll, '_>, + debug_context: &CrateDebugContext<'ll, 'tcx>, ) -> &'ll DIDescriptor { let mut name_in_debuginfo = match tcx.sess.local_crate_source_file { Some(ref path) => path.clone(), - None => PathBuf::from(&*tcx.crate_name(LOCAL_CRATE).as_str()), + None => PathBuf::from(tcx.crate_name(LOCAL_CRATE).as_str()), }; - // The OSX linker has an idiosyncrasy where it will ignore some debuginfo - // if multiple object files with the same `DW_AT_name` are linked together. - // As a workaround we generate unique names for each object file. Those do - // not correspond to an actual source file but that is harmless. - if tcx.sess.target.is_like_osx { - name_in_debuginfo.push("@"); - name_in_debuginfo.push(codegen_unit_name); - } + // To avoid breaking split DWARF, we need to ensure that each codegen unit + // has a unique `DW_AT_name`. This is because there's a remote chance that + // different codegen units for the same module will have entirely + // identical DWARF entries for the purpose of the DWO ID, which would + // violate Appendix F ("Split Dwarf Object Files") of the DWARF 5 + // specification. LLVM uses the algorithm specified in section 7.32 "Type + // Signature Computation" to compute the DWO ID, which does not include + // any fields that would distinguish compilation units. So we must embed + // the codegen unit name into the `DW_AT_name`. (Issue #88521.) + // + // Additionally, the OSX linker has an idiosyncrasy where it will ignore + // some debuginfo if multiple object files with the same `DW_AT_name` are + // linked together. + // + // As a workaround for these two issues, we generate unique names for each + // object file. Those do not correspond to an actual source file but that + // is harmless. + name_in_debuginfo.push("@"); + name_in_debuginfo.push(codegen_unit_name); debug!("compile_unit_metadata: {:?}", name_in_debuginfo); let rustc_producer = @@ -1055,11 +1071,15 @@ pub fn compile_unit_metadata( let work_dir = tcx.sess.opts.working_dir.to_string_lossy(FileNameDisplayPreference::Remapped); let flags = "\0"; let output_filenames = tcx.output_filenames(()); - let out_dir = &output_filenames.out_directory; let split_name = if tcx.sess.target_can_use_split_dwarf() { output_filenames - .split_dwarf_path(tcx.sess.split_debuginfo(), Some(codegen_unit_name)) - .map(|f| out_dir.join(f)) + .split_dwarf_path( + tcx.sess.split_debuginfo(), + tcx.sess.opts.debugging_opts.split_dwarf_kind, + Some(codegen_unit_name), + ) + // We get a path relative to the working directory from split_dwarf_path + .map(|f| tcx.sess.source_map().path_mapping().map_prefix(f).0) } else { None } @@ -1159,7 +1179,7 @@ pub fn compile_unit_metadata( return unit_metadata; }; - fn path_to_mdstring(llcx: &'ll llvm::Context, path: &Path) -> &'ll Value { + fn path_to_mdstring<'ll>(llcx: &'ll llvm::Context, path: &Path) -> &'ll Value { let path_str = path_to_c_string(path); unsafe { llvm::LLVMMDStringInContext( @@ -1176,7 +1196,7 @@ struct MetadataCreationResult<'ll> { already_stored_in_typemap: bool, } -impl MetadataCreationResult<'ll> { +impl<'ll> MetadataCreationResult<'ll> { fn new(metadata: &'ll DIType, already_stored_in_typemap: bool) -> Self { MetadataCreationResult { metadata, already_stored_in_typemap } } @@ -1243,7 +1263,7 @@ enum MemberDescriptionFactory<'ll, 'tcx> { VariantMDF(VariantMemberDescriptionFactory<'tcx>), } -impl MemberDescriptionFactory<'ll, 'tcx> { +impl<'ll, 'tcx> MemberDescriptionFactory<'ll, 'tcx> { fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec> { match *self { StructMDF(ref this) => this.create_member_descriptions(cx), @@ -1267,7 +1287,10 @@ struct StructMemberDescriptionFactory<'tcx> { } impl<'tcx> StructMemberDescriptionFactory<'tcx> { - fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec> { + fn create_member_descriptions<'ll>( + &self, + cx: &CodegenCx<'ll, 'tcx>, + ) -> Vec> { let layout = cx.layout_of(self.ty); self.variant .fields @@ -1295,7 +1318,7 @@ impl<'tcx> StructMemberDescriptionFactory<'tcx> { } } -fn prepare_struct_metadata( +fn prepare_struct_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, struct_type: Ty<'tcx>, unique_type_id: UniqueTypeId, @@ -1338,7 +1361,7 @@ fn prepare_struct_metadata( /// Here are some examples: /// - `name__field1__field2` when the upvar is captured by value. /// - `_ref__name__field` when the upvar is captured by reference. -fn closure_saved_names_of_captured_variables(tcx: TyCtxt<'tcx>, def_id: DefId) -> Vec { +fn closure_saved_names_of_captured_variables(tcx: TyCtxt<'_>, def_id: DefId) -> Vec { let body = tcx.optimized_mir(def_id); body.var_debug_info @@ -1353,7 +1376,7 @@ fn closure_saved_names_of_captured_variables(tcx: TyCtxt<'tcx>, def_id: DefId) - _ => return None, }; let prefix = if is_ref { "_ref__" } else { "" }; - Some(prefix.to_owned() + &var.name.as_str()) + Some(prefix.to_owned() + var.name.as_str()) }) .collect::>() } @@ -1366,7 +1389,10 @@ struct TupleMemberDescriptionFactory<'tcx> { } impl<'tcx> TupleMemberDescriptionFactory<'tcx> { - fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec> { + fn create_member_descriptions<'ll>( + &self, + cx: &CodegenCx<'ll, 'tcx>, + ) -> Vec> { let mut capture_names = match *self.ty.kind() { ty::Generator(def_id, ..) | ty::Closure(def_id, ..) => { Some(closure_saved_names_of_captured_variables(cx.tcx, def_id).into_iter()) @@ -1399,7 +1425,7 @@ impl<'tcx> TupleMemberDescriptionFactory<'tcx> { } } -fn prepare_tuple_metadata( +fn prepare_tuple_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, tuple_type: Ty<'tcx>, component_types: &[Ty<'tcx>], @@ -1443,7 +1469,10 @@ struct UnionMemberDescriptionFactory<'tcx> { } impl<'tcx> UnionMemberDescriptionFactory<'tcx> { - fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec> { + fn create_member_descriptions<'ll>( + &self, + cx: &CodegenCx<'ll, 'tcx>, + ) -> Vec> { self.variant .fields .iter() @@ -1465,7 +1494,7 @@ impl<'tcx> UnionMemberDescriptionFactory<'tcx> { } } -fn prepare_union_metadata( +fn prepare_union_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, union_type: Ty<'tcx>, unique_type_id: UniqueTypeId, @@ -1497,16 +1526,9 @@ fn prepare_union_metadata( // Enums //=----------------------------------------------------------------------------- -/// DWARF variant support is only available starting in LLVM 8, but -/// on MSVC we have to use the fallback mode, because LLVM doesn't -/// lower variant parts to PDB. -fn use_enum_fallback(cx: &CodegenCx<'_, '_>) -> bool { - cx.sess().target.is_like_msvc -} - // FIXME(eddyb) maybe precompute this? Right now it's computed once // per generator monomorphization, but it doesn't depend on substs. -fn generator_layout_and_saved_local_names( +fn generator_layout_and_saved_local_names<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, ) -> (&'tcx GeneratorLayout<'tcx>, IndexVec>) { @@ -1525,14 +1547,12 @@ fn generator_layout_and_saved_local_names( // Deref of the `Pin<&mut Self>` state argument. mir::ProjectionElem::Field(..), mir::ProjectionElem::Deref, - // Field of a variant of the state. mir::ProjectionElem::Downcast(_, variant), mir::ProjectionElem::Field(field, _), ] => { - let name = &mut generator_saved_local_names[ - generator_layout.variant_fields[variant][field] - ]; + let name = &mut generator_saved_local_names + [generator_layout.variant_fields[variant][field]]; if name.is_none() { name.replace(var.name); } @@ -1556,7 +1576,7 @@ struct EnumMemberDescriptionFactory<'ll, 'tcx> { span: Span, } -impl EnumMemberDescriptionFactory<'ll, 'tcx> { +impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec> { let generator_variant_info_data = match *self.enum_type.kind() { ty::Generator(def_id, ..) => { @@ -1580,7 +1600,10 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { _ => bug!(), }; - let fallback = use_enum_fallback(cx); + // While LLVM supports generating debuginfo for variant types (enums), it doesn't support + // lowering that debuginfo to CodeView records for msvc targets. So if we are targeting + // msvc, then we need to use a different, fallback encoding of the debuginfo. + let fallback = cpp_like_debuginfo(cx.tcx); // This will always find the metadata in the type map. let self_metadata = type_metadata(cx, self.enum_type, self.span); @@ -1888,8 +1911,11 @@ struct VariantMemberDescriptionFactory<'tcx> { span: Span, } -impl VariantMemberDescriptionFactory<'tcx> { - fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec> { +impl<'tcx> VariantMemberDescriptionFactory<'tcx> { + fn create_member_descriptions<'ll>( + &self, + cx: &CodegenCx<'ll, 'tcx>, + ) -> Vec> { self.args .iter() .enumerate() @@ -1924,7 +1950,7 @@ enum VariantInfo<'a, 'tcx> { impl<'tcx> VariantInfo<'_, 'tcx> { fn map_struct_name(&self, f: impl FnOnce(&str) -> R) -> R { match self { - VariantInfo::Adt(variant) => f(&variant.ident.as_str()), + VariantInfo::Adt(variant) => f(variant.ident.as_str()), VariantInfo::Generator { variant_index, .. } => { f(&GeneratorSubsts::variant_name(*variant_index)) } @@ -1963,7 +1989,7 @@ impl<'tcx> VariantInfo<'_, 'tcx> { field_name.map(|name| name.to_string()).unwrap_or_else(|| format!("__{}", i)) } - fn source_info(&self, cx: &CodegenCx<'ll, 'tcx>) -> Option> { + fn source_info<'ll>(&self, cx: &CodegenCx<'ll, 'tcx>) -> Option> { if let VariantInfo::Generator { def_id, variant_index, .. } = self { let span = cx.tcx.generator_layout(*def_id).unwrap().variant_source_info[*variant_index].span; @@ -1980,7 +2006,7 @@ impl<'tcx> VariantInfo<'_, 'tcx> { /// `MemberDescriptionFactory` for producing the descriptions of the /// fields of the variant. This is a rudimentary version of a full /// `RecursiveTypeDescription`. -fn describe_enum_variant( +fn describe_enum_variant<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, layout: layout::TyAndLayout<'tcx>, variant: VariantInfo<'_, 'tcx>, @@ -2013,7 +2039,7 @@ fn describe_enum_variant( (metadata_stub, member_description_factory) } -fn prepare_enum_metadata( +fn prepare_enum_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, enum_type: Ty<'tcx>, enum_def_id: DefId, @@ -2089,8 +2115,8 @@ fn prepare_enum_metadata( let item_name; let discriminant_name = match enum_type.kind() { ty::Adt(..) => { - item_name = tcx.item_name(enum_def_id).as_str(); - &*item_name + item_name = tcx.item_name(enum_def_id); + item_name.as_str() } ty::Generator(..) => enum_name.as_str(), _ => bug!(), @@ -2130,7 +2156,10 @@ fn prepare_enum_metadata( return FinalMetadata(discriminant_type_metadata(tag.value)); } - if use_enum_fallback(cx) { + // While LLVM supports generating debuginfo for variant types (enums), it doesn't support + // lowering that debuginfo to CodeView records for msvc targets. So if we are targeting + // msvc, then we need to use a different encoding of the debuginfo. + if cpp_like_debuginfo(tcx) { let discriminant_type_metadata = match layout.variants { Variants::Single { .. } => None, Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, tag, .. } @@ -2332,7 +2361,7 @@ fn prepare_enum_metadata( /// results in a LLVM struct. /// /// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums. -fn composite_type_metadata( +fn composite_type_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, composite_type: Ty<'tcx>, composite_type_name: &str, @@ -2366,7 +2395,7 @@ fn composite_type_metadata( composite_type_metadata } -fn set_members_of_composite_type( +fn set_members_of_composite_type<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, composite_type: Ty<'tcx>, composite_type_metadata: &'ll DICompositeType, @@ -2400,7 +2429,7 @@ fn set_members_of_composite_type( let type_params = compute_type_parameters(cx, composite_type); unsafe { - let type_array = create_DIArray(DIB(cx), &member_metadata[..]); + let type_array = create_DIArray(DIB(cx), &member_metadata); llvm::LLVMRustDICompositeTypeReplaceArrays( DIB(cx), composite_type_metadata, @@ -2411,7 +2440,7 @@ fn set_members_of_composite_type( } /// Computes the type parameters for a type, if any, for the given metadata. -fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> &'ll DIArray { +fn compute_type_parameters<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> &'ll DIArray { if let ty::Adt(def, substs) = *ty.kind() { if substs.types().next().is_some() { let generics = cx.tcx.generics_of(def.did); @@ -2423,7 +2452,7 @@ fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> &'ll DIAr cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); let actual_type_metadata = type_metadata(cx, actual_type, rustc_span::DUMMY_SP); - let name = &name.as_str(); + let name = name.as_str(); Some(unsafe { Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( DIB(cx), @@ -2439,7 +2468,7 @@ fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> &'ll DIAr }) .collect(); - return create_DIArray(DIB(cx), &template_params[..]); + return create_DIArray(DIB(cx), &template_params); } } return create_DIArray(DIB(cx), &[]); @@ -2456,7 +2485,7 @@ fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> &'ll DIAr /// A convenience wrapper around `LLVMRustDIBuilderCreateStructType()`. Does not do /// any caching, does not add any fields to the struct. This can be done later /// with `set_members_of_composite_type()`. -fn create_struct_stub( +fn create_struct_stub<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, struct_type: Ty<'tcx>, struct_type_name: &str, @@ -2497,7 +2526,7 @@ fn create_struct_stub( metadata_stub } -fn create_union_stub( +fn create_union_stub<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, union_type: Ty<'tcx>, union_type_name: &str, @@ -2538,7 +2567,7 @@ fn create_union_stub( /// Creates debug information for the given global variable. /// /// Adds the created metadata nodes directly to the crate's IR. -pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global: &'ll Value) { +pub fn create_global_var_metadata<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId, global: &'ll Value) { if cx.dbg_cx.is_none() { return; } @@ -2565,7 +2594,8 @@ pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global let is_local_to_unit = is_node_local_to_unit(cx, def_id); let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx, ty::ParamEnv::reveal_all()); let type_metadata = type_metadata(cx, variable_type, span); - let var_name = tcx.item_name(def_id).as_str(); + let var_name = tcx.item_name(def_id); + let var_name = var_name.as_str(); let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id)).name; // When empty, linkage_name field is omitted, // which is what we want for no_mangle statics @@ -2593,7 +2623,7 @@ pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global } /// Generates LLVM debuginfo for a vtable. -fn vtable_type_metadata( +fn vtable_type_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, poly_trait_ref: Option>, @@ -2625,7 +2655,7 @@ fn vtable_type_metadata( /// given type. /// /// Adds the created metadata nodes directly to the crate's IR. -pub fn create_vtable_metadata( +pub fn create_vtable_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, poly_trait_ref: Option>, @@ -2664,7 +2694,7 @@ pub fn create_vtable_metadata( } /// Creates an "extension" of an existing `DIScope` into another file. -pub fn extend_scope_to_file( +pub fn extend_scope_to_file<'ll>( cx: &CodegenCx<'ll, '_>, scope_metadata: &'ll DIScope, file: &SourceFile, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 2a6bf7d9b1..01f7868df3 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -71,7 +71,7 @@ pub struct CrateDebugContext<'a, 'tcx> { composite_types_completed: RefCell>, } -impl Drop for CrateDebugContext<'a, 'tcx> { +impl Drop for CrateDebugContext<'_, '_> { fn drop(&mut self) { unsafe { llvm::LLVMRustDIBuilderDispose(&mut *(self.builder as *mut _)); @@ -144,7 +144,7 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) { } } -impl DebugInfoBuilderMethods for Builder<'a, 'll, 'tcx> { +impl<'ll> DebugInfoBuilderMethods for Builder<'_, 'll, '_> { // FIXME(eddyb) find a common convention for all of the debuginfo-related // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.). fn dbg_var_addr( @@ -160,17 +160,17 @@ impl DebugInfoBuilderMethods for Builder<'a, 'll, 'tcx> { // the values should match the ones in the DWARF standard anyway. let op_deref = || unsafe { llvm::LLVMRustDIBuilderCreateOpDeref() }; let op_plus_uconst = || unsafe { llvm::LLVMRustDIBuilderCreateOpPlusUconst() }; - let mut addr_ops = SmallVec::<[_; 8]>::new(); + let mut addr_ops = SmallVec::<[u64; 8]>::new(); if direct_offset.bytes() > 0 { addr_ops.push(op_plus_uconst()); - addr_ops.push(direct_offset.bytes() as i64); + addr_ops.push(direct_offset.bytes() as u64); } for &offset in indirect_offsets { addr_ops.push(op_deref()); if offset.bytes() > 0 { addr_ops.push(op_plus_uconst()); - addr_ops.push(offset.bytes() as i64); + addr_ops.push(offset.bytes() as u64); } } @@ -236,7 +236,7 @@ pub struct DebugLoc { pub col: u32, } -impl CodegenCx<'ll, '_> { +impl CodegenCx<'_, '_> { /// Looks up debug source information about a `BytePos`. // FIXME(eddyb) rename this to better indicate it's a duplicate of // `lookup_char_pos` rather than `dbg_loc`, perhaps by making @@ -266,7 +266,7 @@ impl CodegenCx<'ll, '_> { } } -impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { +impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn create_function_debug_context( &self, instance: Instance<'tcx>, @@ -474,7 +474,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { vec![] }; - create_DIArray(DIB(cx), &template_params[..]) + create_DIArray(DIB(cx), &template_params) } fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs index 1cbf538699..d5ea48c311 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs @@ -17,7 +17,7 @@ pub fn mangled_name_of_instance<'a, 'tcx>( tcx.symbol_name(instance) } -pub fn item_namespace(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { +pub fn item_namespace<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { if let Some(&scope) = debug_context(cx).namespace_map.borrow().get(&def_id) { return scope; } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs index ee188e69be..953b6765a4 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs @@ -23,21 +23,26 @@ pub fn is_node_local_to_unit(cx: &CodegenCx<'_, '_>, def_id: DefId) -> bool { } #[allow(non_snake_case)] -pub fn create_DIArray(builder: &DIBuilder<'ll>, arr: &[Option<&'ll DIDescriptor>]) -> &'ll DIArray { +pub fn create_DIArray<'ll>( + builder: &DIBuilder<'ll>, + arr: &[Option<&'ll DIDescriptor>], +) -> &'ll DIArray { unsafe { llvm::LLVMRustDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32) } } #[inline] -pub fn debug_context(cx: &'a CodegenCx<'ll, 'tcx>) -> &'a CrateDebugContext<'ll, 'tcx> { +pub fn debug_context<'a, 'll, 'tcx>( + cx: &'a CodegenCx<'ll, 'tcx>, +) -> &'a CrateDebugContext<'ll, 'tcx> { cx.dbg_cx.as_ref().unwrap() } #[inline] #[allow(non_snake_case)] -pub fn DIB(cx: &'a CodegenCx<'ll, '_>) -> &'a DIBuilder<'ll> { +pub fn DIB<'a, 'll>(cx: &'a CodegenCx<'ll, '_>) -> &'a DIBuilder<'ll> { cx.dbg_cx.as_ref().unwrap().builder } -pub fn get_namespace_for_item(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { +pub fn get_namespace_for_item<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { item_namespace(cx, cx.tcx.parent(def_id).expect("get_namespace_for_item: missing parent?")) } diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs index 8977fa085b..90d0d5caba 100644 --- a/compiler/rustc_codegen_llvm/src/declare.rs +++ b/compiler/rustc_codegen_llvm/src/declare.rs @@ -26,7 +26,7 @@ use tracing::debug; /// /// If there’s a value with the same name already declared, the function will /// update the declaration and return existing Value instead. -fn declare_raw_fn( +fn declare_raw_fn<'ll>( cx: &CodegenCx<'ll, '_>, name: &str, callconv: llvm::CallConv, @@ -50,7 +50,7 @@ fn declare_raw_fn( llfn } -impl CodegenCx<'ll, 'tcx> { +impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { /// Declare a global value. /// /// If there’s a value with the same name already declared, the function will diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index a7e34b0805..07d49b6e72 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -25,7 +25,10 @@ use rustc_target::spec::{HasTargetSpec, PanicStrategy}; use std::cmp::Ordering; use std::iter; -fn get_simple_intrinsic(cx: &CodegenCx<'ll, '_>, name: Symbol) -> Option<(&'ll Type, &'ll Value)> { +fn get_simple_intrinsic<'ll>( + cx: &CodegenCx<'ll, '_>, + name: Symbol, +) -> Option<(&'ll Type, &'ll Value)> { let llvm_name = match name { sym::sqrtf32 => "llvm.sqrt.f32", sym::sqrtf64 => "llvm.sqrt.f64", @@ -74,7 +77,7 @@ fn get_simple_intrinsic(cx: &CodegenCx<'ll, '_>, name: Symbol) -> Option<(&'ll T Some(cx.get_intrinsic(llvm_name)) } -impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { +impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> { fn codegen_intrinsic_call( &mut self, instance: ty::Instance<'tcx>, @@ -350,6 +353,8 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { false, ast::LlvmAsmDialect::Att, &[span], + false, + None, ) .unwrap_or_else(|| bug!("failed to generate inline asm call for `black_box`")); @@ -409,8 +414,8 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { } } -fn try_intrinsic( - bx: &mut Builder<'a, 'll, 'tcx>, +fn try_intrinsic<'ll>( + bx: &mut Builder<'_, 'll, '_>, try_func: &'ll Value, data: &'ll Value, catch_func: &'ll Value, @@ -439,8 +444,8 @@ fn try_intrinsic( // instructions are meant to work for all targets, as of the time of this // writing, however, LLVM does not recommend the usage of these new instructions // as the old ones are still more optimized. -fn codegen_msvc_try( - bx: &mut Builder<'a, 'll, 'tcx>, +fn codegen_msvc_try<'ll>( + bx: &mut Builder<'_, 'll, '_>, try_func: &'ll Value, data: &'ll Value, catch_func: &'ll Value, @@ -591,8 +596,8 @@ fn codegen_msvc_try( // function calling it, and that function may already have other personality // functions in play. By calling a shim we're guaranteed that our shim will have // the right personality function. -fn codegen_gnu_try( - bx: &mut Builder<'a, 'll, 'tcx>, +fn codegen_gnu_try<'ll>( + bx: &mut Builder<'_, 'll, '_>, try_func: &'ll Value, data: &'ll Value, catch_func: &'ll Value, @@ -647,8 +652,8 @@ fn codegen_gnu_try( // Variant of codegen_gnu_try used for emscripten where Rust panics are // implemented using C++ exceptions. Here we use exceptions of a specific type // (`struct rust_panic`) to represent Rust panics. -fn codegen_emcc_try( - bx: &mut Builder<'a, 'll, 'tcx>, +fn codegen_emcc_try<'ll>( + bx: &mut Builder<'_, 'll, '_>, try_func: &'ll Value, data: &'ll Value, catch_func: &'ll Value, @@ -797,8 +802,8 @@ fn get_rust_try_fn<'ll, 'tcx>( rust_try } -fn generic_simd_intrinsic( - bx: &mut Builder<'a, 'll, 'tcx>, +fn generic_simd_intrinsic<'ll, 'tcx>( + bx: &mut Builder<'_, 'll, 'tcx>, name: Symbol, callee_ty: Ty<'tcx>, args: &[OperandRef<'tcx, &'ll Value>], @@ -1127,12 +1132,12 @@ fn generic_simd_intrinsic( } } - fn simd_simple_float_intrinsic( + fn simd_simple_float_intrinsic<'ll, 'tcx>( name: Symbol, in_elem: &::rustc_middle::ty::TyS<'_>, in_ty: &::rustc_middle::ty::TyS<'_>, in_len: u64, - bx: &mut Builder<'a, 'll, 'tcx>, + bx: &mut Builder<'_, 'll, 'tcx>, span: Span, args: &[OperandRef<'tcx, &'ll Value>], ) -> Result<&'ll Value, ()> { @@ -1230,7 +1235,7 @@ fn generic_simd_intrinsic( elem_ty: Ty<'_>, vec_len: u64, no_pointers: usize, - bx: &Builder<'a, 'll, 'tcx>, + bx: &Builder<'_, '_, '_>, ) -> String { let p0s: String = "p0".repeat(no_pointers); match *elem_ty.kind() { @@ -1253,7 +1258,7 @@ fn generic_simd_intrinsic( } } - fn llvm_vector_ty( + fn llvm_vector_ty<'ll>( cx: &CodegenCx<'ll, '_>, elem_ty: Ty<'_>, vec_len: u64, diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index c66d7d872c..cea4595fbb 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -6,11 +6,8 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(bool_to_option)] -#![feature(const_cstr_unchecked)] #![feature(crate_visibility_modifier)] #![feature(extern_types)] -#![feature(in_band_lifetimes)] -#![feature(iter_zip)] #![feature(nll)] #![recursion_limit = "256"] @@ -102,14 +99,6 @@ impl ExtraBackendMethods for LlvmCodegenBackend { ModuleLlvm::new_metadata(tcx, mod_name) } - fn write_compressed_metadata<'tcx>( - &self, - tcx: TyCtxt<'tcx>, - metadata: &EncodedMetadata, - llvm_module: &mut ModuleLlvm, - ) { - base::write_compressed_metadata(tcx, metadata, llvm_module) - } fn codegen_allocator<'tcx>( &self, tcx: TyCtxt<'tcx>, @@ -348,6 +337,7 @@ impl CodegenBackend for LlvmCodegenBackend { &self, ongoing_codegen: Box, sess: &Session, + outputs: &OutputFilenames, ) -> Result<(CodegenResults, FxHashMap), ErrorReported> { let (codegen_results, work_products) = ongoing_codegen .downcast::>() @@ -356,7 +346,8 @@ impl CodegenBackend for LlvmCodegenBackend { sess.time("llvm_dump_timing_file", || { if sess.opts.debugging_opts.llvm_time_trace { - llvm_util::time_trace_profiler_finish("llvm_timings.json"); + let file_name = outputs.with_extension("llvm_timings.json"); + llvm_util::time_trace_profiler_finish(&file_name); } }); diff --git a/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs b/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs index 36aa022d74..e2fa5e488e 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs @@ -43,7 +43,7 @@ pub struct OptimizationDiagnostic<'ll> { pub message: String, } -impl OptimizationDiagnostic<'ll> { +impl<'ll> OptimizationDiagnostic<'ll> { unsafe fn unpack(kind: OptimizationDiagnosticKind, di: &'ll DiagnosticInfo) -> Self { let mut function = None; let mut line = 0; @@ -142,7 +142,7 @@ pub struct InlineAsmDiagnostic { } impl InlineAsmDiagnostic { - unsafe fn unpackInlineAsm(di: &'ll DiagnosticInfo) -> Self { + unsafe fn unpackInlineAsm(di: &DiagnosticInfo) -> Self { let mut cookie = 0; let mut message = None; let mut level = super::DiagnosticLevel::Error; @@ -157,7 +157,7 @@ impl InlineAsmDiagnostic { } } - unsafe fn unpackSrcMgr(di: &'ll DiagnosticInfo) -> Self { + unsafe fn unpackSrcMgr(di: &DiagnosticInfo) -> Self { let mut cookie = 0; let smdiag = SrcMgrDiagnostic::unpack(super::LLVMRustGetSMDiagnostic(di, &mut cookie)); InlineAsmDiagnostic { @@ -180,7 +180,7 @@ pub enum Diagnostic<'ll> { UnknownDiagnostic(&'ll DiagnosticInfo), } -impl Diagnostic<'ll> { +impl<'ll> Diagnostic<'ll> { pub unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self { use super::DiagnosticKind as Dk; let kind = super::LLVMRustGetDiagInfoKind(di); diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 1d255c0755..f2782f84f5 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -675,13 +675,17 @@ pub struct OperandBundleDef<'a>(InvariantOpaque<'a>); #[repr(C)] pub struct Linker<'a>(InvariantOpaque<'a>); -pub type DiagnosticHandler = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void); -pub type InlineAsmDiagHandler = unsafe extern "C" fn(&SMDiagnostic, *const c_void, c_uint); +extern "C" { + pub type DiagnosticHandler; +} + +pub type DiagnosticHandlerTy = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void); +pub type InlineAsmDiagHandlerTy = unsafe extern "C" fn(&SMDiagnostic, *const c_void, c_uint); pub mod coverageinfo { use super::coverage_map; - /// Aligns with [llvm::coverage::CounterMappingRegion::RegionKind](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L206-L222) + /// Aligns with [llvm::coverage::CounterMappingRegion::RegionKind](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L209-L230) #[derive(Copy, Clone, Debug)] #[repr(C)] pub enum RegionKind { @@ -700,11 +704,16 @@ pub mod coverageinfo { /// A GapRegion is like a CodeRegion, but its count is only set as the /// line execution count when its the only region in the line. GapRegion = 3, + + /// A BranchRegion represents leaf-level boolean expressions and is + /// associated with two counters, each representing the number of times the + /// expression evaluates to true or false. + BranchRegion = 4, } /// This struct provides LLVM's representation of a "CoverageMappingRegion", encoded into the /// coverage map, in accordance with the - /// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format). + /// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format). /// The struct composes fields representing the `Counter` type and value(s) (injected counter /// ID, or expression type and operands), the source file (an indirect index into a "filenames /// array", encoded separately), and source location (start and end positions of the represented @@ -717,6 +726,10 @@ pub mod coverageinfo { /// The counter type and type-dependent counter data, if any. counter: coverage_map::Counter, + /// If the `RegionKind` is a `BranchRegion`, this represents the counter + /// for the false branch of the region. + false_counter: coverage_map::Counter, + /// An indirect reference to the source filename. In the LLVM Coverage Mapping Format, the /// file_id is an index into a function-specific `virtual_file_mapping` array of indexes /// that, in turn, are used to look up the filename for this region. @@ -754,6 +767,7 @@ pub mod coverageinfo { ) -> Self { Self { counter, + false_counter: coverage_map::Counter::zero(), file_id, expanded_file_id: 0, start_line, @@ -764,6 +778,31 @@ pub mod coverageinfo { } } + // This function might be used in the future; the LLVM API is still evolving, as is coverage + // support. + #[allow(dead_code)] + crate fn branch_region( + counter: coverage_map::Counter, + false_counter: coverage_map::Counter, + file_id: u32, + start_line: u32, + start_col: u32, + end_line: u32, + end_col: u32, + ) -> Self { + Self { + counter, + false_counter, + file_id, + expanded_file_id: 0, + start_line, + start_col, + end_line, + end_col, + kind: RegionKind::BranchRegion, + } + } + // This function might be used in the future; the LLVM API is still evolving, as is coverage // support. #[allow(dead_code)] @@ -777,6 +816,7 @@ pub mod coverageinfo { ) -> Self { Self { counter: coverage_map::Counter::zero(), + false_counter: coverage_map::Counter::zero(), file_id, expanded_file_id, start_line, @@ -799,6 +839,7 @@ pub mod coverageinfo { ) -> Self { Self { counter: coverage_map::Counter::zero(), + false_counter: coverage_map::Counter::zero(), file_id, expanded_file_id: 0, start_line, @@ -822,6 +863,7 @@ pub mod coverageinfo { ) -> Self { Self { counter, + false_counter: coverage_map::Counter::zero(), file_id, expanded_file_id: 0, start_line, @@ -971,17 +1013,17 @@ extern "C" { pub fn LLVMDoubleTypeInContext(C: &Context) -> &Type; // Operations on function types - pub fn LLVMFunctionType( + pub fn LLVMFunctionType<'a>( ReturnType: &'a Type, ParamTypes: *const &'a Type, ParamCount: c_uint, IsVarArg: Bool, ) -> &'a Type; pub fn LLVMCountParamTypes(FunctionTy: &Type) -> c_uint; - pub fn LLVMGetParamTypes(FunctionTy: &'a Type, Dest: *mut &'a Type); + pub fn LLVMGetParamTypes<'a>(FunctionTy: &'a Type, Dest: *mut &'a Type); // Operations on struct types - pub fn LLVMStructTypeInContext( + pub fn LLVMStructTypeInContext<'a>( C: &'a Context, ElementTypes: *const &'a Type, ElementCount: c_uint, @@ -1004,10 +1046,10 @@ extern "C" { pub fn LLVMTypeOf(Val: &Value) -> &Type; pub fn LLVMGetValueName2(Val: &Value, Length: *mut size_t) -> *const c_char; pub fn LLVMSetValueName2(Val: &Value, Name: *const c_char, NameLen: size_t); - pub fn LLVMReplaceAllUsesWith(OldVal: &'a Value, NewVal: &'a Value); - pub fn LLVMSetMetadata(Val: &'a Value, KindID: c_uint, Node: &'a Value); - pub fn LLVMGlobalSetMetadata(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata); - pub fn LLVMValueAsMetadata(Node: &'a Value) -> &Metadata; + pub fn LLVMReplaceAllUsesWith<'a>(OldVal: &'a Value, NewVal: &'a Value); + pub fn LLVMSetMetadata<'a>(Val: &'a Value, KindID: c_uint, Node: &'a Value); + pub fn LLVMGlobalSetMetadata<'a>(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata); + pub fn LLVMValueAsMetadata(Node: &Value) -> &Metadata; // Operations on constants of any type pub fn LLVMConstNull(Ty: &Type) -> &Value; @@ -1015,8 +1057,12 @@ extern "C" { // Operations on metadata pub fn LLVMMDStringInContext(C: &Context, Str: *const c_char, SLen: c_uint) -> &Value; - pub fn LLVMMDNodeInContext(C: &'a Context, Vals: *const &'a Value, Count: c_uint) -> &'a Value; - pub fn LLVMAddNamedMetadataOperand(M: &'a Module, Name: *const c_char, Val: &'a Value); + pub fn LLVMMDNodeInContext<'a>( + C: &'a Context, + Vals: *const &'a Value, + Count: c_uint, + ) -> &'a Value; + pub fn LLVMAddNamedMetadataOperand<'a>(M: &'a Module, Name: *const c_char, Val: &'a Value); // Operations on scalar constants pub fn LLVMConstInt(IntTy: &Type, N: c_ulonglong, SignExtend: Bool) -> &Value; @@ -1037,14 +1083,14 @@ extern "C" { Length: c_uint, DontNullTerminate: Bool, ) -> &Value; - pub fn LLVMConstStructInContext( + pub fn LLVMConstStructInContext<'a>( C: &'a Context, ConstantVals: *const &'a Value, Count: c_uint, Packed: Bool, ) -> &'a Value; - pub fn LLVMConstArray( + pub fn LLVMConstArray<'a>( ElementTy: &'a Type, ConstantVals: *const &'a Value, Length: c_uint, @@ -1052,17 +1098,17 @@ extern "C" { pub fn LLVMConstVector(ScalarConstantVals: *const &Value, Size: c_uint) -> &Value; // Constant expressions - pub fn LLVMRustConstInBoundsGEP2( + pub fn LLVMRustConstInBoundsGEP2<'a>( ty: &'a Type, ConstantVal: &'a Value, ConstantIndices: *const &'a Value, NumIndices: c_uint, ) -> &'a Value; - pub fn LLVMConstZExt(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; - pub fn LLVMConstPtrToInt(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; - pub fn LLVMConstIntToPtr(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; - pub fn LLVMConstBitCast(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; - pub fn LLVMConstPointerCast(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; + pub fn LLVMConstZExt<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; + pub fn LLVMConstPtrToInt<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; + pub fn LLVMConstIntToPtr<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; + pub fn LLVMConstBitCast<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; + pub fn LLVMConstPointerCast<'a>(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; pub fn LLVMConstExtractValue( AggConstant: &Value, IdxList: *const c_uint, @@ -1083,20 +1129,20 @@ extern "C" { // Operations on global variables pub fn LLVMIsAGlobalVariable(GlobalVar: &Value) -> Option<&Value>; - pub fn LLVMAddGlobal(M: &'a Module, Ty: &'a Type, Name: *const c_char) -> &'a Value; + pub fn LLVMAddGlobal<'a>(M: &'a Module, Ty: &'a Type, Name: *const c_char) -> &'a Value; pub fn LLVMGetNamedGlobal(M: &Module, Name: *const c_char) -> Option<&Value>; - pub fn LLVMRustGetOrInsertGlobal( + pub fn LLVMRustGetOrInsertGlobal<'a>( M: &'a Module, Name: *const c_char, NameLen: size_t, T: &'a Type, ) -> &'a Value; - pub fn LLVMRustInsertPrivateGlobal(M: &'a Module, T: &'a Type) -> &'a Value; + pub fn LLVMRustInsertPrivateGlobal<'a>(M: &'a Module, T: &'a Type) -> &'a Value; pub fn LLVMGetFirstGlobal(M: &Module) -> Option<&Value>; pub fn LLVMGetNextGlobal(GlobalVar: &Value) -> Option<&Value>; pub fn LLVMDeleteGlobal(GlobalVar: &Value); pub fn LLVMGetInitializer(GlobalVar: &Value) -> Option<&Value>; - pub fn LLVMSetInitializer(GlobalVar: &'a Value, ConstantVal: &'a Value); + pub fn LLVMSetInitializer<'a>(GlobalVar: &'a Value, ConstantVal: &'a Value); pub fn LLVMIsThreadLocal(GlobalVar: &Value) -> Bool; pub fn LLVMSetThreadLocal(GlobalVar: &Value, IsThreadLocal: Bool); pub fn LLVMSetThreadLocalMode(GlobalVar: &Value, Mode: ThreadLocalMode); @@ -1110,7 +1156,7 @@ extern "C" { pub fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool); // Operations on functions - pub fn LLVMRustGetOrInsertFunction( + pub fn LLVMRustGetOrInsertFunction<'a>( M: &'a Module, Name: *const c_char, NameLen: size_t, @@ -1138,7 +1184,7 @@ extern "C" { // Operations on basic blocks pub fn LLVMGetBasicBlockParent(BB: &BasicBlock) -> &Value; - pub fn LLVMAppendBasicBlockInContext( + pub fn LLVMAppendBasicBlockInContext<'a>( C: &'a Context, Fn: &'a Value, Name: *const c_char, @@ -1162,7 +1208,7 @@ extern "C" { pub fn LLVMSetVolatile(MemoryAccessInst: &Value, volatile: Bool); // Operations on phi nodes - pub fn LLVMAddIncoming( + pub fn LLVMAddIncoming<'a>( PhiNode: &'a Value, IncomingValues: *const &'a Value, IncomingBlocks: *const &'a BasicBlock, @@ -1170,31 +1216,31 @@ extern "C" { ); // Instruction builders - pub fn LLVMCreateBuilderInContext(C: &'a Context) -> &'a mut Builder<'a>; - pub fn LLVMPositionBuilderAtEnd(Builder: &Builder<'a>, Block: &'a BasicBlock); - pub fn LLVMGetInsertBlock(Builder: &Builder<'a>) -> &'a BasicBlock; - pub fn LLVMDisposeBuilder(Builder: &'a mut Builder<'a>); + pub fn LLVMCreateBuilderInContext(C: &Context) -> &mut Builder<'_>; + pub fn LLVMPositionBuilderAtEnd<'a>(Builder: &Builder<'a>, Block: &'a BasicBlock); + pub fn LLVMGetInsertBlock<'a>(Builder: &Builder<'a>) -> &'a BasicBlock; + pub fn LLVMDisposeBuilder<'a>(Builder: &'a mut Builder<'a>); // Metadata - pub fn LLVMSetCurrentDebugLocation(Builder: &Builder<'a>, L: &'a Value); + pub fn LLVMSetCurrentDebugLocation<'a>(Builder: &Builder<'a>, L: &'a Value); // Terminators - pub fn LLVMBuildRetVoid(B: &Builder<'a>) -> &'a Value; - pub fn LLVMBuildRet(B: &Builder<'a>, V: &'a Value) -> &'a Value; - pub fn LLVMBuildBr(B: &Builder<'a>, Dest: &'a BasicBlock) -> &'a Value; - pub fn LLVMBuildCondBr( + pub fn LLVMBuildRetVoid<'a>(B: &Builder<'a>) -> &'a Value; + pub fn LLVMBuildRet<'a>(B: &Builder<'a>, V: &'a Value) -> &'a Value; + pub fn LLVMBuildBr<'a>(B: &Builder<'a>, Dest: &'a BasicBlock) -> &'a Value; + pub fn LLVMBuildCondBr<'a>( B: &Builder<'a>, If: &'a Value, Then: &'a BasicBlock, Else: &'a BasicBlock, ) -> &'a Value; - pub fn LLVMBuildSwitch( + pub fn LLVMBuildSwitch<'a>( B: &Builder<'a>, V: &'a Value, Else: &'a BasicBlock, NumCases: c_uint, ) -> &'a Value; - pub fn LLVMRustBuildInvoke( + pub fn LLVMRustBuildInvoke<'a>( B: &Builder<'a>, Ty: &'a Type, Fn: &'a Value, @@ -1205,239 +1251,239 @@ extern "C" { Bundle: Option<&OperandBundleDef<'a>>, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildLandingPad( + pub fn LLVMBuildLandingPad<'a>( B: &Builder<'a>, Ty: &'a Type, PersFn: Option<&'a Value>, NumClauses: c_uint, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildResume(B: &Builder<'a>, Exn: &'a Value) -> &'a Value; - pub fn LLVMBuildUnreachable(B: &Builder<'a>) -> &'a Value; + pub fn LLVMBuildResume<'a>(B: &Builder<'a>, Exn: &'a Value) -> &'a Value; + pub fn LLVMBuildUnreachable<'a>(B: &Builder<'a>) -> &'a Value; - pub fn LLVMRustBuildCleanupPad( + pub fn LLVMRustBuildCleanupPad<'a>( B: &Builder<'a>, ParentPad: Option<&'a Value>, ArgCnt: c_uint, Args: *const &'a Value, Name: *const c_char, ) -> Option<&'a Value>; - pub fn LLVMRustBuildCleanupRet( + pub fn LLVMRustBuildCleanupRet<'a>( B: &Builder<'a>, CleanupPad: &'a Value, UnwindBB: Option<&'a BasicBlock>, ) -> Option<&'a Value>; - pub fn LLVMRustBuildCatchPad( + pub fn LLVMRustBuildCatchPad<'a>( B: &Builder<'a>, ParentPad: &'a Value, ArgCnt: c_uint, Args: *const &'a Value, Name: *const c_char, ) -> Option<&'a Value>; - pub fn LLVMRustBuildCatchRet( + pub fn LLVMRustBuildCatchRet<'a>( B: &Builder<'a>, Pad: &'a Value, BB: &'a BasicBlock, ) -> Option<&'a Value>; - pub fn LLVMRustBuildCatchSwitch( + pub fn LLVMRustBuildCatchSwitch<'a>( Builder: &Builder<'a>, ParentPad: Option<&'a Value>, BB: Option<&'a BasicBlock>, NumHandlers: c_uint, Name: *const c_char, ) -> Option<&'a Value>; - pub fn LLVMRustAddHandler(CatchSwitch: &'a Value, Handler: &'a BasicBlock); - pub fn LLVMSetPersonalityFn(Func: &'a Value, Pers: &'a Value); + pub fn LLVMRustAddHandler<'a>(CatchSwitch: &'a Value, Handler: &'a BasicBlock); + pub fn LLVMSetPersonalityFn<'a>(Func: &'a Value, Pers: &'a Value); // Add a case to the switch instruction - pub fn LLVMAddCase(Switch: &'a Value, OnVal: &'a Value, Dest: &'a BasicBlock); + pub fn LLVMAddCase<'a>(Switch: &'a Value, OnVal: &'a Value, Dest: &'a BasicBlock); // Add a clause to the landing pad instruction - pub fn LLVMAddClause(LandingPad: &'a Value, ClauseVal: &'a Value); + pub fn LLVMAddClause<'a>(LandingPad: &'a Value, ClauseVal: &'a Value); // Set the cleanup on a landing pad instruction pub fn LLVMSetCleanup(LandingPad: &Value, Val: Bool); // Arithmetic - pub fn LLVMBuildAdd( + pub fn LLVMBuildAdd<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildFAdd( + pub fn LLVMBuildFAdd<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildSub( + pub fn LLVMBuildSub<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildFSub( + pub fn LLVMBuildFSub<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildMul( + pub fn LLVMBuildMul<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildFMul( + pub fn LLVMBuildFMul<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildUDiv( + pub fn LLVMBuildUDiv<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildExactUDiv( + pub fn LLVMBuildExactUDiv<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildSDiv( + pub fn LLVMBuildSDiv<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildExactSDiv( + pub fn LLVMBuildExactSDiv<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildFDiv( + pub fn LLVMBuildFDiv<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildURem( + pub fn LLVMBuildURem<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildSRem( + pub fn LLVMBuildSRem<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildFRem( + pub fn LLVMBuildFRem<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildShl( + pub fn LLVMBuildShl<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildLShr( + pub fn LLVMBuildLShr<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildAShr( + pub fn LLVMBuildAShr<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildNSWAdd( + pub fn LLVMBuildNSWAdd<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildNUWAdd( + pub fn LLVMBuildNUWAdd<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildNSWSub( + pub fn LLVMBuildNSWSub<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildNUWSub( + pub fn LLVMBuildNUWSub<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildNSWMul( + pub fn LLVMBuildNSWMul<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildNUWMul( + pub fn LLVMBuildNUWMul<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildAnd( + pub fn LLVMBuildAnd<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildOr( + pub fn LLVMBuildOr<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildXor( + pub fn LLVMBuildXor<'a>( B: &Builder<'a>, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildNeg(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; - pub fn LLVMBuildFNeg(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; - pub fn LLVMBuildNot(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; + pub fn LLVMBuildNeg<'a>(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; + pub fn LLVMBuildFNeg<'a>(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; + pub fn LLVMBuildNot<'a>(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; pub fn LLVMRustSetFastMath(Instr: &Value); // Memory - pub fn LLVMBuildAlloca(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value; - pub fn LLVMBuildArrayAlloca( + pub fn LLVMBuildAlloca<'a>(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value; + pub fn LLVMBuildArrayAlloca<'a>( B: &Builder<'a>, Ty: &'a Type, Val: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildLoad2( + pub fn LLVMBuildLoad2<'a>( B: &Builder<'a>, Ty: &'a Type, PointerVal: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildStore(B: &Builder<'a>, Val: &'a Value, Ptr: &'a Value) -> &'a Value; + pub fn LLVMBuildStore<'a>(B: &Builder<'a>, Val: &'a Value, Ptr: &'a Value) -> &'a Value; - pub fn LLVMBuildGEP2( + pub fn LLVMBuildGEP2<'a>( B: &Builder<'a>, Ty: &'a Type, Pointer: &'a Value, @@ -1445,7 +1491,7 @@ extern "C" { NumIndices: c_uint, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildInBoundsGEP2( + pub fn LLVMBuildInBoundsGEP2<'a>( B: &Builder<'a>, Ty: &'a Type, Pointer: &'a Value, @@ -1453,7 +1499,7 @@ extern "C" { NumIndices: c_uint, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildStructGEP2( + pub fn LLVMBuildStructGEP2<'a>( B: &Builder<'a>, Ty: &'a Type, Pointer: &'a Value, @@ -1462,85 +1508,85 @@ extern "C" { ) -> &'a Value; // Casts - pub fn LLVMBuildTrunc( + pub fn LLVMBuildTrunc<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildZExt( + pub fn LLVMBuildZExt<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildSExt( + pub fn LLVMBuildSExt<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildFPToUI( + pub fn LLVMBuildFPToUI<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildFPToSI( + pub fn LLVMBuildFPToSI<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildUIToFP( + pub fn LLVMBuildUIToFP<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildSIToFP( + pub fn LLVMBuildSIToFP<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildFPTrunc( + pub fn LLVMBuildFPTrunc<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildFPExt( + pub fn LLVMBuildFPExt<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildPtrToInt( + pub fn LLVMBuildPtrToInt<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildIntToPtr( + pub fn LLVMBuildIntToPtr<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildBitCast( + pub fn LLVMBuildBitCast<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildPointerCast( + pub fn LLVMBuildPointerCast<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMRustBuildIntCast( + pub fn LLVMRustBuildIntCast<'a>( B: &Builder<'a>, Val: &'a Value, DestTy: &'a Type, @@ -1548,14 +1594,14 @@ extern "C" { ) -> &'a Value; // Comparisons - pub fn LLVMBuildICmp( + pub fn LLVMBuildICmp<'a>( B: &Builder<'a>, Op: c_uint, LHS: &'a Value, RHS: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildFCmp( + pub fn LLVMBuildFCmp<'a>( B: &Builder<'a>, Op: c_uint, LHS: &'a Value, @@ -1564,9 +1610,9 @@ extern "C" { ) -> &'a Value; // Miscellaneous instructions - pub fn LLVMBuildPhi(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value; - pub fn LLVMRustGetInstrProfIncrementIntrinsic(M: &Module) -> &'a Value; - pub fn LLVMRustBuildCall( + pub fn LLVMBuildPhi<'a>(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value; + pub fn LLVMRustGetInstrProfIncrementIntrinsic(M: &Module) -> &Value; + pub fn LLVMRustBuildCall<'a>( B: &Builder<'a>, Ty: &'a Type, Fn: &'a Value, @@ -1574,7 +1620,7 @@ extern "C" { NumArgs: c_uint, Bundle: Option<&OperandBundleDef<'a>>, ) -> &'a Value; - pub fn LLVMRustBuildMemCpy( + pub fn LLVMRustBuildMemCpy<'a>( B: &Builder<'a>, Dst: &'a Value, DstAlign: c_uint, @@ -1583,7 +1629,7 @@ extern "C" { Size: &'a Value, IsVolatile: bool, ) -> &'a Value; - pub fn LLVMRustBuildMemMove( + pub fn LLVMRustBuildMemMove<'a>( B: &Builder<'a>, Dst: &'a Value, DstAlign: c_uint, @@ -1592,7 +1638,7 @@ extern "C" { Size: &'a Value, IsVolatile: bool, ) -> &'a Value; - pub fn LLVMRustBuildMemSet( + pub fn LLVMRustBuildMemSet<'a>( B: &Builder<'a>, Dst: &'a Value, DstAlign: c_uint, @@ -1600,46 +1646,46 @@ extern "C" { Size: &'a Value, IsVolatile: bool, ) -> &'a Value; - pub fn LLVMBuildSelect( + pub fn LLVMBuildSelect<'a>( B: &Builder<'a>, If: &'a Value, Then: &'a Value, Else: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildVAArg( + pub fn LLVMBuildVAArg<'a>( B: &Builder<'a>, list: &'a Value, Ty: &'a Type, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildExtractElement( + pub fn LLVMBuildExtractElement<'a>( B: &Builder<'a>, VecVal: &'a Value, Index: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildInsertElement( + pub fn LLVMBuildInsertElement<'a>( B: &Builder<'a>, VecVal: &'a Value, EltVal: &'a Value, Index: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildShuffleVector( + pub fn LLVMBuildShuffleVector<'a>( B: &Builder<'a>, V1: &'a Value, V2: &'a Value, Mask: &'a Value, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildExtractValue( + pub fn LLVMBuildExtractValue<'a>( B: &Builder<'a>, AggVal: &'a Value, Index: c_uint, Name: *const c_char, ) -> &'a Value; - pub fn LLVMBuildInsertValue( + pub fn LLVMBuildInsertValue<'a>( B: &Builder<'a>, AggVal: &'a Value, EltVal: &'a Value, @@ -1647,41 +1693,47 @@ extern "C" { Name: *const c_char, ) -> &'a Value; - pub fn LLVMRustBuildVectorReduceFAdd( + pub fn LLVMRustBuildVectorReduceFAdd<'a>( B: &Builder<'a>, Acc: &'a Value, Src: &'a Value, ) -> &'a Value; - pub fn LLVMRustBuildVectorReduceFMul( + pub fn LLVMRustBuildVectorReduceFMul<'a>( B: &Builder<'a>, Acc: &'a Value, Src: &'a Value, ) -> &'a Value; - pub fn LLVMRustBuildVectorReduceAdd(B: &Builder<'a>, Src: &'a Value) -> &'a Value; - pub fn LLVMRustBuildVectorReduceMul(B: &Builder<'a>, Src: &'a Value) -> &'a Value; - pub fn LLVMRustBuildVectorReduceAnd(B: &Builder<'a>, Src: &'a Value) -> &'a Value; - pub fn LLVMRustBuildVectorReduceOr(B: &Builder<'a>, Src: &'a Value) -> &'a Value; - pub fn LLVMRustBuildVectorReduceXor(B: &Builder<'a>, Src: &'a Value) -> &'a Value; - pub fn LLVMRustBuildVectorReduceMin( + pub fn LLVMRustBuildVectorReduceAdd<'a>(B: &Builder<'a>, Src: &'a Value) -> &'a Value; + pub fn LLVMRustBuildVectorReduceMul<'a>(B: &Builder<'a>, Src: &'a Value) -> &'a Value; + pub fn LLVMRustBuildVectorReduceAnd<'a>(B: &Builder<'a>, Src: &'a Value) -> &'a Value; + pub fn LLVMRustBuildVectorReduceOr<'a>(B: &Builder<'a>, Src: &'a Value) -> &'a Value; + pub fn LLVMRustBuildVectorReduceXor<'a>(B: &Builder<'a>, Src: &'a Value) -> &'a Value; + pub fn LLVMRustBuildVectorReduceMin<'a>( B: &Builder<'a>, Src: &'a Value, IsSigned: bool, ) -> &'a Value; - pub fn LLVMRustBuildVectorReduceMax( + pub fn LLVMRustBuildVectorReduceMax<'a>( B: &Builder<'a>, Src: &'a Value, IsSigned: bool, ) -> &'a Value; - pub fn LLVMRustBuildVectorReduceFMin(B: &Builder<'a>, Src: &'a Value, IsNaN: bool) - -> &'a Value; - pub fn LLVMRustBuildVectorReduceFMax(B: &Builder<'a>, Src: &'a Value, IsNaN: bool) - -> &'a Value; + pub fn LLVMRustBuildVectorReduceFMin<'a>( + B: &Builder<'a>, + Src: &'a Value, + IsNaN: bool, + ) -> &'a Value; + pub fn LLVMRustBuildVectorReduceFMax<'a>( + B: &Builder<'a>, + Src: &'a Value, + IsNaN: bool, + ) -> &'a Value; - pub fn LLVMRustBuildMinNum(B: &Builder<'a>, LHS: &'a Value, LHS: &'a Value) -> &'a Value; - pub fn LLVMRustBuildMaxNum(B: &Builder<'a>, LHS: &'a Value, LHS: &'a Value) -> &'a Value; + pub fn LLVMRustBuildMinNum<'a>(B: &Builder<'a>, LHS: &'a Value, LHS: &'a Value) -> &'a Value; + pub fn LLVMRustBuildMaxNum<'a>(B: &Builder<'a>, LHS: &'a Value, LHS: &'a Value) -> &'a Value; // Atomic Operations - pub fn LLVMRustBuildAtomicLoad( + pub fn LLVMRustBuildAtomicLoad<'a>( B: &Builder<'a>, ElementType: &'a Type, PointerVal: &'a Value, @@ -1689,14 +1741,14 @@ extern "C" { Order: AtomicOrdering, ) -> &'a Value; - pub fn LLVMRustBuildAtomicStore( + pub fn LLVMRustBuildAtomicStore<'a>( B: &Builder<'a>, Val: &'a Value, Ptr: &'a Value, Order: AtomicOrdering, ) -> &'a Value; - pub fn LLVMRustBuildAtomicCmpXchg( + pub fn LLVMRustBuildAtomicCmpXchg<'a>( B: &Builder<'a>, LHS: &'a Value, CMP: &'a Value, @@ -1706,7 +1758,7 @@ extern "C" { Weak: Bool, ) -> &'a Value; - pub fn LLVMBuildAtomicRMW( + pub fn LLVMBuildAtomicRMW<'a>( B: &Builder<'a>, Op: AtomicRmwBinOp, LHS: &'a Value, @@ -1725,16 +1777,16 @@ extern "C" { pub fn LLVMWriteBitcodeToFile(M: &Module, Path: *const c_char) -> c_int; /// Creates a pass manager. - pub fn LLVMCreatePassManager() -> &'a mut PassManager<'a>; + pub fn LLVMCreatePassManager<'a>() -> &'a mut PassManager<'a>; /// Creates a function-by-function pass manager - pub fn LLVMCreateFunctionPassManagerForModule(M: &'a Module) -> &'a mut PassManager<'a>; + pub fn LLVMCreateFunctionPassManagerForModule(M: &Module) -> &mut PassManager<'_>; /// Disposes a pass manager. - pub fn LLVMDisposePassManager(PM: &'a mut PassManager<'a>); + pub fn LLVMDisposePassManager<'a>(PM: &'a mut PassManager<'a>); /// Runs a pass manager on a module. - pub fn LLVMRunPassManager(PM: &PassManager<'a>, M: &'a Module) -> Bool; + pub fn LLVMRunPassManager<'a>(PM: &PassManager<'a>, M: &'a Module) -> Bool; pub fn LLVMInitializePasses(); @@ -1744,7 +1796,7 @@ extern "C" { pub fn LLVMTimeTraceProfilerFinish(FileName: *const c_char); - pub fn LLVMAddAnalysisPasses(T: &'a TargetMachine, PM: &PassManager<'a>); + pub fn LLVMAddAnalysisPasses<'a>(T: &'a TargetMachine, PM: &PassManager<'a>); pub fn LLVMPassManagerBuilderCreate() -> &'static mut PassManagerBuilder; pub fn LLVMPassManagerBuilderDispose(PMB: &'static mut PassManagerBuilder); @@ -1788,7 +1840,7 @@ extern "C" { pub fn LLVMStructCreateNamed(C: &Context, Name: *const c_char) -> &Type; - pub fn LLVMStructSetBody( + pub fn LLVMStructSetBody<'a>( StructTy: &'a Type, ElementTypes: *const &'a Type, ElementCount: c_uint, @@ -1805,6 +1857,7 @@ extern "C" { SideEffects: Bool, AlignStack: Bool, Dialect: AsmDialect, + CanThrow: Bool, ) -> &Value; pub fn LLVMRustInlineAsmVerify( Ty: &Type, @@ -1830,8 +1883,7 @@ extern "C" { BufferOut: &RustString, ); - pub fn LLVMRustCoverageCreatePGOFuncNameVar(F: &'a Value, FuncName: *const c_char) - -> &'a Value; + pub fn LLVMRustCoverageCreatePGOFuncNameVar(F: &Value, FuncName: *const c_char) -> &Value; pub fn LLVMRustCoverageHashCString(StrVal: *const c_char) -> u64; pub fn LLVMRustCoverageHashByteArray(Bytes: *const c_char, NumBytes: size_t) -> u64; @@ -1850,17 +1902,19 @@ extern "C" { pub fn LLVMRustVersionMinor() -> u32; pub fn LLVMRustVersionPatch() -> u32; + pub fn LLVMRustIsRustLLVM() -> bool; + pub fn LLVMRustAddModuleFlag(M: &Module, name: *const c_char, value: u32); - pub fn LLVMRustMetadataAsValue(C: &'a Context, MD: &'a Metadata) -> &'a Value; + pub fn LLVMRustMetadataAsValue<'a>(C: &'a Context, MD: &'a Metadata) -> &'a Value; - pub fn LLVMRustDIBuilderCreate(M: &'a Module) -> &'a mut DIBuilder<'a>; + pub fn LLVMRustDIBuilderCreate(M: &Module) -> &mut DIBuilder<'_>; - pub fn LLVMRustDIBuilderDispose(Builder: &'a mut DIBuilder<'a>); + pub fn LLVMRustDIBuilderDispose<'a>(Builder: &'a mut DIBuilder<'a>); pub fn LLVMRustDIBuilderFinalize(Builder: &DIBuilder<'_>); - pub fn LLVMRustDIBuilderCreateCompileUnit( + pub fn LLVMRustDIBuilderCreateCompileUnit<'a>( Builder: &DIBuilder<'a>, Lang: c_uint, File: &'a DIFile, @@ -1876,7 +1930,7 @@ extern "C" { SplitDebugInlining: bool, ) -> &'a DIDescriptor; - pub fn LLVMRustDIBuilderCreateFile( + pub fn LLVMRustDIBuilderCreateFile<'a>( Builder: &DIBuilder<'a>, Filename: *const c_char, FilenameLen: size_t, @@ -1887,12 +1941,12 @@ extern "C" { ChecksumLen: size_t, ) -> &'a DIFile; - pub fn LLVMRustDIBuilderCreateSubroutineType( + pub fn LLVMRustDIBuilderCreateSubroutineType<'a>( Builder: &DIBuilder<'a>, ParameterTypes: &'a DIArray, ) -> &'a DICompositeType; - pub fn LLVMRustDIBuilderCreateFunction( + pub fn LLVMRustDIBuilderCreateFunction<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIDescriptor, Name: *const c_char, @@ -1910,7 +1964,7 @@ extern "C" { Decl: Option<&'a DIDescriptor>, ) -> &'a DISubprogram; - pub fn LLVMRustDIBuilderCreateBasicType( + pub fn LLVMRustDIBuilderCreateBasicType<'a>( Builder: &DIBuilder<'a>, Name: *const c_char, NameLen: size_t, @@ -1918,7 +1972,7 @@ extern "C" { Encoding: c_uint, ) -> &'a DIBasicType; - pub fn LLVMRustDIBuilderCreateTypedef( + pub fn LLVMRustDIBuilderCreateTypedef<'a>( Builder: &DIBuilder<'a>, Type: &'a DIBasicType, Name: *const c_char, @@ -1928,7 +1982,7 @@ extern "C" { Scope: Option<&'a DIScope>, ) -> &'a DIDerivedType; - pub fn LLVMRustDIBuilderCreatePointerType( + pub fn LLVMRustDIBuilderCreatePointerType<'a>( Builder: &DIBuilder<'a>, PointeeTy: &'a DIType, SizeInBits: u64, @@ -1938,7 +1992,7 @@ extern "C" { NameLen: size_t, ) -> &'a DIDerivedType; - pub fn LLVMRustDIBuilderCreateStructType( + pub fn LLVMRustDIBuilderCreateStructType<'a>( Builder: &DIBuilder<'a>, Scope: Option<&'a DIDescriptor>, Name: *const c_char, @@ -1956,7 +2010,7 @@ extern "C" { UniqueIdLen: size_t, ) -> &'a DICompositeType; - pub fn LLVMRustDIBuilderCreateMemberType( + pub fn LLVMRustDIBuilderCreateMemberType<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIDescriptor, Name: *const c_char, @@ -1970,7 +2024,7 @@ extern "C" { Ty: &'a DIType, ) -> &'a DIDerivedType; - pub fn LLVMRustDIBuilderCreateVariantMemberType( + pub fn LLVMRustDIBuilderCreateVariantMemberType<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIScope, Name: *const c_char, @@ -1985,7 +2039,7 @@ extern "C" { Ty: &'a DIType, ) -> &'a DIType; - pub fn LLVMRustDIBuilderCreateLexicalBlock( + pub fn LLVMRustDIBuilderCreateLexicalBlock<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIScope, File: &'a DIFile, @@ -1993,13 +2047,13 @@ extern "C" { Col: c_uint, ) -> &'a DILexicalBlock; - pub fn LLVMRustDIBuilderCreateLexicalBlockFile( + pub fn LLVMRustDIBuilderCreateLexicalBlockFile<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIScope, File: &'a DIFile, ) -> &'a DILexicalBlock; - pub fn LLVMRustDIBuilderCreateStaticVariable( + pub fn LLVMRustDIBuilderCreateStaticVariable<'a>( Builder: &DIBuilder<'a>, Context: Option<&'a DIScope>, Name: *const c_char, @@ -2015,7 +2069,7 @@ extern "C" { AlignInBits: u32, ) -> &'a DIGlobalVariableExpression; - pub fn LLVMRustDIBuilderCreateVariable( + pub fn LLVMRustDIBuilderCreateVariable<'a>( Builder: &DIBuilder<'a>, Tag: c_uint, Scope: &'a DIDescriptor, @@ -2030,7 +2084,7 @@ extern "C" { AlignInBits: u32, ) -> &'a DIVariable; - pub fn LLVMRustDIBuilderCreateArrayType( + pub fn LLVMRustDIBuilderCreateArrayType<'a>( Builder: &DIBuilder<'a>, Size: u64, AlignInBits: u32, @@ -2038,29 +2092,29 @@ extern "C" { Subscripts: &'a DIArray, ) -> &'a DIType; - pub fn LLVMRustDIBuilderGetOrCreateSubrange( + pub fn LLVMRustDIBuilderGetOrCreateSubrange<'a>( Builder: &DIBuilder<'a>, Lo: i64, Count: i64, ) -> &'a DISubrange; - pub fn LLVMRustDIBuilderGetOrCreateArray( + pub fn LLVMRustDIBuilderGetOrCreateArray<'a>( Builder: &DIBuilder<'a>, Ptr: *const Option<&'a DIDescriptor>, Count: c_uint, ) -> &'a DIArray; - pub fn LLVMRustDIBuilderInsertDeclareAtEnd( + pub fn LLVMRustDIBuilderInsertDeclareAtEnd<'a>( Builder: &DIBuilder<'a>, Val: &'a Value, VarInfo: &'a DIVariable, - AddrOps: *const i64, + AddrOps: *const u64, AddrOpsCount: c_uint, DL: &'a DILocation, InsertAtEnd: &'a BasicBlock, ) -> &'a Value; - pub fn LLVMRustDIBuilderCreateEnumerator( + pub fn LLVMRustDIBuilderCreateEnumerator<'a>( Builder: &DIBuilder<'a>, Name: *const c_char, NameLen: size_t, @@ -2068,7 +2122,7 @@ extern "C" { IsUnsigned: bool, ) -> &'a DIEnumerator; - pub fn LLVMRustDIBuilderCreateEnumerationType( + pub fn LLVMRustDIBuilderCreateEnumerationType<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIScope, Name: *const c_char, @@ -2082,7 +2136,7 @@ extern "C" { IsScoped: bool, ) -> &'a DIType; - pub fn LLVMRustDIBuilderCreateUnionType( + pub fn LLVMRustDIBuilderCreateUnionType<'a>( Builder: &DIBuilder<'a>, Scope: Option<&'a DIScope>, Name: *const c_char, @@ -2098,7 +2152,7 @@ extern "C" { UniqueIdLen: size_t, ) -> &'a DIType; - pub fn LLVMRustDIBuilderCreateVariantPart( + pub fn LLVMRustDIBuilderCreateVariantPart<'a>( Builder: &DIBuilder<'a>, Scope: &'a DIScope, Name: *const c_char, @@ -2116,7 +2170,7 @@ extern "C" { pub fn LLVMSetUnnamedAddress(Global: &Value, UnnamedAddr: UnnamedAddr); - pub fn LLVMRustDIBuilderCreateTemplateTypeParameter( + pub fn LLVMRustDIBuilderCreateTemplateTypeParameter<'a>( Builder: &DIBuilder<'a>, Scope: Option<&'a DIScope>, Name: *const c_char, @@ -2124,7 +2178,7 @@ extern "C" { Ty: &'a DIType, ) -> &'a DITemplateTypeParameter; - pub fn LLVMRustDIBuilderCreateNameSpace( + pub fn LLVMRustDIBuilderCreateNameSpace<'a>( Builder: &DIBuilder<'a>, Scope: Option<&'a DIScope>, Name: *const c_char, @@ -2132,21 +2186,21 @@ extern "C" { ExportSymbols: bool, ) -> &'a DINameSpace; - pub fn LLVMRustDICompositeTypeReplaceArrays( + pub fn LLVMRustDICompositeTypeReplaceArrays<'a>( Builder: &DIBuilder<'a>, CompositeType: &'a DIType, Elements: Option<&'a DIArray>, Params: Option<&'a DIArray>, ); - pub fn LLVMRustDIBuilderCreateDebugLocation( + pub fn LLVMRustDIBuilderCreateDebugLocation<'a>( Line: c_uint, Column: c_uint, Scope: &'a DIScope, InlinedAt: Option<&'a DILocation>, ) -> &'a DILocation; - pub fn LLVMRustDIBuilderCreateOpDeref() -> i64; - pub fn LLVMRustDIBuilderCreateOpPlusUconst() -> i64; + pub fn LLVMRustDIBuilderCreateOpDeref() -> u64; + pub fn LLVMRustDIBuilderCreateOpPlusUconst() -> u64; #[allow(improper_ctypes)] pub fn LLVMRustWriteTypeToString(Type: &Type, s: &RustString); @@ -2205,7 +2259,7 @@ extern "C" { SplitDwarfFile: *const c_char, ) -> Option<&'static mut TargetMachine>; pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine); - pub fn LLVMRustAddBuilderLibraryInfo( + pub fn LLVMRustAddBuilderLibraryInfo<'a>( PMB: &'a PassManagerBuilder, M: &'a Module, DisableSimplifyLibCalls: bool, @@ -2221,13 +2275,13 @@ extern "C" { PGOUsePath: *const c_char, PGOSampleUsePath: *const c_char, ); - pub fn LLVMRustAddLibraryInfo( + pub fn LLVMRustAddLibraryInfo<'a>( PM: &PassManager<'a>, M: &'a Module, DisableSimplifyLibCalls: bool, ); - pub fn LLVMRustRunFunctionPassManager(PM: &PassManager<'a>, M: &'a Module); - pub fn LLVMRustWriteOutputFile( + pub fn LLVMRustRunFunctionPassManager<'a>(PM: &PassManager<'a>, M: &'a Module); + pub fn LLVMRustWriteOutputFile<'a>( T: &'a TargetMachine, PM: &PassManager<'a>, M: &'a Module, @@ -2235,7 +2289,7 @@ extern "C" { DwoOutput: *const c_char, FileType: FileType, ) -> LLVMRustResult; - pub fn LLVMRustOptimizeWithNewPassManager( + pub fn LLVMRustOptimizeWithNewPassManager<'a>( M: &'a Module, TM: &'a TargetMachine, OptLevel: PassBuilderOptLevel, @@ -2261,9 +2315,11 @@ extern "C" { end_callback: SelfProfileAfterPassCallback, ExtraPasses: *const c_char, ExtraPassesLen: size_t, + LLVMPlugins: *const c_char, + LLVMPluginsLen: size_t, ) -> LLVMRustResult; pub fn LLVMRustPrintModule( - M: &'a Module, + M: &Module, Output: *const c_char, Demangle: extern "C" fn(*const c_char, size_t, *mut c_char, size_t) -> size_t, ) -> LLVMRustResult; @@ -2276,27 +2332,21 @@ extern "C" { pub fn LLVMRustMarkAllFunctionsNounwind(M: &Module); pub fn LLVMRustOpenArchive(path: *const c_char) -> Option<&'static mut Archive>; - pub fn LLVMRustArchiveIteratorNew(AR: &'a Archive) -> &'a mut ArchiveIterator<'a>; - pub fn LLVMRustArchiveIteratorNext( + pub fn LLVMRustArchiveIteratorNew(AR: &Archive) -> &mut ArchiveIterator<'_>; + pub fn LLVMRustArchiveIteratorNext<'a>( AIR: &ArchiveIterator<'a>, ) -> Option<&'a mut ArchiveChild<'a>>; pub fn LLVMRustArchiveChildName(ACR: &ArchiveChild<'_>, size: &mut size_t) -> *const c_char; pub fn LLVMRustArchiveChildData(ACR: &ArchiveChild<'_>, size: &mut size_t) -> *const c_char; - pub fn LLVMRustArchiveChildFree(ACR: &'a mut ArchiveChild<'a>); - pub fn LLVMRustArchiveIteratorFree(AIR: &'a mut ArchiveIterator<'a>); + pub fn LLVMRustArchiveChildFree<'a>(ACR: &'a mut ArchiveChild<'a>); + pub fn LLVMRustArchiveIteratorFree<'a>(AIR: &'a mut ArchiveIterator<'a>); pub fn LLVMRustDestroyArchive(AR: &'static mut Archive); #[allow(improper_ctypes)] pub fn LLVMRustWriteTwineToString(T: &Twine, s: &RustString); - pub fn LLVMContextSetDiagnosticHandler( - C: &Context, - Handler: DiagnosticHandler, - DiagnosticContext: *mut c_void, - ); - #[allow(improper_ctypes)] - pub fn LLVMRustUnpackOptimizationDiagnostic( + pub fn LLVMRustUnpackOptimizationDiagnostic<'a>( DI: &'a DiagnosticInfo, pass_name_out: &RustString, function_out: &mut Option<&'a Value>, @@ -2306,7 +2356,7 @@ extern "C" { message_out: &RustString, ); - pub fn LLVMRustUnpackInlineAsmDiagnostic( + pub fn LLVMRustUnpackInlineAsmDiagnostic<'a>( DI: &'a DiagnosticInfo, level_out: &mut DiagnosticLevel, cookie_out: &mut c_uint, @@ -2317,14 +2367,14 @@ extern "C" { pub fn LLVMRustWriteDiagnosticInfoToString(DI: &DiagnosticInfo, s: &RustString); pub fn LLVMRustGetDiagInfoKind(DI: &DiagnosticInfo) -> DiagnosticKind; - pub fn LLVMRustGetSMDiagnostic( + pub fn LLVMRustGetSMDiagnostic<'a>( DI: &'a DiagnosticInfo, cookie_out: &mut c_uint, ) -> &'a SMDiagnostic; pub fn LLVMRustSetInlineAsmDiagnosticHandler( C: &Context, - H: InlineAsmDiagHandler, + H: InlineAsmDiagHandlerTy, CX: *mut c_void, ); @@ -2346,12 +2396,12 @@ extern "C" { WriteSymbtab: bool, Kind: ArchiveKind, ) -> LLVMRustResult; - pub fn LLVMRustArchiveMemberNew( + pub fn LLVMRustArchiveMemberNew<'a>( Filename: *const c_char, Name: *const c_char, Child: Option<&ArchiveChild<'a>>, ) -> &'a mut RustArchiveMember<'a>; - pub fn LLVMRustArchiveMemberFree(Member: &'a mut RustArchiveMember<'a>); + pub fn LLVMRustArchiveMemberFree<'a>(Member: &'a mut RustArchiveMember<'a>); pub fn LLVMRustWriteImportLibrary( ImportName: *const c_char, @@ -2362,18 +2412,18 @@ extern "C" { MinGW: bool, ) -> LLVMRustResult; - pub fn LLVMRustSetDataLayoutFromTargetMachine(M: &'a Module, TM: &'a TargetMachine); + pub fn LLVMRustSetDataLayoutFromTargetMachine<'a>(M: &'a Module, TM: &'a TargetMachine); - pub fn LLVMRustBuildOperandBundleDef( + pub fn LLVMRustBuildOperandBundleDef<'a>( Name: *const c_char, Inputs: *const &'a Value, NumInputs: c_uint, ) -> &'a mut OperandBundleDef<'a>; - pub fn LLVMRustFreeOperandBundleDef(Bundle: &'a mut OperandBundleDef<'a>); + pub fn LLVMRustFreeOperandBundleDef<'a>(Bundle: &'a mut OperandBundleDef<'a>); - pub fn LLVMRustPositionBuilderAtStart(B: &Builder<'a>, BB: &'a BasicBlock); + pub fn LLVMRustPositionBuilderAtStart<'a>(B: &Builder<'a>, BB: &'a BasicBlock); - pub fn LLVMRustSetComdat(M: &'a Module, V: &'a Value, Name: *const c_char, NameLen: size_t); + pub fn LLVMRustSetComdat<'a>(M: &'a Module, V: &'a Value, Name: *const c_char, NameLen: size_t); pub fn LLVMRustUnsetComdat(V: &Value); pub fn LLVMRustSetModulePICLevel(M: &Module); pub fn LLVMRustSetModulePIELevel(M: &Module); @@ -2426,17 +2476,32 @@ extern "C" { pub fn LLVMRustLTOGetDICompileUnit(M: &Module, CU1: &mut *mut c_void, CU2: &mut *mut c_void); pub fn LLVMRustLTOPatchDICompileUnit(M: &Module, CU: *mut c_void); - pub fn LLVMRustLinkerNew(M: &'a Module) -> &'a mut Linker<'a>; + pub fn LLVMRustLinkerNew(M: &Module) -> &mut Linker<'_>; pub fn LLVMRustLinkerAdd( linker: &Linker<'_>, bytecode: *const c_char, bytecode_len: usize, ) -> bool; - pub fn LLVMRustLinkerFree(linker: &'a mut Linker<'a>); + pub fn LLVMRustLinkerFree<'a>(linker: &'a mut Linker<'a>); #[allow(improper_ctypes)] pub fn LLVMRustComputeLTOCacheKey( key_out: &RustString, mod_id: *const c_char, data: &ThinLTOData, ); + + pub fn LLVMRustContextGetDiagnosticHandler(Context: &Context) -> Option<&DiagnosticHandler>; + pub fn LLVMRustContextSetDiagnosticHandler( + context: &Context, + diagnostic_handler: Option<&DiagnosticHandler>, + ); + pub fn LLVMRustContextConfigureDiagnosticHandler( + context: &Context, + diagnostic_handler_callback: DiagnosticHandlerTy, + diagnostic_handler_context: *mut c_void, + remark_all_passes: bool, + remark_passes: *const *const c_char, + remark_passes_len: usize, + ); + } diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index c1521a760b..a1117a11fc 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -31,13 +31,13 @@ impl LLVMRustResult { } } -pub fn AddFunctionAttrStringValue(llfn: &'a Value, idx: AttributePlace, attr: &CStr, value: &CStr) { +pub fn AddFunctionAttrStringValue(llfn: &Value, idx: AttributePlace, attr: &CStr, value: &CStr) { unsafe { LLVMRustAddFunctionAttrStringValue(llfn, idx.as_uint(), attr.as_ptr(), value.as_ptr()) } } -pub fn AddFunctionAttrString(llfn: &'a Value, idx: AttributePlace, attr: &CStr) { +pub fn AddFunctionAttrString(llfn: &Value, idx: AttributePlace, attr: &CStr) { unsafe { LLVMRustAddFunctionAttrStringValue(llfn, idx.as_uint(), attr.as_ptr(), std::ptr::null()) } @@ -86,12 +86,12 @@ impl FromStr for ArchiveKind { } } -pub fn SetInstructionCallConv(instr: &'a Value, cc: CallConv) { +pub fn SetInstructionCallConv(instr: &Value, cc: CallConv) { unsafe { LLVMSetInstructionCallConv(instr, cc as c_uint); } } -pub fn SetFunctionCallConv(fn_: &'a Value, cc: CallConv) { +pub fn SetFunctionCallConv(fn_: &Value, cc: CallConv) { unsafe { LLVMSetFunctionCallConv(fn_, cc as c_uint); } @@ -103,26 +103,26 @@ pub fn SetFunctionCallConv(fn_: &'a Value, cc: CallConv) { // value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the // function. // For more details on COMDAT sections see e.g., https://www.airs.com/blog/archives/52 -pub fn SetUniqueComdat(llmod: &Module, val: &'a Value) { +pub fn SetUniqueComdat(llmod: &Module, val: &Value) { unsafe { let name = get_value_name(val); LLVMRustSetComdat(llmod, val, name.as_ptr().cast(), name.len()); } } -pub fn UnsetComdat(val: &'a Value) { +pub fn UnsetComdat(val: &Value) { unsafe { LLVMRustUnsetComdat(val); } } -pub fn SetUnnamedAddress(global: &'a Value, unnamed: UnnamedAddr) { +pub fn SetUnnamedAddress(global: &Value, unnamed: UnnamedAddr) { unsafe { LLVMSetUnnamedAddress(global, unnamed); } } -pub fn set_thread_local_mode(global: &'a Value, mode: ThreadLocalMode) { +pub fn set_thread_local_mode(global: &Value, mode: ThreadLocalMode) { unsafe { LLVMSetThreadLocalMode(global, mode); } @@ -264,7 +264,7 @@ pub struct OperandBundleDef<'a> { pub raw: &'a mut ffi::OperandBundleDef<'a>, } -impl OperandBundleDef<'a> { +impl<'a> OperandBundleDef<'a> { pub fn new(name: &str, vals: &[&'a Value]) -> Self { let name = SmallCStr::new(name); let def = unsafe { @@ -274,7 +274,7 @@ impl OperandBundleDef<'a> { } } -impl Drop for OperandBundleDef<'a> { +impl Drop for OperandBundleDef<'_> { fn drop(&mut self) { unsafe { LLVMRustFreeOperandBundleDef(&mut *(self.raw as *mut _)); diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 3393c9baa2..d49df29f45 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -1,9 +1,10 @@ use crate::back::write::create_informational_target_machine; use crate::{llvm, llvm_util}; use libc::c_int; +use libloading::Library; use rustc_codegen_ssa::target_features::supported_target_features; use rustc_data_structures::fx::FxHashSet; -use rustc_metadata::dynamic_lib::DynamicLibrary; +use rustc_fs_util::path_to_c_string; use rustc_middle::bug; use rustc_session::config::PrintRequest; use rustc_session::Session; @@ -120,14 +121,20 @@ unsafe fn configure_llvm(sess: &Session) { llvm::LLVMInitializePasses(); - for plugin in &sess.opts.debugging_opts.llvm_plugins { - let path = Path::new(plugin); - let res = DynamicLibrary::open(path); - match res { - Ok(_) => debug!("LLVM plugin loaded succesfully {} ({})", path.display(), plugin), - Err(e) => bug!("couldn't load plugin: {}", e), + // Use the legacy plugin registration if we don't use the new pass manager + if !should_use_new_llvm_pass_manager( + &sess.opts.debugging_opts.new_llvm_pass_manager, + &sess.target.arch, + ) { + // Register LLVM plugins by loading them into the compiler process. + for plugin in &sess.opts.debugging_opts.llvm_plugins { + let lib = Library::new(plugin).unwrap_or_else(|e| bug!("couldn't load plugin: {}", e)); + debug!("LLVM plugin loaded successfully {:?} ({})", lib, plugin); + + // Intentionally leak the dynamic library. We can't ever unload it + // since the library can make things that will live arbitrarily long. + mem::forget(lib); } - mem::forget(res); } rustc_llvm::initialize_available_targets(); @@ -135,9 +142,9 @@ unsafe fn configure_llvm(sess: &Session) { llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr()); } -pub fn time_trace_profiler_finish(file_name: &str) { +pub fn time_trace_profiler_finish(file_name: &Path) { unsafe { - let file_name = CString::new(file_name).unwrap(); + let file_name = path_to_c_string(file_name); llvm::LLVMTimeTraceProfilerFinish(file_name.as_ptr()); } } @@ -216,6 +223,12 @@ pub fn get_version() -> (u32, u32, u32) { } } +/// Returns `true` if this LLVM is Rust's bundled LLVM (and not system LLVM). +pub fn is_rust_llvm() -> bool { + // Can be called without initializing LLVM + unsafe { llvm::LLVMRustIsRustLLVM() } +} + pub fn print_passes() { // Can be called without initializing LLVM unsafe { @@ -410,3 +423,13 @@ pub fn tune_cpu(sess: &Session) -> Option<&str> { let name = sess.opts.debugging_opts.tune_cpu.as_ref()?; Some(handle_native(name)) } + +pub(crate) fn should_use_new_llvm_pass_manager(user_opt: &Option, target_arch: &str) -> bool { + // The new pass manager is enabled by default for LLVM >= 13. + // This matches Clang, which also enables it since Clang 13. + + // FIXME: There are some perf issues with the new pass manager + // when targeting s390x, so it is temporarily disabled for that + // arch, see https://github.com/rust-lang/rust/issues/89609 + user_opt.unwrap_or_else(|| target_arch != "s390x" && llvm_util::get_version() >= (13, 0, 0)) +} diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index 88498cf47d..a3053742aa 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -13,7 +13,7 @@ use rustc_session::config::CrateType; use rustc_target::spec::RelocModel; use tracing::debug; -impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { +impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> { fn predefine_static( &self, def_id: DefId, @@ -92,7 +92,7 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { } } -impl CodegenCx<'ll, 'tcx> { +impl CodegenCx<'_, '_> { /// Whether a definition or declaration can be assumed to be local to a group of /// libraries that form a single DSO or executable. pub(crate) unsafe fn should_assume_dso_local( diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index 2ae0a08f19..21b77f7dea 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -38,7 +38,7 @@ impl fmt::Debug for Type { } } -impl CodegenCx<'ll, 'tcx> { +impl<'ll> CodegenCx<'ll, '_> { crate fn type_named_struct(&self, name: &str) -> &'ll Type { let name = SmallCStr::new(name); unsafe { llvm::LLVMStructCreateNamed(self.llcx, name.as_ptr()) } @@ -133,7 +133,7 @@ impl CodegenCx<'ll, 'tcx> { } } -impl BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { +impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn type_i1(&self) -> &'ll Type { unsafe { llvm::LLVMInt1TypeInContext(self.llcx) } } @@ -252,7 +252,7 @@ impl Type { } } -impl LayoutTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { +impl<'ll, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn backend_type(&self, layout: TyAndLayout<'tcx>) -> &'ll Type { layout.llvm_type(self) } diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index 591f659f11..f090ae6ecb 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -11,8 +11,8 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; use rustc_middle::ty::Ty; use rustc_target::abi::{Align, Endian, HasDataLayout, Size}; -fn round_pointer_up_to_alignment( - bx: &mut Builder<'a, 'll, 'tcx>, +fn round_pointer_up_to_alignment<'ll>( + bx: &mut Builder<'_, 'll, '_>, addr: &'ll Value, align: Align, ptr_ty: &'ll Type, @@ -23,8 +23,8 @@ fn round_pointer_up_to_alignment( bx.inttoptr(ptr_as_int, ptr_ty) } -fn emit_direct_ptr_va_arg( - bx: &mut Builder<'a, 'll, 'tcx>, +fn emit_direct_ptr_va_arg<'ll, 'tcx>( + bx: &mut Builder<'_, 'll, 'tcx>, list: OperandRef<'tcx, &'ll Value>, llty: &'ll Type, size: Size, @@ -62,8 +62,8 @@ fn emit_direct_ptr_va_arg( } } -fn emit_ptr_va_arg( - bx: &mut Builder<'a, 'll, 'tcx>, +fn emit_ptr_va_arg<'ll, 'tcx>( + bx: &mut Builder<'_, 'll, 'tcx>, list: OperandRef<'tcx, &'ll Value>, target_ty: Ty<'tcx>, indirect: bool, @@ -90,8 +90,8 @@ fn emit_ptr_va_arg( } } -fn emit_aapcs_va_arg( - bx: &mut Builder<'a, 'll, 'tcx>, +fn emit_aapcs_va_arg<'ll, 'tcx>( + bx: &mut Builder<'_, 'll, 'tcx>, list: OperandRef<'tcx, &'ll Value>, target_ty: Ty<'tcx>, ) -> &'ll Value { @@ -175,8 +175,8 @@ fn emit_aapcs_va_arg( val } -pub(super) fn emit_va_arg( - bx: &mut Builder<'a, 'll, 'tcx>, +pub(super) fn emit_va_arg<'ll, 'tcx>( + bx: &mut Builder<'_, 'll, 'tcx>, addr: OperandRef<'tcx, &'ll Value>, target_ty: Ty<'tcx>, ) -> &'ll Value { diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 83dd625611..5c13dfdc1b 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -14,11 +14,14 @@ tracing = "0.1" libc = "0.2.50" jobserver = "0.1.22" tempfile = "3.2" +thorin-dwp = "0.1.1" pathdiff = "0.2.0" +snap = "1" smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } regex = "1.4" rustc_serialize = { path = "../rustc_serialize" } +rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } rustc_middle = { path = "../rustc_middle" } diff --git a/compiler/rustc_codegen_ssa/src/back/command.rs b/compiler/rustc_codegen_ssa/src/back/command.rs index 503c51d24b..17071ba1b5 100644 --- a/compiler/rustc_codegen_ssa/src/back/command.rs +++ b/compiler/rustc_codegen_ssa/src/back/command.rs @@ -48,7 +48,7 @@ impl Command { } pub fn sym_arg(&mut self, arg: Symbol) -> &mut Command { - self.arg(&*arg.as_str()); + self.arg(arg.as_str()); self } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 638b2a7b5a..f7fe194d20 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1,11 +1,13 @@ +use rustc_arena::TypedArena; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; +use rustc_data_structures::memmap::Mmap; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_errors::{ErrorReported, Handler}; use rustc_fs_util::fix_windows_verbatim_for_gcc; use rustc_hir::def_id::CrateNum; use rustc_middle::middle::dependency_format::Linkage; use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip}; -use rustc_session::config::{OutputFilenames, OutputType, PrintRequest}; +use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SplitDwarfKind}; use rustc_session::cstore::DllImport; use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename}; use rustc_session::search_paths::PathKind; @@ -14,7 +16,6 @@ use rustc_session::utils::NativeLibKind; /// need out of the shared crate context before we get rid of it. use rustc_session::{filesearch, Session}; use rustc_span::symbol::Symbol; -use rustc_target::abi::Endian; use rustc_target::spec::crt_objects::{CrtObjects, CrtObjectsFallback}; use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor, SplitDebuginfo}; use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Target}; @@ -22,6 +23,7 @@ use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Ta use super::archive::{find_library, ArchiveBuilder}; use super::command::Command; use super::linker::{self, Linker}; +use super::metadata::create_rmeta_file; use super::rpath::{self, RPathConfig}; use crate::{ looks_like_rust_object_file, CodegenResults, CompiledModule, CrateInfo, NativeLib, @@ -29,13 +31,13 @@ use crate::{ }; use cc::windows_registry; -use object::elf; -use object::write::Object; -use object::{Architecture, BinaryFormat, Endianness, FileFlags, SectionFlags, SectionKind}; use regex::Regex; use tempfile::Builder as TempFileBuilder; +use std::borrow::Borrow; use std::ffi::OsString; +use std::fs::{File, OpenOptions}; +use std::io::{BufWriter, Write}; use std::lazy::OnceCell; use std::path::{Path, PathBuf}; use std::process::{ExitStatus, Output, Stdio}; @@ -91,7 +93,7 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( sess, crate_type, outputs, - &codegen_results.crate_info.local_crate_name.as_str(), + codegen_results.crate_info.local_crate_name.as_str(), ); match crate_type { CrateType::Rlib => { @@ -137,31 +139,47 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( } } - // Remove the temporary object file and metadata if we aren't saving temps + // Remove the temporary object file and metadata if we aren't saving temps. sess.time("link_binary_remove_temps", || { - if !sess.opts.cg.save_temps { - let remove_temps_from_module = |module: &CompiledModule| { - if let Some(ref obj) = module.object { - ensure_removed(sess.diagnostic(), obj); - } + // If the user requests that temporaries are saved, don't delete any. + if sess.opts.cg.save_temps { + return; + } + let remove_temps_from_module = |module: &CompiledModule| { + if let Some(ref obj) = module.object { + ensure_removed(sess.diagnostic(), obj); + } + }; + + // Otherwise, always remove the metadata and allocator module temporaries. + if let Some(ref metadata_module) = codegen_results.metadata_module { + remove_temps_from_module(metadata_module); + } + + if let Some(ref allocator_module) = codegen_results.allocator_module { + remove_temps_from_module(allocator_module); + } + + // If no requested outputs require linking, then the object temporaries should + // be kept. + if !sess.opts.output_types.should_link() { + return; + } + + // Potentially keep objects for their debuginfo. + let (preserve_objects, preserve_dwarf_objects) = preserve_objects_for_their_debuginfo(sess); + debug!(?preserve_objects, ?preserve_dwarf_objects); + + for module in &codegen_results.modules { + if !preserve_objects { + remove_temps_from_module(module); + } + + if !preserve_dwarf_objects { if let Some(ref obj) = module.dwarf_object { ensure_removed(sess.diagnostic(), obj); } - }; - - if sess.opts.output_types.should_link() && !preserve_objects_for_their_debuginfo(sess) { - for module in &codegen_results.modules { - remove_temps_from_module(module); - } - } - - if let Some(ref metadata_module) = codegen_results.metadata_module { - remove_temps_from_module(metadata_module); - } - - if let Some(ref allocator_module) = codegen_results.allocator_module { - remove_temps_from_module(allocator_module); } } }); @@ -248,8 +266,14 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( let mut ab = ::new(sess, out_filename, None); - for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) { - ab.add_file(obj); + for m in &codegen_results.modules { + if let Some(obj) = m.object.as_ref() { + ab.add_file(obj); + } + + if let Some(dwarf_obj) = m.dwarf_object.as_ref() { + ab.add_file(dwarf_obj); + } } // Note that in this loop we are ignoring the value of `lib.cfg`. That is, @@ -339,7 +363,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( // metadata in rlib files is wrapped in a "dummy" object file for // the target platform so the rlib can be processed entirely by // normal linkers for the platform. - let metadata = create_metadata_file(sess, codegen_results.metadata.raw_data()); + let metadata = create_rmeta_file(sess, codegen_results.metadata.raw_data()); ab.add_file(&emit_metadata(sess, &metadata, tmpdir)); // After adding all files to the archive, we need to update the @@ -358,136 +382,6 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( } } return Ok(ab); - - // For rlibs we "pack" rustc metadata into a dummy object file. When rustc - // creates a dylib crate type it will pass `--whole-archive` (or the - // platform equivalent) to include all object files from an rlib into the - // final dylib itself. This causes linkers to iterate and try to include all - // files located in an archive, so if metadata is stored in an archive then - // it needs to be of a form that the linker will be able to process. - // - // Note, though, that we don't actually want this metadata to show up in any - // final output of the compiler. Instead this is purely for rustc's own - // metadata tracking purposes. - // - // With the above in mind, each "flavor" of object format gets special - // handling here depending on the target: - // - // * MachO - macos-like targets will insert the metadata into a section that - // is sort of fake dwarf debug info. Inspecting the source of the macos - // linker this causes these sections to be skipped automatically because - // it's not in an allowlist of otherwise well known dwarf section names to - // go into the final artifact. - // - // * WebAssembly - we actually don't have any container format for this - // target. WebAssembly doesn't support the `dylib` crate type anyway so - // there's no need for us to support this at this time. Consequently the - // metadata bytes are simply stored as-is into an rlib. - // - // * COFF - Windows-like targets create an object with a section that has - // the `IMAGE_SCN_LNK_REMOVE` flag set which ensures that if the linker - // ever sees the section it doesn't process it and it's removed. - // - // * ELF - All other targets are similar to Windows in that there's a - // `SHF_EXCLUDE` flag we can set on sections in an object file to get - // automatically removed from the final output. - // - // Note that this metdata format is kept in sync with - // `rustc_codegen_ssa/src/back/metadata.rs`. - fn create_metadata_file(sess: &Session, metadata: &[u8]) -> Vec { - let endianness = match sess.target.options.endian { - Endian::Little => Endianness::Little, - Endian::Big => Endianness::Big, - }; - let architecture = match &sess.target.arch[..] { - "arm" => Architecture::Arm, - "aarch64" => Architecture::Aarch64, - "x86" => Architecture::I386, - "s390x" => Architecture::S390x, - "mips" => Architecture::Mips, - "mips64" => Architecture::Mips64, - "x86_64" => { - if sess.target.pointer_width == 32 { - Architecture::X86_64_X32 - } else { - Architecture::X86_64 - } - } - "powerpc" => Architecture::PowerPc, - "powerpc64" => Architecture::PowerPc64, - "riscv32" => Architecture::Riscv32, - "riscv64" => Architecture::Riscv64, - "sparc64" => Architecture::Sparc64, - - // This is used to handle all "other" targets. This includes targets - // in two categories: - // - // * Some targets don't have support in the `object` crate just yet - // to write an object file. These targets are likely to get filled - // out over time. - // - // * Targets like WebAssembly don't support dylibs, so the purpose - // of putting metadata in object files, to support linking rlibs - // into dylibs, is moot. - // - // In both of these cases it means that linking into dylibs will - // not be supported by rustc. This doesn't matter for targets like - // WebAssembly and for targets not supported by the `object` crate - // yet it means that work will need to be done in the `object` crate - // to add a case above. - _ => return metadata.to_vec(), - }; - - if sess.target.is_like_osx { - let mut file = Object::new(BinaryFormat::MachO, architecture, endianness); - - let section = - file.add_section(b"__DWARF".to_vec(), b".rmeta".to_vec(), SectionKind::Debug); - file.append_section_data(section, metadata, 1); - file.write().unwrap() - } else if sess.target.is_like_windows { - const IMAGE_SCN_LNK_REMOVE: u32 = 0; - let mut file = Object::new(BinaryFormat::Coff, architecture, endianness); - - let section = file.add_section(Vec::new(), b".rmeta".to_vec(), SectionKind::Debug); - file.section_mut(section).flags = - SectionFlags::Coff { characteristics: IMAGE_SCN_LNK_REMOVE }; - file.append_section_data(section, metadata, 1); - file.write().unwrap() - } else { - const SHF_EXCLUDE: u64 = 0x80000000; - let mut file = Object::new(BinaryFormat::Elf, architecture, endianness); - - match &sess.target.arch[..] { - // copied from `mipsel-linux-gnu-gcc foo.c -c` and - // inspecting the resulting `e_flags` field. - "mips" => { - let e_flags = elf::EF_MIPS_ARCH_32R2 | elf::EF_MIPS_CPIC | elf::EF_MIPS_PIC; - file.flags = FileFlags::Elf { e_flags }; - } - // copied from `mips64el-linux-gnuabi64-gcc foo.c -c` - "mips64" => { - let e_flags = elf::EF_MIPS_ARCH_64R2 | elf::EF_MIPS_CPIC | elf::EF_MIPS_PIC; - file.flags = FileFlags::Elf { e_flags }; - } - - // copied from `riscv64-linux-gnu-gcc foo.c -c`, note though - // that the `+d` target feature represents whether the double - // float abi is enabled. - "riscv64" if sess.target.options.features.contains("+d") => { - let e_flags = elf::EF_RISCV_RVC | elf::EF_RISCV_FLOAT_ABI_DOUBLE; - file.flags = FileFlags::Elf { e_flags }; - } - - _ => {} - } - - let section = file.add_section(Vec::new(), b".rmeta".to_vec(), SectionKind::Debug); - file.section_mut(section).flags = SectionFlags::Elf { sh_flags: SHF_EXCLUDE }; - file.append_section_data(section, metadata, 1); - file.write().unwrap() - } - } } /// Extract all symbols defined in raw-dylib libraries, collated by library name. @@ -635,57 +529,108 @@ fn escape_stdout_stderr_string(s: &[u8]) -> String { }) } -const LLVM_DWP_EXECUTABLE: &'static str = "rust-llvm-dwp"; - -/// Invoke `llvm-dwp` (shipped alongside rustc) to link `dwo` files from Split DWARF into a `dwp` -/// file. -fn link_dwarf_object<'a>(sess: &'a Session, executable_out_filename: &Path) { - info!("preparing dwp to {}.dwp", executable_out_filename.to_str().unwrap()); - +/// Use `thorin` (rust implementation of a dwarf packaging utility) to link DWARF objects into a +/// DWARF package. +fn link_dwarf_object<'a>( + sess: &'a Session, + cg_results: &CodegenResults, + executable_out_filename: &Path, +) { let dwp_out_filename = executable_out_filename.with_extension("dwp"); - let mut cmd = Command::new(LLVM_DWP_EXECUTABLE); - cmd.arg("-e"); - cmd.arg(executable_out_filename); - cmd.arg("-o"); - cmd.arg(&dwp_out_filename); + debug!(?dwp_out_filename, ?executable_out_filename); - let mut new_path = sess.get_tools_search_paths(false); - if let Some(path) = env::var_os("PATH") { - new_path.extend(env::split_paths(&path)); + #[derive(Default)] + struct ThorinSession { + arena_data: TypedArena>, + arena_mmap: TypedArena, + arena_relocations: TypedArena, } - let new_path = env::join_paths(new_path).unwrap(); - cmd.env("PATH", new_path); - info!("{:?}", &cmd); - match sess.time("run_dwp", || cmd.output()) { - Ok(prog) if !prog.status.success() => { - sess.struct_err(&format!( - "linking dwarf objects with `{}` failed: {}", - LLVM_DWP_EXECUTABLE, prog.status - )) - .note(&format!("{:?}", &cmd)) - .note(&escape_stdout_stderr_string(&prog.stdout)) - .note(&escape_stdout_stderr_string(&prog.stderr)) - .emit(); - info!("linker stderr:\n{}", escape_stdout_stderr_string(&prog.stderr)); - info!("linker stdout:\n{}", escape_stdout_stderr_string(&prog.stdout)); + impl ThorinSession { + fn alloc_mmap<'arena>(&'arena self, data: Mmap) -> &'arena Mmap { + (*self.arena_mmap.alloc(data)).borrow() } - Ok(_) => {} - Err(e) => { - let dwp_not_found = e.kind() == io::ErrorKind::NotFound; - let mut err = if dwp_not_found { - sess.struct_err(&format!("linker `{}` not found", LLVM_DWP_EXECUTABLE)) - } else { - sess.struct_err(&format!("could not exec the linker `{}`", LLVM_DWP_EXECUTABLE)) - }; + } - err.note(&e.to_string()); + impl thorin::Session for ThorinSession { + fn alloc_data<'arena>(&'arena self, data: Vec) -> &'arena [u8] { + (*self.arena_data.alloc(data)).borrow() + } - if !dwp_not_found { - err.note(&format!("{:?}", &cmd)); + fn alloc_relocation<'arena>(&'arena self, data: Relocations) -> &'arena Relocations { + (*self.arena_relocations.alloc(data)).borrow() + } + + fn read_input<'arena>(&'arena self, path: &Path) -> std::io::Result<&'arena [u8]> { + let file = File::open(&path)?; + let mmap = (unsafe { Mmap::map(file) })?; + Ok(self.alloc_mmap(mmap)) + } + } + + match sess.time("run_thorin", || -> Result<(), thorin::Error> { + let thorin_sess = ThorinSession::default(); + let mut package = thorin::DwarfPackage::new(&thorin_sess); + + // Input objs contain .o/.dwo files from the current crate. + match sess.opts.debugging_opts.split_dwarf_kind { + SplitDwarfKind::Single => { + for input_obj in cg_results.modules.iter().filter_map(|m| m.object.as_ref()) { + package.add_input_object(input_obj)?; + } } + SplitDwarfKind::Split => { + for input_obj in cg_results.modules.iter().filter_map(|m| m.dwarf_object.as_ref()) { + package.add_input_object(input_obj)?; + } + } + } - err.emit(); + // Input rlibs contain .o/.dwo files from dependencies. + let input_rlibs = cg_results + .crate_info + .used_crate_source + .values() + .filter_map(|csource| csource.rlib.as_ref()) + .map(|(path, _)| path); + for input_rlib in input_rlibs { + debug!(?input_rlib); + package.add_input_object(input_rlib)?; + } + + // Failing to read the referenced objects is expected for dependencies where the path in the + // executable will have been cleaned by Cargo, but the referenced objects will be contained + // within rlibs provided as inputs. + // + // If paths have been remapped, then .o/.dwo files from the current crate also won't be + // found, but are provided explicitly above. + // + // Adding an executable is primarily done to make `thorin` check that all the referenced + // dwarf objects are found in the end. + package.add_executable( + &executable_out_filename, + thorin::MissingReferencedObjectBehaviour::Skip, + )?; + + let output = package.finish()?.write()?; + let mut output_stream = BufWriter::new( + OpenOptions::new() + .read(true) + .write(true) + .create(true) + .truncate(true) + .open(dwp_out_filename)?, + ); + output_stream.write_all(&output)?; + output_stream.flush()?; + + Ok(()) + }) { + Ok(()) => {} + Err(e) => { + sess.struct_err("linking dwarf objects with thorin failed") + .note(&format!("{:?}", e)) + .emit(); } } } @@ -1031,7 +976,11 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( SplitDebuginfo::Packed if sess.target.is_like_msvc => {} // ... and otherwise we're processing a `*.dwp` packed dwarf file. - SplitDebuginfo::Packed => link_dwarf_object(sess, &out_filename), + // + // We cannot rely on the .o paths in the exectuable because they may have been + // remapped by --remap-path-prefix and therefore invalid, so we need to provide + // the .o/.dwo paths explicitly. + SplitDebuginfo::Packed => link_dwarf_object(sess, codegen_results, out_filename), } let strip = strip_value(sess); @@ -1262,26 +1211,36 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { bug!("Not enough information provided to determine how to invoke the linker"); } -/// Returns a boolean indicating whether we should preserve the object files on -/// the filesystem for their debug information. This is often useful with -/// split-dwarf like schemes. -fn preserve_objects_for_their_debuginfo(sess: &Session) -> bool { +/// Returns a pair of boolean indicating whether we should preserve the object and +/// dwarf object files on the filesystem for their debug information. This is often +/// useful with split-dwarf like schemes. +fn preserve_objects_for_their_debuginfo(sess: &Session) -> (bool, bool) { // If the objects don't have debuginfo there's nothing to preserve. if sess.opts.debuginfo == config::DebugInfo::None { - return false; + return (false, false); } // If we're only producing artifacts that are archives, no need to preserve // the objects as they're losslessly contained inside the archives. - let output_linked = - sess.crate_types().iter().any(|&x| x != CrateType::Rlib && x != CrateType::Staticlib); - if !output_linked { - return false; + if sess.crate_types().iter().all(|&x| x.is_archive()) { + return (false, false); } - // "unpacked" split debuginfo means that we leave object files as the - // debuginfo is found in the original object files themselves - sess.split_debuginfo() == SplitDebuginfo::Unpacked + match (sess.split_debuginfo(), sess.opts.debugging_opts.split_dwarf_kind) { + // If there is no split debuginfo then do not preserve objects. + (SplitDebuginfo::Off, _) => (false, false), + // If there is packed split debuginfo, then the debuginfo in the objects + // has been packaged and the objects can be deleted. + (SplitDebuginfo::Packed, _) => (false, false), + // If there is unpacked split debuginfo and the current target can not use + // split dwarf, then keep objects. + (SplitDebuginfo::Unpacked, _) if !sess.target_can_use_split_dwarf() => (true, false), + // If there is unpacked split debuginfo and the target can use split dwarf, then + // keep the object containing that debuginfo (whether that is an object file or + // dwarf object file depends on the split dwarf kind). + (SplitDebuginfo::Unpacked, SplitDwarfKind::Single) => (true, false), + (SplitDebuginfo::Unpacked, SplitDwarfKind::Split) => (false, true), + } } fn archive_search_paths(sess: &Session) -> Vec { @@ -2359,8 +2318,8 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( continue; } - let canonical = f.replace("-", "_"); - let canonical_name = name.replace("-", "_"); + let canonical = f.replace('-', "_"); + let canonical_name = name.replace('-', "_"); let is_rust_object = canonical.starts_with(&canonical_name) && looks_like_rust_object_file(&f); diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index ffeb926e64..79c24f0f17 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -1,14 +1,25 @@ //! Reading of the rustc metadata for rlibs and dylibs use std::fs::File; +use std::io::Write; use std::path::Path; -use object::{Object, ObjectSection}; +use object::write::{self, StandardSegment, Symbol, SymbolSection}; +use object::{ + elf, pe, Architecture, BinaryFormat, Endianness, FileFlags, Object, ObjectSection, + SectionFlags, SectionKind, SymbolFlags, SymbolKind, SymbolScope, +}; + +use snap::write::FrameEncoder; + use rustc_data_structures::memmap::Mmap; use rustc_data_structures::owning_ref::OwningRef; use rustc_data_structures::rustc_erase_owner; use rustc_data_structures::sync::MetadataRef; +use rustc_metadata::EncodedMetadata; use rustc_session::cstore::MetadataLoader; +use rustc_session::Session; +use rustc_target::abi::Endian; use rustc_target::spec::Target; use crate::METADATA_FILENAME; @@ -83,3 +94,193 @@ fn search_for_metadata<'a>( .data() .map_err(|e| format!("failed to read {} section in '{}': {}", section, path.display(), e)) } + +fn create_object_file(sess: &Session) -> Option { + let endianness = match sess.target.options.endian { + Endian::Little => Endianness::Little, + Endian::Big => Endianness::Big, + }; + let architecture = match &sess.target.arch[..] { + "arm" => Architecture::Arm, + "aarch64" => Architecture::Aarch64, + "x86" => Architecture::I386, + "s390x" => Architecture::S390x, + "mips" => Architecture::Mips, + "mips64" => Architecture::Mips64, + "x86_64" => { + if sess.target.pointer_width == 32 { + Architecture::X86_64_X32 + } else { + Architecture::X86_64 + } + } + "powerpc" => Architecture::PowerPc, + "powerpc64" => Architecture::PowerPc64, + "riscv32" => Architecture::Riscv32, + "riscv64" => Architecture::Riscv64, + "sparc64" => Architecture::Sparc64, + // Unsupported architecture. + _ => return None, + }; + let binary_format = if sess.target.is_like_osx { + BinaryFormat::MachO + } else if sess.target.is_like_windows { + BinaryFormat::Coff + } else { + BinaryFormat::Elf + }; + + let mut file = write::Object::new(binary_format, architecture, endianness); + match architecture { + Architecture::Mips => { + // copied from `mipsel-linux-gnu-gcc foo.c -c` and + // inspecting the resulting `e_flags` field. + let e_flags = elf::EF_MIPS_ARCH_32R2 | elf::EF_MIPS_CPIC | elf::EF_MIPS_PIC; + file.flags = FileFlags::Elf { e_flags }; + } + Architecture::Mips64 => { + // copied from `mips64el-linux-gnuabi64-gcc foo.c -c` + let e_flags = elf::EF_MIPS_ARCH_64R2 | elf::EF_MIPS_CPIC | elf::EF_MIPS_PIC; + file.flags = FileFlags::Elf { e_flags }; + } + Architecture::Riscv64 if sess.target.options.features.contains("+d") => { + // copied from `riscv64-linux-gnu-gcc foo.c -c`, note though + // that the `+d` target feature represents whether the double + // float abi is enabled. + let e_flags = elf::EF_RISCV_RVC | elf::EF_RISCV_FLOAT_ABI_DOUBLE; + file.flags = FileFlags::Elf { e_flags }; + } + _ => {} + }; + Some(file) +} + +// For rlibs we "pack" rustc metadata into a dummy object file. When rustc +// creates a dylib crate type it will pass `--whole-archive` (or the +// platform equivalent) to include all object files from an rlib into the +// final dylib itself. This causes linkers to iterate and try to include all +// files located in an archive, so if metadata is stored in an archive then +// it needs to be of a form that the linker will be able to process. +// +// Note, though, that we don't actually want this metadata to show up in any +// final output of the compiler. Instead this is purely for rustc's own +// metadata tracking purposes. +// +// With the above in mind, each "flavor" of object format gets special +// handling here depending on the target: +// +// * MachO - macos-like targets will insert the metadata into a section that +// is sort of fake dwarf debug info. Inspecting the source of the macos +// linker this causes these sections to be skipped automatically because +// it's not in an allowlist of otherwise well known dwarf section names to +// go into the final artifact. +// +// * WebAssembly - we actually don't have any container format for this +// target. WebAssembly doesn't support the `dylib` crate type anyway so +// there's no need for us to support this at this time. Consequently the +// metadata bytes are simply stored as-is into an rlib. +// +// * COFF - Windows-like targets create an object with a section that has +// the `IMAGE_SCN_LNK_REMOVE` flag set which ensures that if the linker +// ever sees the section it doesn't process it and it's removed. +// +// * ELF - All other targets are similar to Windows in that there's a +// `SHF_EXCLUDE` flag we can set on sections in an object file to get +// automatically removed from the final output. +pub fn create_rmeta_file(sess: &Session, metadata: &[u8]) -> Vec { + let mut file = if let Some(file) = create_object_file(sess) { + file + } else { + // This is used to handle all "other" targets. This includes targets + // in two categories: + // + // * Some targets don't have support in the `object` crate just yet + // to write an object file. These targets are likely to get filled + // out over time. + // + // * Targets like WebAssembly don't support dylibs, so the purpose + // of putting metadata in object files, to support linking rlibs + // into dylibs, is moot. + // + // In both of these cases it means that linking into dylibs will + // not be supported by rustc. This doesn't matter for targets like + // WebAssembly and for targets not supported by the `object` crate + // yet it means that work will need to be done in the `object` crate + // to add a case above. + return metadata.to_vec(); + }; + let section = file.add_section( + file.segment_name(StandardSegment::Debug).to_vec(), + b".rmeta".to_vec(), + SectionKind::Debug, + ); + match file.format() { + BinaryFormat::Coff => { + file.section_mut(section).flags = + SectionFlags::Coff { characteristics: pe::IMAGE_SCN_LNK_REMOVE }; + } + BinaryFormat::Elf => { + file.section_mut(section).flags = + SectionFlags::Elf { sh_flags: elf::SHF_EXCLUDE as u64 }; + } + _ => {} + }; + file.append_section_data(section, metadata, 1); + file.write().unwrap() +} + +// Historical note: +// +// When using link.exe it was seen that the section name `.note.rustc` +// was getting shortened to `.note.ru`, and according to the PE and COFF +// specification: +// +// > Executable images do not use a string table and do not support +// > section names longer than 8 characters +// +// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format +// +// As a result, we choose a slightly shorter name! As to why +// `.note.rustc` works on MinGW, see +// https://github.com/llvm/llvm-project/blob/llvmorg-12.0.0/lld/COFF/Writer.cpp#L1190-L1197 +pub fn create_compressed_metadata_file( + sess: &Session, + metadata: &EncodedMetadata, + symbol_name: &str, +) -> Vec { + let mut compressed = rustc_metadata::METADATA_HEADER.to_vec(); + FrameEncoder::new(&mut compressed).write_all(metadata.raw_data()).unwrap(); + let mut file = if let Some(file) = create_object_file(sess) { + file + } else { + return compressed.to_vec(); + }; + let section = file.add_section( + file.segment_name(StandardSegment::Data).to_vec(), + b".rustc".to_vec(), + SectionKind::ReadOnlyData, + ); + match file.format() { + BinaryFormat::Elf => { + // Explicitly set no flags to avoid SHF_ALLOC default for data section. + file.section_mut(section).flags = SectionFlags::Elf { sh_flags: 0 }; + } + _ => {} + }; + let offset = file.append_section_data(section, &compressed, 1); + + // For MachO and probably PE this is necessary to prevent the linker from throwing away the + // .rustc section. For ELF this isn't necessary, but it also doesn't harm. + file.add_symbol(Symbol { + name: symbol_name.as_bytes().to_vec(), + value: offset, + size: compressed.len() as u64, + kind: SymbolKind::Data, + scope: SymbolScope::Dynamic, + weak: false, + section: SymbolSection::Section(section), + flags: SymbolFlags::None, + }); + + file.write().unwrap() +} diff --git a/compiler/rustc_codegen_ssa/src/back/rpath.rs b/compiler/rustc_codegen_ssa/src/back/rpath.rs index 61c3ef62fb..0b5656c9ad 100644 --- a/compiler/rustc_codegen_ssa/src/back/rpath.rs +++ b/compiler/rustc_codegen_ssa/src/back/rpath.rs @@ -23,9 +23,12 @@ pub fn get_rpath_flags(config: &mut RPathConfig<'_>) -> Vec { let rpaths = get_rpaths(config); let mut flags = rpaths_to_flags(&rpaths); - // Use DT_RUNPATH instead of DT_RPATH if available if config.linker_is_gnu { + // Use DT_RUNPATH instead of DT_RPATH if available flags.push("-Wl,--enable-new-dtags".to_owned()); + + // Set DF_ORIGIN for substitute $ORIGIN + flags.push("-Wl,-z,origin".to_owned()); } flags diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index f80f9965f4..baafa74b13 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -154,7 +154,7 @@ fn is_reachable_non_generic_provider_extern(tcx: TyCtxt<'_>, def_id: DefId) -> b tcx.reachable_non_generics(def_id.krate).contains_key(&def_id) } -fn exported_symbols_provider_local( +fn exported_symbols_provider_local<'tcx>( tcx: TyCtxt<'tcx>, cnum: CrateNum, ) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportLevel)] { diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 85d51ea9a2..bea454458c 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -113,6 +113,7 @@ pub struct ModuleConfig { pub inline_threshold: Option, pub new_llvm_pass_manager: Option, pub emit_lifetime_markers: bool, + pub llvm_plugins: Vec, } impl ModuleConfig { @@ -260,6 +261,7 @@ impl ModuleConfig { inline_threshold: sess.opts.cg.inline_threshold, new_llvm_pass_manager: sess.opts.debugging_opts.new_llvm_pass_manager, emit_lifetime_markers: sess.emit_lifetime_markers(), + llvm_plugins: if_regular!(sess.opts.debugging_opts.llvm_plugins.clone(), vec![]), } } @@ -284,7 +286,11 @@ impl TargetMachineFactoryConfig { module_name: &str, ) -> TargetMachineFactoryConfig { let split_dwarf_file = if cgcx.target_can_use_split_dwarf { - cgcx.output_filenames.split_dwarf_path(cgcx.split_debuginfo, Some(module_name)) + cgcx.output_filenames.split_dwarf_path( + cgcx.split_debuginfo, + cgcx.split_dwarf_kind, + Some(module_name), + ) } else { None }; @@ -327,6 +333,7 @@ pub struct CodegenContext { pub target_arch: String, pub debuginfo: config::DebugInfo, pub split_debuginfo: rustc_target::spec::SplitDebuginfo, + pub split_dwarf_kind: rustc_session::config::SplitDwarfKind, // Number of cgus excluding the allocator/metadata modules pub total_cgus: usize, @@ -397,7 +404,6 @@ fn generate_lto_work( pub struct CompiledModules { pub modules: Vec, - pub metadata_module: Option, pub allocator_module: Option, } @@ -425,6 +431,7 @@ pub fn start_async_codegen( tcx: TyCtxt<'_>, target_cpu: String, metadata: EncodedMetadata, + metadata_module: Option, total_cgus: usize, ) -> OngoingCodegen { let (coordinator_send, coordinator_receive) = channel(); @@ -464,6 +471,7 @@ pub fn start_async_codegen( OngoingCodegen { backend, metadata, + metadata_module, crate_info, coordinator_send, @@ -640,12 +648,6 @@ fn produce_final_output_artifacts( } if !user_wants_bitcode { - if let Some(ref metadata_module) = compiled_modules.metadata_module { - if let Some(ref path) = metadata_module.bytecode { - ensure_removed(sess.diagnostic(), &path); - } - } - if let Some(ref allocator_module) = compiled_modules.allocator_module { if let Some(ref path) = allocator_module.bytecode { ensure_removed(sess.diagnostic(), path); @@ -682,11 +684,11 @@ impl WorkItem { fn start_profiling<'a>(&self, cgcx: &'a CodegenContext) -> TimingGuard<'a> { match *self { WorkItem::Optimize(ref m) => { - cgcx.prof.generic_activity_with_arg("codegen_module_optimize", &m.name[..]) + cgcx.prof.generic_activity_with_arg("codegen_module_optimize", &*m.name) } WorkItem::CopyPostLtoArtifacts(ref m) => cgcx .prof - .generic_activity_with_arg("codegen_copy_artifacts_from_incr_cache", &m.name[..]), + .generic_activity_with_arg("codegen_copy_artifacts_from_incr_cache", &*m.name), WorkItem::LTO(ref m) => { cgcx.prof.generic_activity_with_arg("codegen_module_perform_lto", m.name()) } @@ -1063,6 +1065,7 @@ fn start_executing_work( target_arch: tcx.sess.target.arch.clone(), debuginfo: tcx.sess.opts.debuginfo, split_debuginfo: tcx.sess.split_debuginfo(), + split_dwarf_kind: tcx.sess.opts.debugging_opts.split_dwarf_kind, }; // This is the "main loop" of parallel work happening for parallel codegen. @@ -1216,7 +1219,6 @@ fn start_executing_work( // This is where we collect codegen units that have gone all the way // through codegen and LLVM. let mut compiled_modules = vec![]; - let mut compiled_metadata_module = None; let mut compiled_allocator_module = None; let mut needs_link = Vec::new(); let mut needs_fat_lto = Vec::new(); @@ -1475,14 +1477,11 @@ fn start_executing_work( ModuleKind::Regular => { compiled_modules.push(compiled_module); } - ModuleKind::Metadata => { - assert!(compiled_metadata_module.is_none()); - compiled_metadata_module = Some(compiled_module); - } ModuleKind::Allocator => { assert!(compiled_allocator_module.is_none()); compiled_allocator_module = Some(compiled_module); } + ModuleKind::Metadata => bug!("Should be handled separately"), } } Message::NeedsLink { module, worker_id } => { @@ -1539,7 +1538,6 @@ fn start_executing_work( Ok(CompiledModules { modules: compiled_modules, - metadata_module: compiled_metadata_module, allocator_module: compiled_allocator_module, }) }); @@ -1800,6 +1798,7 @@ impl SharedEmitterMain { pub struct OngoingCodegen { pub backend: B, pub metadata: EncodedMetadata, + pub metadata_module: Option, pub crate_info: CrateInfo, pub coordinator_send: Sender>, pub codegen_worker_receive: Receiver>, @@ -1846,7 +1845,7 @@ impl OngoingCodegen { modules: compiled_modules.modules, allocator_module: compiled_modules.allocator_module, - metadata_module: compiled_modules.metadata_module, + metadata_module: self.metadata_module, }, work_products, ) diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 9bb4982754..49b785afa6 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -1,3 +1,4 @@ +use crate::back::metadata::create_compressed_metadata_file; use crate::back::write::{ compute_per_cgu_lto_type, start_async_codegen, submit_codegened_module_to_llvm, submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm, ComputedLtoType, OngoingCodegen, @@ -8,7 +9,7 @@ use crate::mir; use crate::mir::operand::OperandValue; use crate::mir::place::PlaceRef; use crate::traits::*; -use crate::{CachedModuleCodegen, CrateInfo, MemFlags, ModuleCodegen, ModuleKind}; +use crate::{CachedModuleCodegen, CompiledModule, CrateInfo, MemFlags, ModuleCodegen, ModuleKind}; use rustc_attr as attr; use rustc_data_structures::fx::FxHashMap; @@ -20,13 +21,14 @@ use rustc_hir::lang_items::LangItem; use rustc_index::vec::Idx; use rustc_metadata::EncodedMetadata; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; +use rustc_middle::middle::exported_symbols; use rustc_middle::middle::lang_items; use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_session::cgu_reuse_tracker::CguReuse; -use rustc_session::config::{self, EntryFnType}; +use rustc_session::config::{self, EntryFnType, OutputType}; use rustc_session::Session; use rustc_span::symbol::sym; use rustc_target::abi::{Align, VariantIdx}; @@ -484,14 +486,14 @@ fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( pub fn codegen_crate( backend: B, - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, target_cpu: String, metadata: EncodedMetadata, need_metadata_module: bool, ) -> OngoingCodegen { // Skip crate items and just output metadata in -Z no-codegen mode. if tcx.sess.opts.debugging_opts.no_codegen || !tcx.sess.opts.output_types.should_codegen() { - let ongoing_codegen = start_async_codegen(backend, tcx, target_cpu, metadata, 1); + let ongoing_codegen = start_async_codegen(backend, tcx, target_cpu, metadata, None, 1); ongoing_codegen.codegen_finished(tcx); @@ -517,8 +519,41 @@ pub fn codegen_crate( } } - let ongoing_codegen = - start_async_codegen(backend.clone(), tcx, target_cpu, metadata, codegen_units.len()); + let metadata_module = if need_metadata_module { + // Emit compressed metadata object. + let metadata_cgu_name = + cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("metadata")).to_string(); + tcx.sess.time("write_compressed_metadata", || { + let file_name = + tcx.output_filenames(()).temp_path(OutputType::Metadata, Some(&metadata_cgu_name)); + let data = create_compressed_metadata_file( + tcx.sess, + &metadata, + &exported_symbols::metadata_symbol_name(tcx), + ); + if let Err(err) = std::fs::write(&file_name, data) { + tcx.sess.fatal(&format!("error writing metadata object file: {}", err)); + } + Some(CompiledModule { + name: metadata_cgu_name, + kind: ModuleKind::Metadata, + object: Some(file_name), + dwarf_object: None, + bytecode: None, + }) + }) + } else { + None + }; + + let ongoing_codegen = start_async_codegen( + backend.clone(), + tcx, + target_cpu, + metadata, + metadata_module, + codegen_units.len(), + ); let ongoing_codegen = AbortCodegenOnDrop::(Some(ongoing_codegen)); // Codegen an allocator shim, if necessary. @@ -558,27 +593,6 @@ pub fn codegen_crate( ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, allocator_module); } - if need_metadata_module { - // Codegen the encoded metadata. - let metadata_cgu_name = - cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("metadata")).to_string(); - let mut metadata_llvm_module = backend.new_metadata(tcx, &metadata_cgu_name); - tcx.sess.time("write_compressed_metadata", || { - backend.write_compressed_metadata( - tcx, - &ongoing_codegen.metadata, - &mut metadata_llvm_module, - ); - }); - - let metadata_module = ModuleCodegen { - name: metadata_cgu_name, - module_llvm: metadata_llvm_module, - kind: ModuleKind::Metadata, - }; - ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, metadata_module); - } - // For better throughput during parallel processing by LLVM, we used to sort // CGUs largest to smallest. This would lead to better thread utilization // by, for example, preventing a large CGU from being processed last and @@ -658,7 +672,7 @@ pub fn codegen_crate( } let cgu_reuse = cgu_reuse[i]; - tcx.sess.cgu_reuse_tracker.set_actual_reuse(&cgu.name().as_str(), cgu_reuse); + tcx.sess.cgu_reuse_tracker.set_actual_reuse(cgu.name().as_str(), cgu_reuse); match cgu_reuse { CguReuse::No => { diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs index 1fa60612d2..2df58ecc9f 100644 --- a/compiler/rustc_codegen_ssa/src/common.rs +++ b/compiler/rustc_codegen_ssa/src/common.rs @@ -122,8 +122,8 @@ pub fn langcall(tcx: TyCtxt<'_>, span: Option, msg: &str, li: LangItem) -> tcx.lang_items().require(li).unwrap_or_else(|s| { let msg = format!("{} {}", msg, s); match span { - Some(span) => tcx.sess.span_fatal(span, &msg[..]), - None => tcx.sess.fatal(&msg[..]), + Some(span) => tcx.sess.span_fatal(span, &msg), + None => tcx.sess.fatal(&msg), } }) } diff --git a/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs index 962c01c2ee..e288760a02 100644 --- a/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs @@ -1,6 +1,6 @@ use rustc_middle::mir::coverage::{CounterValueReference, MappedExpressionIndex}; -/// Aligns with [llvm::coverage::Counter::CounterKind](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L206-L222) +/// Aligns with [llvm::coverage::Counter::CounterKind](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L95) #[derive(Copy, Clone, Debug)] #[repr(C)] pub enum CounterKind { @@ -17,7 +17,7 @@ pub enum CounterKind { /// `instrprof.increment()`) /// * For `CounterKind::Expression`, `id` is the index into the coverage map's array of /// counter expressions. -/// Aligns with [llvm::coverage::Counter](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L99-L100) +/// Aligns with [llvm::coverage::Counter](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L102-L103) /// Important: The Rust struct layout (order and types of fields) must match its C++ counterpart. #[derive(Copy, Clone, Debug)] #[repr(C)] @@ -59,7 +59,7 @@ impl Counter { } } -/// Aligns with [llvm::coverage::CounterExpression::ExprKind](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L147) +/// Aligns with [llvm::coverage::CounterExpression::ExprKind](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L150) #[derive(Copy, Clone, Debug)] #[repr(C)] pub enum ExprKind { @@ -67,7 +67,7 @@ pub enum ExprKind { Add = 1, } -/// Aligns with [llvm::coverage::CounterExpression](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L148-L149) +/// Aligns with [llvm::coverage::CounterExpression](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L151-L152) /// Important: The Rust struct layout (order and types of fields) must match its C++ /// counterpart. #[derive(Copy, Clone, Debug)] diff --git a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs b/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs index c1dfe1ef85..1a6495cb15 100644 --- a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs +++ b/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs @@ -150,9 +150,9 @@ impl<'tcx> FunctionCoverage<'tcx> { /// Generate an array of CounterExpressions, and an iterator over all `Counter`s and their /// associated `Regions` (from which the LLVM-specific `CoverageMapGenerator` will create /// `CounterMappingRegion`s. - pub fn get_expressions_and_counter_regions<'a>( - &'a self, - ) -> (Vec, impl Iterator) { + pub fn get_expressions_and_counter_regions( + &self, + ) -> (Vec, impl Iterator) { assert!( self.source_hash != 0 || !self.is_used, "No counters provided the source_hash for used function: {:?}", @@ -168,7 +168,7 @@ impl<'tcx> FunctionCoverage<'tcx> { (counter_expressions, counter_regions) } - fn counter_regions<'a>(&'a self) -> impl Iterator { + fn counter_regions(&self) -> impl Iterator { self.counters.iter_enumerated().filter_map(|(index, entry)| { // Option::map() will return None to filter out missing counters. This may happen // if, for example, a MIR-instrumented counter is removed during an optimization. @@ -177,8 +177,8 @@ impl<'tcx> FunctionCoverage<'tcx> { } fn expressions_with_regions( - &'a self, - ) -> (Vec, impl Iterator) { + &self, + ) -> (Vec, impl Iterator) { let mut counter_expressions = Vec::with_capacity(self.expressions.len()); let mut expression_regions = Vec::with_capacity(self.expressions.len()); let mut new_indexes = IndexVec::from_elem_n(None, self.expressions.len()); @@ -336,7 +336,7 @@ impl<'tcx> FunctionCoverage<'tcx> { (counter_expressions, expression_regions.into_iter()) } - fn unreachable_regions<'a>(&'a self) -> impl Iterator { + fn unreachable_regions(&self) -> impl Iterator { self.unreachable_regions.iter().map(|region| (Counter::zero(), region)) } diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index ab119ae25f..93bb1aee25 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -53,14 +53,14 @@ fn push_debuginfo_type_name<'tcx>( ) { // When targeting MSVC, emit C++ style type names for compatibility with // .natvis visualizers (and perhaps other existing native debuggers?) - let cpp_like_names = cpp_like_names(tcx); + let cpp_like_debuginfo = cpp_like_debuginfo(tcx); match *t.kind() { ty::Bool => output.push_str("bool"), ty::Char => output.push_str("char"), ty::Str => output.push_str("str"), ty::Never => { - if cpp_like_names { + if cpp_like_debuginfo { output.push_str("never$"); } else { output.push('!'); @@ -71,7 +71,7 @@ fn push_debuginfo_type_name<'tcx>( ty::Float(float_ty) => output.push_str(float_ty.name_str()), ty::Foreign(def_id) => push_item_name(tcx, def_id, qualified, output), ty::Adt(def, substs) => { - if def.is_enum() && cpp_like_names { + if def.is_enum() && cpp_like_debuginfo { msvc_enum_fallback(tcx, t, def, substs, output, visited); } else { push_item_name(tcx, def.did, qualified, output); @@ -79,7 +79,7 @@ fn push_debuginfo_type_name<'tcx>( } } ty::Tuple(component_types) => { - if cpp_like_names { + if cpp_like_debuginfo { output.push_str("tuple$<"); } else { output.push('('); @@ -87,20 +87,20 @@ fn push_debuginfo_type_name<'tcx>( for component_type in component_types { push_debuginfo_type_name(tcx, component_type.expect_ty(), true, output, visited); - push_arg_separator(cpp_like_names, output); + push_arg_separator(cpp_like_debuginfo, output); } if !component_types.is_empty() { pop_arg_separator(output); } - if cpp_like_names { - push_close_angle_bracket(cpp_like_names, output); + if cpp_like_debuginfo { + push_close_angle_bracket(cpp_like_debuginfo, output); } else { output.push(')'); } } ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl }) => { - if cpp_like_names { + if cpp_like_debuginfo { match mutbl { hir::Mutability::Not => output.push_str("ptr_const$<"), hir::Mutability::Mut => output.push_str("ptr_mut$<"), @@ -115,8 +115,8 @@ fn push_debuginfo_type_name<'tcx>( push_debuginfo_type_name(tcx, inner_type, qualified, output, visited); - if cpp_like_names { - push_close_angle_bracket(cpp_like_names, output); + if cpp_like_debuginfo { + push_close_angle_bracket(cpp_like_debuginfo, output); } } ty::Ref(_, inner_type, mutbl) => { @@ -126,7 +126,7 @@ fn push_debuginfo_type_name<'tcx>( // types out to aid debugging in MSVC. let is_slice_or_str = matches!(*inner_type.kind(), ty::Slice(_) | ty::Str); - if !cpp_like_names { + if !cpp_like_debuginfo { output.push('&'); output.push_str(mutbl.prefix_str()); } else if !is_slice_or_str { @@ -138,12 +138,12 @@ fn push_debuginfo_type_name<'tcx>( push_debuginfo_type_name(tcx, inner_type, qualified, output, visited); - if cpp_like_names && !is_slice_or_str { - push_close_angle_bracket(cpp_like_names, output); + if cpp_like_debuginfo && !is_slice_or_str { + push_close_angle_bracket(cpp_like_debuginfo, output); } } ty::Array(inner_type, len) => { - if cpp_like_names { + if cpp_like_debuginfo { output.push_str("array$<"); push_debuginfo_type_name(tcx, inner_type, true, output, visited); match len.val { @@ -162,7 +162,7 @@ fn push_debuginfo_type_name<'tcx>( } } ty::Slice(inner_type) => { - if cpp_like_names { + if cpp_like_debuginfo { output.push_str("slice$<"); } else { output.push('['); @@ -170,8 +170,8 @@ fn push_debuginfo_type_name<'tcx>( push_debuginfo_type_name(tcx, inner_type, true, output, visited); - if cpp_like_names { - push_close_angle_bracket(cpp_like_names, output); + if cpp_like_debuginfo { + push_close_angle_bracket(cpp_like_debuginfo, output); } else { output.push(']'); } @@ -179,7 +179,7 @@ fn push_debuginfo_type_name<'tcx>( ty::Dynamic(ref trait_data, ..) => { let auto_traits: SmallVec<[DefId; 4]> = trait_data.auto_traits().collect(); - let has_enclosing_parens = if cpp_like_names { + let has_enclosing_parens = if cpp_like_debuginfo { output.push_str("dyn$<"); false } else { @@ -216,14 +216,14 @@ fn push_debuginfo_type_name<'tcx>( } for (item_def_id, ty) in projection_bounds { - push_arg_separator(cpp_like_names, output); + push_arg_separator(cpp_like_debuginfo, output); - if cpp_like_names { + if cpp_like_debuginfo { output.push_str("assoc$<"); push_item_name(tcx, item_def_id, false, output); - push_arg_separator(cpp_like_names, output); + push_arg_separator(cpp_like_debuginfo, output); push_debuginfo_type_name(tcx, ty, true, output, visited); - push_close_angle_bracket(cpp_like_names, output); + push_close_angle_bracket(cpp_like_debuginfo, output); } else { push_item_name(tcx, item_def_id, false, output); output.push('='); @@ -231,11 +231,11 @@ fn push_debuginfo_type_name<'tcx>( } } - push_close_angle_bracket(cpp_like_names, output); + push_close_angle_bracket(cpp_like_debuginfo, output); } if auto_traits.len() != 0 { - push_auto_trait_separator(cpp_like_names, output); + push_auto_trait_separator(cpp_like_debuginfo, output); } } @@ -252,14 +252,14 @@ fn push_debuginfo_type_name<'tcx>( for auto_trait in auto_traits { output.push_str(&auto_trait); - push_auto_trait_separator(cpp_like_names, output); + push_auto_trait_separator(cpp_like_debuginfo, output); } pop_auto_trait_separator(output); } - if cpp_like_names { - push_close_angle_bracket(cpp_like_names, output); + if cpp_like_debuginfo { + push_close_angle_bracket(cpp_like_debuginfo, output); } else if has_enclosing_parens { output.push(')'); } @@ -279,7 +279,7 @@ fn push_debuginfo_type_name<'tcx>( // use a dummy string that should make it clear // that something unusual is going on if !visited.insert(t) { - output.push_str(if cpp_like_names { + output.push_str(if cpp_like_debuginfo { "recursive_type$" } else { "" @@ -290,7 +290,7 @@ fn push_debuginfo_type_name<'tcx>( let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), t.fn_sig(tcx)); - if cpp_like_names { + if cpp_like_debuginfo { // Format as a C++ function pointer: return_type (*)(params...) if sig.output().is_unit() { output.push_str("void"); @@ -313,7 +313,7 @@ fn push_debuginfo_type_name<'tcx>( if !sig.inputs().is_empty() { for ¶meter_type in sig.inputs() { push_debuginfo_type_name(tcx, parameter_type, true, output, visited); - push_arg_separator(cpp_like_names, output); + push_arg_separator(cpp_like_debuginfo, output); } pop_arg_separator(output); } @@ -328,7 +328,7 @@ fn push_debuginfo_type_name<'tcx>( output.push(')'); - if !cpp_like_names && !sig.output().is_unit() { + if !cpp_like_debuginfo && !sig.output().is_unit() { output.push_str(" -> "); push_debuginfo_type_name(tcx, sig.output(), true, output, visited); } @@ -376,7 +376,7 @@ fn push_debuginfo_type_name<'tcx>( // format (natvis) is able to understand enums and render the active variant correctly in the // debugger. For more information, look in `src/etc/natvis/intrinsic.natvis` and // `EnumMemberDescriptionFactor::create_member_descriptions`. - fn msvc_enum_fallback( + fn msvc_enum_fallback<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, def: &AdtDef, @@ -426,9 +426,9 @@ fn push_debuginfo_type_name<'tcx>( const NON_CPP_AUTO_TRAIT_SEPARATOR: &str = " + "; - fn push_auto_trait_separator(cpp_like_names: bool, output: &mut String) { - if cpp_like_names { - push_arg_separator(cpp_like_names, output); + fn push_auto_trait_separator(cpp_like_debuginfo: bool, output: &mut String) { + if cpp_like_debuginfo { + push_arg_separator(cpp_like_debuginfo, output); } else { output.push_str(NON_CPP_AUTO_TRAIT_SEPARATOR); } @@ -457,11 +457,11 @@ pub fn compute_debuginfo_vtable_name<'tcx>( t: Ty<'tcx>, trait_ref: Option>, ) -> String { - let cpp_like_names = cpp_like_names(tcx); + let cpp_like_debuginfo = cpp_like_debuginfo(tcx); let mut vtable_name = String::with_capacity(64); - if cpp_like_names { + if cpp_like_debuginfo { vtable_name.push_str("impl$<"); } else { vtable_name.push('<'); @@ -470,7 +470,7 @@ pub fn compute_debuginfo_vtable_name<'tcx>( let mut visited = FxHashSet::default(); push_debuginfo_type_name(tcx, t, true, &mut vtable_name, &mut visited); - if cpp_like_names { + if cpp_like_debuginfo { vtable_name.push_str(", "); } else { vtable_name.push_str(" as "); @@ -486,9 +486,9 @@ pub fn compute_debuginfo_vtable_name<'tcx>( vtable_name.push_str("_"); } - push_close_angle_bracket(cpp_like_names, &mut vtable_name); + push_close_angle_bracket(cpp_like_debuginfo, &mut vtable_name); - let suffix = if cpp_like_names { "::vtable$" } else { "::{vtable}" }; + let suffix = if cpp_like_debuginfo { "::vtable$" } else { "::{vtable}" }; vtable_name.reserve_exact(suffix.len()); vtable_name.push_str(suffix); @@ -496,7 +496,7 @@ pub fn compute_debuginfo_vtable_name<'tcx>( vtable_name } -pub fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: &mut String) { +pub fn push_item_name(tcx: TyCtxt<'_>, def_id: DefId, qualified: bool, output: &mut String) { let def_key = tcx.def_key(def_id); if qualified { if let Some(parent) = def_key.parent { @@ -509,19 +509,19 @@ pub fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: } fn push_unqualified_item_name( - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, def_id: DefId, disambiguated_data: DisambiguatedDefPathData, output: &mut String, ) { match disambiguated_data.data { DefPathData::CrateRoot => { - output.push_str(&tcx.crate_name(def_id.krate).as_str()); + output.push_str(tcx.crate_name(def_id.krate).as_str()); } DefPathData::ClosureExpr if tcx.generator_kind(def_id).is_some() => { // Generators look like closures, but we want to treat them differently // in the debug info. - if cpp_like_names(tcx) { + if cpp_like_debuginfo(tcx) { write!(output, "generator${}", disambiguated_data.disambiguator).unwrap(); } else { write!(output, "{{generator#{}}}", disambiguated_data.disambiguator).unwrap(); @@ -529,10 +529,10 @@ fn push_unqualified_item_name( } _ => match disambiguated_data.data.name() { DefPathDataName::Named(name) => { - output.push_str(&name.as_str()); + output.push_str(name.as_str()); } DefPathDataName::Anon { namespace } => { - if cpp_like_names(tcx) { + if cpp_like_debuginfo(tcx) { write!(output, "{}${}", namespace, disambiguated_data.disambiguator).unwrap(); } else { write!(output, "{{{}#{}}}", namespace, disambiguated_data.disambiguator) @@ -560,7 +560,7 @@ fn push_generic_params_internal<'tcx>( debug_assert_eq!(substs, tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substs)); - let cpp_like_names = cpp_like_names(tcx); + let cpp_like_debuginfo = cpp_like_debuginfo(tcx); output.push('<'); @@ -575,10 +575,10 @@ fn push_generic_params_internal<'tcx>( other => bug!("Unexpected non-erasable generic: {:?}", other), } - push_arg_separator(cpp_like_names, output); + push_arg_separator(cpp_like_debuginfo, output); } pop_arg_separator(output); - push_close_angle_bracket(cpp_like_names, output); + push_close_angle_bracket(cpp_like_debuginfo, output); true } @@ -617,7 +617,7 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: &'tcx ty::Const<'tcx>, output: // avoiding collisions and will make the emitted type names shorter. let hash: u64 = hasher.finish(); - if cpp_like_names(tcx) { + if cpp_like_debuginfo(tcx) { write!(output, "CONST${:x}", hash) } else { write!(output, "{{CONST#{:x}}}", hash) @@ -634,10 +634,10 @@ pub fn push_generic_params<'tcx>(tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, out push_generic_params_internal(tcx, substs, output, &mut visited); } -fn push_close_angle_bracket(cpp_like_names: bool, output: &mut String) { +fn push_close_angle_bracket(cpp_like_debuginfo: bool, output: &mut String) { // MSVC debugger always treats `>>` as a shift, even when parsing templates, // so add a space to avoid confusion. - if cpp_like_names && output.ends_with('>') { + if cpp_like_debuginfo && output.ends_with('>') { output.push(' ') }; @@ -652,11 +652,11 @@ fn pop_close_angle_bracket(output: &mut String) { } } -fn push_arg_separator(cpp_like_names: bool, output: &mut String) { +fn push_arg_separator(cpp_like_debuginfo: bool, output: &mut String) { // Natvis does not always like having spaces between parts of the type name // and this causes issues when we need to write a typename in natvis, for example // as part of a cast like the `HashMap` visualizer does. - if cpp_like_names { + if cpp_like_debuginfo { output.push(','); } else { output.push_str(", "); @@ -673,6 +673,7 @@ fn pop_arg_separator(output: &mut String) { output.pop(); } -fn cpp_like_names(tcx: TyCtxt<'_>) -> bool { +/// Check if we should generate C++ like names and debug information. +pub fn cpp_like_debuginfo(tcx: TyCtxt<'_>) -> bool { tcx.sess.target.is_like_msvc } diff --git a/compiler/rustc_codegen_ssa/src/glue.rs b/compiler/rustc_codegen_ssa/src/glue.rs index cf217b52c8..2c4e6bbe9a 100644 --- a/compiler/rustc_codegen_ssa/src/glue.rs +++ b/compiler/rustc_codegen_ssa/src/glue.rs @@ -6,6 +6,7 @@ use crate::common::IntPredicate; use crate::meth; use crate::traits::*; use rustc_middle::ty::{self, Ty}; +use rustc_target::abi::WrappingRange; pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, @@ -21,14 +22,17 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } match t.kind() { ty::Dynamic(..) => { - // load size/align from vtable + // Load size/align from vtable. let vtable = info.unwrap(); - ( - meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_SIZE) - .get_usize(bx, vtable), - meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_ALIGN) - .get_usize(bx, vtable), - ) + let size = meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_SIZE) + .get_usize(bx, vtable); + let align = meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_ALIGN) + .get_usize(bx, vtable); + + // Alignment is always nonzero. + bx.range_metadata(align, WrappingRange { start: 1, end: !0 }); + + (size, align) } ty::Slice(_) | ty::Str => { let unit = layout.field(bx, 0); diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 4c87d4d896..350199f4e9 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -2,7 +2,6 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(try_blocks)] -#![feature(in_band_lifetimes)] #![feature(let_else)] #![feature(once_cell)] #![feature(nll)] diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index 8d75b2e7a3..b1b3f1d6d8 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -73,7 +73,7 @@ struct LocalAnalyzer<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { locals: IndexVec, } -impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { +impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { fn assign(&mut self, local: mir::Local, location: Location) { let kind = &mut self.locals[local]; match *kind { @@ -211,6 +211,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> PlaceContext::MutatingUse( MutatingUseContext::Store + | MutatingUseContext::LlvmAsmOutput | MutatingUseContext::AsmOutput | MutatingUseContext::Borrow | MutatingUseContext::AddressOf @@ -275,9 +276,9 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec { /* nothing to do */ } + | TerminatorKind::FalseUnwind { .. } => { /* nothing to do */ } TerminatorKind::Call { cleanup: unwind, .. } + | TerminatorKind::InlineAsm { cleanup: unwind, .. } | TerminatorKind::Assert { cleanup: unwind, .. } | TerminatorKind::DropAndReplace { unwind, .. } | TerminatorKind::Drop { unwind, .. } => { diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index c8f388bfa1..dcfe5fcc2c 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -10,6 +10,7 @@ use crate::traits::*; use crate::MemFlags; use rustc_ast as ast; +use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::lang_items::LangItem; use rustc_index::vec::Idx; use rustc_middle::mir::AssertKind; @@ -159,11 +160,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { let llret = bx.call(fn_ty, fn_ptr, &llargs, self.funclet(fx)); bx.apply_attrs_callsite(&fn_abi, llret); if fx.mir[self.bb].is_cleanup { - // Cleanup is always the cold path. Don't inline - // drop glue. Also, when there is a deeply-nested - // struct, there are "symmetry" issues that cause - // exponential inlining - see issue #41696. - bx.do_not_inline(llret); + bx.apply_attrs_to_cleanup_callsite(llret); } if let Some((ret_dest, target)) = destination { @@ -174,6 +171,45 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { } } } + + /// Generates inline assembly with optional `destination` and `cleanup`. + fn do_inlineasm>( + &self, + fx: &mut FunctionCx<'a, 'tcx, Bx>, + bx: &mut Bx, + template: &[InlineAsmTemplatePiece], + operands: &[InlineAsmOperandRef<'tcx, Bx>], + options: InlineAsmOptions, + line_spans: &[Span], + destination: Option, + cleanup: Option, + instance: Instance<'_>, + ) { + if let Some(cleanup) = cleanup { + let ret_llbb = if let Some(target) = destination { + fx.llbb(target) + } else { + fx.unreachable_block() + }; + + bx.codegen_inline_asm( + template, + &operands, + options, + line_spans, + instance, + Some((ret_llbb, self.llblock(fx, cleanup), self.funclet(fx))), + ); + } else { + bx.codegen_inline_asm(template, &operands, options, line_spans, instance, None); + + if let Some(target) = destination { + self.funclet_br(fx, bx, target); + } else { + bx.unreachable(); + } + } + } } /// Codegen implementations for some terminator variants. @@ -877,6 +913,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { options: ast::InlineAsmOptions, line_spans: &[Span], destination: Option, + cleanup: Option, instance: Instance<'_>, ) { let span = terminator.source_info.span; @@ -931,13 +968,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }) .collect(); - bx.codegen_inline_asm(template, &operands, options, line_spans, instance); - - if let Some(target) = destination { - helper.funclet_br(self, &mut bx, target); - } else { - bx.unreachable(); - } + helper.do_inlineasm( + self, + &mut bx, + template, + &operands, + options, + line_spans, + destination, + cleanup, + instance, + ); } } @@ -1041,6 +1082,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { options, line_spans, destination, + cleanup, } => { self.codegen_asm_terminator( helper, @@ -1051,6 +1093,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { options, line_spans, destination, + cleanup, self.instance, ); } diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index f943157dc6..3657f80c2d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -68,7 +68,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let arg_tys = sig.inputs(); let ret_ty = sig.output(); let name = bx.tcx().item_name(def_id); - let name_str = &*name.as_str(); + let name_str = name.as_str(); let llret_ty = bx.backend_type(bx.layout_of(ret_ty)); let result = PlaceRef::new_sized(llresult, fn_abi.ret.layout); @@ -375,7 +375,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { use crate::common::AtomicOrdering::*; use crate::common::{AtomicRmwBinOp, SynchronizationScope}; - let split: Vec<&str> = name_str.split('_').collect(); + let split: Vec<_> = name_str.split('_').collect(); let is_cxchg = split[1] == "cxchg" || split[1] == "cxchgweak"; let (order, failorder) = match split.len() { diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index bea55bbc87..0c526ff13f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -47,7 +47,7 @@ pub struct OperandRef<'tcx, V> { pub layout: TyAndLayout<'tcx>, } -impl fmt::Debug for OperandRef<'tcx, V> { +impl fmt::Debug for OperandRef<'_, V> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "OperandRef({:?} @ {:?})", self.val, self.layout) } diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index f087b9f781..679c457670 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -8,7 +8,6 @@ use crate::traits::*; use crate::MemFlags; use rustc_apfloat::{ieee, Float, Round, Status}; -use rustc_hir::lang_items::LangItem; use rustc_middle::mir; use rustc_middle::ty::cast::{CastTy, IntTy}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; @@ -112,9 +111,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::Rvalue::Aggregate(ref kind, ref operands) => { let (dest, active_field_index) = match **kind { - mir::AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => { + mir::AggregateKind::Adt(adt_did, variant_index, _, _, active_field_index) => { dest.codegen_set_discr(&mut bx, variant_index); - if adt_def.is_enum() { + if bx.tcx().adt_def(adt_did).is_enum() { (dest.project_downcast(&mut bx, variant_index), active_field_index) } else { (dest, active_field_index) @@ -486,31 +485,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ) } - mir::Rvalue::NullaryOp(mir::NullOp::Box, content_ty) => { - let content_ty = self.monomorphize(content_ty); - let content_layout = bx.cx().layout_of(content_ty); - let llsize = bx.cx().const_usize(content_layout.size.bytes()); - let llalign = bx.cx().const_usize(content_layout.align.abi.bytes()); - let box_layout = bx.cx().layout_of(bx.tcx().mk_box(content_ty)); - let llty_ptr = bx.cx().backend_type(box_layout); - - // Allocate space: - let def_id = match bx.tcx().lang_items().require(LangItem::ExchangeMalloc) { - Ok(id) => id, - Err(s) => { - bx.cx().sess().fatal(&format!("allocation of `{}` {}", box_layout.ty, s)); - } - }; - let instance = ty::Instance::mono(bx.tcx(), def_id); - let r = bx.cx().get_fn_addr(instance); - let ty = bx.type_func(&[bx.type_isize(), bx.type_isize()], bx.type_i8p()); - let call = bx.call(ty, r, &[llsize, llalign], None); - let val = bx.pointercast(call, llty_ptr); - - let operand = OperandRef { val: OperandValue::Immediate(val), layout: box_layout }; - (bx, operand) - } - mir::Rvalue::NullaryOp(null_op, ty) => { let ty = self.monomorphize(ty); assert!(bx.cx().type_is_sized(ty)); @@ -518,7 +492,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let val = match null_op { mir::NullOp::SizeOf => layout.size.bytes(), mir::NullOp::AlignOf => layout.align.abi.bytes(), - mir::NullOp::Box => unreachable!(), }; let val = bx.cx().const_usize(val); let tcx = self.cx.tcx(); diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index b4420df5df..63cc6faf9e 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -35,6 +35,8 @@ const ARM_ALLOWED_FEATURES: &[(&str, Option)] = &[ // since it should be enabled per-function using #[instruction_set], not // #[target_feature]. ("thumb-mode", Some(sym::arm_target_feature)), + ("thumb2", Some(sym::arm_target_feature)), + ("reserve-r9", Some(sym::arm_target_feature)), ]; const AARCH64_ALLOWED_FEATURES: &[(&str, Option)] = &[ diff --git a/compiler/rustc_codegen_ssa/src/traits/asm.rs b/compiler/rustc_codegen_ssa/src/traits/asm.rs index 31f539e1b0..65f3c754d2 100644 --- a/compiler/rustc_codegen_ssa/src/traits/asm.rs +++ b/compiler/rustc_codegen_ssa/src/traits/asm.rs @@ -59,6 +59,7 @@ pub trait AsmBuilderMethods<'tcx>: BackendTypes { options: InlineAsmOptions, line_spans: &[Span], instance: Instance<'_>, + dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>, ); } diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 9c8bc3b210..c6abb3f6eb 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -97,6 +97,7 @@ pub trait CodegenBackend { &self, ongoing_codegen: Box, sess: &Session, + outputs: &OutputFilenames, ) -> Result<(CodegenResults, FxHashMap), ErrorReported>; /// This is called on the returned `Box` from `join_codegen` @@ -114,12 +115,6 @@ pub trait CodegenBackend { pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Send + Sync { fn new_metadata(&self, sess: TyCtxt<'_>, mod_name: &str) -> Self::Module; - fn write_compressed_metadata<'tcx>( - &self, - tcx: TyCtxt<'tcx>, - metadata: &EncodedMetadata, - llvm_module: &mut Self::Module, - ); fn codegen_allocator<'tcx>( &self, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 158e658301..48d8809585 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -311,5 +311,5 @@ pub trait BuilderMethods<'a, 'tcx>: ) -> Self::Value; fn zext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; - fn do_not_inline(&mut self, llret: Self::Value); + fn apply_attrs_to_cleanup_callsite(&mut self, llret: Self::Value); } diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index b94fb1e10d..5d3f07317a 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -97,7 +97,7 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> { } } -impl DerivedTypeMethods<'tcx> for T where Self: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {} +impl<'tcx, T> DerivedTypeMethods<'tcx> for T where Self: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {} pub trait LayoutTypeMethods<'tcx>: Backend<'tcx> { fn backend_type(&self, layout: TyAndLayout<'tcx>) -> Self::Type; @@ -135,4 +135,4 @@ pub trait ArgAbiMethods<'tcx>: HasCodegen<'tcx> { pub trait TypeMethods<'tcx>: DerivedTypeMethods<'tcx> + LayoutTypeMethods<'tcx> {} -impl TypeMethods<'tcx> for T where Self: DerivedTypeMethods<'tcx> + LayoutTypeMethods<'tcx> {} +impl<'tcx, T> TypeMethods<'tcx> for T where Self: DerivedTypeMethods<'tcx> + LayoutTypeMethods<'tcx> {} diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 6d3a89c0a8..3ec9f3ca3b 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -7,6 +7,7 @@ use crate::interpret::{ }; use rustc_errors::ErrorReported; +use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_middle::mir; use rustc_middle::mir::interpret::ErrorHandled; @@ -62,7 +63,7 @@ fn eval_body_using_ecx<'mir, 'tcx>( cid.instance, body, Some(&ret.into()), - StackPopCleanup::None { cleanup: false }, + StackPopCleanup::Root { cleanup: false }, )?; // The main interpreter loop. @@ -215,6 +216,7 @@ pub fn eval_to_const_value_raw_provider<'tcx>( tcx: TyCtxt<'tcx>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, ) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> { + assert!(key.param_env.constness() == hir::Constness::Const); // see comment in eval_to_allocation_raw_provider for what we're doing here if key.param_env.reveal() == Reveal::All { let mut key = key; @@ -249,6 +251,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>( tcx: TyCtxt<'tcx>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, ) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> { + assert!(key.param_env.constness() == hir::Constness::Const); // Because the constant is computed twice (once per value of `Reveal`), we are at risk of // reporting the same error twice here. To resolve this, we check whether we can evaluate the // constant in the more restrictive `Reveal::UserFacing`, which most likely already was diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index dacd8f7c12..30e9cbe440 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -260,7 +260,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, args: &[OpTy<'tcx>], _ret: Option<(&PlaceTy<'tcx>, mir::BasicBlock)>, _unwind: StackPopUnwind, // unwinding is not supported in consts - ) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>> { + ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> { debug!("find_mir_or_eval_fn: {:?}", instance); // Only check non-glue functions @@ -279,11 +279,21 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, if let Some(new_instance) = ecx.hook_special_const_fn(instance, args)? { // We call another const fn instead. - return Self::find_mir_or_eval_fn(ecx, new_instance, _abi, args, _ret, _unwind); + // However, we return the *original* instance to make backtraces work out + // (and we hope this does not confuse the FnAbi checks too much). + return Ok(Self::find_mir_or_eval_fn( + ecx, + new_instance, + _abi, + args, + _ret, + _unwind, + )? + .map(|(body, _instance)| (body, instance))); } } // This is a const fn. Call it. - Ok(Some(ecx.load_mir(instance.def, None)?)) + Ok(Some((ecx.load_mir(instance.def, None)?, instance))) } fn call_intrinsic( @@ -388,13 +398,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, Err(ConstEvalErrKind::NeedsRfc("pointer arithmetic or comparison".to_string()).into()) } - fn box_alloc( - _ecx: &mut InterpCx<'mir, 'tcx, Self>, - _dest: &PlaceTy<'tcx>, - ) -> InterpResult<'tcx> { - Err(ConstEvalErrKind::NeedsRfc("heap allocations via `box` keyword".to_string()).into()) - } - fn before_terminator(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { // The step limit has already been hit in a previous call to `before_terminator`. if ecx.machine.steps_remaining == 0 { @@ -423,14 +426,14 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } #[inline(always)] - fn stack( + fn stack<'a>( ecx: &'a InterpCx<'mir, 'tcx, Self>, ) -> &'a [Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>] { &ecx.machine.stack } #[inline(always)] - fn stack_mut( + fn stack_mut<'a>( ecx: &'a mut InterpCx<'mir, 'tcx, Self>, ) -> &'a mut Vec> { &mut ecx.machine.stack diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index a334165df4..91b17d1ac1 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -25,9 +25,9 @@ pub use fn_queries::*; pub use machine::*; pub(crate) fn const_caller_location( - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, (file, line, col): (Symbol, u32, u32), -) -> ConstValue<'tcx> { +) -> ConstValue<'_> { trace!("const_caller_location: {}:{}:{}", file, line, col); let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), false); diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index cf084faade..0a8112da2a 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -7,7 +7,11 @@ use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData}; use rustc_index::vec::IndexVec; use rustc_macros::HashStable; use rustc_middle::mir; -use rustc_middle::ty::layout::{self, LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout}; +use rustc_middle::mir::interpret::{InterpError, InvalidProgramInfo}; +use rustc_middle::ty::layout::{ + self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOf, LayoutOfHelpers, + TyAndLayout, +}; use rustc_middle::ty::{ self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, }; @@ -15,7 +19,7 @@ use rustc_mir_dataflow::storage::AlwaysLiveLocals; use rustc_query_system::ich::StableHashingContext; use rustc_session::Limit; use rustc_span::{Pos, Span}; -use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout}; +use rustc_target::abi::{call::FnAbi, Align, HasDataLayout, Size, TargetDataLayout}; use super::{ AllocId, GlobalId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine, MemPlace, @@ -152,11 +156,11 @@ pub enum StackPopCleanup { /// `ret` stores the block we jump to on a normal return, while `unwind` /// stores the block used for cleanup during unwinding. Goto { ret: Option, unwind: StackPopUnwind }, - /// Just do nothing: Used by Main and for the `box_alloc` hook in miri. + /// The root frame of the stack: nowhere else to jump to. /// `cleanup` says whether locals are deallocated. Static computation /// wants them leaked to intern what they need (and just throw away /// the entire `ecx` when it is done). - None { cleanup: bool }, + Root { cleanup: bool }, } /// State of a local variable including a memoized layout @@ -332,6 +336,24 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> LayoutOfHelpers<'tcx> for InterpC } } +impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> FnAbiOfHelpers<'tcx> for InterpCx<'mir, 'tcx, M> { + type FnAbiOfResult = InterpResult<'tcx, &'tcx FnAbi<'tcx, Ty<'tcx>>>; + + fn handle_fn_abi_err( + &self, + err: FnAbiError<'tcx>, + _span: Span, + _fn_abi_request: FnAbiRequest<'tcx>, + ) -> InterpErrorInfo<'tcx> { + match err { + FnAbiError::Layout(err) => err_inval!(Layout(err)).into(), + FnAbiError::AdjustForForeignAbi(err) => { + err_inval!(FnAbiAdjustForForeignAbi(err)).into() + } + } + } +} + /// Test if it is valid for a MIR assignment to assign `src`-typed place to `dest`-typed value. /// This test should be symmetric, as it is primarily about layout compatibility. pub(super) fn mir_assign_valid_types<'tcx>( @@ -508,7 +530,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { pub(super) fn subst_from_current_frame_and_normalize_erasing_regions>( &self, value: T, - ) -> T { + ) -> Result> { self.subst_from_frame_and_normalize_erasing_regions(self.frame(), value) } @@ -518,8 +540,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &self, frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>, value: T, - ) -> T { - frame.instance.subst_mir_and_normalize_erasing_regions(*self.tcx, self.param_env, value) + ) -> Result> { + frame + .instance + .try_subst_mir_and_normalize_erasing_regions(*self.tcx, self.param_env, value) + .or_else(|e| { + self.tcx.sess.delay_span_bug( + self.cur_span(), + format!("failed to normalize {}", e.get_type_for_failure()).as_str(), + ); + + Err(InterpError::InvalidProgram(InvalidProgramInfo::TooGeneric)) + }) } /// The `substs` are assumed to already be in our interpreter "universe" (param_env). @@ -554,7 +586,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let layout = from_known_layout(self.tcx, self.param_env, layout, || { let local_ty = frame.body.local_decls[local].ty; let local_ty = - self.subst_from_frame_and_normalize_erasing_regions(frame, local_ty); + self.subst_from_frame_and_normalize_erasing_regions(frame, local_ty)?; self.layout_of(local_ty) })?; if let Some(state) = frame.locals.get(local) { @@ -605,19 +637,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { match self.size_and_align_of(metadata, &field)? { Some(size_and_align) => size_and_align, None => { - // A field with extern type. If this field is at offset 0, we behave - // like the underlying extern type. - // FIXME: Once we have made decisions for how to handle size and alignment - // of `extern type`, this should be adapted. It is just a temporary hack - // to get some code to work that probably ought to work. - if sized_size == Size::ZERO { - return Ok(None); - } else { - span_bug!( - self.cur_span(), - "Fields cannot be extern types, unless they are at offset 0" - ) - } + // A field with an extern type. We don't know the actual dynamic size + // or the alignment. + return Ok(None); } }; @@ -702,7 +724,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { for const_ in &body.required_consts { let span = const_.span; let const_ = - self.subst_from_current_frame_and_normalize_erasing_regions(const_.literal); + self.subst_from_current_frame_and_normalize_erasing_regions(const_.literal)?; self.mir_const_to_op(&const_, None).map_err(|err| { // If there was an error, set the span of the current frame to this constant. // Avoiding doing this when evaluation succeeds. @@ -827,7 +849,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // because this is CTFE and the final value will be thoroughly validated anyway. let cleanup = match return_to_block { StackPopCleanup::Goto { .. } => true, - StackPopCleanup::None { cleanup, .. } => cleanup, + StackPopCleanup::Root { cleanup, .. } => cleanup, }; if !cleanup { @@ -852,8 +874,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Follow the unwind edge. let unwind = match return_to_block { StackPopCleanup::Goto { unwind, .. } => unwind, - StackPopCleanup::None { .. } => { - panic!("Encountered StackPopCleanup::None when unwinding!") + StackPopCleanup::Root { .. } => { + panic!("encountered StackPopCleanup::Root when unwinding!") } }; self.unwind_to_block(unwind) @@ -861,7 +883,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Follow the normal return edge. match return_to_block { StackPopCleanup::Goto { ret, .. } => self.return_to_block(ret), - StackPopCleanup::None { .. } => Ok(()), + StackPopCleanup::Root { .. } => { + assert!( + self.stack().is_empty(), + "only the topmost frame can have StackPopCleanup::Root" + ); + Ok(()) + } } } } @@ -918,12 +946,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } else { self.param_env }; + let param_env = param_env.with_const(); let val = self.tcx.eval_to_allocation_raw(param_env.and(gid))?; self.raw_const_to_mplace(val) } #[must_use] - pub fn dump_place(&'a self, place: Place) -> PlacePrinter<'a, 'mir, 'tcx, M> { + pub fn dump_place(&self, place: Place) -> PlacePrinter<'_, 'mir, 'tcx, M> { PlacePrinter { ecx: self, place } } diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index 84e7940839..a1dd587c17 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -292,14 +292,15 @@ pub enum InternKind { /// Any errors here would anyway be turned into `const_err` lints, whereas validation failures /// are hard errors. #[tracing::instrument(level = "debug", skip(ecx))] -pub fn intern_const_alloc_recursive>( +pub fn intern_const_alloc_recursive< + 'mir, + 'tcx: 'mir, + M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>, +>( ecx: &mut InterpCx<'mir, 'tcx, M>, intern_kind: InternKind, ret: &MPlaceTy<'tcx>, -) -> Result<(), ErrorReported> -where - 'tcx: 'mir, -{ +) -> Result<(), ErrorReported> { let tcx = ecx.tcx; let base_intern_mode = match intern_kind { InternKind::Static(mutbl) => InternMode::Static(mutbl), diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 44da27a43d..d6f856a6f0 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -140,7 +140,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { sym::min_align_of_val | sym::size_of_val => { // Avoid `deref_operand` -- this is not a deref, the ptr does not have to be - // dereferencable! + // dereferenceable! let place = self.ref_to_mplace(&self.read_immediate(&args[0])?)?; let (size, align) = self .size_and_align_of_mplace(&place)? @@ -322,6 +322,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { sym::copy => { self.copy_intrinsic(&args[0], &args[1], &args[2], /*nonoverlapping*/ false)?; } + sym::write_bytes => { + self.write_bytes_intrinsic(&args[0], &args[1], &args[2])?; + } sym::offset => { let ptr = self.read_pointer(&args[0])?; let offset_count = self.read_scalar(&args[1])?.to_machine_isize(self)?; @@ -394,10 +397,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { sym::transmute => { self.copy_op_transmute(&args[0], dest)?; } - sym::assert_inhabited => { + sym::assert_inhabited | sym::assert_zero_valid | sym::assert_uninit_valid => { let ty = instance.substs.type_at(0); let layout = self.layout_of(ty)?; + // For *all* intrinsics we first check `is_uninhabited` to give a more specific + // error message. if layout.abi.is_uninhabited() { // The run-time intrinsic panics just to get a good backtrace; here we abort // since there is no problem showing a backtrace even for aborts. @@ -409,6 +414,28 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ), )?; } + if intrinsic_name == sym::assert_zero_valid + && !layout.might_permit_raw_init(self, /*zero:*/ true) + { + M::abort( + self, + format!( + "aborted execution: attempted to zero-initialize type `{}`, which is invalid", + ty + ), + )?; + } + if intrinsic_name == sym::assert_uninit_valid + && !layout.might_permit_raw_init(self, /*zero:*/ false) + { + M::abort( + self, + format!( + "aborted execution: attempted to leave type `{}` uninitialized, which is invalid", + ty + ), + )?; + } } sym::simd_insert => { let index = u64::from(self.read_scalar(&args[1])?.to_u32()?); @@ -543,6 +570,27 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.memory.copy(src, align, dst, align, size, nonoverlapping) } + pub(crate) fn write_bytes_intrinsic( + &mut self, + dst: &OpTy<'tcx, >::PointerTag>, + byte: &OpTy<'tcx, >::PointerTag>, + count: &OpTy<'tcx, >::PointerTag>, + ) -> InterpResult<'tcx> { + let layout = self.layout_of(dst.layout.ty.builtin_deref(true).unwrap().ty)?; + + let dst = self.read_pointer(&dst)?; + let byte = self.read_scalar(&byte)?.to_u8()?; + let count = self.read_scalar(&count)?.to_machine_usize(self)?; + + let len = layout + .size + .checked_mul(count, self) + .ok_or_else(|| err_ub_format!("overflow computing total size of `write_bytes`"))?; + + let bytes = std::iter::repeat(byte).take(len.bytes_usize()); + self.memory.write_bytes(dst, bytes) + } + pub(crate) fn raw_eq_intrinsic( &mut self, lhs: &OpTy<'tcx, >::PointerTag>, diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs index b5e97ec8fe..058903dcde 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs @@ -82,7 +82,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> MPlaceTy<'tcx, M::PointerTag> { let loc_details = &self.tcx.sess.opts.debugging_opts.location_detail; let file = if loc_details.file { - self.allocate_str(&filename.as_str(), MemoryKind::CallerLocation, Mutability::Not) + self.allocate_str(filename.as_str(), MemoryKind::CallerLocation, Mutability::Not) } else { // FIXME: This creates a new allocation each time. It might be preferable to // perform this allocation only once, and re-use the `MPlaceTy`. diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs index 5b4a5ac357..ca000f93eb 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs @@ -88,7 +88,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { } fn path_crate(mut self, cnum: CrateNum) -> Result { - self.path.push_str(&self.tcx.crate_name(cnum).as_str()); + self.path.push_str(self.tcx.crate_name(cnum).as_str()); Ok(self) } @@ -148,7 +148,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { } } -impl PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> { +impl<'tcx> PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> { fn region_should_not_be_omitted(&self, _region: ty::Region<'_>) -> bool { false } diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 5120782893..23ec3875cb 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -167,7 +167,7 @@ pub trait Machine<'mir, 'tcx>: Sized { args: &[OpTy<'tcx, Self::PointerTag>], ret: Option<(&PlaceTy<'tcx, Self::PointerTag>, mir::BasicBlock)>, unwind: StackPopUnwind, - ) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>>; + ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>>; /// Execute `fn_val`. It is the hook's responsibility to advance the instruction /// pointer as appropriate. @@ -212,12 +212,6 @@ pub trait Machine<'mir, 'tcx>: Sized { right: &ImmTy<'tcx, Self::PointerTag>, ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)>; - /// Heap allocations via the `box` keyword. - fn box_alloc( - ecx: &mut InterpCx<'mir, 'tcx, Self>, - dest: &PlaceTy<'tcx, Self::PointerTag>, - ) -> InterpResult<'tcx>; - /// Called to read the specified `local` from the `frame`. /// Since reading a ZST is not actually accessing memory or locals, this is never invoked /// for ZST reads. @@ -374,12 +368,12 @@ pub trait Machine<'mir, 'tcx>: Sized { ) -> InterpResult<'tcx, Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>>; /// Borrow the current thread's stack. - fn stack( + fn stack<'a>( ecx: &'a InterpCx<'mir, 'tcx, Self>, ) -> &'a [Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>]; /// Mutably borrow the current thread's stack. - fn stack_mut( + fn stack_mut<'a>( ecx: &'a mut InterpCx<'mir, 'tcx, Self>, ) -> &'a mut Vec>; diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index de9e94ce2a..dfec450968 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -106,7 +106,7 @@ pub struct ImmTy<'tcx, Tag: Provenance = AllocId> { #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] rustc_data_structures::static_assert_size!(ImmTy<'_>, 72); -impl std::fmt::Display for ImmTy<'tcx, Tag> { +impl std::fmt::Display for ImmTy<'_, Tag> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { /// Helper function for printing a scalar to a FmtPrinter fn p<'a, 'tcx, F: std::fmt::Write, Tag: Provenance>( @@ -512,7 +512,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.param_env, self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions( place.ty(&self.frame().body.local_decls, *self.tcx).ty - ))?, + )?)?, op.layout, )); Ok(op) @@ -534,7 +534,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Constant(ref constant) => { let val = - self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal); + self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal)?; // This can still fail: // * During ConstProp, with `TooGeneric` or since the `requried_consts` were not all // checked yet. diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index a90582fc33..48c90e1881 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -328,9 +328,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.binary_int_op(bin_op, l, left.layout, r, right.layout) } _ if left.layout.ty.is_any_ptr() => { - // The RHS type must be the same *or an integer type* (for `Offset`). + // The RHS type must be a `pointer` *or an integer type* (for `Offset`). + // (Even when both sides are pointers, their type might differ, see issue #91636) assert!( - right.layout.ty == left.layout.ty || right.layout.ty.is_integral(), + right.layout.ty.is_any_ptr() || right.layout.ty.is_integral(), "Unexpected types for BinOp: {:?} {:?} {:?}", left.layout.ty, bin_op, diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index d7f2853fc8..818b95b7fc 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -150,7 +150,7 @@ impl MemPlace { } #[inline] - pub fn offset( + pub fn offset<'tcx>( self, offset: Size, meta: MemPlaceMeta, @@ -327,7 +327,7 @@ where self.memory.get_mut(place.ptr, size, place.align) } - /// Check if this mplace is dereferencable and sufficiently aligned. + /// Check if this mplace is dereferenceable and sufficiently aligned. fn check_mplace_access( &self, mplace: MPlaceTy<'tcx, M::PointerTag>, @@ -362,21 +362,15 @@ where // Re-use parent metadata to determine dynamic field layout. // With custom DSTS, this *will* execute user-defined code, but the same // happens at run-time so that's okay. - let align = match self.size_and_align_of(&base.meta, &field_layout)? { - Some((_, align)) => align, - None if offset == Size::ZERO => { - // An extern type at offset 0, we fall back to its static alignment. - // FIXME: Once we have made decisions for how to handle size and alignment - // of `extern type`, this should be adapted. It is just a temporary hack - // to get some code to work that probably ought to work. - field_layout.align.abi + match self.size_and_align_of(&base.meta, &field_layout)? { + Some((_, align)) => (base.meta, offset.align_to(align)), + None => { + // For unsized types with an extern type tail we perform no adjustments. + // NOTE: keep this in sync with `PlaceRef::project_field` in the codegen backend. + assert!(matches!(base.meta, MemPlaceMeta::None)); + (base.meta, offset) } - None => span_bug!( - self.cur_span(), - "cannot compute offset for extern type field at non-0 offset" - ), - }; - (base.meta, offset.align_to(align)) + } } else { // base.meta could be present; we might be accessing a sized field of an unsized // struct. @@ -420,7 +414,7 @@ where // Iterates over all fields of an array. Much more efficient than doing the // same by repeatedly calling `mplace_array`. - pub(super) fn mplace_array_fields( + pub(super) fn mplace_array_fields<'a>( &self, base: &'a MPlaceTy<'tcx, Tag>, ) -> InterpResult<'tcx, impl Iterator>> + 'a> @@ -643,7 +637,7 @@ where self.param_env, self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions( place.ty(&self.frame().body.local_decls, *self.tcx).ty - ))?, + )?)?, place_ty.layout, )); Ok(place_ty) diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index e6037d561d..3daa1d3c2b 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -199,9 +199,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Aggregate(ref kind, ref operands) => { // active_field_index is for union initialization. let (dest, active_field_index) = match **kind { - mir::AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => { + mir::AggregateKind::Adt(adt_did, variant_index, _, _, active_field_index) => { self.write_discriminant(variant_index, &dest)?; - if adt_def.is_enum() { + if self.tcx.adt_def(adt_did).is_enum() { assert!(active_field_index.is_none()); (self.place_downcast(&dest, variant_index)?, None) } else { @@ -242,11 +242,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let elem_size = first.layout.size; let first_ptr = first.ptr; let rest_ptr = first_ptr.offset(elem_size, self)?; + // For the alignment of `rest_ptr`, we crucially do *not* use `first.align` as + // that place might be more aligned than its type mandates (a `u8` array could + // be 4-aligned if it sits at the right spot in a struct). Instead we use + // `first.layout.align`, i.e., the alignment given by the type. self.memory.copy_repeatedly( first_ptr, first.align, rest_ptr, - first.align, + first.layout.align.abi, elem_size, length - 1, /*nonoverlapping:*/ true, @@ -267,12 +271,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.write_immediate(place.to_ref(self), &dest)?; } - NullaryOp(mir::NullOp::Box, _) => { - M::box_alloc(self, &dest)?; - } - NullaryOp(null_op, ty) => { - let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty); + let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty)?; let layout = self.layout_of(ty)?; if layout.is_unsized() { // FIXME: This should be a span_bug (#80742) @@ -285,7 +285,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let val = match null_op { mir::NullOp::SizeOf => layout.size.bytes(), mir::NullOp::AlignOf => layout.align.abi.bytes(), - mir::NullOp::Box => unreachable!(), }; self.write_scalar(Scalar::from_machine_usize(val, self), &dest)?; } @@ -298,7 +297,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Cast(cast_kind, ref operand, cast_ty) => { let src = self.eval_operand(operand, None)?; - let cast_ty = self.subst_from_current_frame_and_normalize_erasing_regions(cast_ty); + let cast_ty = + self.subst_from_current_frame_and_normalize_erasing_regions(cast_ty)?; self.cast(&src, cast_kind, cast_ty, &dest)?; } diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 00208574c5..f3910c9765 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -1,14 +1,14 @@ use std::borrow::Cow; use std::convert::TryFrom; -use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_middle::ty::layout::{self, LayoutOf as _, TyAndLayout}; +use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; use rustc_middle::ty::Instance; use rustc_middle::{ mir, ty::{self, Ty}, }; use rustc_target::abi; +use rustc_target::abi::call::{ArgAbi, ArgAttribute, ArgAttributes, FnAbi, PassMode}; use rustc_target::spec::abi::Abi; use super::{ @@ -17,10 +17,6 @@ use super::{ }; impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { - fn fn_can_unwind(&self, attrs: CodegenFnAttrFlags, abi: Abi) -> bool { - layout::fn_can_unwind(*self.tcx, attrs, abi) - } - pub(super) fn eval_terminator( &mut self, terminator: &mir::Terminator<'tcx>, @@ -64,25 +60,27 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let old_stack = self.frame_idx(); let old_loc = self.frame().loc; let func = self.eval_operand(func, None)?; - let (fn_val, abi, caller_can_unwind) = match *func.layout.ty.kind() { - ty::FnPtr(sig) => { - let caller_abi = sig.abi(); + let args = self.eval_operands(args)?; + + let fn_sig_binder = func.layout.ty.fn_sig(*self.tcx); + let fn_sig = + self.tcx.normalize_erasing_late_bound_regions(self.param_env, fn_sig_binder); + let extra_args = &args[fn_sig.inputs().len()..]; + let extra_args = self.tcx.mk_type_list(extra_args.iter().map(|arg| arg.layout.ty)); + + let (fn_val, fn_abi, with_caller_location) = match *func.layout.ty.kind() { + ty::FnPtr(_sig) => { let fn_ptr = self.read_pointer(&func)?; let fn_val = self.memory.get_fn(fn_ptr)?; - ( - fn_val, - caller_abi, - self.fn_can_unwind(CodegenFnAttrFlags::empty(), caller_abi), - ) + (fn_val, self.fn_abi_of_fn_ptr(fn_sig_binder, extra_args)?, false) } ty::FnDef(def_id, substs) => { - let sig = func.layout.ty.fn_sig(*self.tcx); + let instance = + self.resolve(ty::WithOptConstParam::unknown(def_id), substs)?; ( - FnVal::Instance( - self.resolve(ty::WithOptConstParam::unknown(def_id), substs)?, - ), - sig.abi(), - self.fn_can_unwind(self.tcx.codegen_fn_attrs(def_id).flags, sig.abi()), + FnVal::Instance(instance), + self.fn_abi_of_instance(instance, extra_args)?, + instance.def.requires_caller_location(*self.tcx), ) } _ => span_bug!( @@ -91,7 +89,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { func.layout.ty ), }; - let args = self.eval_operands(args)?; + let dest_place; let ret = match destination { Some((dest, ret)) => { @@ -102,10 +100,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; self.eval_fn_call( fn_val, - abi, - &args[..], + (fn_sig.abi, fn_abi), + &args, + with_caller_location, ret, - match (cleanup, caller_can_unwind) { + match (cleanup, fn_abi.can_unwind) { (Some(cleanup), true) => StackPopUnwind::Cleanup(*cleanup), (None, true) => StackPopUnwind::Skip, (_, false) => StackPopUnwind::NotAllowed, @@ -174,68 +173,128 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } fn check_argument_compat( - rust_abi: bool, - caller: TyAndLayout<'tcx>, - callee: TyAndLayout<'tcx>, + caller_abi: &ArgAbi<'tcx, Ty<'tcx>>, + callee_abi: &ArgAbi<'tcx, Ty<'tcx>>, ) -> bool { - if caller.ty == callee.ty { - // No question + // Heuristic for type comparison. + let layout_compat = || { + if caller_abi.layout.ty == callee_abi.layout.ty { + // No question + return true; + } + // Compare layout + match (caller_abi.layout.abi, callee_abi.layout.abi) { + // Different valid ranges are okay (once we enforce validity, + // that will take care to make it UB to leave the range, just + // like for transmute). + (abi::Abi::Scalar(caller), abi::Abi::Scalar(callee)) => { + caller.value == callee.value + } + ( + abi::Abi::ScalarPair(caller1, caller2), + abi::Abi::ScalarPair(callee1, callee2), + ) => caller1.value == callee1.value && caller2.value == callee2.value, + // Be conservative + _ => false, + } + }; + // Padding must be fully equal. + let pad_compat = || caller_abi.pad == callee_abi.pad; + // When comparing the PassMode, we have to be smart about comparing the attributes. + let arg_attr_compat = |a1: ArgAttributes, a2: ArgAttributes| { + // There's only one regular attribute that matters for the call ABI: InReg. + // Everything else is things like noalias, dereferencable, nonnull, ... + // (This also applies to pointee_size, pointee_align.) + if a1.regular.contains(ArgAttribute::InReg) != a2.regular.contains(ArgAttribute::InReg) + { + return false; + } + // We also compare the sign extension mode -- this could let the callee make assumptions + // about bits that conceptually were not even passed. + if a1.arg_ext != a2.arg_ext { + return false; + } + return true; + }; + let mode_compat = || match (caller_abi.mode, callee_abi.mode) { + (PassMode::Ignore, PassMode::Ignore) => true, + (PassMode::Direct(a1), PassMode::Direct(a2)) => arg_attr_compat(a1, a2), + (PassMode::Pair(a1, b1), PassMode::Pair(a2, b2)) => { + arg_attr_compat(a1, a2) && arg_attr_compat(b1, b2) + } + (PassMode::Cast(c1), PassMode::Cast(c2)) => c1 == c2, + ( + PassMode::Indirect { attrs: a1, extra_attrs: None, on_stack: s1 }, + PassMode::Indirect { attrs: a2, extra_attrs: None, on_stack: s2 }, + ) => arg_attr_compat(a1, a2) && s1 == s2, + ( + PassMode::Indirect { attrs: a1, extra_attrs: Some(e1), on_stack: s1 }, + PassMode::Indirect { attrs: a2, extra_attrs: Some(e2), on_stack: s2 }, + ) => arg_attr_compat(a1, a2) && arg_attr_compat(e1, e2) && s1 == s2, + _ => false, + }; + + if layout_compat() && pad_compat() && mode_compat() { return true; } - if !rust_abi { - // Don't risk anything - return false; - } - // Compare layout - match (caller.abi, callee.abi) { - // Different valid ranges are okay (once we enforce validity, - // that will take care to make it UB to leave the range, just - // like for transmute). - (abi::Abi::Scalar(caller), abi::Abi::Scalar(callee)) => caller.value == callee.value, - (abi::Abi::ScalarPair(caller1, caller2), abi::Abi::ScalarPair(callee1, callee2)) => { - caller1.value == callee1.value && caller2.value == callee2.value - } - // Be conservative - _ => false, - } + trace!( + "check_argument_compat: incompatible ABIs:\ncaller: {:?}\ncallee: {:?}", + caller_abi, + callee_abi + ); + return false; } - /// Pass a single argument, checking the types for compatibility. - fn pass_argument( + /// Initialize a single callee argument, checking the types for compatibility. + fn pass_argument<'x, 'y>( &mut self, - rust_abi: bool, - caller_arg: &mut impl Iterator>, + caller_args: &mut impl Iterator< + Item = (&'x OpTy<'tcx, M::PointerTag>, &'y ArgAbi<'tcx, Ty<'tcx>>), + >, + callee_abi: &ArgAbi<'tcx, Ty<'tcx>>, callee_arg: &PlaceTy<'tcx, M::PointerTag>, - ) -> InterpResult<'tcx> { - if rust_abi && callee_arg.layout.is_zst() { - // Nothing to do. - trace!("Skipping callee ZST"); + ) -> InterpResult<'tcx> + where + 'tcx: 'x, + 'tcx: 'y, + { + if matches!(callee_abi.mode, PassMode::Ignore) { + // This one is skipped. return Ok(()); } - let caller_arg = caller_arg.next().ok_or_else(|| { + // Find next caller arg. + let (caller_arg, caller_abi) = caller_args.next().ok_or_else(|| { err_ub_format!("calling a function with fewer arguments than it requires") })?; - if rust_abi { - assert!(!caller_arg.layout.is_zst(), "ZSTs must have been already filtered out"); - } // Now, check - if !Self::check_argument_compat(rust_abi, caller_arg.layout, callee_arg.layout) { + if !Self::check_argument_compat(caller_abi, callee_abi) { throw_ub_format!( "calling a function with argument of type {:?} passing data of type {:?}", callee_arg.layout.ty, caller_arg.layout.ty ) } - // We allow some transmutes here + // We allow some transmutes here. + // FIXME: Depending on the PassMode, this should reset some padding to uninitialized. (This + // is true for all `copy_op`, but there are a lot of special cases for argument passing + // specifically.) self.copy_op_transmute(&caller_arg, callee_arg) } /// Call this function -- pushing the stack frame and initializing the arguments. + /// + /// `caller_fn_abi` is used to determine if all the arguments are passed the proper way. + /// However, we also need `caller_abi` to determine if we need to do untupling of arguments. + /// + /// `with_caller_location` indicates whether the caller passed a caller location. Miri + /// implements caller locations without argument passing, but to match `FnAbi` we need to know + /// when those arguments are present. pub(crate) fn eval_fn_call( &mut self, fn_val: FnVal<'tcx, M::ExtraFnVal>, - caller_abi: Abi, + (caller_abi, caller_fn_abi): (Abi, &FnAbi<'tcx, Ty<'tcx>>), args: &[OpTy<'tcx, M::PointerTag>], + with_caller_location: bool, ret: Option<(&PlaceTy<'tcx, M::PointerTag>, mir::BasicBlock)>, mut unwind: StackPopUnwind, ) -> InterpResult<'tcx> { @@ -248,39 +307,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } }; - let get_abi = |this: &Self, instance_ty: Ty<'tcx>| match instance_ty.kind() { - ty::FnDef(..) => instance_ty.fn_sig(*this.tcx).abi(), - ty::Closure(..) => Abi::RustCall, - ty::Generator(..) => Abi::Rust, - _ => span_bug!(this.cur_span(), "unexpected callee ty: {:?}", instance_ty), - }; - - // ABI check - let check_abi = |callee_abi: Abi| -> InterpResult<'tcx> { - let normalize_abi = |abi| match abi { - Abi::Rust | Abi::RustCall | Abi::RustIntrinsic | Abi::PlatformIntrinsic => - // These are all the same ABI, really. - { - Abi::Rust - } - abi => abi, - }; - if normalize_abi(caller_abi) != normalize_abi(callee_abi) { - throw_ub_format!( - "calling a function with ABI {} using caller ABI {}", - callee_abi.name(), - caller_abi.name() - ) - } - Ok(()) - }; - match instance.def { ty::InstanceDef::Intrinsic(..) => { - if M::enforce_abi(self) { - check_abi(get_abi(self, instance.ty(*self.tcx, self.param_env)))?; - } assert!(caller_abi == Abi::RustIntrinsic || caller_abi == Abi::PlatformIntrinsic); + // caller_fn_abi is not relevant here, we interpret the arguments directly for each intrinsic. M::call_intrinsic(self, instance, args, ret, unwind) } ty::InstanceDef::VtableShim(..) @@ -291,26 +321,37 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | ty::InstanceDef::CloneShim(..) | ty::InstanceDef::Item(_) => { // We need MIR for this fn - let body = + let (body, instance) = match M::find_mir_or_eval_fn(self, instance, caller_abi, args, ret, unwind)? { Some(body) => body, None => return Ok(()), }; - // Check against the ABI of the MIR body we are calling (not the ABI of `instance`; - // these can differ when `find_mir_or_eval_fn` does something clever like resolve - // exported symbol names). - let callee_def_id = body.source.def_id(); - let callee_abi = get_abi(self, self.tcx.type_of(callee_def_id)); + // Compute callee information using the `instance` returned by + // `find_mir_or_eval_fn`. + // FIXME: for variadic support, do we have to somehow determine calle's extra_args? + let callee_fn_abi = self.fn_abi_of_instance(instance, ty::List::empty())?; - if M::enforce_abi(self) { - check_abi(callee_abi)?; + if callee_fn_abi.c_variadic != caller_fn_abi.c_variadic { + throw_ub_format!( + "calling a c-variadic function via a non-variadic call site, or vice versa" + ); + } + if callee_fn_abi.c_variadic { + throw_unsup_format!("calling a c-variadic function is not supported"); } - if !matches!(unwind, StackPopUnwind::NotAllowed) - && !self - .fn_can_unwind(self.tcx.codegen_fn_attrs(callee_def_id).flags, callee_abi) - { + if M::enforce_abi(self) { + if caller_fn_abi.conv != callee_fn_abi.conv { + throw_ub_format!( + "calling a function with calling convention {:?} using calling convention {:?}", + callee_fn_abi.conv, + caller_fn_abi.conv + ) + } + } + + if !matches!(unwind, StackPopUnwind::NotAllowed) && !callee_fn_abi.can_unwind { // The callee cannot unwind. unwind = StackPopUnwind::NotAllowed; } @@ -343,12 +384,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .collect::>() ); - // Figure out how to pass which arguments. - // The Rust ABI is special: ZST get skipped. - let rust_abi = matches!(caller_abi, Abi::Rust | Abi::RustCall); - - // We have two iterators: Where the arguments come from, - // and where they go to. + // In principle, we have two iterators: Where the arguments come from, and where + // they go to. // For where they come from: If the ABI is RustCall, we untuple the // last incoming argument. These two iterators do not have the same type, @@ -373,53 +410,59 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Plain arg passing Cow::from(args) }; - // Skip ZSTs - let mut caller_iter = - caller_args.iter().filter(|op| !rust_abi || !op.layout.is_zst()).copied(); + // If `with_caller_location` is set we pretend there is an extra argument (that + // we will not pass). + assert_eq!( + caller_args.len() + if with_caller_location { 1 } else { 0 }, + caller_fn_abi.args.len(), + "mismatch between caller ABI and caller arguments", + ); + let mut caller_args = caller_args + .iter() + .zip(caller_fn_abi.args.iter()) + .filter(|arg_and_abi| !matches!(arg_and_abi.1.mode, PassMode::Ignore)); // Now we have to spread them out across the callee's locals, // taking into account the `spread_arg`. If we could write // this is a single iterator (that handles `spread_arg`), then // `pass_argument` would be the loop body. It takes care to // not advance `caller_iter` for ZSTs. + let mut callee_args_abis = callee_fn_abi.args.iter(); for local in body.args_iter() { let dest = self.eval_place(mir::Place::from(local))?; if Some(local) == body.spread_arg { // Must be a tuple for i in 0..dest.layout.fields.count() { let dest = self.place_field(&dest, i)?; - self.pass_argument(rust_abi, &mut caller_iter, &dest)?; + let callee_abi = callee_args_abis.next().unwrap(); + self.pass_argument(&mut caller_args, callee_abi, &dest)?; } } else { // Normal argument - self.pass_argument(rust_abi, &mut caller_iter, &dest)?; + let callee_abi = callee_args_abis.next().unwrap(); + self.pass_argument(&mut caller_args, callee_abi, &dest)?; } } - // Now we should have no more caller args - if caller_iter.next().is_some() { + // If the callee needs a caller location, pretend we consume one more argument from the ABI. + if instance.def.requires_caller_location(*self.tcx) { + callee_args_abis.next().unwrap(); + } + // Now we should have no more caller args or callee arg ABIs + assert!( + callee_args_abis.next().is_none(), + "mismatch between callee ABI and callee body arguments" + ); + if caller_args.next().is_some() { throw_ub_format!("calling a function with more arguments than it expected") } // Don't forget to check the return type! - if let Some((caller_ret, _)) = ret { - let callee_ret = self.eval_place(mir::Place::return_place())?; - if !Self::check_argument_compat( - rust_abi, - caller_ret.layout, - callee_ret.layout, - ) { - throw_ub_format!( - "calling a function with return type {:?} passing \ - return place of type {:?}", - callee_ret.layout.ty, - caller_ret.layout.ty - ) - } - } else { - let local = mir::RETURN_PLACE; - let callee_layout = self.layout_of_local(self.frame(), local, None)?; - if !callee_layout.abi.is_uninhabited() { - throw_ub_format!("calling a returning function without a return place") - } + if !Self::check_argument_compat(&caller_fn_abi.ret, &callee_fn_abi.ret) { + throw_ub_format!( + "calling a function with return type {:?} passing \ + return place of type {:?}", + callee_fn_abi.ret.layout.ty, + caller_fn_abi.ret.layout.ty, + ) } }; match res { @@ -464,7 +507,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { )); trace!("Patched self operand to {:#?}", args[0]); // recurse with concrete function - self.eval_fn_call(fn_val, caller_abi, &args, ret, unwind) + self.eval_fn_call( + fn_val, + (caller_abi, caller_fn_abi), + &args, + with_caller_location, + ret, + unwind, + ) } } } @@ -489,6 +539,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } _ => (instance, place), }; + let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty())?; let arg = ImmTy::from_immediate( place.to_ref(self), @@ -500,8 +551,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.eval_fn_call( FnVal::Instance(instance), - Abi::Rust, + (Abi::Rust, fn_abi), &[arg.into()], + false, Some((&dest.into(), target)), match unwind { Some(cleanup) => StackPopUnwind::Cleanup(cleanup), diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 6be3e19a83..5a398c2f45 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -14,6 +14,7 @@ use rustc_middle::mir::interpret::InterpError; use rustc_middle::ty; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_span::symbol::{sym, Symbol}; +use rustc_span::DUMMY_SP; use rustc_target::abi::{Abi, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange}; use std::hash::Hash; @@ -736,9 +737,15 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> #[inline(always)] fn visit_union( &mut self, - _op: &OpTy<'tcx, M::PointerTag>, + op: &OpTy<'tcx, M::PointerTag>, _fields: NonZeroUsize, ) -> InterpResult<'tcx> { + // Special check preventing `UnsafeCell` inside unions in the inner part of constants. + if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { inner: true, .. })) { + if !op.layout.ty.is_freeze(self.ecx.tcx.at(DUMMY_SP), self.ecx.param_env) { + throw_validation_failure!(self.path, { "`UnsafeCell` in a `const`" }); + } + } Ok(()) } diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index f308e764e8..92854af55b 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -11,8 +11,6 @@ Rust MIR: a lowered representation of Rust. #![feature(crate_visibility_modifier)] #![feature(decl_macro)] #![feature(exact_size_is_empty)] -#![feature(in_band_lifetimes)] -#![feature(iter_zip)] #![feature(let_else)] #![feature(map_try_insert)] #![feature(min_specialization)] diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 4e3a8b6409..dd749c0393 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -1,8 +1,8 @@ //! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations. use rustc_errors::{Applicability, Diagnostic, ErrorReported}; +use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, HirId, LangItem}; use rustc_index::bit_set::BitSet; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{ImplSource, Obligation, ObligationCause}; @@ -14,8 +14,7 @@ use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, use rustc_middle::ty::{Binder, TraitPredicate, TraitRef}; use rustc_mir_dataflow::{self, Analysis}; use rustc_span::{sym, Span, Symbol}; -use rustc_trait_selection::traits::error_reporting::InferCtxtExt; -use rustc_trait_selection::traits::{self, SelectionContext, TraitEngine}; +use rustc_trait_selection::traits::SelectionContext; use std::mem; use std::ops::Deref; @@ -36,7 +35,7 @@ pub struct Qualifs<'mir, 'tcx> { needs_non_const_drop: Option>, } -impl Qualifs<'mir, 'tcx> { +impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { /// Returns `true` if `local` is `NeedsDrop` at the given `Location`. /// /// Only updates the cursor if absolutely necessary @@ -186,7 +185,7 @@ pub struct Checker<'mir, 'tcx> { secondary_errors: Vec, } -impl Deref for Checker<'mir, 'tcx> { +impl<'mir, 'tcx> Deref for Checker<'mir, 'tcx> { type Target = ConstCx<'mir, 'tcx>; fn deref(&self) -> &Self::Target { @@ -194,7 +193,7 @@ impl Deref for Checker<'mir, 'tcx> { } } -impl Checker<'mir, 'tcx> { +impl<'mir, 'tcx> Checker<'mir, 'tcx> { pub fn new(ccx: &'mir ConstCx<'mir, 'tcx>) -> Self { Checker { span: ccx.body.span, @@ -255,16 +254,6 @@ impl Checker<'mir, 'tcx> { self.visit_body(&body); } - // Ensure that the end result is `Sync` in a non-thread local `static`. - let should_check_for_sync = self.const_kind() - == hir::ConstContext::Static(hir::Mutability::Not) - && !tcx.is_thread_local_static(def_id.to_def_id()); - - if should_check_for_sync { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - check_return_ty_is_sync(tcx, &body, hir_id); - } - // If we got through const-checking without emitting any "primary" errors, emit any // "secondary" errors if they occurred. let secondary_errors = mem::take(&mut self.secondary_errors); @@ -284,7 +273,7 @@ impl Checker<'mir, 'tcx> { struct StorageDeads { locals: BitSet, } - impl Visitor<'tcx> for StorageDeads { + impl<'tcx> Visitor<'tcx> for StorageDeads { fn visit_statement(&mut self, stmt: &Statement<'tcx>, _: Location) { if let StatementKind::StorageDead(l) = stmt.kind { self.locals.insert(l); @@ -471,7 +460,7 @@ impl Checker<'mir, 'tcx> { } } -impl Visitor<'tcx> for Checker<'mir, 'tcx> { +impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { fn visit_basic_block_data(&mut self, bb: BasicBlock, block: &BasicBlockData<'tcx>) { trace!("visit_basic_block_data: bb={:?} is_cleanup={:?}", bb, block.is_cleanup); @@ -643,7 +632,6 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> { } Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {} - Rvalue::NullaryOp(NullOp::Box, _) => self.check_op(ops::HeapAllocation), Rvalue::ShallowInitBox(_, _) => {} Rvalue::UnaryOp(_, ref operand) => { @@ -812,7 +800,7 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> { if let Some(trait_id) = tcx.trait_of_item(callee) { trace!("attempting to call a trait method"); if !self.tcx.features().const_trait_impl { - self.check_op(ops::FnCallNonConst); + self.check_op(ops::FnCallNonConst(Some((callee, substs)))); return; } @@ -828,8 +816,7 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> { ); let implsrc = tcx.infer_ctxt().enter(|infcx| { - let mut selcx = - SelectionContext::with_constness(&infcx, hir::Constness::Const); + let mut selcx = SelectionContext::new(&infcx); selcx.select(&obligation) }); @@ -868,7 +855,7 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> { } if !nonconst_call_permission { - self.check_op(ops::FnCallNonConst); + self.check_op(ops::FnCallNonConst(None)); return; } } @@ -937,7 +924,7 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> { } if !nonconst_call_permission { - self.check_op(ops::FnCallNonConst); + self.check_op(ops::FnCallNonConst(None)); return; } } @@ -1054,21 +1041,7 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> { } } -fn check_return_ty_is_sync(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, hir_id: HirId) { - let ty = body.return_ty(); - tcx.infer_ctxt().enter(|infcx| { - let cause = traits::ObligationCause::new(body.span, hir_id, traits::SharedStatic); - let mut fulfillment_cx = traits::FulfillmentContext::new(); - let sync_def_id = tcx.require_lang_item(LangItem::Sync, Some(body.span)); - fulfillment_cx.register_bound(&infcx, ty::ParamEnv::empty(), ty, sync_def_id, cause); - let errors = fulfillment_cx.select_all_or_error(&infcx); - if !errors.is_empty() { - infcx.report_fulfillment_errors(&errors, None, false); - } - }); -} - -fn place_as_reborrow( +fn place_as_reborrow<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, place: Place<'tcx>, diff --git a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs index dc44409d50..b026bb2bad 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs @@ -28,7 +28,7 @@ pub struct ConstCx<'mir, 'tcx> { pub const_kind: Option, } -impl ConstCx<'mir, 'tcx> { +impl<'mir, 'tcx> ConstCx<'mir, 'tcx> { pub fn new(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>) -> Self { let def_id = body.source.def_id().expect_local(); let param_env = tcx.param_env(def_id); @@ -72,11 +72,7 @@ impl ConstCx<'mir, 'tcx> { } } -pub fn rustc_allow_const_fn_unstable( - tcx: TyCtxt<'tcx>, - def_id: DefId, - feature_gate: Symbol, -) -> bool { +pub fn rustc_allow_const_fn_unstable(tcx: TyCtxt<'_>, def_id: DefId, feature_gate: Symbol) -> bool { let attrs = tcx.get_attrs(def_id); attr::rustc_allow_const_fn_unstable(&tcx.sess, attrs).any(|name| name == feature_gate) } @@ -89,7 +85,7 @@ pub fn rustc_allow_const_fn_unstable( // functions can be called in a const-context by users of the stable compiler. "const-stable" // functions are subject to more stringent restrictions than "const-unstable" functions: They // cannot use unstable features and can only call other "const-stable" functions. -pub fn is_const_stable_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { +pub fn is_const_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { use attr::{ConstStability, Stability, StabilityLevel}; // A default body marked const is not const-stable because const diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index 6391c88600..24c4a4915e 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -1,12 +1,14 @@ //! Concrete error types for all operations which may be invalid in a certain const context. -use rustc_errors::{struct_span_err, DiagnosticBuilder}; +use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_middle::mir; +use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; +use rustc_middle::{mir, ty::AssocKind}; use rustc_session::parse::feature_err; use rustc_span::symbol::sym; -use rustc_span::{Span, Symbol}; +use rustc_span::{symbol::Ident, Span, Symbol}; +use rustc_span::{BytePos, Pos}; use super::ConstCx; @@ -37,7 +39,7 @@ pub trait NonConstOp: std::fmt::Debug { DiagnosticImportance::Primary } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx>; + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx>; } #[derive(Debug)] @@ -51,7 +53,7 @@ impl NonConstOp for FloatingPointOp { } } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { feature_err( &ccx.tcx.sess.parse_sess, sym::const_fn_floating_point_arithmetic, @@ -65,24 +67,78 @@ impl NonConstOp for FloatingPointOp { #[derive(Debug)] pub struct FnCallIndirect; impl NonConstOp for FnCallIndirect { - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { ccx.tcx.sess.struct_span_err(span, "function pointers are not allowed in const fn") } } /// A function call where the callee is not marked as `const`. #[derive(Debug)] -pub struct FnCallNonConst; -impl NonConstOp for FnCallNonConst { - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { - struct_span_err!( +pub struct FnCallNonConst<'tcx>(pub Option<(DefId, SubstsRef<'tcx>)>); +impl<'a> NonConstOp for FnCallNonConst<'a> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + let mut err = struct_span_err!( ccx.tcx.sess, span, E0015, "calls in {}s are limited to constant functions, \ tuple structs and tuple variants", ccx.const_kind(), - ) + ); + + if let FnCallNonConst(Some((callee, substs))) = *self { + if let Some(trait_def_id) = ccx.tcx.lang_items().eq_trait() { + if let Some(eq_item) = ccx.tcx.associated_items(trait_def_id).find_by_name_and_kind( + ccx.tcx, + Ident::with_dummy_span(sym::eq), + AssocKind::Fn, + trait_def_id, + ) { + if callee == eq_item.def_id && substs.len() == 2 { + match (substs[0].unpack(), substs[1].unpack()) { + (GenericArgKind::Type(self_ty), GenericArgKind::Type(rhs_ty)) + if self_ty == rhs_ty + && self_ty.is_ref() + && self_ty.peel_refs().is_primitive() => + { + let mut num_refs = 0; + let mut tmp_ty = self_ty; + while let rustc_middle::ty::Ref(_, inner_ty, _) = tmp_ty.kind() { + num_refs += 1; + tmp_ty = inner_ty; + } + let deref = "*".repeat(num_refs); + + if let Ok(call_str) = + ccx.tcx.sess.source_map().span_to_snippet(span) + { + if let Some(eq_idx) = call_str.find("==") { + if let Some(rhs_idx) = call_str[(eq_idx + 2)..] + .find(|c: char| !c.is_whitespace()) + { + let rhs_pos = span.lo() + + BytePos::from_usize(eq_idx + 2 + rhs_idx); + let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos); + err.multipart_suggestion( + "consider dereferencing here", + vec![ + (span.shrink_to_lo(), deref.clone()), + (rhs_span, deref), + ], + Applicability::MachineApplicable, + ); + } + } + } + } + _ => {} + } + } + } + } + } + + err } } @@ -93,7 +149,7 @@ impl NonConstOp for FnCallNonConst { pub struct FnCallUnstable(pub DefId, pub Option); impl NonConstOp for FnCallUnstable { - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let FnCallUnstable(def_id, feature) = *self; let mut err = ccx.tcx.sess.struct_span_err( @@ -127,7 +183,7 @@ impl NonConstOp for FnPtrCast { } } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { feature_err( &ccx.tcx.sess.parse_sess, sym::const_fn_fn_ptr_basics, @@ -148,7 +204,7 @@ impl NonConstOp for Generator { } } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let msg = format!("{}s are not allowed in {}s", self.0, ccx.const_kind()); if let hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) = self.0 { feature_err(&ccx.tcx.sess.parse_sess, sym::const_async_blocks, span, &msg) @@ -161,7 +217,7 @@ impl NonConstOp for Generator { #[derive(Debug)] pub struct HeapAllocation; impl NonConstOp for HeapAllocation { - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let mut err = struct_span_err!( ccx.tcx.sess, span, @@ -185,7 +241,7 @@ impl NonConstOp for HeapAllocation { #[derive(Debug)] pub struct InlineAsm; impl NonConstOp for InlineAsm { - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { struct_span_err!( ccx.tcx.sess, span, @@ -201,7 +257,7 @@ pub struct LiveDrop { pub dropped_at: Option, } impl NonConstOp for LiveDrop { - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let mut err = struct_span_err!( ccx.tcx.sess, span, @@ -229,7 +285,7 @@ impl NonConstOp for TransientCellBorrow { // not additionally emit a feature gate error if activating the feature gate won't work. DiagnosticImportance::Secondary } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { feature_err( &ccx.tcx.sess.parse_sess, sym::const_refs_to_cell, @@ -245,7 +301,7 @@ impl NonConstOp for TransientCellBorrow { /// it in the future for static items. pub struct CellBorrow; impl NonConstOp for CellBorrow { - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let mut err = struct_span_err!( ccx.tcx.sess, span, @@ -292,7 +348,7 @@ impl NonConstOp for MutBorrow { DiagnosticImportance::Secondary } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let raw = match self.0 { hir::BorrowKind::Raw => "raw ", hir::BorrowKind::Ref => "", @@ -331,7 +387,7 @@ impl NonConstOp for TransientMutBorrow { Status::Unstable(sym::const_mut_refs) } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let raw = match self.0 { hir::BorrowKind::Raw => "raw ", hir::BorrowKind::Ref => "", @@ -358,7 +414,7 @@ impl NonConstOp for MutDeref { DiagnosticImportance::Secondary } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { feature_err( &ccx.tcx.sess.parse_sess, sym::const_mut_refs, @@ -372,7 +428,7 @@ impl NonConstOp for MutDeref { #[derive(Debug)] pub struct PanicNonStr; impl NonConstOp for PanicNonStr { - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { ccx.tcx.sess.struct_span_err( span, "argument to `panic!()` in a const context must have type `&str`", @@ -386,7 +442,7 @@ impl NonConstOp for PanicNonStr { #[derive(Debug)] pub struct RawPtrComparison; impl NonConstOp for RawPtrComparison { - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let mut err = ccx .tcx .sess @@ -406,7 +462,7 @@ impl NonConstOp for RawMutPtrDeref { Status::Unstable(sym::const_mut_refs) } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { feature_err( &ccx.tcx.sess.parse_sess, sym::const_mut_refs, @@ -422,7 +478,7 @@ impl NonConstOp for RawMutPtrDeref { #[derive(Debug)] pub struct RawPtrToIntCast; impl NonConstOp for RawPtrToIntCast { - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let mut err = ccx .tcx .sess @@ -447,7 +503,7 @@ impl NonConstOp for StaticAccess { } } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { let mut err = struct_span_err!( ccx.tcx.sess, span, @@ -473,7 +529,7 @@ impl NonConstOp for StaticAccess { #[derive(Debug)] pub struct ThreadLocalAccess; impl NonConstOp for ThreadLocalAccess { - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { struct_span_err!( ccx.tcx.sess, span, @@ -504,7 +560,11 @@ pub mod ty { } } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>( + &self, + ccx: &ConstCx<'_, 'tcx>, + span: Span, + ) -> DiagnosticBuilder<'tcx> { feature_err( &ccx.tcx.sess.parse_sess, sym::const_mut_refs, @@ -534,7 +594,11 @@ pub mod ty { } } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>( + &self, + ccx: &ConstCx<'_, 'tcx>, + span: Span, + ) -> DiagnosticBuilder<'tcx> { feature_err( &ccx.tcx.sess.parse_sess, sym::const_fn_fn_ptr_basics, @@ -551,7 +615,11 @@ pub mod ty { Status::Unstable(sym::const_impl_trait) } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>( + &self, + ccx: &ConstCx<'_, 'tcx>, + span: Span, + ) -> DiagnosticBuilder<'tcx> { feature_err( &ccx.tcx.sess.parse_sess, sym::const_impl_trait, @@ -581,7 +649,11 @@ pub mod ty { } } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>( + &self, + ccx: &ConstCx<'_, 'tcx>, + span: Span, + ) -> DiagnosticBuilder<'tcx> { let mut err = feature_err( &ccx.tcx.sess.parse_sess, sym::const_fn_trait_bound, @@ -620,7 +692,11 @@ pub mod ty { } } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>( + &self, + ccx: &ConstCx<'_, 'tcx>, + span: Span, + ) -> DiagnosticBuilder<'tcx> { let mut err = feature_err( &ccx.tcx.sess.parse_sess, sym::const_fn_trait_bound, @@ -647,7 +723,11 @@ pub mod ty { Status::Unstable(sym::const_trait_bound_opt_out) } - fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { + fn build_error<'tcx>( + &self, + ccx: &ConstCx<'_, 'tcx>, + span: Span, + ) -> DiagnosticBuilder<'tcx> { feature_err( &ccx.tcx.sess.parse_sess, sym::const_trait_bound_opt_out, diff --git a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs index 7a2be3c3ba..4e210f6635 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs @@ -23,7 +23,7 @@ pub fn checking_enabled(ccx: &ConstCx<'_, '_>) -> bool { /// /// This is separate from the rest of the const checking logic because it must run after drop /// elaboration. -pub fn check_live_drops(tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>) { +pub fn check_live_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>) { let def_id = body.source.def_id().expect_local(); let const_kind = tcx.hir().body_const_context(def_id); if const_kind.is_none() { @@ -50,7 +50,7 @@ struct CheckLiveDrops<'mir, 'tcx> { } // So we can access `body` and `tcx`. -impl std::ops::Deref for CheckLiveDrops<'mir, 'tcx> { +impl<'mir, 'tcx> std::ops::Deref for CheckLiveDrops<'mir, 'tcx> { type Target = ConstCx<'mir, 'tcx>; fn deref(&self) -> &Self::Target { @@ -58,13 +58,13 @@ impl std::ops::Deref for CheckLiveDrops<'mir, 'tcx> { } } -impl CheckLiveDrops<'mir, 'tcx> { +impl CheckLiveDrops<'_, '_> { fn check_live_drop(&self, span: Span) { ops::LiveDrop { dropped_at: None }.build_error(self.ccx, span).emit(); } } -impl Visitor<'tcx> for CheckLiveDrops<'mir, 'tcx> { +impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> { fn visit_basic_block_data(&mut self, bb: BasicBlock, block: &mir::BasicBlockData<'tcx>) { trace!("visit_basic_block_data: bb={:?} is_cleanup={:?}", bb, block.is_cleanup); @@ -80,7 +80,8 @@ impl Visitor<'tcx> for CheckLiveDrops<'mir, 'tcx> { trace!("visit_terminator: terminator={:?} location={:?}", terminator, location); match &terminator.kind { - mir::TerminatorKind::Drop { place: dropped_place, .. } => { + mir::TerminatorKind::Drop { place: dropped_place, .. } + | mir::TerminatorKind::DropAndReplace { place: dropped_place, .. } => { let dropped_ty = dropped_place.ty(self.body, self.tcx).ty; if !NeedsNonConstDrop::in_any_value_of_ty(self.ccx, dropped_ty) { // Instead of throwing a bug, we just return here. This is because we have to @@ -104,11 +105,6 @@ impl Visitor<'tcx> for CheckLiveDrops<'mir, 'tcx> { } } - mir::TerminatorKind::DropAndReplace { .. } => span_bug!( - terminator.source_info.span, - "`DropAndReplace` should be removed by drop elaboration", - ), - mir::TerminatorKind::Abort | mir::TerminatorKind::Call { .. } | mir::TerminatorKind::Assert { .. } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index abc5a3c6a5..27f2da3426 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -3,7 +3,6 @@ //! See the `Qualif` trait for more info. use rustc_errors::ErrorReported; -use rustc_hir as hir; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir::*; use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty}; @@ -14,7 +13,7 @@ use rustc_trait_selection::traits::{ use super::ConstCx; -pub fn in_any_value_of_ty( +pub fn in_any_value_of_ty<'tcx>( cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>, error_occured: Option, @@ -59,7 +58,7 @@ pub trait Qualif { /// from a call to another function. /// /// It also determines the `Qualif`s for primitive types. - fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool; + fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool; /// Returns `true` if this `Qualif` is inherent to the given struct or enum. /// @@ -69,7 +68,7 @@ pub trait Qualif { /// with a custom `Drop` impl is inherently `NeedsDrop`. /// /// Returning `true` for `in_adt_inherently` but `false` for `in_any_value_of_ty` is unsound. - fn in_adt_inherently( + fn in_adt_inherently<'tcx>( cx: &ConstCx<'_, 'tcx>, adt: &'tcx AdtDef, substs: SubstsRef<'tcx>, @@ -90,11 +89,15 @@ impl Qualif for HasMutInterior { qualifs.has_mut_interior } - fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { + fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { !ty.is_freeze(cx.tcx.at(DUMMY_SP), cx.param_env) } - fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &'tcx AdtDef, _: SubstsRef<'tcx>) -> bool { + fn in_adt_inherently<'tcx>( + cx: &ConstCx<'_, 'tcx>, + adt: &'tcx AdtDef, + _: SubstsRef<'tcx>, + ) -> bool { // Exactly one type, `UnsafeCell`, has the `HasMutInterior` qualif inherently. // It arises structurally for all other types. Some(adt.did) == cx.tcx.lang_items().unsafe_cell_type() @@ -116,11 +119,15 @@ impl Qualif for NeedsDrop { qualifs.needs_drop } - fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { + fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { ty.needs_drop(cx.tcx, cx.param_env) } - fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &'tcx AdtDef, _: SubstsRef<'tcx>) -> bool { + fn in_adt_inherently<'tcx>( + cx: &ConstCx<'_, 'tcx>, + adt: &'tcx AdtDef, + _: SubstsRef<'tcx>, + ) -> bool { adt.has_dtor(cx.tcx) } } @@ -138,7 +145,7 @@ impl Qualif for NeedsNonConstDrop { qualifs.needs_non_const_drop } - fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, mut ty: Ty<'tcx>) -> bool { + fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, mut ty: Ty<'tcx>) -> bool { // Avoid selecting for simple cases. match ty::util::needs_drop_components(ty, &cx.tcx.data_layout).as_deref() { Ok([]) => return false, @@ -167,7 +174,7 @@ impl Qualif for NeedsNonConstDrop { ); let implsrc = cx.tcx.infer_ctxt().enter(|infcx| { - let mut selcx = SelectionContext::with_constness(&infcx, hir::Constness::Const); + let mut selcx = SelectionContext::new(&infcx); selcx.select(&obligation) }); !matches!( @@ -178,7 +185,11 @@ impl Qualif for NeedsNonConstDrop { ) } - fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &'tcx AdtDef, _: SubstsRef<'tcx>) -> bool { + fn in_adt_inherently<'tcx>( + cx: &ConstCx<'_, 'tcx>, + adt: &'tcx AdtDef, + _: SubstsRef<'tcx>, + ) -> bool { adt.has_non_const_dtor(cx.tcx) } } @@ -193,7 +204,7 @@ impl Qualif for CustomEq { qualifs.custom_eq } - fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { + fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { // If *any* component of a composite data type does not implement `Structural{Partial,}Eq`, // we know that at least some values of that type are not structural-match. I say "some" // because that component may be part of an enum variant (e.g., @@ -203,7 +214,7 @@ impl Qualif for CustomEq { traits::search_for_structural_match_violation(id, cx.body.span, cx.tcx, ty).is_some() } - fn in_adt_inherently( + fn in_adt_inherently<'tcx>( cx: &ConstCx<'_, 'tcx>, adt: &'tcx AdtDef, substs: SubstsRef<'tcx>, @@ -216,7 +227,11 @@ impl Qualif for CustomEq { // FIXME: Use `mir::visit::Visitor` for the `in_*` functions if/when it supports early return. /// Returns `true` if this `Rvalue` contains qualif `Q`. -pub fn in_rvalue(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, rvalue: &Rvalue<'tcx>) -> bool +pub fn in_rvalue<'tcx, Q, F>( + cx: &ConstCx<'_, 'tcx>, + in_local: &mut F, + rvalue: &Rvalue<'tcx>, +) -> bool where Q: Qualif, F: FnMut(Local) -> bool, @@ -255,7 +270,8 @@ where Rvalue::Aggregate(kind, operands) => { // Return early if we know that the struct or enum being constructed is always // qualified. - if let AggregateKind::Adt(def, _, substs, ..) = **kind { + if let AggregateKind::Adt(adt_did, _, substs, ..) = **kind { + let def = cx.tcx.adt_def(adt_did); if Q::in_adt_inherently(cx, def, substs) { return true; } @@ -271,7 +287,7 @@ where } /// Returns `true` if this `Place` contains qualif `Q`. -pub fn in_place(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, place: PlaceRef<'tcx>) -> bool +pub fn in_place<'tcx, Q, F>(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, place: PlaceRef<'tcx>) -> bool where Q: Qualif, F: FnMut(Local) -> bool, @@ -303,7 +319,11 @@ where } /// Returns `true` if this `Operand` contains qualif `Q`. -pub fn in_operand(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, operand: &Operand<'tcx>) -> bool +pub fn in_operand<'tcx, Q, F>( + cx: &ConstCx<'_, 'tcx>, + in_local: &mut F, + operand: &Operand<'tcx>, +) -> bool where Q: Qualif, F: FnMut(Local) -> bool, diff --git a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs index b70b38754c..fd7febc17a 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs @@ -7,6 +7,7 @@ use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{self, BasicBlock, Local, Location, Statement, StatementKind}; use rustc_mir_dataflow::fmt::DebugWithContext; use rustc_mir_dataflow::JoinSemiLattice; +use rustc_mir_dataflow::{Analysis, AnalysisDomain, CallReturnPlaces}; use rustc_span::DUMMY_SP; use std::fmt; @@ -27,7 +28,7 @@ struct TransferFunction<'a, 'mir, 'tcx, Q> { _qualif: PhantomData, } -impl TransferFunction<'a, 'mir, 'tcx, Q> +impl<'a, 'mir, 'tcx, Q> TransferFunction<'a, 'mir, 'tcx, Q> where Q: Qualif, { @@ -80,18 +81,18 @@ where fn apply_call_return_effect( &mut self, _block: BasicBlock, - _func: &mir::Operand<'tcx>, - _args: &[mir::Operand<'tcx>], - return_place: mir::Place<'tcx>, + return_places: CallReturnPlaces<'_, 'tcx>, ) { - // We cannot reason about another function's internals, so use conservative type-based - // qualification for the result of a function call. - let return_ty = return_place.ty(self.ccx.body, self.ccx.tcx).ty; - let qualif = Q::in_any_value_of_ty(self.ccx, return_ty); + return_places.for_each(|place| { + // We cannot reason about another function's internals, so use conservative type-based + // qualification for the result of a function call. + let return_ty = place.ty(self.ccx.body, self.ccx.tcx).ty; + let qualif = Q::in_any_value_of_ty(self.ccx, return_ty); - if !return_place.is_indirect() { - self.assign_qualif_direct(&return_place, qualif); - } + if !place.is_indirect() { + self.assign_qualif_direct(&place, qualif); + } + }); } fn address_of_allows_mutation(&self, _mt: mir::Mutability, _place: mir::Place<'tcx>) -> bool { @@ -126,7 +127,7 @@ where } } -impl Visitor<'tcx> for TransferFunction<'_, '_, 'tcx, Q> +impl<'tcx, Q> Visitor<'tcx> for TransferFunction<'_, '_, 'tcx, Q> where Q: Qualif, { @@ -329,7 +330,7 @@ impl JoinSemiLattice for State { } } -impl rustc_mir_dataflow::AnalysisDomain<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q> +impl<'tcx, Q> AnalysisDomain<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q> where Q: Qualif, { @@ -349,7 +350,7 @@ where } } -impl rustc_mir_dataflow::Analysis<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q> +impl<'tcx, Q> Analysis<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q> where Q: Qualif, { @@ -375,10 +376,8 @@ where &self, state: &mut Self::Domain, block: BasicBlock, - func: &mir::Operand<'tcx>, - args: &[mir::Operand<'tcx>], - return_place: mir::Place<'tcx>, + return_places: CallReturnPlaces<'_, 'tcx>, ) { - self.transfer_function(state).apply_call_return_effect(block, func, args, return_place) + self.transfer_function(state).apply_call_return_effect(block, return_places) } } diff --git a/compiler/rustc_const_eval/src/transform/mod.rs b/compiler/rustc_const_eval/src/transform/mod.rs index 38c28f3493..a2928bdf51 100644 --- a/compiler/rustc_const_eval/src/transform/mod.rs +++ b/compiler/rustc_const_eval/src/transform/mod.rs @@ -1,5 +1,3 @@ pub mod check_consts; pub mod promote_consts; pub mod validate; - -pub use rustc_middle::mir::MirPass; diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index a92b20f5cb..55fba5d7dd 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -27,7 +27,6 @@ use std::cell::Cell; use std::{cmp, iter, mem}; use crate::transform::check_consts::{qualifs, ConstCx}; -use crate::transform::MirPass; /// A `MirPass` for promotion. /// @@ -42,6 +41,10 @@ pub struct PromoteTemps<'tcx> { } impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> { + fn phase_change(&self) -> Option { + Some(MirPhase::ConstPromotion) + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // There's not really any point in promoting errorful MIR. // @@ -165,8 +168,8 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> { } } -pub fn collect_temps_and_candidates( - ccx: &ConstCx<'mir, 'tcx>, +pub fn collect_temps_and_candidates<'tcx>( + ccx: &ConstCx<'_, 'tcx>, rpo: &mut ReversePostorder<'_, 'tcx>, ) -> (IndexVec, Vec) { let mut collector = Collector { @@ -188,7 +191,7 @@ struct Validator<'a, 'tcx> { temps: &'a IndexVec, } -impl std::ops::Deref for Validator<'a, 'tcx> { +impl<'a, 'tcx> std::ops::Deref for Validator<'a, 'tcx> { type Target = ConstCx<'a, 'tcx>; fn deref(&self) -> &Self::Target { @@ -505,7 +508,6 @@ impl<'tcx> Validator<'_, 'tcx> { } Rvalue::NullaryOp(op, _) => match op { - NullOp::Box => return Err(Unpromotable), NullOp::SizeOf => {} NullOp::AlignOf => {} }, diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index b09b2227f3..c3f81a3ab8 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -1,14 +1,13 @@ //! Validates the MIR to ensure that invariants are upheld. -use super::MirPass; use rustc_index::bit_set::BitSet; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::traversal; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::{ - AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, PlaceElem, - PlaceRef, ProjectionElem, Rvalue, SourceScope, Statement, StatementKind, Terminator, + AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPass, MirPhase, Operand, + PlaceElem, PlaceRef, ProjectionElem, Rvalue, SourceScope, Statement, StatementKind, Terminator, TerminatorKind, START_BLOCK, }; use rustc_middle::ty::fold::BottomUpFolder; @@ -67,7 +66,7 @@ impl<'tcx> MirPass<'tcx> for Validator { /// /// The point of this function is to approximate "equal up to subtyping". However, /// the approximation is incorrect as variance is ignored. -pub fn equal_up_to_regions( +pub fn equal_up_to_regions<'tcx>( tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, src: Ty<'tcx>, @@ -496,10 +495,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { self.check_edge(location, *unwind, EdgeKind::Unwind); } } - TerminatorKind::InlineAsm { destination, .. } => { + TerminatorKind::InlineAsm { destination, cleanup, .. } => { if let Some(destination) = destination { self.check_edge(location, *destination, EdgeKind::Normal); } + if let Some(cleanup) = cleanup { + self.check_edge(location, *cleanup, EdgeKind::Unwind); + } } // Nothing to validate for these. TerminatorKind::Resume diff --git a/compiler/rustc_const_eval/src/util/aggregate.rs b/compiler/rustc_const_eval/src/util/aggregate.rs index 4bc0357cab..e5f5e7072d 100644 --- a/compiler/rustc_const_eval/src/util/aggregate.rs +++ b/compiler/rustc_const_eval/src/util/aggregate.rs @@ -22,7 +22,8 @@ pub fn expand_aggregate<'tcx>( ) -> impl Iterator> + TrustedLen { let mut set_discriminant = None; let active_field_index = match kind { - AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => { + AggregateKind::Adt(adt_did, variant_index, _, _, active_field_index) => { + let adt_def = tcx.adt_def(adt_did); if adt_def.is_enum() { set_discriminant = Some(Statement { kind: StatementKind::SetDiscriminant { place: Box::new(lhs), variant_index }, diff --git a/compiler/rustc_data_structures/src/binary_search_util/mod.rs b/compiler/rustc_data_structures/src/binary_search_util/mod.rs index ede5757a47..bf09b2f8ee 100644 --- a/compiler/rustc_data_structures/src/binary_search_util/mod.rs +++ b/compiler/rustc_data_structures/src/binary_search_util/mod.rs @@ -6,7 +6,7 @@ mod tests; /// function finds the range of elements that match the key. `data` /// must have been sorted as if by a call to `sort_by_key` for this to /// work. -pub fn binary_search_slice(data: &'d [E], key_fn: impl Fn(&E) -> K, key: &K) -> &'d [E] +pub fn binary_search_slice<'d, E, K>(data: &'d [E], key_fn: impl Fn(&E) -> K, key: &K) -> &'d [E] where K: Ord, { diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs index c0c0e7be3c..c9af35da4b 100644 --- a/compiler/rustc_data_structures/src/fingerprint.rs +++ b/compiler/rustc_data_structures/src/fingerprint.rs @@ -142,7 +142,7 @@ impl_stable_hash_via_hash!(Fingerprint); impl Encodable for Fingerprint { #[inline] fn encode(&self, s: &mut E) -> Result<(), E::Error> { - s.emit_raw_bytes(&self.to_le_bytes()[..])?; + s.emit_raw_bytes(&self.to_le_bytes())?; Ok(()) } } @@ -151,7 +151,7 @@ impl Decodable for Fingerprint { #[inline] fn decode(d: &mut D) -> Result { let mut bytes = [0u8; 16]; - d.read_raw_bytes_into(&mut bytes[..])?; + d.read_raw_bytes_into(&mut bytes)?; Ok(Fingerprint::from_le_bytes(bytes)) } } diff --git a/compiler/rustc_data_structures/src/functor.rs b/compiler/rustc_data_structures/src/functor.rs index 5b83ae3124..a3d3f98834 100644 --- a/compiler/rustc_data_structures/src/functor.rs +++ b/compiler/rustc_data_structures/src/functor.rs @@ -1,35 +1,32 @@ use rustc_index::vec::{Idx, IndexVec}; use std::mem; -use std::ptr; -pub trait IdFunctor { +pub trait IdFunctor: Sized { type Inner; - fn map_id(self, f: F) -> Self + fn try_map_id(self, f: F) -> Result where - F: FnMut(Self::Inner) -> Self::Inner; + F: FnMut(Self::Inner) -> Result; } impl IdFunctor for Box { type Inner = T; #[inline] - fn map_id(self, mut f: F) -> Self + fn try_map_id(self, mut f: F) -> Result where - F: FnMut(Self::Inner) -> Self::Inner, + F: FnMut(Self::Inner) -> Result, { let raw = Box::into_raw(self); - unsafe { + Ok(unsafe { // SAFETY: The raw pointer points to a valid value of type `T`. - let value = ptr::read(raw); + let value = raw.read(); // SAFETY: Converts `Box` to `Box>` which is the // inverse of `Box::assume_init()` and should be safe. - let mut raw: Box> = Box::from_raw(raw.cast()); + let raw: Box> = Box::from_raw(raw.cast()); // SAFETY: Write the mapped value back into the `Box`. - raw.write(f(value)); - // SAFETY: We just initialized `raw`. - raw.assume_init() - } + Box::write(raw, f(value)?) + }) } } @@ -37,23 +34,43 @@ impl IdFunctor for Vec { type Inner = T; #[inline] - fn map_id(mut self, mut f: F) -> Self + fn try_map_id(self, mut f: F) -> Result where - F: FnMut(Self::Inner) -> Self::Inner, + F: FnMut(Self::Inner) -> Result, { - // FIXME: We don't really care about panics here and leak - // far more than we should, but that should be fine for now. - let len = self.len(); - unsafe { - self.set_len(0); - let start = self.as_mut_ptr(); - for i in 0..len { - let p = start.add(i); - ptr::write(p, f(ptr::read(p))); - } - self.set_len(len); + struct HoleVec { + vec: Vec>, + hole: Option, + } + + impl Drop for HoleVec { + fn drop(&mut self) { + unsafe { + for (index, slot) in self.vec.iter_mut().enumerate() { + if self.hole != Some(index) { + mem::ManuallyDrop::drop(slot); + } + } + } + } + } + + unsafe { + let (ptr, length, capacity) = self.into_raw_parts(); + let vec = Vec::from_raw_parts(ptr.cast(), length, capacity); + let mut hole_vec = HoleVec { vec, hole: None }; + + for (index, slot) in hole_vec.vec.iter_mut().enumerate() { + hole_vec.hole = Some(index); + let original = mem::ManuallyDrop::take(slot); + let mapped = f(original)?; + *slot = mem::ManuallyDrop::new(mapped); + hole_vec.hole = None; + } + + mem::forget(hole_vec); + Ok(Vec::from_raw_parts(ptr, length, capacity)) } - self } } @@ -61,11 +78,11 @@ impl IdFunctor for Box<[T]> { type Inner = T; #[inline] - fn map_id(self, f: F) -> Self + fn try_map_id(self, f: F) -> Result where - F: FnMut(Self::Inner) -> Self::Inner, + F: FnMut(Self::Inner) -> Result, { - Vec::from(self).map_id(f).into() + Vec::from(self).try_map_id(f).map(Into::into) } } @@ -73,10 +90,10 @@ impl IdFunctor for IndexVec { type Inner = T; #[inline] - fn map_id(self, f: F) -> Self + fn try_map_id(self, f: F) -> Result where - F: FnMut(Self::Inner) -> Self::Inner, + F: FnMut(Self::Inner) -> Result, { - IndexVec::from_raw(self.raw.map_id(f)) + self.raw.try_map_id(f).map(IndexVec::from_raw) } } diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs index 1cd170599b..0d2ae115cb 100644 --- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs +++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs @@ -1,11 +1,14 @@ //! Finding the dominators in a control-flow graph. //! -//! Algorithm based on Keith D. Cooper, Timothy J. Harvey, and Ken Kennedy, -//! "A Simple, Fast Dominance Algorithm", -//! Rice Computer Science TS-06-33870, -//! . +//! Algorithm based on Loukas Georgiadis, +//! "Linear-Time Algorithms for Dominators and Related Problems", +//! +//! +//! Additionally useful is the original Lengauer-Tarjan paper on this subject, +//! "A Fast Algorithm for Finding Dominators in a Flowgraph" +//! Thomas Lengauer and Robert Endre Tarjan. +//! -use super::iterate::reverse_post_order; use super::ControlFlowGraph; use rustc_index::vec::{Idx, IndexVec}; use std::cmp::Ordering; @@ -13,69 +16,239 @@ use std::cmp::Ordering; #[cfg(test)] mod tests; -pub fn dominators(graph: G) -> Dominators { - let start_node = graph.start_node(); - let rpo = reverse_post_order(&graph, start_node); - dominators_given_rpo(graph, &rpo) +struct PreOrderFrame { + pre_order_idx: PreorderIndex, + iter: Iter, } -fn dominators_given_rpo(graph: G, rpo: &[G::Node]) -> Dominators { - let start_node = graph.start_node(); - assert_eq!(rpo[0], start_node); +rustc_index::newtype_index! { + struct PreorderIndex { .. } +} +pub fn dominators(graph: G) -> Dominators { // compute the post order index (rank) for each node let mut post_order_rank = IndexVec::from_elem_n(0, graph.num_nodes()); - for (index, node) in rpo.iter().rev().cloned().enumerate() { - post_order_rank[node] = index; + + // We allocate capacity for the full set of nodes, because most of the time + // most of the nodes *are* reachable. + let mut parent: IndexVec = + IndexVec::with_capacity(graph.num_nodes()); + + let mut stack = vec![PreOrderFrame { + pre_order_idx: PreorderIndex::new(0), + iter: graph.successors(graph.start_node()), + }]; + let mut pre_order_to_real: IndexVec = + IndexVec::with_capacity(graph.num_nodes()); + let mut real_to_pre_order: IndexVec> = + IndexVec::from_elem_n(None, graph.num_nodes()); + pre_order_to_real.push(graph.start_node()); + parent.push(PreorderIndex::new(0)); // the parent of the root node is the root for now. + real_to_pre_order[graph.start_node()] = Some(PreorderIndex::new(0)); + let mut post_order_idx = 0; + + // Traverse the graph, collecting a number of things: + // + // * Preorder mapping (to it, and back to the actual ordering) + // * Postorder mapping (used exclusively for rank_partial_cmp on the final product) + // * Parents for each vertex in the preorder tree + // + // These are all done here rather than through one of the 'standard' + // graph traversals to help make this fast. + 'recurse: while let Some(frame) = stack.last_mut() { + while let Some(successor) = frame.iter.next() { + if real_to_pre_order[successor].is_none() { + let pre_order_idx = pre_order_to_real.push(successor); + real_to_pre_order[successor] = Some(pre_order_idx); + parent.push(frame.pre_order_idx); + stack.push(PreOrderFrame { pre_order_idx, iter: graph.successors(successor) }); + + continue 'recurse; + } + } + post_order_rank[pre_order_to_real[frame.pre_order_idx]] = post_order_idx; + post_order_idx += 1; + + stack.pop(); + } + + let reachable_vertices = pre_order_to_real.len(); + + let mut idom = IndexVec::from_elem_n(PreorderIndex::new(0), reachable_vertices); + let mut semi = IndexVec::from_fn_n(std::convert::identity, reachable_vertices); + let mut label = semi.clone(); + let mut bucket = IndexVec::from_elem_n(vec![], reachable_vertices); + let mut lastlinked = None; + + // We loop over vertices in reverse preorder. This implements the pseudocode + // of the simple Lengauer-Tarjan algorithm. A few key facts are noted here + // which are helpful for understanding the code (full proofs and such are + // found in various papers, including one cited at the top of this file). + // + // For each vertex w (which is not the root), + // * semi[w] is a proper ancestor of the vertex w (i.e., semi[w] != w) + // * idom[w] is an ancestor of semi[w] (i.e., idom[w] may equal semi[w]) + // + // An immediate dominator of w (idom[w]) is a vertex v where v dominates w + // and every other dominator of w dominates v. (Every vertex except the root has + // a unique immediate dominator.) + // + // A semidominator for a given vertex w (semi[w]) is the vertex v with minimum + // preorder number such that there exists a path from v to w in which all elements (other than w) have + // preorder numbers greater than w (i.e., this path is not the tree path to + // w). + for w in (PreorderIndex::new(1)..PreorderIndex::new(reachable_vertices)).rev() { + // Optimization: process buckets just once, at the start of the + // iteration. Do not explicitly empty the bucket (even though it will + // not be used again), to save some instructions. + // + // The bucket here contains the vertices whose semidominator is the + // vertex w, which we are guaranteed to have found: all vertices who can + // be semidominated by w must have a preorder number exceeding w, so + // they have been placed in the bucket. + // + // We compute a partial set of immediate dominators here. + let z = parent[w]; + for &v in bucket[z].iter() { + // This uses the result of Lemma 5 from section 2 from the original + // 1979 paper, to compute either the immediate or relative dominator + // for a given vertex v. + // + // eval returns a vertex y, for which semi[y] is minimum among + // vertices semi[v] +> y *> v. Note that semi[v] = z as we're in the + // z bucket. + // + // Given such a vertex y, semi[y] <= semi[v] and idom[y] = idom[v]. + // If semi[y] = semi[v], though, idom[v] = semi[v]. + // + // Using this, we can either set idom[v] to be: + // * semi[v] (i.e. z), if semi[y] is z + // * idom[y], otherwise + // + // We don't directly set to idom[y] though as it's not necessarily + // known yet. The second preorder traversal will cleanup by updating + // the idom for any that were missed in this pass. + let y = eval(&mut parent, lastlinked, &semi, &mut label, v); + idom[v] = if semi[y] < z { y } else { z }; + } + + // This loop computes the semi[w] for w. + semi[w] = w; + for v in graph.predecessors(pre_order_to_real[w]) { + let v = real_to_pre_order[v].unwrap(); + + // eval returns a vertex x from which semi[x] is minimum among + // vertices semi[v] +> x *> v. + // + // From Lemma 4 from section 2, we know that the semidominator of a + // vertex w is the minimum (by preorder number) vertex of the + // following: + // + // * direct predecessors of w with preorder number less than w + // * semidominators of u such that u > w and there exists (v, w) + // such that u *> v + // + // This loop therefore identifies such a minima. Note that any + // semidominator path to w must have all but the first vertex go + // through vertices numbered greater than w, so the reverse preorder + // traversal we are using guarantees that all of the information we + // might need is available at this point. + // + // The eval call will give us semi[x], which is either: + // + // * v itself, if v has not yet been processed + // * A possible 'best' semidominator for w. + let x = eval(&mut parent, lastlinked, &semi, &mut label, v); + semi[w] = std::cmp::min(semi[w], semi[x]); + } + // semi[w] is now semidominator(w) and won't change any more. + + // Optimization: Do not insert into buckets if parent[w] = semi[w], as + // we then immediately know the idom. + // + // If we don't yet know the idom directly, then push this vertex into + // our semidominator's bucket, where it will get processed at a later + // stage to compute its immediate dominator. + if parent[w] != semi[w] { + bucket[semi[w]].push(w); + } else { + idom[w] = parent[w]; + } + + // Optimization: We share the parent array between processed and not + // processed elements; lastlinked represents the divider. + lastlinked = Some(w); + } + + // Finalize the idoms for any that were not fully settable during initial + // traversal. + // + // If idom[w] != semi[w] then we know that we've stored vertex y from above + // into idom[w]. It is known to be our 'relative dominator', which means + // that it's one of w's ancestors and has the same immediate dominator as w, + // so use that idom. + for w in PreorderIndex::new(1)..PreorderIndex::new(reachable_vertices) { + if idom[w] != semi[w] { + idom[w] = idom[idom[w]]; + } } let mut immediate_dominators = IndexVec::from_elem_n(None, graph.num_nodes()); - immediate_dominators[start_node] = Some(start_node); - - let mut changed = true; - while changed { - changed = false; - - for &node in &rpo[1..] { - let mut new_idom = None; - for pred in graph.predecessors(node) { - if immediate_dominators[pred].is_some() { - // (*) dominators for `pred` have been calculated - new_idom = Some(if let Some(new_idom) = new_idom { - intersect(&post_order_rank, &immediate_dominators, new_idom, pred) - } else { - pred - }); - } - } - - if new_idom != immediate_dominators[node] { - immediate_dominators[node] = new_idom; - changed = true; - } - } + for (idx, node) in pre_order_to_real.iter_enumerated() { + immediate_dominators[*node] = Some(pre_order_to_real[idom[idx]]); } Dominators { post_order_rank, immediate_dominators } } -fn intersect( - post_order_rank: &IndexVec, - immediate_dominators: &IndexVec>, - mut node1: Node, - mut node2: Node, -) -> Node { - while node1 != node2 { - while post_order_rank[node1] < post_order_rank[node2] { - node1 = immediate_dominators[node1].unwrap(); - } - - while post_order_rank[node2] < post_order_rank[node1] { - node2 = immediate_dominators[node2].unwrap(); - } +/// Evaluate the link-eval virtual forest, providing the currently minimum semi +/// value for the passed `node` (which may be itself). +/// +/// This maintains that for every vertex v, `label[v]` is such that: +/// +/// ```text +/// semi[eval(v)] = min { semi[label[u]] | root_in_forest(v) +> u *> v } +/// ``` +/// +/// where `+>` is a proper ancestor and `*>` is just an ancestor. +#[inline] +fn eval( + ancestor: &mut IndexVec, + lastlinked: Option, + semi: &IndexVec, + label: &mut IndexVec, + node: PreorderIndex, +) -> PreorderIndex { + if is_processed(node, lastlinked) { + compress(ancestor, lastlinked, semi, label, node); + label[node] + } else { + node } +} - node1 +#[inline] +fn is_processed(v: PreorderIndex, lastlinked: Option) -> bool { + if let Some(ll) = lastlinked { v >= ll } else { false } +} + +#[inline] +fn compress( + ancestor: &mut IndexVec, + lastlinked: Option, + semi: &IndexVec, + label: &mut IndexVec, + v: PreorderIndex, +) { + assert!(is_processed(v, lastlinked)); + let u = ancestor[v]; + if is_processed(u, lastlinked) { + compress(ancestor, lastlinked, semi, label, u); + if semi[label[u]] < semi[label[v]] { + label[v] = label[u]; + } + ancestor[v] = ancestor[u]; + } } #[derive(Clone, Debug)] diff --git a/compiler/rustc_data_structures/src/graph/dominators/tests.rs b/compiler/rustc_data_structures/src/graph/dominators/tests.rs index 1160df5186..ff31d8f7fd 100644 --- a/compiler/rustc_data_structures/src/graph/dominators/tests.rs +++ b/compiler/rustc_data_structures/src/graph/dominators/tests.rs @@ -32,3 +32,14 @@ fn paper() { assert_eq!(immediate_dominators[5], Some(6)); assert_eq!(immediate_dominators[6], Some(6)); } + +#[test] +fn paper_slt() { + // example from the paper: + let graph = TestGraph::new( + 1, + &[(1, 2), (1, 3), (2, 3), (2, 7), (3, 4), (3, 6), (4, 5), (5, 4), (6, 7), (7, 8), (8, 5)], + ); + + dominators(&graph); +} diff --git a/compiler/rustc_data_structures/src/graph/iterate/mod.rs b/compiler/rustc_data_structures/src/graph/iterate/mod.rs index a9db3497b2..57007611a7 100644 --- a/compiler/rustc_data_structures/src/graph/iterate/mod.rs +++ b/compiler/rustc_data_structures/src/graph/iterate/mod.rs @@ -79,7 +79,7 @@ where visited: BitSet, } -impl DepthFirstSearch<'graph, G> +impl<'graph, G> DepthFirstSearch<'graph, G> where G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors, { @@ -209,7 +209,7 @@ where settled: BitSet, } -impl TriColorDepthFirstSearch<'graph, G> +impl<'graph, G> TriColorDepthFirstSearch<'graph, G> where G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors, { @@ -276,7 +276,7 @@ where } } -impl TriColorDepthFirstSearch<'graph, G> +impl TriColorDepthFirstSearch<'_, G> where G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors + WithStartNode, { diff --git a/compiler/rustc_data_structures/src/graph/scc/mod.rs b/compiler/rustc_data_structures/src/graph/scc/mod.rs index b84f28b6a9..7099ca7eb8 100644 --- a/compiler/rustc_data_structures/src/graph/scc/mod.rs +++ b/compiler/rustc_data_structures/src/graph/scc/mod.rs @@ -9,6 +9,7 @@ use crate::fx::FxHashSet; use crate::graph::vec_graph::VecGraph; use crate::graph::{DirectedGraph, GraphSuccessors, WithNumEdges, WithNumNodes, WithSuccessors}; use rustc_index::vec::{Idx, IndexVec}; +use std::cmp::Ord; use std::ops::Range; #[cfg(test)] @@ -38,7 +39,7 @@ struct SccData { all_successors: Vec, } -impl Sccs { +impl Sccs { pub fn new(graph: &(impl DirectedGraph + WithNumNodes + WithSuccessors)) -> Self { SccsConstruction::construct(graph) } @@ -85,7 +86,7 @@ impl DirectedGraph for Sccs { type Node = S; } -impl WithNumNodes for Sccs { +impl WithNumNodes for Sccs { fn num_nodes(&self) -> usize { self.num_sccs() } @@ -97,13 +98,13 @@ impl WithNumEdges for Sccs { } } -impl GraphSuccessors<'graph> for Sccs { +impl<'graph, N: Idx, S: Idx> GraphSuccessors<'graph> for Sccs { type Item = S; type Iter = std::iter::Cloned>; } -impl WithSuccessors for Sccs { +impl WithSuccessors for Sccs { fn successors(&self, node: S) -> >::Iter { self.successors(node).iter().cloned() } diff --git a/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs b/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs index 4ed8887841..3d91bcade5 100644 --- a/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs +++ b/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs @@ -1,3 +1,5 @@ +use std::cmp::Ord; + use crate::graph::{DirectedGraph, GraphSuccessors, WithNumEdges, WithNumNodes, WithSuccessors}; use rustc_index::vec::{Idx, IndexVec}; @@ -17,7 +19,7 @@ pub struct VecGraph { edge_targets: Vec, } -impl VecGraph { +impl VecGraph { pub fn new(num_nodes: usize, mut edge_pairs: Vec<(N, N)>) -> Self { // Sort the edges by the source -- this is important. edge_pairs.sort(); @@ -94,13 +96,13 @@ impl WithNumEdges for VecGraph { } } -impl GraphSuccessors<'graph> for VecGraph { +impl<'graph, N: Idx> GraphSuccessors<'graph> for VecGraph { type Item = N; type Iter = std::iter::Cloned>; } -impl WithSuccessors for VecGraph { +impl WithSuccessors for VecGraph { fn successors(&self, node: N) -> >::Iter { self.successors(node).iter().cloned() } diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 77784bf170..181e5180d5 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -15,16 +15,15 @@ #![feature(core_intrinsics)] #![feature(extend_one)] #![feature(hash_raw_entry)] -#![feature(in_band_lifetimes)] #![feature(maybe_uninit_uninit_array)] #![feature(min_specialization)] #![feature(never_type)] #![feature(type_alias_impl_trait)] #![feature(new_uninit)] -#![feature(nll)] #![feature(once_cell)] #![feature(test)] #![feature(thread_id_value)] +#![feature(vec_into_raw_parts)] #![allow(rustc::default_hash_types)] #![deny(unaligned_references)] diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs index c21939209f..fd6ff086b0 100644 --- a/compiler/rustc_data_structures/src/profiling.rs +++ b/compiler/rustc_data_structures/src/profiling.rs @@ -649,7 +649,7 @@ impl Drop for VerboseTimingGuard<'_> { fn drop(&mut self) { if let Some((start_time, start_rss, ref message)) = self.start_and_message { let end_rss = get_resident_set_size(); - print_time_passes_entry(&message[..], start_time.elapsed(), start_rss, end_rss); + print_time_passes_entry(&message, start_time.elapsed(), start_rss, end_rss); } } } diff --git a/compiler/rustc_data_structures/src/small_c_str.rs b/compiler/rustc_data_structures/src/small_c_str.rs index 4a089398ce..33e72914e1 100644 --- a/compiler/rustc_data_structures/src/small_c_str.rs +++ b/compiler/rustc_data_structures/src/small_c_str.rs @@ -46,7 +46,7 @@ impl SmallCStr { #[inline] pub fn as_c_str(&self) -> &ffi::CStr { - unsafe { ffi::CStr::from_bytes_with_nul_unchecked(&self.data[..]) } + unsafe { ffi::CStr::from_bytes_with_nul_unchecked(&self.data) } } #[inline] diff --git a/compiler/rustc_data_structures/src/sorted_map/index_map.rs b/compiler/rustc_data_structures/src/sorted_map/index_map.rs index 61c7239c55..593316e269 100644 --- a/compiler/rustc_data_structures/src/sorted_map/index_map.rs +++ b/compiler/rustc_data_structures/src/sorted_map/index_map.rs @@ -84,7 +84,7 @@ impl SortedIndexMultiMap { /// If there are multiple items that are equivalent to `key`, they will be yielded in /// insertion order. #[inline] - pub fn get_by_key(&'a self, key: K) -> impl 'a + Iterator { + pub fn get_by_key(&self, key: K) -> impl Iterator + '_ { self.get_by_key_enumerated(key).map(|(_, v)| v) } @@ -94,7 +94,7 @@ impl SortedIndexMultiMap { /// If there are multiple items that are equivalent to `key`, they will be yielded in /// insertion order. #[inline] - pub fn get_by_key_enumerated(&'a self, key: K) -> impl '_ + Iterator { + pub fn get_by_key_enumerated(&self, key: K) -> impl Iterator + '_ { let lower_bound = self.idx_sorted_by_item_key.partition_point(|&i| self.items[i].0 < key); self.idx_sorted_by_item_key[lower_bound..].iter().map_while(move |&i| { let (k, v) = &self.items[i]; diff --git a/compiler/rustc_data_structures/src/sso/map.rs b/compiler/rustc_data_structures/src/sso/map.rs index 2de05cd4e5..ec6a62016a 100644 --- a/compiler/rustc_data_structures/src/sso/map.rs +++ b/compiler/rustc_data_structures/src/sso/map.rs @@ -423,14 +423,14 @@ impl IntoIterator for SsoHashMap { /// adapts Item of array reference iterator to Item of hashmap reference iterator. #[inline(always)] -fn adapt_array_ref_it(pair: &'a (K, V)) -> (&'a K, &'a V) { +fn adapt_array_ref_it(pair: &(K, V)) -> (&K, &V) { let (a, b) = pair; (a, b) } /// adapts Item of array mut reference iterator to Item of hashmap mut reference iterator. #[inline(always)] -fn adapt_array_mut_it(pair: &'a mut (K, V)) -> (&'a K, &'a mut V) { +fn adapt_array_mut_it(pair: &mut (K, V)) -> (&K, &mut V) { let (a, b) = pair; (a, b) } diff --git a/compiler/rustc_data_structures/src/sso/set.rs b/compiler/rustc_data_structures/src/sso/set.rs index 29baf4e1dd..f71522d371 100644 --- a/compiler/rustc_data_structures/src/sso/set.rs +++ b/compiler/rustc_data_structures/src/sso/set.rs @@ -75,7 +75,7 @@ impl SsoHashSet { /// An iterator visiting all elements in arbitrary order. /// The iterator element type is `&'a T`. #[inline] - pub fn iter(&'a self) -> impl Iterator { + pub fn iter(&self) -> impl Iterator { self.into_iter() } diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index f800ec6a6a..3da3517895 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -42,6 +42,7 @@ impl StableHasher { } impl StableHasherResult for u128 { + #[inline] fn finish(hasher: StableHasher) -> Self { let (_0, _1) = hasher.finalize(); u128::from(_0) | (u128::from(_1) << 64) @@ -49,6 +50,7 @@ impl StableHasherResult for u128 { } impl StableHasherResult for u64 { + #[inline] fn finish(hasher: StableHasher) -> Self { hasher.finalize().0 } @@ -377,9 +379,8 @@ impl, CTX> HashStable for ::std::sync::Arc { impl HashStable for str { #[inline] - fn hash_stable(&self, _: &mut CTX, hasher: &mut StableHasher) { - self.len().hash(hasher); - self.as_bytes().hash(hasher); + fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + self.as_bytes().hash_stable(ctx, hasher); } } @@ -476,14 +477,14 @@ where } impl HashStable for bit_set::BitSet { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - self.words().hash_stable(ctx, hasher); + fn hash_stable(&self, _ctx: &mut CTX, hasher: &mut StableHasher) { + ::std::hash::Hash::hash(self, hasher); } } impl HashStable for bit_set::BitMatrix { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - self.words().hash_stable(ctx, hasher); + fn hash_stable(&self, _ctx: &mut CTX, hasher: &mut StableHasher) { + ::std::hash::Hash::hash(self, hasher); } } @@ -507,7 +508,11 @@ where { #[inline] fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { - hash_stable_hashmap(hcx, hasher, self, ToStableHashKey::to_stable_hash_key); + stable_hash_reduce(hcx, hasher, self.iter(), self.len(), |hasher, hcx, (key, value)| { + let key = key.to_stable_hash_key(hcx); + key.hash_stable(hcx, hasher); + value.hash_stable(hcx, hasher); + }); } } @@ -517,9 +522,10 @@ where R: BuildHasher, { fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { - let mut keys: Vec<_> = self.iter().map(|k| k.to_stable_hash_key(hcx)).collect(); - keys.sort_unstable(); - keys.hash_stable(hcx, hasher); + stable_hash_reduce(hcx, hasher, self.iter(), self.len(), |hasher, hcx, key| { + let key = key.to_stable_hash_key(hcx); + key.hash_stable(hcx, hasher); + }); } } @@ -529,10 +535,11 @@ where V: HashStable, { fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { - let mut entries: Vec<_> = - self.iter().map(|(k, v)| (k.to_stable_hash_key(hcx), v)).collect(); - entries.sort_unstable_by(|&(ref sk1, _), &(ref sk2, _)| sk1.cmp(sk2)); - entries.hash_stable(hcx, hasher); + stable_hash_reduce(hcx, hasher, self.iter(), self.len(), |hasher, hcx, (key, value)| { + let key = key.to_stable_hash_key(hcx); + key.hash_stable(hcx, hasher); + value.hash_stable(hcx, hasher); + }); } } @@ -541,25 +548,38 @@ where K: ToStableHashKey, { fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { - let mut keys: Vec<_> = self.iter().map(|k| k.to_stable_hash_key(hcx)).collect(); - keys.sort_unstable(); - keys.hash_stable(hcx, hasher); + stable_hash_reduce(hcx, hasher, self.iter(), self.len(), |hasher, hcx, key| { + let key = key.to_stable_hash_key(hcx); + key.hash_stable(hcx, hasher); + }); } } -pub fn hash_stable_hashmap( +fn stable_hash_reduce( hcx: &mut HCX, hasher: &mut StableHasher, - map: &::std::collections::HashMap, - to_stable_hash_key: F, + mut collection: C, + length: usize, + hash_function: F, ) where - K: Eq, - V: HashStable, - R: BuildHasher, - SK: HashStable + Ord, - F: Fn(&K, &HCX) -> SK, + C: Iterator, + F: Fn(&mut StableHasher, &mut HCX, I), { - let mut entries: Vec<_> = map.iter().map(|(k, v)| (to_stable_hash_key(k, hcx), v)).collect(); - entries.sort_unstable_by(|&(ref sk1, _), &(ref sk2, _)| sk1.cmp(sk2)); - entries.hash_stable(hcx, hasher); + length.hash_stable(hcx, hasher); + + match length { + 1 => { + hash_function(hasher, hcx, collection.next().unwrap()); + } + _ => { + let hash = collection + .map(|value| { + let mut hasher = StableHasher::new(); + hash_function(&mut hasher, hcx, value); + hasher.finish::() + }) + .reduce(|accum, value| accum.wrapping_add(value)); + hash.hash_stable(hcx, hasher); + } + } } diff --git a/compiler/rustc_data_structures/src/stable_hasher/tests.rs b/compiler/rustc_data_structures/src/stable_hasher/tests.rs index cd6ff96a55..391db67d29 100644 --- a/compiler/rustc_data_structures/src/stable_hasher/tests.rs +++ b/compiler/rustc_data_structures/src/stable_hasher/tests.rs @@ -71,3 +71,30 @@ fn test_hash_isize() { assert_eq!(h.finalize(), expected); } + +fn hash>(t: &T) -> u128 { + let mut h = StableHasher::new(); + let ctx = &mut (); + t.hash_stable(ctx, &mut h); + h.finish() +} + +// Check that bit set hash includes the domain size. +#[test] +fn test_hash_bit_set() { + use rustc_index::bit_set::BitSet; + let a: BitSet = BitSet::new_empty(1); + let b: BitSet = BitSet::new_empty(2); + assert_ne!(a, b); + assert_ne!(hash(&a), hash(&b)); +} + +// Check that bit matrix hash includes the matrix dimensions. +#[test] +fn test_hash_bit_matrix() { + use rustc_index::bit_set::BitMatrix; + let a: BitMatrix = BitMatrix::new(1, 1); + let b: BitMatrix = BitMatrix::new(1, 2); + assert_ne!(a, b); + assert_ne!(hash(&a), hash(&b)); +} diff --git a/compiler/rustc_data_structures/src/tagged_ptr/copy.rs b/compiler/rustc_data_structures/src/tagged_ptr/copy.rs index d63bcdb3c2..e1d3e0bd35 100644 --- a/compiler/rustc_data_structures/src/tagged_ptr/copy.rs +++ b/compiler/rustc_data_structures/src/tagged_ptr/copy.rs @@ -94,9 +94,11 @@ where // SAFETY: pointer_raw returns the original pointer unsafe { std::mem::transmute_copy(&self.pointer_raw()) } } + #[inline] pub fn tag(&self) -> T { unsafe { T::from_usize(self.packed.get() >> Self::TAG_BIT_SHIFT) } } + #[inline] pub fn set_tag(&mut self, tag: T) { let mut packed = self.packed.get(); let new_tag = T::into_usize(tag) << Self::TAG_BIT_SHIFT; diff --git a/compiler/rustc_data_structures/src/thin_vec.rs b/compiler/rustc_data_structures/src/thin_vec.rs index b5d2d24736..716259142d 100644 --- a/compiler/rustc_data_structures/src/thin_vec.rs +++ b/compiler/rustc_data_structures/src/thin_vec.rs @@ -5,7 +5,7 @@ use std::iter::FromIterator; /// A vector type optimized for cases where this size is usually 0 (cf. `SmallVec`). /// The `Option>` wrapping allows us to represent a zero sized vector with `None`, /// which uses only a single (null) pointer. -#[derive(Clone, Encodable, Decodable, Debug)] +#[derive(Clone, Encodable, Decodable, Debug, Hash, Eq, PartialEq)] pub struct ThinVec(Option>>); impl ThinVec { @@ -20,6 +20,13 @@ impl ThinVec { pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> { self.into_iter() } + + pub fn push(&mut self, item: T) { + match *self { + ThinVec(Some(ref mut vec)) => vec.push(item), + ThinVec(None) => *self = vec![item].into(), + } + } } impl From> for ThinVec { @@ -101,10 +108,7 @@ impl Extend for ThinVec { } fn extend_one(&mut self, item: T) { - match *self { - ThinVec(Some(ref mut vec)) => vec.push(item), - ThinVec(None) => *self = vec![item].into(), - } + self.push(item) } fn extend_reserve(&mut self, additional: usize) { diff --git a/compiler/rustc_data_structures/src/vec_linked_list.rs b/compiler/rustc_data_structures/src/vec_linked_list.rs index 1cf030d852..ce60d40b24 100644 --- a/compiler/rustc_data_structures/src/vec_linked_list.rs +++ b/compiler/rustc_data_structures/src/vec_linked_list.rs @@ -2,8 +2,8 @@ use rustc_index::vec::{Idx, IndexVec}; pub fn iter( first: Option, - links: &'a Ls, -) -> impl Iterator + 'a + links: &Ls, +) -> impl Iterator + '_ where Ls: Links, { diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml index ce3a3f5a3a..872f946bf7 100644 --- a/compiler/rustc_driver/Cargo.toml +++ b/compiler/rustc_driver/Cargo.toml @@ -8,10 +8,8 @@ crate-type = ["dylib"] [dependencies] libc = "0.2" -atty = "0.2" tracing = { version = "0.1.28" } -tracing-subscriber = { version = "0.2.16", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] } -tracing-tree = "0.1.9" +rustc_log = { path = "../rustc_log" } rustc_middle = { path = "../rustc_middle" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_target = { path = "../rustc_target" } @@ -40,4 +38,4 @@ winapi = { version = "0.3", features = ["consoleapi", "debugapi", "processenv"] [features] llvm = ['rustc_interface/llvm'] -max_level_info = ['tracing/max_level_info'] +max_level_info = ['rustc_log/max_level_info'] diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 6ff9434114..694c679c15 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -24,6 +24,7 @@ use rustc_feature::find_gated_cfg; use rustc_interface::util::{self, collect_crate_types, get_codegen_backend}; use rustc_interface::{interface, Queries}; use rustc_lint::LintStore; +use rustc_log::stdout_isatty; use rustc_metadata::locator; use rustc_save_analysis as save; use rustc_save_analysis::DumpHandler; @@ -514,14 +515,6 @@ impl Compilation { #[derive(Copy, Clone)] pub struct RustcDefaultCalls; -fn stdout_isatty() -> bool { - atty::is(atty::Stream::Stdout) -} - -fn stderr_isatty() -> bool { - atty::is(atty::Stream::Stderr) -} - fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) { let upper_cased_code = code.to_ascii_uppercase(); let normalised = if upper_cased_code.starts_with('E') { @@ -872,7 +865,7 @@ Available lint options: let print_lints = |lints: Vec<&Lint>| { for lint in lints { - let name = lint.name_lower().replace("_", "-"); + let name = lint.name_lower().replace('_', "-"); println!( " {} {:7.7} {}", padded(&name), @@ -908,10 +901,10 @@ Available lint options: let print_lint_groups = |lints: Vec<(&'static str, Vec)>| { for (name, to) in lints { - let name = name.to_lowercase().replace("_", "-"); + let name = name.to_lowercase().replace('_', "-"); let desc = to .into_iter() - .map(|x| x.to_string().replace("_", "-")) + .map(|x| x.to_string().replace('_', "-")) .collect::>() .join(", "); println!(" {} {}", padded(&name), desc); @@ -960,7 +953,7 @@ fn print_flag_list( println!( " {} {:>width$}=val -- {}", cmdline_opt, - name.replace("_", "-"), + name.replace('_', "-"), desc, width = max_len ); @@ -1015,7 +1008,7 @@ pub fn handle_options(args: &[String]) -> Option { .iter() .map(|&(name, ..)| ('C', name)) .chain(DB_OPTIONS.iter().map(|&(name, ..)| ('Z', name))) - .find(|&(_, name)| *opt == name.replace("_", "-")) + .find(|&(_, name)| *opt == name.replace('_', "-")) .map(|(flag, _)| format!("{}. Did you mean `-{} {}`?", e, flag, opt)), _ => None, }; @@ -1047,7 +1040,7 @@ pub fn handle_options(args: &[String]) -> Option { let wall = matches.opt_strs("W"); if wall.iter().any(|x| *x == "all") { print_wall_help(); - return None; + rustc_errors::FatalError.raise(); } // Don't handle -W help here, because we might first load plugins. @@ -1254,54 +1247,18 @@ pub fn install_ice_hook() { /// This allows tools to enable rust logging without having to magically match rustc's /// tracing crate version. pub fn init_rustc_env_logger() { - init_env_logger("RUSTC_LOG") + if let Err(error) = rustc_log::init_rustc_env_logger() { + early_error(ErrorOutputType::default(), &error.to_string()); + } } /// This allows tools to enable rust logging without having to magically match rustc's /// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to choose an env var /// other than `RUSTC_LOG`. pub fn init_env_logger(env: &str) { - use tracing_subscriber::{ - filter::{self, EnvFilter, LevelFilter}, - layer::SubscriberExt, - }; - - let filter = match std::env::var(env) { - Ok(env) => EnvFilter::new(env), - _ => EnvFilter::default().add_directive(filter::Directive::from(LevelFilter::WARN)), - }; - - let color_logs = match std::env::var(String::from(env) + "_COLOR") { - Ok(value) => match value.as_ref() { - "always" => true, - "never" => false, - "auto" => stderr_isatty(), - _ => early_error( - ErrorOutputType::default(), - &format!( - "invalid log color value '{}': expected one of always, never, or auto", - value - ), - ), - }, - Err(std::env::VarError::NotPresent) => stderr_isatty(), - Err(std::env::VarError::NotUnicode(_value)) => early_error( - ErrorOutputType::default(), - "non-Unicode log color value: expected one of always, never, or auto", - ), - }; - - let layer = tracing_tree::HierarchicalLayer::default() - .with_writer(io::stderr) - .with_indent_lines(true) - .with_ansi(color_logs) - .with_targets(true) - .with_indent_amount(2); - #[cfg(parallel_compiler)] - let layer = layer.with_thread_ids(true).with_thread_names(true); - - let subscriber = tracing_subscriber::Registry::default().with(filter).with(layer); - tracing::subscriber::set_global_default(subscriber).unwrap(); + if let Err(error) = rustc_log::init_env_logger(env) { + early_error(ErrorOutputType::default(), &error.to_string()); + } } #[cfg(all(unix, any(target_env = "gnu", target_os = "macos")))] diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index ce26ff6223..79d9c55b54 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -120,6 +120,7 @@ E0223: include_str!("./error_codes/E0223.md"), E0224: include_str!("./error_codes/E0224.md"), E0225: include_str!("./error_codes/E0225.md"), E0226: include_str!("./error_codes/E0226.md"), +E0227: include_str!("./error_codes/E0227.md"), E0228: include_str!("./error_codes/E0228.md"), E0229: include_str!("./error_codes/E0229.md"), E0230: include_str!("./error_codes/E0230.md"), @@ -530,7 +531,6 @@ E0786: include_str!("./error_codes/E0786.md"), // E0217, // ambiguous associated type, defined in multiple supertraits // E0218, // no associated type defined // E0219, // associated type defined in higher-ranked supertrait - E0227, // ambiguous lifetime bound, explicit lifetime bound required // E0233, // E0234, // E0235, // structure constructor specifies a structure of type but diff --git a/compiler/rustc_error_codes/src/error_codes/E0038.md b/compiler/rustc_error_codes/src/error_codes/E0038.md index 019d54b620..ca2eaa5405 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0038.md +++ b/compiler/rustc_error_codes/src/error_codes/E0038.md @@ -1,34 +1,64 @@ -Trait objects like `Box` can only be constructed when certain -requirements are satisfied by the trait in question. +For any given trait `Trait` there may be a related _type_ called the _trait +object type_ which is typically written as `dyn Trait`. In earlier editions of +Rust, trait object types were written as plain `Trait` (just the name of the +trait, written in type positions) but this was a bit too confusing, so we now +write `dyn Trait`. -Trait objects are a form of dynamic dispatch and use a dynamically sized type -for the inner type. So, for a given trait `Trait`, when `Trait` is treated as a -type, as in `Box`, the inner type is 'unsized'. In such cases the boxed -pointer is a 'fat pointer' that contains an extra pointer to a table of methods -(among other things) for dynamic dispatch. This design mandates some -restrictions on the types of traits that are allowed to be used in trait -objects, which are collectively termed as 'object safety' rules. +Some traits are not allowed to be used as trait object types. The traits that +are allowed to be used as trait object types are called "object-safe" traits. +Attempting to use a trait object type for a trait that is not object-safe will +trigger error E0038. -Attempting to create a trait object for a non object-safe trait will trigger -this error. +Two general aspects of trait object types give rise to the restrictions: -There are various rules: + 1. Trait object types are dynamically sized types (DSTs), and trait objects of + these types can only be accessed through pointers, such as `&dyn Trait` or + `Box`. The size of such a pointer is known, but the size of the + `dyn Trait` object pointed-to by the pointer is _opaque_ to code working + with it, and different tait objects with the same trait object type may + have different sizes. -### The trait cannot require `Self: Sized` + 2. The pointer used to access a trait object is paired with an extra pointer + to a "virtual method table" or "vtable", which is used to implement dynamic + dispatch to the object's implementations of the trait's methods. There is a + single such vtable for each trait implementation, but different trait + objects with the same trait object type may point to vtables from different + implementations. -When `Trait` is treated as a type, the type does not implement the special -`Sized` trait, because the type does not have a known size at compile time and -can only be accessed behind a pointer. Thus, if we have a trait like the -following: +The specific conditions that violate object-safety follow, most of which relate +to missing size information and vtable polymorphism arising from these aspects. + +### The trait requires `Self: Sized` + +Traits that are declared as `Trait: Sized` or which otherwise inherit a +constraint of `Self:Sized` are not object-safe. + +The reasoning behind this is somewhat subtle. It derives from the fact that Rust +requires (and defines) that every trait object type `dyn Trait` automatically +implements `Trait`. Rust does this to simplify error reporting and ease +interoperation between static and dynamic polymorphism. For example, this code +works: ``` -trait Foo where Self: Sized { +trait Trait { +} +fn static_foo(b: &T) { +} + +fn dynamic_bar(a: &dyn Trait) { + static_foo(a) } ``` -We cannot create an object of type `Box` or `&Foo` since in this case -`Self` would not be `Sized`. +This code works because `dyn Trait`, if it exists, always implements `Trait`. + +However as we know, any `dyn Trait` is also unsized, and so it can never +implement a sized trait like `Trait:Sized`. So, rather than allow an exception +to the rule that `dyn Trait` always implements `Trait`, Rust chooses to prohibit +such a `dyn Trait` from existing at all. + +Only unsized traits are considered object-safe. Generally, `Self: Sized` is used to indicate that the trait should not be used as a trait object. If the trait comes from your own crate, consider removing @@ -67,7 +97,7 @@ trait Trait { fn foo(&self) -> Self; } -fn call_foo(x: Box) { +fn call_foo(x: Box) { let y = x.foo(); // What type is y? // ... } @@ -76,7 +106,8 @@ fn call_foo(x: Box) { If only some methods aren't object-safe, you can add a `where Self: Sized` bound on them to mark them as explicitly unavailable to trait objects. The functionality will still be available to all other implementers, including -`Box` which is itself sized (assuming you `impl Trait for Box`). +`Box` which is itself sized (assuming you `impl Trait for Box`). ``` trait Trait { @@ -115,7 +146,9 @@ impl Trait for u8 { ``` At compile time each implementation of `Trait` will produce a table containing -the various methods (and other items) related to the implementation. +the various methods (and other items) related to the implementation, which will +be used as the virtual method table for a `dyn Trait` object derived from that +implementation. This works fine, but when the method gains generic parameters, we can have a problem. @@ -174,7 +207,7 @@ Now, if we have the following code: # impl Trait for u8 { fn foo(&self, on: T) {} } # impl Trait for bool { fn foo(&self, on: T) {} } # // etc. -fn call_foo(thing: Box) { +fn call_foo(thing: Box) { thing.foo(true); // this could be any one of the 8 types above thing.foo(1); thing.foo("hello"); @@ -200,7 +233,7 @@ trait Trait { ``` If this is not an option, consider replacing the type parameter with another -trait object (e.g., if `T: OtherTrait`, use `on: Box`). If the +trait object (e.g., if `T: OtherTrait`, use `on: Box`). If the number of types you intend to feed to this method is limited, consider manually listing out the methods of different types. @@ -226,7 +259,7 @@ trait Foo { } ``` -### The trait cannot contain associated constants +### Trait contains associated constants Just like static functions, associated constants aren't stored on the method table. If the trait or any subtrait contain an associated constant, they cannot @@ -248,7 +281,7 @@ trait Foo { } ``` -### The trait cannot use `Self` as a type parameter in the supertrait listing +### Trait uses `Self` as a type parameter in the supertrait listing This is similar to the second sub-error, but subtler. It happens in situations like the following: diff --git a/compiler/rustc_error_codes/src/error_codes/E0227.md b/compiler/rustc_error_codes/src/error_codes/E0227.md new file mode 100644 index 0000000000..f68614723d --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0227.md @@ -0,0 +1,33 @@ +This error indicates that the compiler is unable to determine whether there is +exactly one unique region in the set of derived region bounds. + +Example of erroneous code: + +```compile_fail,E0227 +trait Foo<'foo>: 'foo {} +trait Bar<'bar>: 'bar {} + +trait FooBar<'foo, 'bar>: Foo<'foo> + Bar<'bar> {} + +struct Baz<'foo, 'bar> { + baz: dyn FooBar<'foo, 'bar>, +} +``` + +Here, `baz` can have either `'foo` or `'bar` lifetimes. + +To resolve this error, provide an explicit lifetime: + +```rust +trait Foo<'foo>: 'foo {} +trait Bar<'bar>: 'bar {} + +trait FooBar<'foo, 'bar>: Foo<'foo> + Bar<'bar> {} + +struct Baz<'foo, 'bar, 'baz> +where + 'baz: 'foo + 'bar, +{ + obj: dyn FooBar<'foo, 'bar> + 'baz, +} +``` diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index d64a589bd9..3104bc185e 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -214,7 +214,7 @@ pub trait Emitter { /// Formats the substitutions of the primary_span /// - /// The are a lot of conditions to this method, but in short: + /// There are a lot of conditions to this method, but in short: /// /// * If the current `Diagnostic` has only one visible `CodeSuggestion`, /// we format the `help` suggestion depending on the content of the @@ -736,7 +736,9 @@ impl EmitterWriter { let line_offset = buffer.num_lines(); - let left = margin.left(source_string.len()); // Left trim + // Left trim + let left = margin.left(source_string.len()); + // Account for unicode characters of width !=0 that were removed. let left = source_string .chars() @@ -1623,18 +1625,27 @@ impl EmitterWriter { suggestions.iter().take(MAX_SUGGESTIONS) { notice_capitalization |= only_capitalization; - // Only show underline if the suggestion spans a single line and doesn't cover the - // entirety of the code output. If you have multiple replacements in the same line - // of code, show the underline. - let show_underline = !(parts.len() == 1 && parts[0].snippet.trim() == complete.trim()) - && complete.lines().count() == 1; let has_deletion = parts.iter().any(|p| p.is_deletion()); let is_multiline = complete.lines().count() > 1; - let show_diff = has_deletion && !is_multiline; + enum DisplaySuggestion { + Underline, + Diff, + None, + } - if show_diff { + let show_code_change = if has_deletion && !is_multiline { + DisplaySuggestion::Diff + } else if (parts.len() != 1 || parts[0].snippet.trim() != complete.trim()) + && !is_multiline + { + DisplaySuggestion::Underline + } else { + DisplaySuggestion::None + }; + + if let DisplaySuggestion::Diff = show_code_change { row_num += 1; } @@ -1657,7 +1668,7 @@ impl EmitterWriter { &self.maybe_anonymized(line_start + line_pos), Style::LineNumber, ); - if show_diff { + if let DisplaySuggestion::Diff = show_code_change { // Add the line number for both addition and removal to drive the point home. // // N - fn foo(bar: A) { @@ -1727,7 +1738,7 @@ impl EmitterWriter { let mut offsets: Vec<(usize, isize)> = Vec::new(); // Only show an underline in the suggestions if the suggestion is not the // entirety of the code being shown and the displayed code is not multiline. - if show_underline { + if let DisplaySuggestion::Diff | DisplaySuggestion::Underline = show_code_change { draw_col_separator(&mut buffer, row_num, max_line_num_len + 1); for part in parts { let span_start_pos = sm.lookup_char_pos(part.span.lo()).col_display; @@ -1755,7 +1766,7 @@ impl EmitterWriter { assert!(underline_start >= 0 && underline_end >= 0); let padding: usize = max_line_num_len + 3; for p in underline_start..underline_end { - if !show_diff { + if let DisplaySuggestion::Underline = show_code_change { // If this is a replacement, underline with `^`, if this is an addition // underline with `+`. buffer.putc( @@ -1766,7 +1777,7 @@ impl EmitterWriter { ); } } - if show_diff { + if let DisplaySuggestion::Diff = show_code_change { // Colorize removal with red in diff format. buffer.set_style_range( row_num - 2, @@ -1797,7 +1808,7 @@ impl EmitterWriter { // if we elided some lines, add an ellipsis if lines.next().is_some() { buffer.puts(row_num, max_line_num_len - 1, "...", Style::LineNumber); - } else if !show_underline { + } else if let DisplaySuggestion::None = show_code_change { draw_col_separator_no_space(&mut buffer, row_num, max_line_num_len + 1); row_num += 1; } @@ -2083,7 +2094,7 @@ const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[ ('\t', " "), // We do our own tab replacement ('\u{200D}', ""), // Replace ZWJ with nothing for consistent terminal output of grapheme clusters. ('\u{202A}', ""), // The following unicode text flow control characters are inconsistently - ('\u{202B}', ""), // supported accross CLIs and can cause confusion due to the bytes on disk + ('\u{202B}', ""), // supported across CLIs and can cause confusion due to the bytes on disk ('\u{202D}', ""), // not corresponding to the visible source code, so we replace them always. ('\u{202E}', ""), ('\u{2066}', ""), diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index bb3d3a415e..a681298301 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -6,8 +6,6 @@ #![feature(crate_visibility_modifier)] #![feature(backtrace)] #![feature(if_let_guard)] -#![cfg_attr(bootstrap, feature(format_args_capture))] -#![feature(iter_zip)] #![feature(let_else)] #![feature(nll)] @@ -1013,7 +1011,9 @@ impl HandlerInner { } fn treat_err_as_bug(&self) -> bool { - self.flags.treat_err_as_bug.map_or(false, |c| self.err_count() >= c.get()) + self.flags + .treat_err_as_bug + .map_or(false, |c| self.err_count() + self.lint_err_count >= c.get()) } fn print_error_count(&mut self, registry: &Registry) { @@ -1205,7 +1205,10 @@ impl HandlerInner { fn panic_if_treat_err_as_bug(&self) { if self.treat_err_as_bug() { - match (self.err_count(), self.flags.treat_err_as_bug.map(|c| c.get()).unwrap_or(0)) { + match ( + self.err_count() + self.lint_err_count, + self.flags.treat_err_as_bug.map(|c| c.get()).unwrap_or(0), + ) { (1, 1) => panic!("aborting due to `-Z treat-err-as-bug=1`"), (0, _) | (1, _) => {} (count, as_bug) => panic!( diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index b630bc1f47..07b5e20b2d 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -48,6 +48,7 @@ pub enum Annotatable { Param(ast::Param), FieldDef(ast::FieldDef), Variant(ast::Variant), + Crate(ast::Crate), } impl Annotatable { @@ -66,6 +67,7 @@ impl Annotatable { Annotatable::Param(ref p) => p.span, Annotatable::FieldDef(ref sf) => sf.span, Annotatable::Variant(ref v) => v.span, + Annotatable::Crate(ref c) => c.span, } } @@ -84,6 +86,7 @@ impl Annotatable { Annotatable::Param(p) => p.visit_attrs(f), Annotatable::FieldDef(sf) => sf.visit_attrs(f), Annotatable::Variant(v) => v.visit_attrs(f), + Annotatable::Crate(c) => c.visit_attrs(f), } } @@ -102,6 +105,7 @@ impl Annotatable { Annotatable::Param(p) => visitor.visit_param(p), Annotatable::FieldDef(sf) => visitor.visit_field_def(sf), Annotatable::Variant(v) => visitor.visit_variant(v), + Annotatable::Crate(c) => visitor.visit_crate(c), } } @@ -122,7 +126,8 @@ impl Annotatable { | Annotatable::GenericParam(..) | Annotatable::Param(..) | Annotatable::FieldDef(..) - | Annotatable::Variant(..) => panic!("unexpected annotatable"), + | Annotatable::Variant(..) + | Annotatable::Crate(..) => panic!("unexpected annotatable"), } } @@ -220,6 +225,13 @@ impl Annotatable { _ => panic!("expected variant"), } } + + pub fn expect_crate(self) -> ast::Crate { + match self { + Annotatable::Crate(krate) => krate, + _ => panic!("expected krate"), + } + } } /// Result of an expansion that may need to be retried. @@ -419,6 +431,11 @@ pub trait MacResult { fn make_variants(self: Box) -> Option> { None } + + fn make_crate(self: Box) -> Option { + // Fn-like macros cannot produce a crate. + unreachable!() + } } macro_rules! make_MacEager { diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 1b12352096..db0dea4870 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -171,7 +171,7 @@ fn get_features( } if let Some(allowed) = sess.opts.debugging_opts.allow_features.as_ref() { - if allowed.iter().all(|f| name.as_str() != *f) { + if allowed.iter().all(|f| name.as_str() != f) { struct_span_err!( span_handler, mi.span(), @@ -402,7 +402,24 @@ impl<'a> StripUnconfigured<'a> { ); trees.push((bracket_group, Spacing::Alone)); let tokens = Some(LazyTokenStream::new(AttrAnnotatedTokenStream::new(trees))); - self.process_cfg_attr(attr::mk_attr_from_item(item, tokens, attr.style, span)) + let attr = attr::mk_attr_from_item(item, tokens, attr.style, span); + if attr.has_name(sym::crate_type) { + self.sess.parse_sess.buffer_lint( + rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, + attr.span, + ast::CRATE_NODE_ID, + "`crate_type` within an `#![cfg_attr] attribute is deprecated`", + ); + } + if attr.has_name(sym::crate_name) { + self.sess.parse_sess.buffer_lint( + rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, + attr.span, + ast::CRATE_NODE_ID, + "`crate_name` within an `#![cfg_attr] attribute is deprecated`", + ); + } + self.process_cfg_attr(attr) }) .collect() } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 89dbd64ed8..7f49f80a84 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -14,13 +14,13 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast::visit::{self, AssocCtxt, Visitor}; use rustc_ast::{AstLike, Block, Inline, ItemKind, MacArgs, MacCall}; use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem}; -use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe}; +use rustc_ast::{NodeId, PatKind, Path, StmtKind}; use rustc_ast_pretty::pprust; use rustc_attr::is_builtin_attr; use rustc_data_structures::map_in_place::MapInPlace; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::Lrc; -use rustc_errors::{Applicability, FatalError, PResult}; +use rustc_errors::{Applicability, PResult}; use rustc_feature::Features; use rustc_parse::parser::{ AttemptLocalParseRecovery, ForceCollect, Parser, RecoverColon, RecoverComma, @@ -33,7 +33,7 @@ use rustc_session::Limit; use rustc_span::symbol::{sym, Ident}; use rustc_span::{FileName, LocalExpnId, Span}; -use smallvec::{smallvec, SmallVec}; +use smallvec::SmallVec; use std::ops::DerefMut; use std::path::PathBuf; use std::rc::Rc; @@ -205,6 +205,7 @@ ast_fragments! { Variants(SmallVec<[ast::Variant; 1]>) { "variant"; many fn flat_map_variant; fn visit_variant(); fn make_variants; } + Crate(ast::Crate) { "crate"; one fn visit_crate; fn visit_crate; fn make_crate; } } pub enum SupportsMacroExpansion { @@ -227,9 +228,8 @@ impl AstFragmentKind { AstFragmentKind::Items | AstFragmentKind::TraitItems | AstFragmentKind::ImplItems - | AstFragmentKind::ForeignItems => { - SupportsMacroExpansion::Yes { supports_inner_attrs: true } - } + | AstFragmentKind::ForeignItems + | AstFragmentKind::Crate => SupportsMacroExpansion::Yes { supports_inner_attrs: true }, AstFragmentKind::Arms | AstFragmentKind::Fields | AstFragmentKind::FieldPats @@ -288,6 +288,9 @@ impl AstFragmentKind { AstFragmentKind::OptExpr => { AstFragment::OptExpr(items.next().map(Annotatable::expect_expr)) } + AstFragmentKind::Crate => { + AstFragment::Crate(items.next().expect("expected exactly one crate").expect_crate()) + } AstFragmentKind::Pat | AstFragmentKind::Ty => { panic!("patterns and types aren't annotatable") } @@ -359,9 +362,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { MacroExpander { cx, monotonic } } - // FIXME: Avoid visiting the crate as a `Mod` item, - // make crate a first class expansion target instead. - pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { + pub fn expand_crate(&mut self, krate: ast::Crate) -> ast::Crate { let file_path = match self.cx.source_map().span_to_filename(krate.span) { FileName::Real(name) => name .into_local_path() @@ -375,52 +376,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { file_path_stack: vec![file_path], dir_path, }); - - let krate_item = AstFragment::Items(smallvec![P(ast::Item { - attrs: krate.attrs, - span: krate.span, - kind: ast::ItemKind::Mod( - Unsafe::No, - ModKind::Loaded(krate.items, Inline::Yes, krate.span) - ), - ident: Ident::empty(), - id: ast::DUMMY_NODE_ID, - vis: ast::Visibility { - span: krate.span.shrink_to_lo(), - kind: ast::VisibilityKind::Public, - tokens: None, - }, - tokens: None, - })]); - - match self.fully_expand_fragment(krate_item).make_items().pop().map(P::into_inner) { - Some(ast::Item { - attrs, - kind: ast::ItemKind::Mod(_, ModKind::Loaded(items, ..)), - .. - }) => { - krate.attrs = attrs; - krate.items = items; - } - None => { - // Resolution failed so we return an empty expansion - krate.attrs = vec![]; - krate.items = vec![]; - } - Some(ast::Item { span, kind, .. }) => { - krate.attrs = vec![]; - krate.items = vec![]; - self.cx.span_err( - span, - &format!( - "expected crate top-level item to be a module after macro expansion, found {} {}", - kind.article(), kind.descr() - ), - ); - // FIXME: this workaround issue #84569 - FatalError.raise(); - } - }; + let krate = self.fully_expand_fragment(AstFragment::Crate(krate)).make_crate(); + assert_eq!(krate.id, ast::CRATE_NODE_ID); self.cx.trace_macros_diag(); krate } @@ -708,26 +665,32 @@ impl<'a, 'b> MacroExpander<'a, 'b> { SyntaxExtensionKind::Attr(expander) => { self.gate_proc_macro_input(&item); self.gate_proc_macro_attr_item(span, &item); - let mut fake_tokens = false; - if let Annotatable::Item(item_inner) = &item { - if let ItemKind::Mod(_, mod_kind) = &item_inner.kind { - // FIXME: Collect tokens and use them instead of generating - // fake ones. These are unstable, so it needs to be - // fixed prior to stabilization - // Fake tokens when we are invoking an inner attribute, and: - fake_tokens = matches!(attr.style, ast::AttrStyle::Inner) && - // We are invoking an attribute on the crate root, or an outline - // module - (item_inner.ident.name.is_empty() || !matches!(mod_kind, ast::ModKind::Loaded(_, Inline::Yes, _))); - } - } - let tokens = if fake_tokens { - rustc_parse::fake_token_stream( + let tokens = match &item { + // FIXME: Collect tokens and use them instead of generating + // fake ones. These are unstable, so it needs to be + // fixed prior to stabilization + // Fake tokens when we are invoking an inner attribute, and + // we are invoking it on an out-of-line module or crate. + Annotatable::Crate(krate) => rustc_parse::fake_token_stream_for_crate( &self.cx.sess.parse_sess, - &item.into_nonterminal(), - ) - } else { - item.into_tokens(&self.cx.sess.parse_sess) + krate, + ), + Annotatable::Item(item_inner) + if matches!(attr.style, ast::AttrStyle::Inner) + && matches!( + item_inner.kind, + ItemKind::Mod( + _, + ModKind::Unloaded | ModKind::Loaded(_, Inline::No, _), + ) + ) => + { + rustc_parse::fake_token_stream( + &self.cx.sess.parse_sess, + &item.into_nonterminal(), + ) + } + _ => item.into_tokens(&self.cx.sess.parse_sess), }; let attr_item = attr.unwrap_normal_item(); if let MacArgs::Eq(..) = attr_item.args { @@ -804,7 +767,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { Annotatable::Item(_) | Annotatable::TraitItem(_) | Annotatable::ImplItem(_) - | Annotatable::ForeignItem(_) => return, + | Annotatable::ForeignItem(_) + | Annotatable::Crate(..) => return, Annotatable::Stmt(stmt) => { // Attributes are stable on item statements, // but unstable on all other kinds of statements @@ -949,6 +913,7 @@ pub fn parse_ast_fragment<'a>( RecoverComma::No, RecoverColon::Yes, )?), + AstFragmentKind::Crate => AstFragment::Crate(this.parse_crate_mod()?), AstFragmentKind::Arms | AstFragmentKind::Fields | AstFragmentKind::FieldPats @@ -1195,6 +1160,33 @@ macro_rules! assign_id { } impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { + fn visit_crate(&mut self, krate: &mut ast::Crate) { + visit_clobber(krate, |krate| { + let span = krate.span; + let mut krate = match self.configure(krate) { + Some(krate) => krate, + None => { + return ast::Crate { + attrs: Vec::new(), + items: Vec::new(), + span, + id: self.cx.resolver.next_node_id(), + is_placeholder: false, + }; + } + }; + + if let Some(attr) = self.take_first_attr(&mut krate) { + return self + .collect_attr(attr, Annotatable::Crate(krate), AstFragmentKind::Crate) + .make_crate(); + } + + assign_id!(self, &mut krate.id, || noop_visit_crate(&mut krate, self)); + krate + }) + } + fn visit_expr(&mut self, expr: &mut P) { self.cfg.configure_expr(expr); visit_clobber(expr.deref_mut(), |mut expr| { diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 4e84a9df6c..47a64b457d 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -1,9 +1,7 @@ #![feature(crate_visibility_modifier)] #![feature(decl_macro)] -#![feature(destructuring_assignment)] -#![cfg_attr(bootstrap, feature(format_args_capture))] +#![cfg_attr(bootstrap, feature(destructuring_assignment))] #![feature(if_let_guard)] -#![feature(iter_zip)] #![feature(let_else)] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_internals)] diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index a7434d73ab..dd82add08d 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -584,9 +584,7 @@ fn inner_parse_loop<'root, 'tt>( // // At the beginning of the loop, if we reach the end of the delimited submatcher, // we pop the stack to backtrack out of the descent. - seq - @ - (TokenTree::Delimited(..) + seq @ (TokenTree::Delimited(..) | TokenTree::Token(Token { kind: DocComment(..), .. })) => { let lower_elts = mem::replace(&mut item.top_elts, Tt(seq)); let idx = item.idx; diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index f8491654f3..8065911afb 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -253,7 +253,7 @@ fn generic_extension<'cx>( for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers let lhs_tt = match *lhs { - mbe::TokenTree::Delimited(_, ref delim) => &delim.tts[..], + mbe::TokenTree::Delimited(_, ref delim) => &delim.tts, _ => cx.span_bug(sp, "malformed macro lhs"), }; @@ -353,7 +353,7 @@ fn generic_extension<'cx>( for lhs in lhses { // try each arm's matchers let lhs_tt = match *lhs { - mbe::TokenTree::Delimited(_, ref delim) => &delim.tts[..], + mbe::TokenTree::Delimited(_, ref delim) => &delim.tts, _ => continue, }; if let Success(_) = @@ -677,11 +677,11 @@ impl FirstSets { first.replace_with(tt.clone()); } TokenTree::Delimited(span, ref delimited) => { - build_recur(sets, &delimited.tts[..]); + build_recur(sets, &delimited.tts); first.replace_with(delimited.open_tt(span)); } TokenTree::Sequence(sp, ref seq_rep) => { - let subfirst = build_recur(sets, &seq_rep.tts[..]); + let subfirst = build_recur(sets, &seq_rep.tts); match sets.first.entry(sp.entire()) { Entry::Vacant(vac) => { @@ -748,7 +748,7 @@ impl FirstSets { let subfirst = match self.first.get(&sp.entire()) { Some(&Some(ref subfirst)) => subfirst, Some(&None) => { - subfirst_owned = self.first(&seq_rep.tts[..]); + subfirst_owned = self.first(&seq_rep.tts); &subfirst_owned } None => { @@ -1027,6 +1027,24 @@ fn check_matcher_core( ), ); err.span_label(sp, format!("not allowed after `{}` fragments", kind)); + + if kind == NonterminalKind::PatWithOr + && sess.edition == Edition::Edition2021 + && next_token.is_token(&BinOp(token::BinOpToken::Or)) + { + let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl( + span, + name, + Some(NonterminalKind::PatParam { inferred: false }), + )); + err.span_suggestion( + span, + &format!("try a `pat_param` fragment specifier instead"), + suggestion, + Applicability::MaybeIncorrect, + ); + } + let msg = "allowed there are: "; match possible { &[] => {} diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 88e1623012..01a7f72661 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -175,12 +175,12 @@ pub(super) fn transcribe<'a>( )); } - LockstepIterSize::Contradiction(ref msg) => { + 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(cx.struct_span_err(seq.span(), &msg[..])); + return Err(cx.struct_span_err(seq.span(), &msg)); } LockstepIterSize::Constraint(len, _) => { diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index 1c0b2a9b48..e9532dbe2c 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -103,10 +103,10 @@ crate fn mod_dir_path( if let DirOwnership::Owned { relative } = &mut dir_ownership { if let Some(ident) = relative.take() { // Remove the relative offset. - dir_path.push(&*ident.as_str()); + dir_path.push(ident.as_str()); } } - dir_path.push(&*ident.as_str()); + dir_path.push(ident.as_str()); (dir_path, dir_ownership) } @@ -170,8 +170,8 @@ fn mod_file_path_from_attr( ) -> Option { // Extract path string from first `#[path = "path_string"]` attribute. let first_path = attrs.iter().find(|at| at.has_name(sym::path))?; - let path_string = match first_path.value_str() { - Some(s) => s.as_str(), + let path_sym = match first_path.value_str() { + Some(s) => s, None => { // This check is here mainly to catch attempting to use a macro, // such as #[path = concat!(...)]. This isn't currently supported @@ -189,14 +189,16 @@ fn mod_file_path_from_attr( } }; + let path_str = path_sym.as_str(); + // On windows, the base path might have the form // `\\?\foo\bar` in which case it does not tolerate // mixed `/` and `\` separators, so canonicalize // `/` to `\`. #[cfg(windows)] - let path_string = path_string.replace("/", "\\"); + let path_str = path_str.replace("/", "\\"); - Some(dir_path.join(&*path_string)) + Some(dir_path.join(path_str)) } /// Returns a path to a module. diff --git a/compiler/rustc_expand/src/parse/tests.rs b/compiler/rustc_expand/src/parse/tests.rs index 6402a81e7c..4a8236b2cf 100644 --- a/compiler/rustc_expand/src/parse/tests.rs +++ b/compiler/rustc_expand/src/parse/tests.rs @@ -65,24 +65,33 @@ fn string_to_tts_macro() { let tts: &[TokenTree] = &tts[..]; match tts { - [TokenTree::Token(Token { kind: token::Ident(name_macro_rules, false), .. }), TokenTree::Token(Token { kind: token::Not, .. }), TokenTree::Token(Token { kind: token::Ident(name_zip, false), .. }), TokenTree::Delimited(_, macro_delim, macro_tts)] - if name_macro_rules == &kw::MacroRules && name_zip.as_str() == "zip" => - { + [ + TokenTree::Token(Token { kind: token::Ident(name_macro_rules, false), .. }), + TokenTree::Token(Token { kind: token::Not, .. }), + TokenTree::Token(Token { kind: token::Ident(name_zip, false), .. }), + TokenTree::Delimited(_, macro_delim, macro_tts), + ] if name_macro_rules == &kw::MacroRules && name_zip.as_str() == "zip" => { let tts = ¯o_tts.trees().collect::>(); match &tts[..] { - [TokenTree::Delimited(_, first_delim, first_tts), TokenTree::Token(Token { kind: token::FatArrow, .. }), TokenTree::Delimited(_, second_delim, second_tts)] - if macro_delim == &token::Paren => - { + [ + TokenTree::Delimited(_, first_delim, first_tts), + TokenTree::Token(Token { kind: token::FatArrow, .. }), + TokenTree::Delimited(_, second_delim, second_tts), + ] if macro_delim == &token::Paren => { let tts = &first_tts.trees().collect::>(); match &tts[..] { - [TokenTree::Token(Token { kind: token::Dollar, .. }), TokenTree::Token(Token { kind: token::Ident(name, false), .. })] - if first_delim == &token::Paren && name.as_str() == "a" => {} + [ + TokenTree::Token(Token { kind: token::Dollar, .. }), + TokenTree::Token(Token { kind: token::Ident(name, false), .. }), + ] if first_delim == &token::Paren && name.as_str() == "a" => {} _ => panic!("value 3: {:?} {:?}", first_delim, first_tts), } let tts = &second_tts.trees().collect::>(); match &tts[..] { - [TokenTree::Token(Token { kind: token::Dollar, .. }), TokenTree::Token(Token { kind: token::Ident(name, false), .. })] - if second_delim == &token::Paren && name.as_str() == "a" => {} + [ + TokenTree::Token(Token { kind: token::Dollar, .. }), + TokenTree::Token(Token { kind: token::Ident(name, false), .. }), + ] if second_delim == &token::Paren && name.as_str() == "a" => {} _ => panic!("value 4: {:?} {:?}", second_delim, second_tts), } } diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 12b6bc7bbe..825af9a7b2 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -46,6 +46,13 @@ pub fn placeholder( || P(ast::Pat { id, kind: ast::PatKind::MacCall(mac_placeholder()), span, tokens: None }); match kind { + AstFragmentKind::Crate => AstFragment::Crate(ast::Crate { + attrs: Default::default(), + items: Default::default(), + span, + id, + is_placeholder: true, + }), AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()), AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())), AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item { @@ -354,4 +361,12 @@ impl MutVisitor for PlaceholderExpander { _ => noop_visit_ty(ty, self), } } + + fn visit_crate(&mut self, krate: &mut ast::Crate) { + if krate.is_placeholder { + *krate = self.remove(krate.id).make_crate(); + } else { + noop_visit_crate(krate, self) + } + } } diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index fa9e98be9e..5656465655 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -331,9 +331,9 @@ pub struct Ident { impl Ident { fn new(sess: &ParseSess, sym: Symbol, is_raw: bool, span: Span) -> Ident { - let sym = nfc_normalize(&sym.as_str()); + let sym = nfc_normalize(sym.as_str()); let string = sym.as_str(); - if !rustc_lexer::is_ident(&string) { + if !rustc_lexer::is_ident(string) { panic!("`{:?}` is not a valid identifier", string) } if is_raw && !sym.can_be_raw() { @@ -466,13 +466,12 @@ impl server::TokenStream for Rustc<'_, '_> { ast::ExprKind::Unary(ast::UnOp::Neg, e) => match &e.kind { ast::ExprKind::Lit(l) => match l.token { token::Lit { kind: token::Integer | token::Float, .. } => { - Ok(std::array::IntoIter::new([ + Ok(Self::TokenStream::from_iter([ // FIXME: The span of the `-` token is lost when // parsing, so we cannot faithfully recover it here. tokenstream::TokenTree::token(token::BinOp(token::Minus), e.span), tokenstream::TokenTree::token(token::Literal(l.token), l.span), - ]) - .collect()) + ])) } _ => Err(()), }, diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 6950fae898..32a9d081ed 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -90,6 +90,8 @@ declare_features! ( (accepted, const_fn_union, "1.56.0", Some(51909), None), /// Allows unsizing coercions in `const fn`. (accepted, const_fn_unsize, "1.54.0", Some(64992), None), + /// Allows const generics to have default values (e.g. `struct Foo(...);`). + (accepted, const_generics_defaults, "1.59.0", Some(44580), None), /// Allows the use of `if` and `match` in constants. (accepted, const_if_match, "1.46.0", Some(49146), None), /// Allows indexing into constant arrays. @@ -112,6 +114,8 @@ declare_features! ( (accepted, default_type_params, "1.0.0", None, None), /// Allows `#[deprecated]` attribute. (accepted, deprecated, "1.9.0", Some(29935), None), + /// Allows the use of destructuring assignments. + (accepted, destructuring_assignment, "1.59.0", Some(71126), None), /// Allows `#[doc(alias = "...")]`. (accepted, doc_alias, "1.48.0", Some(50146), None), /// Allows `..` in tuple (struct) patterns. diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 7860f92f96..ebd12d6ab4 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -69,10 +69,6 @@ macro_rules! declare_features { } } - pub fn unordered_const_ty_params(&self) -> bool { - self.const_generics_defaults || self.generic_const_exprs || self.adt_const_params - } - /// Some features are known to be incomplete and using them is likely to have /// unanticipated results, such as compiler crashes. We warn the user about these /// to alert them. @@ -290,6 +286,8 @@ declare_features! ( (active, asm_experimental_arch, "1.58.0", Some(72016), None), /// Allows using `sym` operands in inline assembly. (active, asm_sym, "1.58.0", Some(72016), None), + /// Allows the `may_unwind` option in inline assembly. + (active, asm_unwind, "1.58.0", Some(72016), None), /// Allows the user of associated type bounds. (active, associated_type_bounds, "1.34.0", Some(52662), None), /// Allows associated type defaults. @@ -332,8 +330,6 @@ declare_features! ( (active, const_fn_trait_bound, "1.53.0", Some(57563), None), /// Allows `for _ in _` loops in const contexts. (active, const_for, "1.56.0", Some(87575), None), - /// Allows const generics to have default values (e.g. `struct Foo(...);`). - (active, const_generics_defaults, "1.51.0", Some(44580), None), /// Allows argument and return position `impl Trait` in a `const fn`. (active, const_impl_trait, "1.48.0", Some(77463), None), /// Allows using `&mut` in constant functions. @@ -360,8 +356,6 @@ declare_features! ( (active, default_type_parameter_fallback, "1.3.0", Some(27336), None), /// Allows `#[derive(Default)]` and `#[default]` on enums. (active, derive_default_enum, "1.56.0", Some(86985), None), - /// Allows the use of destructuring assignments. - (active, destructuring_assignment, "1.49.0", Some(71126), None), /// Tells rustdoc to automatically generate `#[doc(cfg(...))]`. (active, doc_auto_cfg, "1.58.0", Some(43781), None), /// Allows `#[doc(cfg(...))]`. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index f25b2d8f56..0644948704 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -339,7 +339,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), // Entry point: - ungated!(main, Normal, template!(Word), WarnFollowing), ungated!(start, Normal, template!(Word), WarnFollowing), ungated!(no_start, CrateLevel, template!(Word), WarnFollowing), ungated!(no_main, CrateLevel, template!(Word), WarnFollowing), diff --git a/compiler/rustc_graphviz/src/lib.rs b/compiler/rustc_graphviz/src/lib.rs index 27390fd2e4..e318090ebe 100644 --- a/compiler/rustc_graphviz/src/lib.rs +++ b/compiler/rustc_graphviz/src/lib.rs @@ -472,7 +472,7 @@ pub trait Labeller<'a> { /// Escape tags in such a way that it is suitable for inclusion in a /// Graphviz HTML label. pub fn escape_html(s: &str) -> String { - s.replace("&", "&").replace("\"", """).replace("<", "<").replace(">", ">") + s.replace('&', "&").replace('\"', """).replace('<', "<").replace('>', ">") } impl<'a> LabelText<'a> { @@ -659,7 +659,7 @@ where } writeln!(text, ";").unwrap(); - w.write_all(&text[..])?; + w.write_all(&text)?; text.clear(); } @@ -684,7 +684,7 @@ where } writeln!(text, ";").unwrap(); - w.write_all(&text[..])?; + w.write_all(&text)?; text.clear(); } diff --git a/compiler/rustc_hir/src/arena.rs b/compiler/rustc_hir/src/arena.rs index f19ca497d8..edad00ed6a 100644 --- a/compiler/rustc_hir/src/arena.rs +++ b/compiler/rustc_hir/src/arena.rs @@ -20,6 +20,7 @@ macro_rules! arena_types { [] generic_bound: rustc_hir::GenericBound<'tcx>, [] generic_param: rustc_hir::GenericParam<'tcx>, [] expr: rustc_hir::Expr<'tcx>, + [] let_expr: rustc_hir::Let<'tcx>, [] expr_field: rustc_hir::ExprField<'tcx>, [] pat_field: rustc_hir::PatField<'tcx>, [] fn_decl: rustc_hir::FnDecl<'tcx>, diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 60761a05de..a43cb0203d 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -113,7 +113,7 @@ pub enum DefKind { Field, /// Lifetime parameter: the `'a` in `struct Foo<'a> { ... }` LifetimeParam, - /// A use of [`global_asm!`]. + /// A use of `global_asm!`. GlobalAsm, Impl, Closure, @@ -443,11 +443,11 @@ impl PerNS { } pub fn into_iter(self) -> IntoIter { - IntoIter::new([self.value_ns, self.type_ns, self.macro_ns]) + [self.value_ns, self.type_ns, self.macro_ns].into_iter() } pub fn iter(&self) -> IntoIter<&T, 3> { - IntoIter::new([&self.value_ns, &self.type_ns, &self.macro_ns]) + [&self.value_ns, &self.type_ns, &self.macro_ns].into_iter() } } @@ -481,7 +481,7 @@ impl PerNS> { /// Returns an iterator over the items which are `Some`. pub fn present_items(self) -> impl Iterator { - IntoIter::new([self.type_ns, self.value_ns, self.macro_ns]).flatten() + [self.type_ns, self.value_ns, self.macro_ns].into_iter().flatten() } } diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index ca29351455..d813c887ee 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -101,7 +101,11 @@ impl DefPathTable { pub struct Definitions { table: DefPathTable, - // FIXME(eddyb) ideally all `LocalDefId`s would be HIR owners. + /// Only [`LocalDefId`]s for items and item-like are HIR owners. + /// The associated `HirId` has a `local_id` of `0`. + /// Generic parameters and closures are also assigned a `LocalDefId` but are not HIR owners. + /// Their `HirId`s are defined by their position while lowering the enclosing owner. + // FIXME(cjgillot) Some `LocalDefId`s from `use` items are dropped during lowering and lack a `HirId`. pub(super) def_id_to_hir_id: IndexVec>, /// The reverse mapping of `def_id_to_hir_id`. pub(super) hir_id_to_def_id: FxHashMap, @@ -173,7 +177,7 @@ impl DisambiguatedDefPathData { if verbose && self.disambiguator != 0 { write!(writer, "{}#{}", name, self.disambiguator) } else { - writer.write_str(&name.as_str()) + writer.write_str(name.as_str()) } } DefPathDataName::Anon { namespace } => { @@ -267,6 +271,8 @@ pub enum DefPathData { // Different kinds of items and item-like things: /// An impl. Impl, + /// An `extern` block. + ForeignMod, /// Something in the type namespace. TypeNs(Symbol), /// Something in the value namespace. @@ -469,7 +475,9 @@ impl DefPathData { match *self { TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name), - Impl | CrateRoot | Misc | ClosureExpr | Ctor | AnonConst | ImplTrait => None, + Impl | ForeignMod | CrateRoot | Misc | ClosureExpr | Ctor | AnonConst | ImplTrait => { + None + } } } @@ -482,6 +490,7 @@ impl DefPathData { // Note that this does not show up in user print-outs. CrateRoot => DefPathDataName::Anon { namespace: kw::Crate }, Impl => DefPathDataName::Anon { namespace: kw::Impl }, + ForeignMod => DefPathDataName::Anon { namespace: kw::Extern }, Misc => DefPathDataName::Anon { namespace: sym::misc }, ClosureExpr => DefPathDataName::Anon { namespace: sym::closure }, Ctor => DefPathDataName::Anon { namespace: sym::constructor }, @@ -494,7 +503,7 @@ impl DefPathData { impl fmt::Display for DefPathData { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.name() { - DefPathDataName::Named(name) => f.write_str(&name.as_str()), + DefPathDataName::Named(name) => f.write_str(name.as_str()), // FIXME(#70334): this will generate legacy {{closure}}, {{impl}}, etc DefPathDataName::Anon { namespace } => write!(f, "{{{{{}}}}}", namespace), } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index c67d3df3de..d59756239d 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -17,8 +17,7 @@ use rustc_index::vec::IndexVec; use rustc_macros::HashStable_Generic; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{def_id::LocalDefId, BytePos}; -use rustc_span::{MultiSpan, Span, DUMMY_SP}; +use rustc_span::{def_id::LocalDefId, BytePos, MultiSpan, Span, DUMMY_SP}; use rustc_target::asm::InlineAsmRegOrRegClass; use rustc_target::spec::abi::Abi; @@ -92,7 +91,9 @@ pub enum LifetimeName { Param(ParamName), /// User wrote nothing (e.g., the lifetime in `&u32`). - Implicit, + /// + /// The bool indicates whether the user should have written something. + Implicit(bool), /// Implicit lifetime in a context like `dyn Foo`. This is /// distinguished from implicit lifetimes elsewhere because the @@ -122,7 +123,7 @@ impl LifetimeName { pub fn ident(&self) -> Ident { match *self { LifetimeName::ImplicitObjectLifetimeDefault - | LifetimeName::Implicit + | LifetimeName::Implicit(_) | LifetimeName::Error => Ident::empty(), LifetimeName::Underscore => Ident::with_dummy_span(kw::UnderscoreLifetime), LifetimeName::Static => Ident::with_dummy_span(kw::StaticLifetime), @@ -133,7 +134,7 @@ impl LifetimeName { pub fn is_elided(&self) -> bool { match self { LifetimeName::ImplicitObjectLifetimeDefault - | LifetimeName::Implicit + | LifetimeName::Implicit(_) | LifetimeName::Underscore => true, // It might seem surprising that `Fresh(_)` counts as @@ -254,23 +255,9 @@ pub struct ConstArg { pub span: Span, } -#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)] -pub enum InferKind { - Const, - Type, -} - -impl InferKind { - #[inline] - pub fn is_type(self) -> bool { - matches!(self, InferKind::Type) - } -} - #[derive(Encodable, Debug, HashStable_Generic)] pub struct InferArg { pub hir_id: HirId, - pub kind: InferKind, pub span: Span, } @@ -324,13 +311,11 @@ impl GenericArg<'_> { } } - pub fn to_ord(&self, feats: &rustc_feature::Features) -> ast::ParamKindOrd { + pub fn to_ord(&self) -> ast::ParamKindOrd { match self { GenericArg::Lifetime(_) => ast::ParamKindOrd::Lifetime, GenericArg::Type(_) => ast::ParamKindOrd::Type, - GenericArg::Const(_) => { - ast::ParamKindOrd::Const { unordered: feats.unordered_const_ty_params() } - } + GenericArg::Const(_) => ast::ParamKindOrd::Const, GenericArg::Infer(_) => ast::ParamKindOrd::Infer, } } @@ -523,13 +508,21 @@ pub struct GenericParam<'hir> { pub kind: GenericParamKind<'hir>, } -impl GenericParam<'hir> { - pub fn bounds_span(&self) -> Option { - self.bounds.iter().fold(None, |span, bound| { - let span = span.map(|s| s.to(bound.span())).unwrap_or_else(|| bound.span()); - - Some(span) - }) +impl<'hir> GenericParam<'hir> { + pub fn bounds_span_for_suggestions(&self) -> Option { + self.bounds + .iter() + .fold(None, |span: Option, bound| { + // We include bounds that come from a `#[derive(_)]` but point at the user's code, + // as we use this method to get a span appropriate for suggestions. + if !bound.span().can_be_used_for_suggestions() { + None + } else { + let span = span.map(|s| s.to(bound.span())).unwrap_or_else(|| bound.span()); + Some(span) + } + }) + .map(|sp| sp.shrink_to_hi()) } } @@ -550,7 +543,7 @@ pub struct Generics<'hir> { pub span: Span, } -impl Generics<'hir> { +impl<'hir> Generics<'hir> { pub const fn empty() -> Generics<'hir> { Generics { params: &[], @@ -615,7 +608,7 @@ pub enum WherePredicate<'hir> { EqPredicate(WhereEqPredicate<'hir>), } -impl WherePredicate<'_> { +impl<'hir> WherePredicate<'hir> { pub fn span(&self) -> Span { match self { WherePredicate::BoundPredicate(p) => p.span, @@ -637,7 +630,7 @@ pub struct WhereBoundPredicate<'hir> { pub bounds: GenericBounds<'hir>, } -impl WhereBoundPredicate<'hir> { +impl<'hir> WhereBoundPredicate<'hir> { /// Returns `true` if `param_def_id` matches the `bounded_ty` of this predicate. pub fn is_param_bound(&self, param_def_id: DefId) -> bool { let path = match self.bounded_ty.kind { @@ -1167,10 +1160,24 @@ pub struct Arm<'hir> { pub body: &'hir Expr<'hir>, } +/// Represents a `let [: ] = ` expression (not a Local), occurring in an `if-let` or +/// `let-else`, evaluating to a boolean. Typically the pattern is refutable. +/// +/// In an if-let, imagine it as `if (let = ) { ... }`; in a let-else, it is part of the +/// desugaring to if-let. Only let-else supports the type annotation at present. +#[derive(Debug, HashStable_Generic)] +pub struct Let<'hir> { + pub hir_id: HirId, + pub span: Span, + pub pat: &'hir Pat<'hir>, + pub ty: Option<&'hir Ty<'hir>>, + pub init: &'hir Expr<'hir>, +} + #[derive(Debug, HashStable_Generic)] pub enum Guard<'hir> { If(&'hir Expr<'hir>), - // FIXME use ExprKind::Let for this. + // FIXME use hir::Let for this. IfLet(&'hir Pat<'hir>, &'hir Expr<'hir>), } @@ -1196,7 +1203,7 @@ pub enum UnsafeSource { UserProvided, } -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Hash, Debug)] pub struct BodyId { pub hir_id: HirId, } @@ -1229,7 +1236,7 @@ pub struct Body<'hir> { pub generator_kind: Option, } -impl Body<'hir> { +impl<'hir> Body<'hir> { pub fn id(&self) -> BodyId { BodyId { hir_id: self.value.hir_id } } @@ -1400,6 +1407,20 @@ impl fmt::Display for ConstContext { /// A literal. pub type Lit = Spanned; +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)] +pub enum ArrayLen { + Infer(HirId, Span), + Body(AnonConst), +} + +impl ArrayLen { + pub fn hir_id(&self) -> HirId { + match self { + &ArrayLen::Infer(hir_id, _) | &ArrayLen::Body(AnonConst { hir_id, body: _ }) => hir_id, + } + } +} + /// A constant (expression) that's not an item or associated item, /// but needs its own `DefId` for type-checking, const-eval, etc. /// These are usually found nested inside types (e.g., array lengths) @@ -1620,13 +1641,13 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool { | LangItem::RangeFrom | LangItem::RangeFull | LangItem::RangeToInclusive, - _, + .. ) ), // `..=` desugars into `::std::ops::RangeInclusive::new(...)`. ExprKind::Call(ref func, _) => { - matches!(func.kind, ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, _))) + matches!(func.kind, ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..))) } _ => false, @@ -1687,7 +1708,7 @@ pub enum ExprKind<'hir> { /// /// These are not `Local` and only occur as expressions. /// The `let Some(x) = foo()` in `if let Some(x) = foo()` is an example of `Let(..)`. - Let(&'hir Pat<'hir>, &'hir Expr<'hir>, Span), + Let(&'hir Let<'hir>), /// An `if` block, with an optional else block. /// /// I.e., `if { } else { }`. @@ -1749,7 +1770,7 @@ pub enum ExprKind<'hir> { /// /// E.g., `[1; 5]`. The first expression is the element /// to be repeated; the second is the number of times to repeat it. - Repeat(&'hir Expr<'hir>, AnonConst), + Repeat(&'hir Expr<'hir>, ArrayLen), /// A suspension point for generators (i.e., `yield `). Yield(&'hir Expr<'hir>, YieldSource), @@ -1781,8 +1802,8 @@ pub enum QPath<'hir> { /// the `X` and `Y` nodes each being a `TyKind::Path(QPath::TypeRelative(..))`. TypeRelative(&'hir Ty<'hir>, &'hir PathSegment<'hir>), - /// Reference to a `#[lang = "foo"]` item. - LangItem(LangItem, Span), + /// Reference to a `#[lang = "foo"]` item. `HirId` of the inner expr. + LangItem(LangItem, Span, Option), } impl<'hir> QPath<'hir> { @@ -1791,7 +1812,7 @@ impl<'hir> QPath<'hir> { match *self { QPath::Resolved(_, path) => path.span, QPath::TypeRelative(qself, ps) => qself.span.to(ps.ident.span), - QPath::LangItem(_, span) => span, + QPath::LangItem(_, span, _) => span, } } @@ -1801,7 +1822,7 @@ impl<'hir> QPath<'hir> { match *self { QPath::Resolved(_, path) => path.span, QPath::TypeRelative(qself, _) => qself.span, - QPath::LangItem(_, span) => span, + QPath::LangItem(_, span, _) => span, } } @@ -1811,7 +1832,7 @@ impl<'hir> QPath<'hir> { match *self { QPath::Resolved(_, path) => path.segments.last().unwrap().ident.span, QPath::TypeRelative(_, segment) => segment.ident.span, - QPath::LangItem(_, span) => span, + QPath::LangItem(_, span, _) => span, } } } @@ -1973,7 +1994,7 @@ pub struct FnSig<'hir> { // The bodies for items are stored "out of line", in a separate // hashmap in the `Crate`. Here we just record the hir-id of the item // so it can fetched later. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug)] pub struct TraitItemId { pub def_id: LocalDefId, } @@ -2036,7 +2057,7 @@ pub enum TraitItemKind<'hir> { // The bodies for items are stored "out of line", in a separate // hashmap in the `Crate`. Here we just record the hir-id of the item // so it can fetched later. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug)] pub struct ImplItemId { pub def_id: LocalDefId, } @@ -2239,7 +2260,6 @@ pub struct BareFnTy<'hir> { pub struct OpaqueTy<'hir> { pub generics: Generics<'hir>, pub bounds: GenericBounds<'hir>, - pub impl_trait_fn: Option, pub origin: OpaqueTyOrigin, } @@ -2247,9 +2267,9 @@ pub struct OpaqueTy<'hir> { #[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)] pub enum OpaqueTyOrigin { /// `-> impl Trait` - FnReturn, + FnReturn(LocalDefId), /// `async fn` - AsyncFn, + AsyncFn(LocalDefId), /// type aliases: `type Foo = impl Trait;` TyAlias, } @@ -2260,7 +2280,7 @@ pub enum TyKind<'hir> { /// A variable length slice (i.e., `[T]`). Slice(&'hir Ty<'hir>), /// A fixed length array (i.e., `[T; n]`). - Array(&'hir Ty<'hir>, AnonConst), + Array(&'hir Ty<'hir>, ArrayLen), /// A raw pointer (i.e., `*const T` or `*mut T`). Ptr(MutTy<'hir>), /// A reference (i.e., `&'a T` or `&'a mut T`). @@ -2478,7 +2498,7 @@ impl FnRetTy<'_> { } } -#[derive(Encodable, Debug)] +#[derive(Encodable, Debug, HashStable_Generic)] pub struct Mod<'hir> { /// A span from the first token past `{` to the last token until `}`. /// For `mod foo;`, the inner span ranges from the first token @@ -2617,7 +2637,7 @@ pub enum VariantData<'hir> { Unit(HirId), } -impl VariantData<'hir> { +impl<'hir> VariantData<'hir> { /// Return the fields of this variant. pub fn fields(&self) -> &'hir [FieldDef<'hir>] { match *self { @@ -2638,7 +2658,7 @@ impl VariantData<'hir> { // The bodies for items are stored "out of line", in a separate // hashmap in the `Crate`. Here we just record the hir-id of the item // so it can fetched later. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, Hash)] pub struct ItemId { pub def_id: LocalDefId, } @@ -2800,7 +2820,9 @@ impl ItemKind<'_> { Some(match *self { ItemKind::Fn(_, ref generics, _) | ItemKind::TyAlias(_, ref generics) - | ItemKind::OpaqueTy(OpaqueTy { ref generics, impl_trait_fn: None, .. }) + | ItemKind::OpaqueTy(OpaqueTy { + ref generics, origin: OpaqueTyOrigin::TyAlias, .. + }) | ItemKind::Enum(_, ref generics) | ItemKind::Struct(_, ref generics) | ItemKind::Union(_, ref generics) @@ -2875,7 +2897,7 @@ pub enum AssocItemKind { // The bodies for items are stored "out of line", in a separate // hashmap in the `Crate`. Here we just record the hir-id of the item // so it can fetched later. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug)] pub struct ForeignItemId { pub def_id: LocalDefId, } @@ -3200,59 +3222,6 @@ impl<'hir> Node<'hir> { } } - pub fn hir_id(&self) -> Option { - match self { - Node::Item(Item { def_id, .. }) - | Node::TraitItem(TraitItem { def_id, .. }) - | Node::ImplItem(ImplItem { def_id, .. }) - | Node::ForeignItem(ForeignItem { def_id, .. }) => Some(HirId::make_owner(*def_id)), - Node::Field(FieldDef { hir_id, .. }) - | Node::AnonConst(AnonConst { hir_id, .. }) - | Node::Expr(Expr { hir_id, .. }) - | Node::Stmt(Stmt { hir_id, .. }) - | Node::Ty(Ty { hir_id, .. }) - | Node::Binding(Pat { hir_id, .. }) - | Node::Pat(Pat { hir_id, .. }) - | Node::Arm(Arm { hir_id, .. }) - | Node::Block(Block { hir_id, .. }) - | Node::Local(Local { hir_id, .. }) - | Node::Lifetime(Lifetime { hir_id, .. }) - | Node::Param(Param { hir_id, .. }) - | Node::Infer(InferArg { hir_id, .. }) - | Node::GenericParam(GenericParam { hir_id, .. }) => Some(*hir_id), - Node::TraitRef(TraitRef { hir_ref_id, .. }) => Some(*hir_ref_id), - Node::PathSegment(PathSegment { hir_id, .. }) => *hir_id, - Node::Variant(Variant { id, .. }) => Some(*id), - Node::Ctor(variant) => variant.ctor_hir_id(), - Node::Crate(_) | Node::Visibility(_) => None, - } - } - - /// Returns `Constness::Const` when this node is a const fn/impl/item. - pub fn constness_for_typeck(&self) -> Constness { - match self { - Node::Item(Item { - kind: ItemKind::Fn(FnSig { header: FnHeader { constness, .. }, .. }, ..), - .. - }) - | Node::TraitItem(TraitItem { - kind: TraitItemKind::Fn(FnSig { header: FnHeader { constness, .. }, .. }, ..), - .. - }) - | Node::ImplItem(ImplItem { - kind: ImplItemKind::Fn(FnSig { header: FnHeader { constness, .. }, .. }, ..), - .. - }) - | Node::Item(Item { kind: ItemKind::Impl(Impl { constness, .. }), .. }) => *constness, - - Node::Item(Item { kind: ItemKind::Const(..), .. }) - | Node::TraitItem(TraitItem { kind: TraitItemKind::Const(..), .. }) - | Node::ImplItem(ImplItem { kind: ImplItemKind::Const(..), .. }) => Constness::Const, - - _ => Constness::NotConst, - } - } - pub fn as_owner(self) -> Option> { match self { Node::Item(i) => Some(OwnerNode::Item(i)), @@ -3298,7 +3267,7 @@ mod size_asserts { rustc_data_structures::static_assert_size!(super::Expr<'static>, 64); rustc_data_structures::static_assert_size!(super::Pat<'static>, 88); rustc_data_structures::static_assert_size!(super::QPath<'static>, 24); - rustc_data_structures::static_assert_size!(super::Ty<'static>, 72); + rustc_data_structures::static_assert_size!(super::Ty<'static>, 80); rustc_data_structures::static_assert_size!(super::Item<'static>, 184); rustc_data_structures::static_assert_size!(super::TraitItem<'static>, 128); diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs index 39552eb9f3..1482a96cae 100644 --- a/compiler/rustc_hir/src/hir_id.rs +++ b/compiler/rustc_hir/src/hir_id.rs @@ -11,7 +11,7 @@ use std::fmt; /// the `local_id` part of the `HirId` changing, which is a very useful property in /// incremental compilation where we have to persist things through changes to /// the code base. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] #[derive(Encodable, Decodable)] pub struct HirId { pub owner: LocalDefId, @@ -32,6 +32,10 @@ impl HirId { pub fn make_owner(owner: LocalDefId) -> Self { Self { owner, local_id: ItemLocalId::from_u32(0) } } + + pub fn index(self) -> (usize, usize) { + (rustc_index::vec::Idx::index(self.owner), rustc_index::vec::Idx::index(self.local_id)) + } } impl fmt::Display for HirId { @@ -40,6 +44,18 @@ impl fmt::Display for HirId { } } +impl Ord for HirId { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + (self.index()).cmp(&(other.index())) + } +} + +impl PartialOrd for HirId { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(&other)) + } +} + rustc_data_structures::define_id_collections!(HirIdMap, HirIdSet, HirId); rustc_data_structures::define_id_collections!(ItemLocalMap, ItemLocalSet, ItemLocalId); diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index cff543760f..d0eee42220 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -139,7 +139,7 @@ pub trait Map<'hir> { } // Used when no map is actually available, forcing manual implementation of nested visitors. -impl Map<'hir> for ! { +impl<'hir> Map<'hir> for ! { fn find(&self, _: HirId) -> Option> { unreachable!() } @@ -383,12 +383,18 @@ pub trait Visitor<'v>: Sized { fn visit_pat(&mut self, p: &'v Pat<'v>) { walk_pat(self, p) } + fn visit_array_length(&mut self, len: &'v ArrayLen) { + walk_array_len(self, len) + } fn visit_anon_const(&mut self, c: &'v AnonConst) { walk_anon_const(self, c) } fn visit_expr(&mut self, ex: &'v Expr<'v>) { walk_expr(self, ex) } + fn visit_let_expr(&mut self, lex: &'v Let<'v>) { + walk_let_expr(self, lex) + } fn visit_ty(&mut self, t: &'v Ty<'v>) { walk_ty(self, t) } @@ -545,7 +551,7 @@ pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime | LifetimeName::Param(ParamName::Error) | LifetimeName::Static | LifetimeName::Error - | LifetimeName::Implicit + | LifetimeName::Implicit(_) | LifetimeName::ImplicitObjectLifetimeDefault | LifetimeName::Underscore => {} } @@ -750,7 +756,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) { } TyKind::Array(ref ty, ref length) => { visitor.visit_ty(ty); - visitor.visit_anon_const(length) + visitor.visit_array_length(length) } TyKind::TraitObject(bounds, ref lifetime, _syntax) => { for bound in bounds { @@ -1121,11 +1127,26 @@ pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) { } } +pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen) { + match len { + &ArrayLen::Infer(hir_id, _span) => visitor.visit_id(hir_id), + ArrayLen::Body(c) => visitor.visit_anon_const(c), + } +} + pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) { visitor.visit_id(constant.hir_id); visitor.visit_nested_body(constant.body); } +pub fn walk_let_expr<'v, V: Visitor<'v>>(visitor: &mut V, let_expr: &'v Let<'v>) { + // match the visit order in walk_local + visitor.visit_expr(let_expr.init); + visitor.visit_id(let_expr.hir_id); + visitor.visit_pat(let_expr.pat); + walk_list!(visitor, visit_ty, let_expr.ty); +} + pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) { visitor.visit_id(expression.hir_id); match expression.kind { @@ -1136,7 +1157,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) ExprKind::ConstBlock(ref anon_const) => visitor.visit_anon_const(anon_const), ExprKind::Repeat(ref element, ref count) => { visitor.visit_expr(element); - visitor.visit_anon_const(count) + visitor.visit_array_length(count) } ExprKind::Struct(ref qpath, fields, ref optional_base) => { visitor.visit_qpath(qpath, expression.hir_id, expression.span); @@ -1172,10 +1193,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) ExprKind::DropTemps(ref subexpression) => { visitor.visit_expr(subexpression); } - ExprKind::Let(ref pat, ref expr, _) => { - visitor.visit_expr(expr); - visitor.visit_pat(pat); - } + ExprKind::Let(ref let_expr) => visitor.visit_let_expr(let_expr), ExprKind::If(ref cond, ref then, ref else_opt) => { visitor.visit_expr(cond); visitor.visit_expr(then); diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 05659e976d..add8bd1393 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -285,7 +285,6 @@ language_item_table! { Panic, sym::panic, panic_fn, Target::Fn, GenericRequirement::Exact(0); PanicFmt, sym::panic_fmt, panic_fmt, Target::Fn, GenericRequirement::None; PanicDisplay, sym::panic_display, panic_display, Target::Fn, GenericRequirement::None; - PanicStr, sym::panic_str, panic_str, Target::Fn, GenericRequirement::None; ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, Target::Fn, GenericRequirement::None; PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn, GenericRequirement::Exact(0); PanicInfo, sym::panic_info, panic_info, Target::Struct, GenericRequirement::None; @@ -348,6 +347,7 @@ language_item_table! { ControlFlowContinue, sym::Continue, cf_continue_variant, Target::Variant, GenericRequirement::None; ControlFlowBreak, sym::Break, cf_break_variant, Target::Variant, GenericRequirement::None; + IntoFutureIntoFuture, sym::into_future, into_future_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None; IntoIterIntoIter, sym::into_iter, into_iter_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None; IteratorNext, sym::next, next_fn, Target::Method(MethodKind::Trait { body: false}), GenericRequirement::None; diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 93224d388c..1df9b5f9c7 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -4,7 +4,6 @@ #![feature(const_btree_new)] #![feature(crate_visibility_modifier)] -#![feature(in_band_lifetimes)] #![feature(once_cell)] #![feature(min_specialization)] #![feature(never_type)] diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index 6e7b765a0c..a43c1f9d9a 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -2,7 +2,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHas use crate::hir::{ AttributeMap, BodyId, Crate, Expr, ForeignItem, ForeignItemId, ImplItem, ImplItemId, Item, - ItemId, Mod, OwnerNodes, TraitCandidate, TraitItem, TraitItemId, Ty, VisibilityKind, + ItemId, OwnerNodes, TraitCandidate, TraitItem, TraitItemId, Ty, VisibilityKind, }; use crate::hir_id::{HirId, ItemLocalId}; use rustc_span::def_id::DefPathHash; @@ -16,7 +16,6 @@ pub trait HashStableContext: fn hash_hir_id(&mut self, _: HirId, hasher: &mut StableHasher); fn hash_body_id(&mut self, _: BodyId, hasher: &mut StableHasher); fn hash_reference_to_item(&mut self, _: HirId, hasher: &mut StableHasher); - fn hash_hir_mod(&mut self, _: &Mod<'_>, hasher: &mut StableHasher); fn hash_hir_expr(&mut self, _: &Expr<'_>, hasher: &mut StableHasher); fn hash_hir_ty(&mut self, _: &Ty<'_>, hasher: &mut StableHasher); fn hash_hir_visibility_kind(&mut self, _: &VisibilityKind<'_>, hasher: &mut StableHasher); @@ -132,12 +131,6 @@ impl HashStable for TraitItemId { } } -impl HashStable for Mod<'_> { - fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { - hcx.hash_hir_mod(self, hasher) - } -} - impl HashStable for Expr<'_> { fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { hcx.hash_hir_expr(self, hasher) @@ -211,7 +204,7 @@ impl HashStable for Item<'_> { } } -impl HashStable for OwnerNodes<'tcx> { +impl<'tcx, HirCtx: crate::HashStableContext> HashStable for OwnerNodes<'tcx> { fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { // We ignore the `nodes` and `bodies` fields since these refer to information included in // `hash` which is hashed in the collector and used for the crate hash. @@ -221,7 +214,7 @@ impl HashStable for OwnerNodes<'tcx> { } } -impl HashStable for AttributeMap<'tcx> { +impl<'tcx, HirCtx: crate::HashStableContext> HashStable for AttributeMap<'tcx> { fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { // We ignore the `map` since it refers to information included in `hash` which is hashed in // the collector and used for the crate hash. diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 9c2927111a..4c9e2d7fe4 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -10,7 +10,7 @@ use rustc_hir::{GenericArg, GenericParam, GenericParamKind, Node}; use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier}; use rustc_span::source_map::{SourceMap, Spanned}; use rustc_span::symbol::{kw, Ident, IdentPrinter, Symbol}; -use rustc_span::{self, BytePos, FileName}; +use rustc_span::{self, FileName}; use rustc_target::spec::abi::Abi; use std::borrow::Cow; @@ -89,7 +89,7 @@ impl<'a> State<'a> { Node::TraitRef(a) => self.print_trait_ref(&a), Node::Binding(a) | Node::Pat(a) => self.print_pat(&a), Node::Arm(a) => self.print_arm(&a), - Node::Infer(_) => self.s.word("_"), + Node::Infer(_) => self.word("_"), Node::Block(a) => { // Containing cbox, will be closed by print-block at `}`. self.cbox(INDENT_UNIT); @@ -130,7 +130,7 @@ impl<'a> PrintState<'a> for State<'a> { } fn print_ident(&mut self, ident: Ident) { - self.s.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string()); + self.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string()); self.ann.post(self, AnnNode::Name(&ident.name)) } @@ -194,7 +194,7 @@ where pub fn visibility_qualified>>(vis: &hir::Visibility<'_>, w: S) -> String { to_string(NO_ANN, |s| { s.print_visibility(vis); - s.s.word(w) + s.word(w) }) } @@ -241,40 +241,10 @@ pub fn enum_def_to_string( } impl<'a> State<'a> { - pub fn cbox(&mut self, u: usize) { - self.s.cbox(u); - } - - pub fn nbsp(&mut self) { - self.s.word(" ") - } - - pub fn word_nbsp>>(&mut self, w: S) { - self.s.word(w); - self.nbsp() - } - - pub fn head>>(&mut self, w: S) { - let w = w.into(); - // outer-box is consistent - self.cbox(INDENT_UNIT); - // head-box is inconsistent - self.ibox(w.len() + 1); - // keyword that starts the head - if !w.is_empty() { - self.word_nbsp(w); - } - } - - pub fn bopen(&mut self) { - self.s.word("{"); - self.end(); // close the head-box - } - pub fn bclose_maybe_open(&mut self, span: rustc_span::Span, close_box: bool) { self.maybe_print_comment(span.hi()); self.break_offset_if_not_bol(1, -(INDENT_UNIT as isize)); - self.s.word("}"); + self.word("}"); if close_box { self.end(); // close the outer-box } @@ -284,33 +254,6 @@ impl<'a> State<'a> { self.bclose_maybe_open(span, true) } - pub fn space_if_not_bol(&mut self) { - if !self.s.is_beginning_of_line() { - self.s.space(); - } - } - - pub fn break_offset_if_not_bol(&mut self, n: usize, off: isize) { - if !self.s.is_beginning_of_line() { - self.s.break_offset(n, off) - } else if off != 0 && self.s.last_token().is_hardbreak_tok() { - // We do something pretty sketchy here: tuck the nonzero - // offset-adjustment we were going to deposit along with the - // break into the previous hardbreak. - self.s.replace_last_token(pp::Printer::hardbreak_tok_offset(off)); - } - } - - // Synthesizes a comment that was not textually present in the original source - // file. - pub fn synth_comment(&mut self, text: String) { - self.s.word("/*"); - self.s.space(); - self.s.word(text); - self.s.space(); - self.s.word("*/") - } - pub fn commasep_cmnt(&mut self, b: Breaks, elts: &[T], mut op: F, mut get_span: G) where F: FnMut(&mut State<'_>, &T), @@ -324,7 +267,7 @@ impl<'a> State<'a> { op(self, elt); i += 1; if i < len { - self.s.word(","); + self.word(","); self.maybe_print_trailing_comment(get_span(elt), Some(get_span(&elts[i]).hi())); self.space_if_not_bol(); } @@ -355,27 +298,27 @@ impl<'a> State<'a> { self.ibox(0); match ty.kind { hir::TyKind::Slice(ref ty) => { - self.s.word("["); + self.word("["); self.print_type(&ty); - self.s.word("]"); + self.word("]"); } hir::TyKind::Ptr(ref mt) => { - self.s.word("*"); + self.word("*"); self.print_mt(mt, true); } hir::TyKind::Rptr(ref lifetime, ref mt) => { - self.s.word("&"); + self.word("&"); self.print_opt_lifetime(lifetime); self.print_mt(mt, false); } hir::TyKind::Never => { - self.s.word("!"); + self.word("!"); } hir::TyKind::Tup(ref elts) => { self.popen(); - self.commasep(Inconsistent, &elts[..], |s, ty| s.print_type(&ty)); + self.commasep(Inconsistent, &elts, |s, ty| s.print_type(&ty)); if elts.len() == 1 { - self.s.word(","); + self.word(","); } self.pclose(); } @@ -389,7 +332,7 @@ impl<'a> State<'a> { f.param_names, ); } - hir::TyKind::OpaqueDef(..) => self.s.word("/*impl Trait*/"), + hir::TyKind::OpaqueDef(..) => self.word("/*impl Trait*/"), hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false), hir::TyKind::TraitObject(bounds, ref lifetime, syntax) => { if syntax == ast::TraitObjectSyntax::Dyn { @@ -412,24 +355,24 @@ impl<'a> State<'a> { } } hir::TyKind::Array(ref ty, ref length) => { - self.s.word("["); + self.word("["); self.print_type(&ty); - self.s.word("; "); - self.print_anon_const(length); - self.s.word("]"); + self.word("; "); + self.print_array_length(length); + self.word("]"); } hir::TyKind::Typeof(ref e) => { - self.s.word("typeof("); + self.word("typeof("); self.print_anon_const(e); - self.s.word(")"); + self.word(")"); } hir::TyKind::Err => { self.popen(); - self.s.word("/*ERROR*/"); + self.word("/*ERROR*/"); self.pclose(); } hir::TyKind::Infer => { - self.s.word("_"); + self.word("_"); } } self.end() @@ -457,7 +400,7 @@ impl<'a> State<'a> { None, ); self.end(); // end head-ibox - self.s.word(";"); + self.word(";"); self.end() // end the outer fn box } hir::ForeignItemKind::Static(ref t, m) => { @@ -468,14 +411,14 @@ impl<'a> State<'a> { self.print_ident(item.ident); self.word_space(":"); self.print_type(&t); - self.s.word(";"); + self.word(";"); self.end(); // end the head-ibox self.end() // end the outer cbox } hir::ForeignItemKind::Type => { self.head(visibility_qualified(&item.vis, "type")); self.print_ident(item.ident); - self.s.word(";"); + self.word(";"); self.end(); // end the head-ibox self.end() // end the outer cbox } @@ -489,17 +432,17 @@ impl<'a> State<'a> { default: Option, vis: &hir::Visibility<'_>, ) { - self.s.word(visibility_qualified(vis, "")); + self.word(visibility_qualified(vis, "")); self.word_space("const"); self.print_ident(ident); self.word_space(":"); self.print_type(ty); if let Some(expr) = default { - self.s.space(); + self.space(); self.word_space("="); self.ann.nested(self, Nested::Body(expr)); } - self.s.word(";") + self.word(";") } fn print_associated_type( @@ -517,11 +460,11 @@ impl<'a> State<'a> { } self.print_where_clause(&generics.where_clause); if let Some(ty) = ty { - self.s.space(); + self.space(); self.word_space("="); self.print_type(ty); } - self.s.word(";") + self.word(";") } fn print_item_type( @@ -536,9 +479,9 @@ impl<'a> State<'a> { self.end(); // end the inner ibox self.print_where_clause(&generics.where_clause); - self.s.space(); + self.space(); inner(self); - self.s.word(";"); + self.word(";"); self.end(); // end the outer ibox } @@ -554,12 +497,12 @@ impl<'a> State<'a> { self.head(visibility_qualified(&item.vis, "extern crate")); if let Some(orig_name) = orig_name { self.print_name(orig_name); - self.s.space(); - self.s.word("as"); - self.s.space(); + self.space(); + self.word("as"); + self.space(); } self.print_ident(item.ident); - self.s.word(";"); + self.word(";"); self.end(); // end inner head-block self.end(); // end outer head-block } @@ -570,14 +513,14 @@ impl<'a> State<'a> { match kind { hir::UseKind::Single => { if path.segments.last().unwrap().ident != item.ident { - self.s.space(); + self.space(); self.word_space("as"); self.print_ident(item.ident); } - self.s.word(";"); + self.word(";"); } - hir::UseKind::Glob => self.s.word("::*;"), - hir::UseKind::ListStem => self.s.word("::{};"), + hir::UseKind::Glob => self.word("::*;"), + hir::UseKind::ListStem => self.word("::{};"), } self.end(); // end inner head-block self.end(); // end outer head-block @@ -590,12 +533,12 @@ impl<'a> State<'a> { self.print_ident(item.ident); self.word_space(":"); self.print_type(&ty); - self.s.space(); + self.space(); self.end(); // end the head-ibox self.word_space("="); self.ann.nested(self, Nested::Body(expr)); - self.s.word(";"); + self.word(";"); self.end(); // end the outer cbox } hir::ItemKind::Const(ref ty, expr) => { @@ -603,12 +546,12 @@ impl<'a> State<'a> { self.print_ident(item.ident); self.word_space(":"); self.print_type(&ty); - self.s.space(); + self.space(); self.end(); // end the head-ibox self.word_space("="); self.ann.nested(self, Nested::Body(expr)); - self.s.word(";"); + self.word(";"); self.end(); // end the outer cbox } hir::ItemKind::Fn(ref sig, ref param_names, body) => { @@ -622,7 +565,7 @@ impl<'a> State<'a> { &[], Some(body), ); - self.s.word(" "); + self.word(" "); self.end(); // need to close a box self.end(); // need to close a box self.ann.nested(self, Nested::Body(body)); @@ -666,7 +609,7 @@ impl<'a> State<'a> { let mut real_bounds = Vec::with_capacity(opaque_ty.bounds.len()); for b in opaque_ty.bounds.iter() { if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b { - state.s.space(); + state.space(); state.word_space("for ?"); state.print_trait_ref(&ptr.trait_ref); } else { @@ -706,7 +649,7 @@ impl<'a> State<'a> { if !generics.params.is_empty() { self.print_generic_params(&generics.params); - self.s.space(); + self.space(); } if constness == hir::Constness::Const { @@ -714,19 +657,19 @@ impl<'a> State<'a> { } if let hir::ImplPolarity::Negative(_) = polarity { - self.s.word("!"); + self.word("!"); } if let Some(ref t) = of_trait { self.print_trait_ref(t); - self.s.space(); + self.space(); self.word_space("for"); } self.print_type(&self_ty); self.print_where_clause(&generics.where_clause); - self.s.space(); + self.space(); self.bopen(); self.print_inner_attributes(attrs); for impl_item in items { @@ -745,7 +688,7 @@ impl<'a> State<'a> { let mut real_bounds = Vec::with_capacity(bounds.len()); for b in bounds.iter() { if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b { - self.s.space(); + self.space(); self.word_space("for ?"); self.print_trait_ref(&ptr.trait_ref); } else { @@ -754,7 +697,7 @@ impl<'a> State<'a> { } self.print_bounds(":", real_bounds); self.print_where_clause(&generics.where_clause); - self.s.word(" "); + self.word(" "); self.bopen(); for trait_item in trait_items { self.ann.nested(self, Nested::TraitItem(trait_item.id)); @@ -771,7 +714,7 @@ impl<'a> State<'a> { // FIXME(durka) this seems to be some quite outdated syntax for b in bounds.iter() { if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b { - self.s.space(); + self.space(); self.word_space("for ?"); self.print_trait_ref(&ptr.trait_ref); } else { @@ -781,7 +724,7 @@ impl<'a> State<'a> { self.nbsp(); self.print_bounds("=", real_bounds); self.print_where_clause(&generics.where_clause); - self.s.word(";"); + self.word(";"); } } self.ann.post(self, AnnNode::Item(item)) @@ -793,7 +736,7 @@ impl<'a> State<'a> { fn print_formal_generic_params(&mut self, generic_params: &[hir::GenericParam<'_>]) { if !generic_params.is_empty() { - self.s.word("for"); + self.word("for"); self.print_generic_params(generic_params); self.nbsp(); } @@ -816,7 +759,7 @@ impl<'a> State<'a> { self.print_name(name); self.print_generic_params(&generics.params); self.print_where_clause(&generics.where_clause); - self.s.space(); + self.space(); self.print_variants(&enum_definition.variants, span) } @@ -828,7 +771,7 @@ impl<'a> State<'a> { self.print_outer_attributes(self.attrs(v.id)); self.ibox(INDENT_UNIT); self.print_variant(v); - self.s.word(","); + self.word(","); self.end(); self.maybe_print_trailing_comment(v.span, None); } @@ -841,10 +784,10 @@ impl<'a> State<'a> { hir::VisibilityKind::Crate(ast::CrateSugar::JustCrate) => self.word_nbsp("crate"), hir::VisibilityKind::Crate(ast::CrateSugar::PubCrate) => self.word_nbsp("pub(crate)"), hir::VisibilityKind::Restricted { ref path, .. } => { - self.s.word("pub("); + self.word("pub("); if path.segments.len() == 1 && path.segments[0].ident.name == kw::Super { // Special case: `super` can print like `pub(super)`. - self.s.word("super"); + self.word("super"); } else { // Everything else requires `in` at present. self.word_nbsp("in"); @@ -887,7 +830,7 @@ impl<'a> State<'a> { } self.print_where_clause(&generics.where_clause); if print_finalizer { - self.s.word(";"); + self.word(";"); } self.end(); self.end() // close the outer-box @@ -906,7 +849,7 @@ impl<'a> State<'a> { self.print_ident(field.ident); self.word_nbsp(":"); self.print_type(&field.ty); - self.s.word(","); + self.word(","); } self.bclose(span) @@ -919,7 +862,7 @@ impl<'a> State<'a> { let generics = hir::Generics::empty(); self.print_struct(&v.data, &generics, v.ident.name, v.span, false); if let Some(ref d) = v.disr_expr { - self.s.space(); + self.space(); self.word_space("="); self.print_anon_const(d); } @@ -951,7 +894,7 @@ impl<'a> State<'a> { let vis = Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited }; self.print_method_sig(ti.ident, sig, &ti.generics, &vis, arg_names, None); - self.s.word(";"); + self.word(";"); } hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { let vis = @@ -1032,11 +975,11 @@ impl<'a> State<'a> { hir::StmtKind::Semi(ref expr) => { self.space_if_not_bol(); self.print_expr(&expr); - self.s.word(";"); + self.word(";"); } } if stmt_ends_with_semi(&st.kind) { - self.s.word(";"); + self.word(";"); } self.maybe_print_trailing_comment(st.span, None) } @@ -1088,9 +1031,9 @@ impl<'a> State<'a> { hir::ExprKind::If(ref i, ref then, ref e) => { self.cbox(INDENT_UNIT - 1); self.ibox(0); - self.s.word(" else if "); + self.word(" else if "); self.print_expr_as_cond(&i); - self.s.space(); + self.space(); self.print_expr(&then); self.print_else(e.as_ref().map(|e| &**e)) } @@ -1098,7 +1041,7 @@ impl<'a> State<'a> { hir::ExprKind::Block(ref b, _) => { self.cbox(INDENT_UNIT - 1); self.ibox(0); - self.s.word(" else "); + self.word(" else "); self.print_block(&b) } // Constraints would be great here! @@ -1117,11 +1060,18 @@ impl<'a> State<'a> { ) { self.head("if"); self.print_expr_as_cond(test); - self.s.space(); + self.space(); self.print_expr(blk); self.print_else(elseopt) } + pub fn print_array_length(&mut self, len: &hir::ArrayLen) { + match len { + hir::ArrayLen::Infer(_, _) => self.word("_"), + hir::ArrayLen::Body(ct) => self.print_anon_const(ct), + } + } + pub fn print_anon_const(&mut self, constant: &hir::AnonConst) { self.ann.nested(self, Nested::Body(constant.body)) } @@ -1158,13 +1108,17 @@ impl<'a> State<'a> { } /// Print a `let pat = expr` expression. - fn print_let(&mut self, pat: &hir::Pat<'_>, expr: &hir::Expr<'_>) { - self.s.word("let "); + fn print_let(&mut self, pat: &hir::Pat<'_>, ty: Option<&hir::Ty<'_>>, init: &hir::Expr<'_>) { + self.word_space("let"); self.print_pat(pat); - self.s.space(); + if let Some(ty) = ty { + self.word_space(":"); + self.print_type(ty); + } + self.space(); self.word_space("="); - let npals = || parser::needs_par_as_let_scrutinee(expr.precedence().order()); - self.print_expr_cond_paren(expr, Self::cond_needs_par(expr) || npals()) + let npals = || parser::needs_par_as_let_scrutinee(init.precedence().order()); + self.print_expr_cond_paren(init, Self::cond_needs_par(init) || npals()) } // Does `expr` need parentheses when printed in a condition position? @@ -1180,26 +1134,26 @@ impl<'a> State<'a> { fn print_expr_vec(&mut self, exprs: &[hir::Expr<'_>]) { self.ibox(INDENT_UNIT); - self.s.word("["); + self.word("["); self.commasep_exprs(Inconsistent, exprs); - self.s.word("]"); + self.word("]"); self.end() } fn print_expr_anon_const(&mut self, anon_const: &hir::AnonConst) { self.ibox(INDENT_UNIT); - self.s.word_space("const"); + self.word_space("const"); self.print_anon_const(anon_const); self.end() } - fn print_expr_repeat(&mut self, element: &hir::Expr<'_>, count: &hir::AnonConst) { + fn print_expr_repeat(&mut self, element: &hir::Expr<'_>, count: &hir::ArrayLen) { self.ibox(INDENT_UNIT); - self.s.word("["); + self.word("["); self.print_expr(element); self.word_space(";"); - self.print_anon_const(count); - self.s.word("]"); + self.print_array_length(count); + self.word("]"); self.end() } @@ -1210,7 +1164,7 @@ impl<'a> State<'a> { wth: &Option<&hir::Expr<'_>>, ) { self.print_qpath(qpath, true); - self.s.word("{"); + self.word("{"); self.commasep_cmnt( Consistent, fields, @@ -1229,27 +1183,27 @@ impl<'a> State<'a> { Some(ref expr) => { self.ibox(INDENT_UNIT); if !fields.is_empty() { - self.s.word(","); - self.s.space(); + self.word(","); + self.space(); } - self.s.word(".."); + self.word(".."); self.print_expr(&expr); self.end(); } _ => { if !fields.is_empty() { - self.s.word(",") + self.word(",") } } } - self.s.word("}"); + self.word("}"); } fn print_expr_tup(&mut self, exprs: &[hir::Expr<'_>]) { self.popen(); self.commasep_exprs(Inconsistent, exprs); if exprs.len() == 1 { - self.s.word(","); + self.word(","); } self.pclose() } @@ -1267,7 +1221,7 @@ impl<'a> State<'a> { fn print_expr_method_call(&mut self, segment: &hir::PathSegment<'_>, args: &[hir::Expr<'_>]) { let base_args = &args[1..]; self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX); - self.s.word("."); + self.word("."); self.print_ident(segment.ident); let generic_args = segment.args(); @@ -1303,13 +1257,13 @@ impl<'a> State<'a> { }; self.print_expr_maybe_paren(lhs, left_prec); - self.s.space(); + self.space(); self.word_space(op.node.as_str()); self.print_expr_maybe_paren(rhs, right_prec) } fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr<'_>) { - self.s.word(op.as_str()); + self.word(op.as_str()); self.print_expr_maybe_paren(expr, parser::PREC_PREFIX) } @@ -1319,7 +1273,7 @@ impl<'a> State<'a> { mutability: hir::Mutability, expr: &hir::Expr<'_>, ) { - self.s.word("&"); + self.word("&"); match kind { hir::BorrowKind::Ref => self.print_mutability(mutability, false), hir::BorrowKind::Raw => { @@ -1433,6 +1387,9 @@ impl<'a> State<'a> { if opts.contains(ast::InlineAsmOptions::RAW) { options.push("raw"); } + if opts.contains(ast::InlineAsmOptions::MAY_UNWIND) { + options.push("may_unwind"); + } s.commasep(Inconsistent, &options, |s, &opt| { s.word(opt); }); @@ -1488,7 +1445,7 @@ impl<'a> State<'a> { hir::ExprKind::Cast(ref expr, ref ty) => { let prec = AssocOp::As.precedence() as i8; self.print_expr_maybe_paren(&expr, prec); - self.s.space(); + self.space(); self.word_space("as"); self.print_type(&ty); } @@ -1507,7 +1464,7 @@ impl<'a> State<'a> { // Print `let _t = $init;`: let temp = Ident::from_str("_t"); self.print_local(Some(init), |this| this.print_ident(temp)); - self.s.word(";"); + self.word(";"); // Print `_t`: self.space_if_not_bol(); @@ -1516,8 +1473,8 @@ impl<'a> State<'a> { // Print `}`: self.bclose_maybe_open(expr.span, true); } - hir::ExprKind::Let(ref pat, ref scrutinee, _) => { - self.print_let(pat, scrutinee); + hir::ExprKind::Let(hir::Let { pat, ty, init, .. }) => { + self.print_let(pat, *ty, init); } hir::ExprKind::If(ref test, ref blk, ref elseopt) => { self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e)); @@ -1535,7 +1492,7 @@ impl<'a> State<'a> { self.ibox(INDENT_UNIT); self.word_nbsp("match"); self.print_expr_as_cond(&expr); - self.s.space(); + self.space(); self.bopen(); for arm in arms { self.print_arm(arm); @@ -1546,7 +1503,7 @@ impl<'a> State<'a> { self.print_capture_clause(capture_clause); self.print_closure_params(&decl, body); - self.s.space(); + self.space(); // This is a bare expression. self.ann.nested(self, Nested::Body(body)); @@ -1571,54 +1528,52 @@ impl<'a> State<'a> { hir::ExprKind::Assign(ref lhs, ref rhs, _) => { let prec = AssocOp::Assign.precedence() as i8; self.print_expr_maybe_paren(&lhs, prec + 1); - self.s.space(); + self.space(); self.word_space("="); self.print_expr_maybe_paren(&rhs, prec); } hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => { let prec = AssocOp::Assign.precedence() as i8; self.print_expr_maybe_paren(&lhs, prec + 1); - self.s.space(); - self.s.word(op.node.as_str()); + self.space(); + self.word(op.node.as_str()); self.word_space("="); self.print_expr_maybe_paren(&rhs, prec); } hir::ExprKind::Field(ref expr, ident) => { self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX); - self.s.word("."); + self.word("."); self.print_ident(ident); } hir::ExprKind::Index(ref expr, ref index) => { self.print_expr_maybe_paren(&expr, parser::PREC_POSTFIX); - self.s.word("["); + self.word("["); self.print_expr(&index); - self.s.word("]"); + self.word("]"); } hir::ExprKind::Path(ref qpath) => self.print_qpath(qpath, true), hir::ExprKind::Break(destination, ref opt_expr) => { - self.s.word("break"); - self.s.space(); + self.word("break"); if let Some(label) = destination.label { + self.space(); self.print_ident(label.ident); - self.s.space(); } if let Some(ref expr) = *opt_expr { + self.space(); self.print_expr_maybe_paren(expr, parser::PREC_JUMP); - self.s.space(); } } hir::ExprKind::Continue(destination) => { - self.s.word("continue"); - self.s.space(); + self.word("continue"); if let Some(label) = destination.label { + self.space(); self.print_ident(label.ident); - self.s.space() } } hir::ExprKind::Ret(ref result) => { - self.s.word("return"); + self.word("return"); if let Some(ref expr) = *result { - self.s.word(" "); + self.word(" "); self.print_expr_maybe_paren(&expr, parser::PREC_JUMP); } } @@ -1628,7 +1583,7 @@ impl<'a> State<'a> { } hir::ExprKind::LlvmInlineAsm(ref a) => { let i = &a.inner; - self.s.word("llvm_asm!"); + self.word("llvm_asm!"); self.popen(); self.print_symbol(i.asm, i.asm_str_style); self.word_space(":"); @@ -1648,7 +1603,7 @@ impl<'a> State<'a> { s.pclose(); out_idx += 1; }); - self.s.space(); + self.space(); self.word_space(":"); let mut in_idx = 0; @@ -1659,7 +1614,7 @@ impl<'a> State<'a> { s.pclose(); in_idx += 1; }); - self.s.space(); + self.space(); self.word_space(":"); self.commasep(Inconsistent, &i.clobbers, |s, &co| { @@ -1678,7 +1633,7 @@ impl<'a> State<'a> { } if !options.is_empty() { - self.s.space(); + self.space(); self.word_space(":"); self.commasep(Inconsistent, &options, |s, &co| { s.print_string(co, ast::StrStyle::Cooked); @@ -1693,7 +1648,7 @@ impl<'a> State<'a> { } hir::ExprKind::Err => { self.popen(); - self.s.word("/*ERROR*/"); + self.word("/*ERROR*/"); self.pclose(); } } @@ -1718,7 +1673,7 @@ impl<'a> State<'a> { for (i, segment) in path.segments.iter().enumerate() { if i > 0 { - self.s.word("::") + self.word("::") } if segment.ident.name != kw::PathRoot { self.print_ident(segment.ident); @@ -1738,14 +1693,14 @@ impl<'a> State<'a> { match *qpath { hir::QPath::Resolved(None, ref path) => self.print_path(path, colons_before_params), hir::QPath::Resolved(Some(ref qself), ref path) => { - self.s.word("<"); + self.word("<"); self.print_type(qself); - self.s.space(); + self.space(); self.word_space("as"); for (i, segment) in path.segments[..path.segments.len() - 1].iter().enumerate() { if i > 0 { - self.s.word("::") + self.word("::") } if segment.ident.name != kw::PathRoot { self.print_ident(segment.ident); @@ -1757,8 +1712,8 @@ impl<'a> State<'a> { } } - self.s.word(">"); - self.s.word("::"); + self.word(">"); + self.word("::"); let item_segment = path.segments.last().unwrap(); self.print_ident(item_segment.ident); self.print_generic_args( @@ -1774,12 +1729,12 @@ impl<'a> State<'a> { if let hir::TyKind::Path(hir::QPath::Resolved(None, _)) = &qself.kind { self.print_type(qself); } else { - self.s.word("<"); + self.word("<"); self.print_type(qself); - self.s.word(">"); + self.word(">"); } - self.s.word("::"); + self.word("::"); self.print_ident(item_segment.ident); self.print_generic_args( item_segment.args(), @@ -1787,10 +1742,10 @@ impl<'a> State<'a> { colons_before_params, ) } - hir::QPath::LangItem(lang_item, span) => { - self.s.word("#[lang = \""); + hir::QPath::LangItem(lang_item, span, _) => { + self.word("#[lang = \""); self.print_ident(Ident::new(lang_item.name(), span)); - self.s.word("\"]"); + self.word("\"]"); } } } @@ -1802,9 +1757,9 @@ impl<'a> State<'a> { colons_before_params: bool, ) { if generic_args.parenthesized { - self.s.word("("); + self.word("("); self.commasep(Inconsistent, generic_args.inputs(), |s, ty| s.print_type(&ty)); - self.s.word(")"); + self.word(")"); self.space_if_not_bol(); self.word_space("->"); @@ -1815,7 +1770,7 @@ impl<'a> State<'a> { let start_or_comma = |this: &mut Self| { if empty.get() { empty.set(false); - this.s.word(start) + this.word(start) } else { this.word_space(",") } @@ -1849,14 +1804,14 @@ impl<'a> State<'a> { // "non-exhaustive patterns: `Some::<..>(_)` not covered"). if infer_args && false { start_or_comma(self); - self.s.word(".."); + self.word(".."); } for binding in generic_args.bindings.iter() { start_or_comma(self); self.print_ident(binding.ident); self.print_generic_args(binding.gen_args, false, false); - self.s.space(); + self.space(); match generic_args.bindings[0].kind { hir::TypeBindingKind::Equality { ref ty } => { self.word_space("="); @@ -1869,7 +1824,7 @@ impl<'a> State<'a> { } if !empty.get() { - self.s.word(">") + self.word(">") } } } @@ -1880,7 +1835,7 @@ impl<'a> State<'a> { // Pat isn't normalized, but the beauty of it // is that it doesn't matter match pat.kind { - PatKind::Wild => self.s.word("_"), + PatKind::Wild => self.word("_"), PatKind::Binding(binding_mode, _, ident, ref sub) => { match binding_mode { hir::BindingAnnotation::Ref => { @@ -1898,7 +1853,7 @@ impl<'a> State<'a> { } self.print_ident(ident); if let Some(ref p) = *sub { - self.s.word("@"); + self.word("@"); self.print_pat(&p); } } @@ -1910,13 +1865,13 @@ impl<'a> State<'a> { if ddpos != 0 { self.word_space(","); } - self.s.word(".."); + self.word(".."); if ddpos != elts.len() { - self.s.word(","); + self.word(","); self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p)); } } else { - self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p)); + self.commasep(Inconsistent, &elts, |s, p| s.print_pat(&p)); } self.pclose(); } @@ -1926,10 +1881,14 @@ impl<'a> State<'a> { PatKind::Struct(ref qpath, ref fields, etc) => { self.print_qpath(qpath, true); self.nbsp(); - self.word_space("{"); + self.word("{"); + let empty = fields.is_empty() && !etc; + if !empty { + self.space(); + } self.commasep_cmnt( Consistent, - &fields[..], + &fields, |s, f| { s.cbox(INDENT_UNIT); if !f.is_shorthand { @@ -1945,13 +1904,15 @@ impl<'a> State<'a> { if !fields.is_empty() { self.word_space(","); } - self.s.word(".."); + self.word(".."); } - self.s.space(); - self.s.word("}"); + if !empty { + self.space(); + } + self.word("}"); } PatKind::Or(ref pats) => { - self.strsep("|", true, Inconsistent, &pats[..], |s, p| s.print_pat(&p)); + self.strsep("|", true, Inconsistent, &pats, |s, p| s.print_pat(&p)); } PatKind::Tuple(ref elts, ddpos) => { self.popen(); @@ -1960,22 +1921,22 @@ impl<'a> State<'a> { if ddpos != 0 { self.word_space(","); } - self.s.word(".."); + self.word(".."); if ddpos != elts.len() { - self.s.word(","); + self.word(","); self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p)); } } else { self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p)); if elts.len() == 1 { - self.s.word(","); + self.word(","); } } self.pclose(); } PatKind::Box(ref inner) => { let is_range_inner = matches!(inner.kind, PatKind::Range(..)); - self.s.word("box "); + self.word("box "); if is_range_inner { self.popen(); } @@ -1986,8 +1947,8 @@ impl<'a> State<'a> { } PatKind::Ref(ref inner, mutbl) => { let is_range_inner = matches!(inner.kind, PatKind::Range(..)); - self.s.word("&"); - self.s.word(mutbl.prefix_str()); + self.word("&"); + self.word(mutbl.prefix_str()); if is_range_inner { self.popen(); } @@ -2000,19 +1961,18 @@ impl<'a> State<'a> { PatKind::Range(ref begin, ref end, ref end_kind) => { if let Some(expr) = begin { self.print_expr(expr); - self.s.space(); } match *end_kind { - RangeEnd::Included => self.s.word("..."), - RangeEnd::Excluded => self.s.word(".."), + RangeEnd::Included => self.word("..."), + RangeEnd::Excluded => self.word(".."), } if let Some(expr) = end { self.print_expr(expr); } } PatKind::Slice(ref before, ref slice, ref after) => { - self.s.word("["); - self.commasep(Inconsistent, &before[..], |s, p| s.print_pat(&p)); + self.word("["); + self.commasep(Inconsistent, &before, |s, p| s.print_pat(&p)); if let Some(ref p) = *slice { if !before.is_empty() { self.word_space(","); @@ -2022,13 +1982,13 @@ impl<'a> State<'a> { } else { self.print_pat(&p); } - self.s.word(".."); + self.word(".."); if !after.is_empty() { self.word_space(","); } } - self.commasep(Inconsistent, &after[..], |s, p| s.print_pat(&p)); - self.s.word("]"); + self.commasep(Inconsistent, &after, |s, p| s.print_pat(&p)); + self.word("]"); } } self.ann.post(self, AnnNode::Pat(pat)) @@ -2043,29 +2003,29 @@ impl<'a> State<'a> { // I have no idea why this check is necessary, but here it // is :( if self.attrs(arm.hir_id).is_empty() { - self.s.space(); + self.space(); } self.cbox(INDENT_UNIT); self.ann.pre(self, AnnNode::Arm(arm)); self.ibox(0); self.print_outer_attributes(&self.attrs(arm.hir_id)); self.print_pat(&arm.pat); - self.s.space(); + self.space(); if let Some(ref g) = arm.guard { match g { hir::Guard::If(e) => { self.word_space("if"); self.print_expr(&e); - self.s.space(); + self.space(); } hir::Guard::IfLet(pat, e) => { self.word_nbsp("if"); self.word_nbsp("let"); self.print_pat(&pat); - self.s.space(); + self.space(); self.word_space("="); self.print_expr(&e); - self.s.space(); + self.space(); } } } @@ -2083,13 +2043,13 @@ impl<'a> State<'a> { // If it is a user-provided unsafe block, print a comma after it if let hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::UserProvided) = blk.rules { - self.s.word(","); + self.word(","); } } _ => { self.end(); // close the ibox for the pattern self.print_expr(&arm.body); - self.s.word(","); + self.word(","); } } self.ann.post(self, AnnNode::Arm(arm)); @@ -2121,20 +2081,20 @@ impl<'a> State<'a> { self.commasep(Inconsistent, &decl.inputs, |s, ty| { s.ibox(INDENT_UNIT); if let Some(arg_name) = arg_names.get(i) { - s.s.word(arg_name.to_string()); - s.s.word(":"); - s.s.space(); + s.word(arg_name.to_string()); + s.word(":"); + s.space(); } else if let Some(body_id) = body_id { s.ann.nested(s, Nested::BodyParamPat(body_id, i)); - s.s.word(":"); - s.s.space(); + s.word(":"); + s.space(); } i += 1; s.print_type(ty); s.end() }); if decl.c_variadic { - self.s.word(", ..."); + self.word(", ..."); } self.pclose(); @@ -2143,7 +2103,7 @@ impl<'a> State<'a> { } fn print_closure_params(&mut self, decl: &hir::FnDecl<'_>, body_id: hir::BodyId) { - self.s.word("|"); + self.word("|"); let mut i = 0; self.commasep(Inconsistent, &decl.inputs, |s, ty| { s.ibox(INDENT_UNIT); @@ -2154,13 +2114,13 @@ impl<'a> State<'a> { if let hir::TyKind::Infer = ty.kind { // Print nothing. } else { - s.s.word(":"); - s.s.space(); + s.word(":"); + s.space(); s.print_type(ty); } s.end(); }); - self.s.word("|"); + self.word("|"); if let hir::FnRetTy::DefaultReturn(..) = decl.output { return; @@ -2171,7 +2131,7 @@ impl<'a> State<'a> { match decl.output { hir::FnRetTy::Return(ref ty) => { self.print_type(&ty); - self.maybe_print_comment(ty.span.lo()) + self.maybe_print_comment(ty.span.lo()); } hir::FnRetTy::DefaultReturn(..) => unreachable!(), } @@ -2192,7 +2152,7 @@ impl<'a> State<'a> { let mut first = true; for bound in bounds { if first { - self.s.word(prefix); + self.word(prefix); } if !(first && prefix.is_empty()) { self.nbsp(); @@ -2206,14 +2166,14 @@ impl<'a> State<'a> { match bound { GenericBound::Trait(tref, modifier) => { if modifier == &TraitBoundModifier::Maybe { - self.s.word("?"); + self.word("?"); } self.print_poly_trait_ref(tref); } GenericBound::LangItemTrait(lang_item, span, ..) => { - self.s.word("#[lang = \""); + self.word("#[lang = \""); self.print_ident(Ident::new(lang_item.name(), *span)); - self.s.word("\"]"); + self.word("\"]"); } GenericBound::Outlives(lt) => { self.print_lifetime(lt); @@ -2224,11 +2184,11 @@ impl<'a> State<'a> { pub fn print_generic_params(&mut self, generic_params: &[GenericParam<'_>]) { if !generic_params.is_empty() { - self.s.word("<"); + self.word("<"); self.commasep(Inconsistent, generic_params, |s, param| s.print_generic_param(param)); - self.s.word(">"); + self.word(">"); } } @@ -2245,7 +2205,7 @@ impl<'a> State<'a> { for bound in param.bounds { match bound { GenericBound::Outlives(ref lt) => { - self.s.word(sep); + self.word(sep); self.print_lifetime(lt); sep = "+"; } @@ -2256,7 +2216,7 @@ impl<'a> State<'a> { GenericParamKind::Type { ref default, .. } => { self.print_bounds(":", param.bounds); if let Some(default) = default { - self.s.space(); + self.space(); self.word_space("="); self.print_type(&default) } @@ -2265,7 +2225,7 @@ impl<'a> State<'a> { self.word_space(":"); self.print_type(ty); if let Some(ref default) = default { - self.s.space(); + self.space(); self.word_space("="); self.print_anon_const(&default) } @@ -2282,7 +2242,7 @@ impl<'a> State<'a> { return; } - self.s.space(); + self.space(); self.word_space("where"); for (i, predicate) in where_clause.predicates.iter().enumerate() { @@ -2307,7 +2267,7 @@ impl<'a> State<'a> { .. }) => { self.print_lifetime(lifetime); - self.s.word(":"); + self.word(":"); for (i, bound) in bounds.iter().enumerate() { match bound { @@ -2318,7 +2278,7 @@ impl<'a> State<'a> { } if i != 0 { - self.s.word(":"); + self.word(":"); } } } @@ -2326,7 +2286,7 @@ impl<'a> State<'a> { lhs_ty, rhs_ty, .. }) => { self.print_type(lhs_ty); - self.s.space(); + self.space(); self.word_space("="); self.print_type(rhs_ty); } @@ -2365,7 +2325,7 @@ impl<'a> State<'a> { self.end(); if let hir::FnRetTy::Return(ref output) = decl.output { - self.maybe_print_comment(output.span.lo()) + self.maybe_print_comment(output.span.lo()); } } @@ -2379,10 +2339,7 @@ impl<'a> State<'a> { arg_names: &[Ident], ) { self.ibox(INDENT_UNIT); - if !generic_params.is_empty() { - self.s.word("for"); - self.print_generic_params(generic_params); - } + self.print_formal_generic_params(generic_params); let generics = hir::Generics { params: &[], where_clause: hir::WhereClause { predicates: &[], span: rustc_span::DUMMY_SP }, @@ -2405,31 +2362,8 @@ impl<'a> State<'a> { self.end(); } - pub fn maybe_print_trailing_comment( - &mut self, - span: rustc_span::Span, - next_pos: Option, - ) { - if let Some(cmnts) = self.comments() { - if let Some(cmnt) = cmnts.trailing_comment(span, next_pos) { - self.print_comment(&cmnt); - } - } - } - - pub fn print_remaining_comments(&mut self) { - // If there aren't any remaining comments, then we need to manually - // make sure there is a line break at the end. - if self.next_comment().is_none() { - self.s.hardbreak(); - } - while let Some(ref cmnt) = self.next_comment() { - self.print_comment(cmnt) - } - } - pub fn print_fn_header_info(&mut self, header: hir::FnHeader, vis: &hir::Visibility<'_>) { - self.s.word(visibility_qualified(vis, "")); + self.word(visibility_qualified(vis, "")); match header.constness { hir::Constness::NotConst => {} @@ -2448,7 +2382,7 @@ impl<'a> State<'a> { self.word_nbsp(header.abi.to_string()); } - self.s.word("fn") + self.word("fn") } pub fn print_unsafety(&mut self, s: hir::Unsafety) { diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index 571337a8dc..0d0d09bde5 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -52,6 +52,7 @@ use std::env; use std::fs::{self, File}; use std::io::{BufWriter, Write}; +#[allow(missing_docs)] pub fn assert_dep_graph(tcx: TyCtxt<'_>) { tcx.dep_graph.with_ignore(|| { if tcx.sess.opts.debugging_opts.dump_dep_graph { @@ -102,7 +103,7 @@ struct IfThisChanged<'tcx> { then_this_would_need: Targets, } -impl IfThisChanged<'tcx> { +impl<'tcx> IfThisChanged<'tcx> { fn argument(&self, attr: &ast::Attribute) -> Option { let mut value = None; for list_item in attr.meta_item_list().unwrap_or_default() { @@ -130,7 +131,7 @@ impl IfThisChanged<'tcx> { DepNode::from_def_path_hash(self.tcx, def_path_hash, DepKind::hir_owner) } Some(n) => { - match DepNode::from_label_string(self.tcx, &n.as_str(), def_path_hash) { + match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) { Ok(n) => n, Err(()) => { self.tcx.sess.span_fatal( @@ -146,7 +147,7 @@ impl IfThisChanged<'tcx> { let dep_node_interned = self.argument(attr); let dep_node = match dep_node_interned { Some(n) => { - match DepNode::from_label_string(self.tcx, &n.as_str(), def_path_hash) { + match DepNode::from_label_string(self.tcx, n.as_str(), def_path_hash) { Ok(n) => n, Err(()) => { self.tcx.sess.span_fatal( @@ -171,7 +172,7 @@ impl IfThisChanged<'tcx> { } } -impl Visitor<'tcx> for IfThisChanged<'tcx> { +impl<'tcx> Visitor<'tcx> for IfThisChanged<'tcx> { type Map = Map<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -262,6 +263,7 @@ fn dump_graph(query: &DepGraphQuery) { } } +#[allow(missing_docs)] pub struct GraphvizDepGraph<'q>(FxHashSet<&'q DepNode>, Vec<(&'q DepNode, &'q DepNode)>); impl<'a, 'q> dot::GraphWalk<'a> for GraphvizDepGraph<'q> { diff --git a/compiler/rustc_incremental/src/assert_module_sources.rs b/compiler/rustc_incremental/src/assert_module_sources.rs index a5f3e4553c..4b235213f7 100644 --- a/compiler/rustc_incremental/src/assert_module_sources.rs +++ b/compiler/rustc_incremental/src/assert_module_sources.rs @@ -29,6 +29,7 @@ use rustc_session::cgu_reuse_tracker::*; use rustc_span::symbol::{sym, Symbol}; use std::collections::BTreeSet; +#[allow(missing_docs)] pub fn assert_module_sources(tcx: TyCtxt<'_>) { tcx.dep_graph.with_ignore(|| { if tcx.sess.opts.incremental.is_none() { @@ -55,7 +56,7 @@ struct AssertModuleSource<'tcx> { available_cgus: BTreeSet, } -impl AssertModuleSource<'tcx> { +impl<'tcx> AssertModuleSource<'tcx> { fn check_attr(&self, attr: &ast::Attribute) { let (expected_reuse, comp_kind) = if attr.has_name(sym::rustc_partition_reused) { (CguReuse::PreLto, ComparisonKind::AtLeast) @@ -123,7 +124,7 @@ impl AssertModuleSource<'tcx> { debug!("mapping '{}' to cgu name '{}'", self.field(attr, sym::module), cgu_name); - if !self.available_cgus.contains(&*cgu_name.as_str()) { + if !self.available_cgus.contains(cgu_name.as_str()) { self.tcx.sess.span_err( attr.span, &format!( diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs index dd3f8c937f..df64534ce5 100644 --- a/compiler/rustc_incremental/src/lib.rs +++ b/compiler/rustc_incremental/src/lib.rs @@ -1,7 +1,7 @@ //! Support for serializing the dep-graph and reloading it. +#![deny(missing_docs)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![feature(in_band_lifetimes)] #![feature(let_else)] #![feature(nll)] #![recursion_limit = "256"] diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index b2eaf61b7d..8879567994 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -9,6 +9,13 @@ //! - `#[rustc_clean(cfg="rev2")]` same as above, except that the //! fingerprints must be the SAME (along with all other fingerprints). //! +//! - `#[rustc_clean(cfg="rev2", loaded_from_disk='typeck")]` asserts that +//! the query result for `DepNode::typeck(X)` was actually +//! loaded from disk (not just marked green). This can be useful +//! to ensure that a test is actually exercising the deserialization +//! logic for a particular query result. This can be combined with +//! `except` +//! //! Errors are reported if we are in the suitable configuration but //! the required condition is not met. @@ -28,6 +35,7 @@ use rustc_span::Span; use std::iter::FromIterator; use std::vec::Vec; +const LOADED_FROM_DISK: Symbol = sym::loaded_from_disk; const EXCEPT: Symbol = sym::except; const CFG: Symbol = sym::cfg; @@ -124,6 +132,7 @@ type Labels = FxHashSet; struct Assertion { clean: Labels, dirty: Labels, + loaded_from_disk: Labels, } pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) { @@ -155,7 +164,7 @@ pub struct DirtyCleanVisitor<'tcx> { checked_attrs: FxHashSet, } -impl DirtyCleanVisitor<'tcx> { +impl<'tcx> DirtyCleanVisitor<'tcx> { /// Possibly "deserialize" the attribute into a clean/dirty assertion fn assertion_maybe(&mut self, item_id: LocalDefId, attr: &Attribute) -> Option { if !attr.has_name(sym::rustc_clean) { @@ -174,6 +183,7 @@ impl DirtyCleanVisitor<'tcx> { fn assertion_auto(&mut self, item_id: LocalDefId, attr: &Attribute) -> Assertion { let (name, mut auto) = self.auto_labels(item_id, attr); let except = self.except(attr); + let loaded_from_disk = self.loaded_from_disk(attr); for e in except.iter() { if !auto.remove(e) { let msg = format!( @@ -183,7 +193,19 @@ impl DirtyCleanVisitor<'tcx> { self.tcx.sess.span_fatal(attr.span, &msg); } } - Assertion { clean: auto, dirty: except } + Assertion { clean: auto, dirty: except, loaded_from_disk } + } + + /// `loaded_from_disk=` attribute value + fn loaded_from_disk(&self, attr: &Attribute) -> Labels { + for item in attr.meta_item_list().unwrap_or_else(Vec::new) { + if item.has_name(LOADED_FROM_DISK) { + let value = expect_associated_value(self.tcx, &item); + return self.resolve_labels(&item, value); + } + } + // If `loaded_from_disk=` is not specified, don't assert anything + Labels::default() } /// `except=` attribute value @@ -332,6 +354,18 @@ impl DirtyCleanVisitor<'tcx> { } } + fn assert_loaded_from_disk(&self, item_span: Span, dep_node: DepNode) { + debug!("assert_loaded_from_disk({:?})", dep_node); + + if !self.tcx.dep_graph.debug_was_loaded_from_disk(dep_node) { + let dep_node_str = self.dep_node_str(&dep_node); + self.tcx.sess.span_err( + item_span, + &format!("`{}` should have been loaded from disk but it was not", dep_node_str), + ); + } + } + fn check_item(&mut self, item_id: LocalDefId, item_span: Span) { let def_path_hash = self.tcx.def_path_hash(item_id.to_def_id()); for attr in self.tcx.get_attrs(item_id.to_def_id()).iter() { @@ -348,11 +382,15 @@ impl DirtyCleanVisitor<'tcx> { let dep_node = DepNode::from_label_string(self.tcx, &label, def_path_hash).unwrap(); self.assert_dirty(item_span, dep_node); } + for label in assertion.loaded_from_disk { + let dep_node = DepNode::from_label_string(self.tcx, &label, def_path_hash).unwrap(); + self.assert_loaded_from_disk(item_span, dep_node); + } } } } -impl ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'tcx> { +impl<'tcx> ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { self.check_item(item.def_id, item.span); } @@ -382,7 +420,7 @@ fn check_config(tcx: TyCtxt<'_>, attr: &Attribute) -> bool { let value = expect_associated_value(tcx, &item); debug!("check_config: searching for cfg {:?}", value); cfg = Some(config.contains(&(value, None))); - } else if !item.has_name(EXCEPT) { + } else if !(item.has_name(EXCEPT) || item.has_name(LOADED_FROM_DISK)) { tcx.sess.span_err(attr.span, &format!("unknown item `{}`", item.name_or_empty())); } } @@ -415,7 +453,7 @@ pub struct FindAllAttrs<'tcx> { found_attrs: Vec<&'tcx Attribute>, } -impl FindAllAttrs<'tcx> { +impl<'tcx> FindAllAttrs<'tcx> { fn is_active_attr(&mut self, attr: &Attribute) -> bool { if attr.has_name(sym::rustc_clean) && check_config(self.tcx, attr) { return true; @@ -434,7 +472,7 @@ impl FindAllAttrs<'tcx> { } } -impl intravisit::Visitor<'tcx> for FindAllAttrs<'tcx> { +impl<'tcx> intravisit::Visitor<'tcx> for FindAllAttrs<'tcx> { type Map = Map<'tcx>; fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index c0137fc7a5..a49a1554d5 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -133,21 +133,26 @@ const QUERY_CACHE_FILENAME: &str = "query-cache.bin"; // case-sensitive (as opposed to base64, for example). const INT_ENCODE_BASE: usize = base_n::CASE_INSENSITIVE; +/// Returns the path to a session's dependency graph. pub fn dep_graph_path(sess: &Session) -> PathBuf { in_incr_comp_dir_sess(sess, DEP_GRAPH_FILENAME) } +/// Returns the path to a session's staging dependency graph. +/// +/// On the difference between dep-graph and staging dep-graph, +/// see `build_dep_graph`. pub fn staging_dep_graph_path(sess: &Session) -> PathBuf { in_incr_comp_dir_sess(sess, STAGING_DEP_GRAPH_FILENAME) } - pub fn work_products_path(sess: &Session) -> PathBuf { in_incr_comp_dir_sess(sess, WORK_PRODUCTS_FILENAME) } - +/// Returns the path to a session's query cache. pub fn query_cache_path(sess: &Session) -> PathBuf { in_incr_comp_dir_sess(sess, QUERY_CACHE_FILENAME) } +/// Locks a given session directory. pub fn lock_file_path(session_dir: &Path) -> PathBuf { let crate_dir = session_dir.parent().unwrap(); @@ -166,23 +171,35 @@ pub fn lock_file_path(session_dir: &Path) -> PathBuf { crate_dir.join(&directory_name[0..dash_indices[2]]).with_extension(&LOCK_FILE_EXT[1..]) } +/// Returns the path for a given filename within the incremental compilation directory +/// in the current session. pub fn in_incr_comp_dir_sess(sess: &Session, file_name: &str) -> PathBuf { in_incr_comp_dir(&sess.incr_comp_session_dir(), file_name) } +/// Returns the path for a given filename within the incremental compilation directory, +/// not necessarily from the current session. +/// +/// To ensure the file is part of the current session, use [`in_incr_comp_dir_sess`]. pub fn in_incr_comp_dir(incr_comp_session_dir: &Path, file_name: &str) -> PathBuf { incr_comp_session_dir.join(file_name) } -/// Allocates the private session directory. The boolean in the Ok() result -/// indicates whether we should try loading a dep graph from the successfully -/// initialized directory, or not. -/// The post-condition of this fn is that we have a valid incremental -/// compilation session directory, if the result is `Ok`. A valid session +/// Allocates the private session directory. +/// +/// If the result of this function is `Ok`, we have a valid incremental +/// compilation session directory. A valid session /// directory is one that contains a locked lock file. It may or may not contain /// a dep-graph and work products from a previous session. -/// If the call fails, the fn may leave behind an invalid session directory. +/// +/// This always attempts to load a dep-graph from the directory. +/// If loading fails for some reason, we fallback to a disabled `DepGraph`. +/// See [`rustc_interface::queries::dep_graph`]. +/// +/// If this function returns an error, it may leave behind an invalid session directory. /// The garbage collection will take care of it. +/// +/// [`rustc_interface::queries::dep_graph`]: ../../rustc_interface/struct.Queries.html#structfield.dep_graph pub fn prepare_session_directory( sess: &Session, crate_name: &str, @@ -661,6 +678,7 @@ fn is_old_enough_to_be_collected(timestamp: SystemTime) -> bool { timestamp < SystemTime::now() - Duration::from_secs(10) } +/// Runs garbage collection for the current session. pub fn garbage_collect_session_directories(sess: &Session) -> io::Result<()> { debug!("garbage_collect_session_directories() - begin"); diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index 9c6e2aeb50..d563a6ca47 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -18,13 +18,24 @@ use super::work_product; type WorkProductMap = FxHashMap; #[derive(Debug)] +/// Represents the result of an attempt to load incremental compilation data. pub enum LoadResult { - Ok { data: T }, + /// Loading was successful. + Ok { + #[allow(missing_docs)] + data: T, + }, + /// The file either didn't exist or was produced by an incompatible compiler version. DataOutOfDate, - Error { message: String }, + /// An error occured. + Error { + #[allow(missing_docs)] + message: String, + }, } impl LoadResult { + /// Accesses the data returned in [`LoadResult::Ok`]. pub fn open(self, sess: &Session) -> T { // Check for errors when using `-Zassert-incremental-state` match (sess.opts.assert_incr_state, &self) { @@ -99,6 +110,7 @@ pub enum MaybeAsync { } impl MaybeAsync> { + /// Accesses the data returned in [`LoadResult::Ok`] in an asynchronous way if possible. pub fn open(self) -> LoadResult { match self { MaybeAsync::Sync(result) => result, @@ -109,6 +121,7 @@ impl MaybeAsync> { } } +/// An asynchronous type for computing the dependency graph. pub type DepGraphFuture = MaybeAsync>; /// Launch a thread and load the dependency graph in the background. @@ -151,7 +164,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { compilation session directory: {}", e ); - sess.fatal(&msg[..]) + sess.fatal(&msg) }); for swp in work_products { diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index 6c683058b1..9601a49267 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -13,9 +13,13 @@ use super::file_format; use super::fs::*; use super::work_product; -/// Save and dump the DepGraph. +/// Saves and writes the [`DepGraph`] to the file system. /// -/// No query must be invoked after this function. +/// This function saves both the dep-graph and the query result cache, +/// and drops the result cache. +/// +/// This function should only run after all queries have completed. +/// Trying to execute a query afterwards would attempt to read the result cache we just dropped. pub fn save_dep_graph(tcx: TyCtxt<'_>) { debug!("save_dep_graph()"); tcx.dep_graph.with_ignore(|| { @@ -75,6 +79,7 @@ pub fn save_dep_graph(tcx: TyCtxt<'_>) { }) } +/// Saves the work product index. pub fn save_work_product_index( sess: &Session, dep_graph: &DepGraph, @@ -139,6 +144,12 @@ fn encode_query_cache(tcx: TyCtxt<'_>, encoder: &mut FileEncoder) -> FileEncodeR tcx.sess.time("incr_comp_serialize_result_cache", || tcx.serialize_query_result_cache(encoder)) } +/// Builds the dependency graph. +/// +/// This function breates the *staging dep-graph*. When the dep-graph is modified by a query +/// execution, the new dependency information is not kept in memory but directly +/// output to this file. `save_dep_graph` then finalizes the staging dep-graph +/// and moves it to the permanent dep-graph path pub fn build_dep_graph( sess: &Session, prev_graph: SerializedDepGraph, diff --git a/compiler/rustc_incremental/src/persist/work_product.rs b/compiler/rustc_incremental/src/persist/work_product.rs index 19d64bda56..85b44ed753 100644 --- a/compiler/rustc_incremental/src/persist/work_product.rs +++ b/compiler/rustc_incremental/src/persist/work_product.rs @@ -1,4 +1,6 @@ -//! This module contains files for saving intermediate work-products. +//! Functions for saving and removing intermediate [work products]. +//! +//! [work products]: WorkProduct use crate::persist::fs::*; use rustc_fs_util::link_or_copy; @@ -7,6 +9,7 @@ use rustc_session::Session; use std::fs as std_fs; use std::path::PathBuf; +/// Copies a CGU work product to the incremental compilation directory, so next compilation can find and reuse it. pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( sess: &Session, cgu_name: &str, @@ -40,6 +43,7 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( Some((work_product_id, work_product)) } +/// Removes files for a given work product. pub fn delete_workproduct_files(sess: &Session, work_product: &WorkProduct) { if let Some(ref file_name) = work_product.saved_file { let path = in_incr_comp_dir_sess(sess, file_name); diff --git a/compiler/rustc_index/Cargo.toml b/compiler/rustc_index/Cargo.toml index b984a1321e..89419bfce6 100644 --- a/compiler/rustc_index/Cargo.toml +++ b/compiler/rustc_index/Cargo.toml @@ -10,3 +10,4 @@ doctest = false arrayvec = { version = "0.7", default-features = false } rustc_serialize = { path = "../rustc_serialize" } rustc_macros = { path = "../rustc_macros" } +smallvec = "1" diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index 08f13d46ee..5aa213cb70 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -87,7 +87,7 @@ macro_rules! bit_relations_inherent_impls { /// to or greater than the domain size. All operations that involve two bitsets /// will panic if the bitsets have differing domain sizes. /// -#[derive(Eq, PartialEq, Decodable, Encodable)] +#[derive(Eq, PartialEq, Hash, Decodable, Encodable)] pub struct BitSet { domain_size: usize, words: Vec, @@ -675,7 +675,7 @@ impl SparseBitSet { fn insert(&mut self, elem: T) -> bool { assert!(elem.index() < self.domain_size); - let changed = if let Some(i) = self.elems.iter().position(|&e| e >= elem) { + let changed = if let Some(i) = self.elems.iter().position(|&e| e.index() >= elem.index()) { if self.elems[i] == elem { // `elem` is already in the set. false @@ -715,6 +715,10 @@ impl SparseBitSet { self.elems.iter() } + bit_relations_inherent_impls! {} +} + +impl SparseBitSet { fn last_set_in(&self, range: impl RangeBounds) -> Option { let mut last_leq = None; for e in self.iter() { @@ -724,8 +728,6 @@ impl SparseBitSet { } last_leq } - - bit_relations_inherent_impls! {} } /// A fixed-size bitset type with a hybrid representation: sparse when there @@ -802,7 +804,10 @@ impl HybridBitSet { /// Returns the previous element present in the bitset from `elem`, /// inclusively of elem. That is, will return `Some(elem)` if elem is in the /// bitset. - pub fn last_set_in(&self, range: impl RangeBounds) -> Option { + pub fn last_set_in(&self, range: impl RangeBounds) -> Option + where + T: Ord, + { match self { HybridBitSet::Sparse(sparse) => sparse.last_set_in(range), HybridBitSet::Dense(dense) => dense.last_set_in(range), @@ -987,7 +992,7 @@ impl GrowableBitSet { /// /// All operations that involve a row and/or column index will panic if the /// index exceeds the relevant bound. -#[derive(Clone, Eq, PartialEq, Decodable, Encodable)] +#[derive(Clone, Eq, PartialEq, Hash, Decodable, Encodable)] pub struct BitMatrix { num_rows: usize, num_columns: usize, diff --git a/compiler/rustc_index/src/interval.rs b/compiler/rustc_index/src/interval.rs new file mode 100644 index 0000000000..6da95053b1 --- /dev/null +++ b/compiler/rustc_index/src/interval.rs @@ -0,0 +1,269 @@ +use std::iter::Step; +use std::marker::PhantomData; +use std::ops::Bound; +use std::ops::RangeBounds; + +use crate::vec::Idx; +use crate::vec::IndexVec; +use smallvec::SmallVec; + +#[cfg(test)] +mod tests; + +/// Stores a set of intervals on the indices. +#[derive(Debug, Clone)] +pub struct IntervalSet { + // Start, end + map: SmallVec<[(u32, u32); 4]>, + domain: usize, + _data: PhantomData, +} + +#[inline] +fn inclusive_start(range: impl RangeBounds) -> u32 { + match range.start_bound() { + Bound::Included(start) => start.index() as u32, + Bound::Excluded(start) => start.index() as u32 + 1, + Bound::Unbounded => 0, + } +} + +#[inline] +fn inclusive_end(domain: usize, range: impl RangeBounds) -> Option { + let end = match range.end_bound() { + Bound::Included(end) => end.index() as u32, + Bound::Excluded(end) => end.index().checked_sub(1)? as u32, + Bound::Unbounded => domain.checked_sub(1)? as u32, + }; + Some(end) +} + +impl IntervalSet { + pub fn new(domain: usize) -> IntervalSet { + IntervalSet { map: SmallVec::new(), domain, _data: PhantomData } + } + + pub fn clear(&mut self) { + self.map.clear(); + } + + pub fn iter(&self) -> impl Iterator + '_ + where + I: Step, + { + self.iter_intervals().flatten() + } + + /// Iterates through intervals stored in the set, in order. + pub fn iter_intervals(&self) -> impl Iterator> + '_ + where + I: Step, + { + self.map.iter().map(|&(start, end)| I::new(start as usize)..I::new(end as usize + 1)) + } + + /// Returns true if we increased the number of elements present. + pub fn insert(&mut self, point: I) -> bool { + self.insert_range(point..=point) + } + + /// Returns true if we increased the number of elements present. + pub fn insert_range(&mut self, range: impl RangeBounds + Clone) -> bool { + let start = inclusive_start(range.clone()); + let Some(mut end) = inclusive_end(self.domain, range) else { + // empty range + return false; + }; + if start > end { + return false; + } + + loop { + // This condition looks a bit weird, but actually makes sense. + // + // if r.0 == end + 1, then we're actually adjacent, so we want to + // continue to the next range. We're looking here for the first + // range which starts *non-adjacently* to our end. + let next = self.map.partition_point(|r| r.0 <= end + 1); + if let Some(last) = next.checked_sub(1) { + let (prev_start, prev_end) = &mut self.map[last]; + if *prev_end + 1 >= start { + // If the start for the inserted range is adjacent to the + // end of the previous, we can extend the previous range. + if start < *prev_start { + // Our range starts before the one we found. We'll need + // to *remove* it, and then try again. + // + // FIXME: This is not so efficient; we may need to + // recurse a bunch of times here. Instead, it's probably + // better to do something like drain_filter(...) on the + // map to be able to delete or modify all the ranges in + // start..=end and then potentially re-insert a new + // range. + end = std::cmp::max(end, *prev_end); + self.map.remove(last); + } else { + // We overlap with the previous range, increase it to + // include us. + // + // Make sure we're actually going to *increase* it though -- + // it may be that end is just inside the previously existing + // set. + return if end > *prev_end { + *prev_end = end; + true + } else { + false + }; + } + } else { + // Otherwise, we don't overlap, so just insert + self.map.insert(last + 1, (start, end)); + return true; + } + } else { + if self.map.is_empty() { + // Quite common in practice, and expensive to call memcpy + // with length zero. + self.map.push((start, end)); + } else { + self.map.insert(next, (start, end)); + } + return true; + } + } + } + + pub fn contains(&self, needle: I) -> bool { + let needle = needle.index() as u32; + let last = match self.map.partition_point(|r| r.0 <= needle).checked_sub(1) { + Some(idx) => idx, + None => { + // All ranges in the map start after the new range's end + return false; + } + }; + let (_, prev_end) = &self.map[last]; + needle <= *prev_end + } + + pub fn superset(&self, other: &IntervalSet) -> bool + where + I: Step, + { + // FIXME: Performance here is probably not great. We will be doing a lot + // of pointless tree traversals. + other.iter().all(|elem| self.contains(elem)) + } + + pub fn is_empty(&self) -> bool { + self.map.is_empty() + } + + /// Returns the maximum (last) element present in the set from `range`. + pub fn last_set_in(&self, range: impl RangeBounds + Clone) -> Option { + let start = inclusive_start(range.clone()); + let Some(end) = inclusive_end(self.domain, range) else { + // empty range + return None; + }; + if start > end { + return None; + } + let last = match self.map.partition_point(|r| r.0 <= end).checked_sub(1) { + Some(idx) => idx, + None => { + // All ranges in the map start after the new range's end + return None; + } + }; + let (_, prev_end) = &self.map[last]; + if start <= *prev_end { Some(I::new(std::cmp::min(*prev_end, end) as usize)) } else { None } + } + + pub fn insert_all(&mut self) { + self.clear(); + self.map.push((0, self.domain.try_into().unwrap())); + } + + pub fn union(&mut self, other: &IntervalSet) -> bool + where + I: Step, + { + assert_eq!(self.domain, other.domain); + let mut did_insert = false; + for range in other.iter_intervals() { + did_insert |= self.insert_range(range); + } + did_insert + } +} + +/// This data structure optimizes for cases where the stored bits in each row +/// are expected to be highly contiguous (long ranges of 1s or 0s), in contrast +/// to BitMatrix and SparseBitMatrix which are optimized for +/// "random"/non-contiguous bits and cheap(er) point queries at the expense of +/// memory usage. +#[derive(Clone)] +pub struct SparseIntervalMatrix +where + R: Idx, + C: Idx, +{ + rows: IndexVec>, + column_size: usize, +} + +impl SparseIntervalMatrix { + pub fn new(column_size: usize) -> SparseIntervalMatrix { + SparseIntervalMatrix { rows: IndexVec::new(), column_size } + } + + pub fn rows(&self) -> impl Iterator { + self.rows.indices() + } + + pub fn row(&self, row: R) -> Option<&IntervalSet> { + self.rows.get(row) + } + + fn ensure_row(&mut self, row: R) -> &mut IntervalSet { + self.rows.ensure_contains_elem(row, || IntervalSet::new(self.column_size)); + &mut self.rows[row] + } + + pub fn union_row(&mut self, row: R, from: &IntervalSet) -> bool + where + C: Step, + { + self.ensure_row(row).union(from) + } + + pub fn union_rows(&mut self, read: R, write: R) -> bool + where + C: Step, + { + if read == write || self.rows.get(read).is_none() { + return false; + } + self.ensure_row(write); + let (read_row, write_row) = self.rows.pick2_mut(read, write); + write_row.union(read_row) + } + + pub fn insert_all_into_row(&mut self, row: R) { + self.ensure_row(row).insert_all(); + } + + pub fn insert_range(&mut self, row: R, range: impl RangeBounds + Clone) { + self.ensure_row(row).insert_range(range); + } + + pub fn insert(&mut self, row: R, point: C) -> bool { + self.ensure_row(row).insert(point) + } + + pub fn contains(&self, row: R, point: C) -> bool { + self.row(row).map_or(false, |r| r.contains(point)) + } +} diff --git a/compiler/rustc_index/src/interval/tests.rs b/compiler/rustc_index/src/interval/tests.rs new file mode 100644 index 0000000000..d90b449f32 --- /dev/null +++ b/compiler/rustc_index/src/interval/tests.rs @@ -0,0 +1,199 @@ +use super::*; + +#[test] +fn insert_collapses() { + let mut set = IntervalSet::::new(3000); + set.insert_range(9831..=9837); + set.insert_range(43..=9830); + assert_eq!(set.iter_intervals().collect::>(), [43..9838]); +} + +#[test] +fn contains() { + let mut set = IntervalSet::new(300); + set.insert(0u32); + assert!(set.contains(0)); + set.insert_range(0..10); + assert!(set.contains(9)); + assert!(!set.contains(10)); + set.insert_range(10..11); + assert!(set.contains(10)); +} + +#[test] +fn insert() { + for i in 0..30usize { + let mut set = IntervalSet::new(300); + for j in i..30usize { + set.insert(j); + for k in i..j { + assert!(set.contains(k)); + } + } + } + + let mut set = IntervalSet::new(300); + set.insert_range(0..1u32); + assert!(set.contains(0), "{:?}", set.map); + assert!(!set.contains(1)); + set.insert_range(1..1); + assert!(set.contains(0)); + assert!(!set.contains(1)); + + let mut set = IntervalSet::new(300); + set.insert_range(4..5u32); + set.insert_range(5..10); + assert_eq!(set.iter().collect::>(), [4, 5, 6, 7, 8, 9]); + set.insert_range(3..7); + assert_eq!(set.iter().collect::>(), [3, 4, 5, 6, 7, 8, 9]); + + let mut set = IntervalSet::new(300); + set.insert_range(0..10u32); + set.insert_range(3..5); + assert_eq!(set.iter().collect::>(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + + let mut set = IntervalSet::new(300); + set.insert_range(0..10u32); + set.insert_range(0..3); + assert_eq!(set.iter().collect::>(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + + let mut set = IntervalSet::new(300); + set.insert_range(0..10u32); + set.insert_range(0..10); + assert_eq!(set.iter().collect::>(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + + let mut set = IntervalSet::new(300); + set.insert_range(0..10u32); + set.insert_range(5..10); + assert_eq!(set.iter().collect::>(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + + let mut set = IntervalSet::new(300); + set.insert_range(0..10u32); + set.insert_range(5..13); + assert_eq!(set.iter().collect::>(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]); +} + +#[test] +fn insert_range() { + #[track_caller] + fn check(range: R) + where + R: RangeBounds + Clone + IntoIterator + std::fmt::Debug, + { + let mut set = IntervalSet::new(300); + set.insert_range(range.clone()); + for i in set.iter() { + assert!(range.contains(&i)); + } + for i in range.clone() { + assert!(set.contains(i), "A: {} in {:?}, inserted {:?}", i, set, range); + } + set.insert_range(range.clone()); + for i in set.iter() { + assert!(range.contains(&i), "{} in {:?}", i, set); + } + for i in range.clone() { + assert!(set.contains(i), "B: {} in {:?}, inserted {:?}", i, set, range); + } + } + check(10..10); + check(10..100); + check(10..30); + check(0..5); + check(0..250); + check(200..250); + + check(10..=10); + check(10..=100); + check(10..=30); + check(0..=5); + check(0..=250); + check(200..=250); + + for i in 0..30 { + for j in i..30 { + check(i..j); + check(i..=j); + } + } +} + +#[test] +fn insert_range_dual() { + let mut set = IntervalSet::::new(300); + set.insert_range(0..3); + assert_eq!(set.iter().collect::>(), [0, 1, 2]); + set.insert_range(5..7); + assert_eq!(set.iter().collect::>(), [0, 1, 2, 5, 6]); + set.insert_range(3..4); + assert_eq!(set.iter().collect::>(), [0, 1, 2, 3, 5, 6]); + set.insert_range(3..5); + assert_eq!(set.iter().collect::>(), [0, 1, 2, 3, 4, 5, 6]); +} + +#[test] +fn last_set_before_adjacent() { + let mut set = IntervalSet::::new(300); + set.insert_range(0..3); + set.insert_range(3..5); + assert_eq!(set.last_set_in(0..3), Some(2)); + assert_eq!(set.last_set_in(0..5), Some(4)); + assert_eq!(set.last_set_in(3..5), Some(4)); + set.insert_range(2..5); + assert_eq!(set.last_set_in(0..3), Some(2)); + assert_eq!(set.last_set_in(0..5), Some(4)); + assert_eq!(set.last_set_in(3..5), Some(4)); +} + +#[test] +fn last_set_in() { + fn easy(set: &IntervalSet, needle: impl RangeBounds) -> Option { + let mut last_leq = None; + for e in set.iter() { + if needle.contains(&e) { + last_leq = Some(e); + } + } + last_leq + } + + #[track_caller] + fn cmp(set: &IntervalSet, needle: impl RangeBounds + Clone + std::fmt::Debug) { + assert_eq!( + set.last_set_in(needle.clone()), + easy(set, needle.clone()), + "{:?} in {:?}", + needle, + set + ); + } + let mut set = IntervalSet::new(300); + cmp(&set, 50..=50); + set.insert(64); + cmp(&set, 64..=64); + set.insert(64 - 1); + cmp(&set, 0..=64 - 1); + cmp(&set, 0..=5); + cmp(&set, 10..100); + set.insert(100); + cmp(&set, 100..110); + cmp(&set, 99..100); + cmp(&set, 99..=100); + + for i in 0..=30 { + for j in i..=30 { + for k in 0..30 { + let mut set = IntervalSet::new(100); + cmp(&set, ..j); + cmp(&set, i..); + cmp(&set, i..j); + cmp(&set, i..=j); + set.insert(k); + cmp(&set, ..j); + cmp(&set, i..); + cmp(&set, i..j); + cmp(&set, i..=j); + } + } + } +} diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index 5149322355..359b1859c6 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -1,13 +1,13 @@ #![feature(allow_internal_unstable)] #![feature(bench_black_box)] #![feature(extend_one)] -#![feature(iter_zip)] #![feature(min_specialization)] #![feature(step_trait)] #![feature(test)] #![feature(let_else)] pub mod bit_set; +pub mod interval; pub mod vec; // FIXME(#56935): Work around ICEs during cross-compilation. diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs index 55ccfd0ad2..e3c6528b21 100644 --- a/compiler/rustc_index/src/vec.rs +++ b/compiler/rustc_index/src/vec.rs @@ -12,7 +12,7 @@ use std::vec; /// Represents some newtyped `usize` wrapper. /// /// Purpose: avoid mixing indexes for different bitvector domains. -pub trait Idx: Copy + 'static + Ord + Debug + Hash { +pub trait Idx: Copy + 'static + Eq + PartialEq + Debug + Hash { fn new(idx: usize) -> Self; fn index(self) -> usize; diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 934ada9932..6023973665 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -134,7 +134,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// response*, then we don't typically replace free regions, as they /// must have been introduced from other parts of the system. trait CanonicalizeRegionMode { - fn canonicalize_free_region( + fn canonicalize_free_region<'tcx>( &self, canonicalizer: &mut Canonicalizer<'_, 'tcx>, r: ty::Region<'tcx>, @@ -146,7 +146,7 @@ trait CanonicalizeRegionMode { struct CanonicalizeQueryResponse; impl CanonicalizeRegionMode for CanonicalizeQueryResponse { - fn canonicalize_free_region( + fn canonicalize_free_region<'tcx>( &self, canonicalizer: &mut Canonicalizer<'_, 'tcx>, r: ty::Region<'tcx>, @@ -203,7 +203,7 @@ impl CanonicalizeRegionMode for CanonicalizeQueryResponse { struct CanonicalizeUserTypeAnnotation; impl CanonicalizeRegionMode for CanonicalizeUserTypeAnnotation { - fn canonicalize_free_region( + fn canonicalize_free_region<'tcx>( &self, canonicalizer: &mut Canonicalizer<'_, 'tcx>, r: ty::Region<'tcx>, @@ -226,7 +226,7 @@ impl CanonicalizeRegionMode for CanonicalizeUserTypeAnnotation { struct CanonicalizeAllFreeRegions; impl CanonicalizeRegionMode for CanonicalizeAllFreeRegions { - fn canonicalize_free_region( + fn canonicalize_free_region<'tcx>( &self, canonicalizer: &mut Canonicalizer<'_, 'tcx>, r: ty::Region<'tcx>, @@ -242,7 +242,7 @@ impl CanonicalizeRegionMode for CanonicalizeAllFreeRegions { struct CanonicalizeFreeRegionsOtherThanStatic; impl CanonicalizeRegionMode for CanonicalizeFreeRegionsOtherThanStatic { - fn canonicalize_free_region( + fn canonicalize_free_region<'tcx>( &self, canonicalizer: &mut Canonicalizer<'_, 'tcx>, r: ty::Region<'tcx>, diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index 09bfb3290f..da71edbd2d 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -37,7 +37,7 @@ use crate::traits::{Obligation, PredicateObligations}; use rustc_data_structures::sso::SsoHashMap; use rustc_hir::def_id::DefId; use rustc_middle::traits::ObligationCause; -use rustc_middle::ty::error::TypeError; +use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable}; @@ -533,7 +533,7 @@ struct Generalization<'tcx> { needs_wf: bool, } -impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { +impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } @@ -572,8 +572,9 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { // (e.g., #41849). relate::relate_substs(self, None, a_subst, b_subst) } else { - let opt_variances = self.tcx().variances_of(item_def_id); - relate::relate_substs(self, Some(&opt_variances), a_subst, b_subst) + let tcx = self.tcx(); + let opt_variances = tcx.variances_of(item_def_id); + relate::relate_substs(self, Some((item_def_id, &opt_variances)), a_subst, b_subst) } } @@ -790,7 +791,7 @@ pub fn const_unification_error<'tcx>( a_is_expected: bool, (a, b): (&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>), ) -> TypeError<'tcx> { - TypeError::ConstMismatch(ty::relate::expected_found_bool(a_is_expected, a, b)) + TypeError::ConstMismatch(ExpectedFound::new(a_is_expected, a, b)) } fn int_unification_error<'tcx>( @@ -798,7 +799,7 @@ fn int_unification_error<'tcx>( v: (ty::IntVarValue, ty::IntVarValue), ) -> TypeError<'tcx> { let (a, b) = v; - TypeError::IntMismatch(ty::relate::expected_found_bool(a_is_expected, a, b)) + TypeError::IntMismatch(ExpectedFound::new(a_is_expected, a, b)) } fn float_unification_error<'tcx>( @@ -806,7 +807,7 @@ fn float_unification_error<'tcx>( v: (ty::FloatVarValue, ty::FloatVarValue), ) -> TypeError<'tcx> { let (ty::FloatVarValue(a), ty::FloatVarValue(b)) = v; - TypeError::FloatMismatch(ty::relate::expected_found_bool(a_is_expected, a, b)) + TypeError::FloatMismatch(ExpectedFound::new(a_is_expected, a, b)) } struct ConstInferUnifier<'cx, 'tcx> { @@ -827,7 +828,7 @@ struct ConstInferUnifier<'cx, 'tcx> { // We use `TypeRelation` here to propagate `RelateResult` upwards. // // Both inputs are expected to be the same. -impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { +impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs index cbc735c98a..90c0ff9226 100644 --- a/compiler/rustc_infer/src/infer/equate.rs +++ b/compiler/rustc_infer/src/infer/equate.rs @@ -23,7 +23,7 @@ impl<'combine, 'infcx, 'tcx> Equate<'combine, 'infcx, 'tcx> { } } -impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> { +impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> { fn tag(&self) -> &'static str { "Equate" } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 85226e60bd..f0c73d0c2f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -83,7 +83,7 @@ pub use need_type_info::TypeAnnotationNeeded; pub mod nice_region_error; -pub(super) fn note_and_explain_region( +pub(super) fn note_and_explain_region<'tcx>( tcx: TyCtxt<'tcx>, err: &mut DiagnosticBuilder<'_>, prefix: &str, @@ -116,7 +116,7 @@ pub(super) fn note_and_explain_region( emit_msg_span(err, prefix, description, span, suffix); } -fn explain_free_region( +fn explain_free_region<'tcx>( tcx: TyCtxt<'tcx>, err: &mut DiagnosticBuilder<'_>, prefix: &str, @@ -128,7 +128,7 @@ fn explain_free_region( label_msg_span(err, prefix, description, span, suffix); } -fn msg_span_from_free_region( +fn msg_span_from_free_region<'tcx>( tcx: TyCtxt<'tcx>, region: ty::Region<'tcx>, alt_span: Option, @@ -145,7 +145,7 @@ fn msg_span_from_free_region( } } -fn msg_span_from_early_bound_and_free_regions( +fn msg_span_from_early_bound_and_free_regions<'tcx>( tcx: TyCtxt<'tcx>, region: ty::Region<'tcx>, ) -> (String, Span) { @@ -226,7 +226,7 @@ fn label_msg_span( } } -pub fn unexpected_hidden_region_diagnostic( +pub fn unexpected_hidden_region_diagnostic<'tcx>( tcx: TyCtxt<'tcx>, span: Span, hidden_ty: Ty<'tcx>, @@ -275,7 +275,7 @@ pub fn unexpected_hidden_region_diagnostic( fn_returns, hidden_region.to_string(), None, - format!("captures {}", hidden_region), + format!("captures `{}`", hidden_region), None, ) } @@ -316,7 +316,7 @@ pub fn unexpected_hidden_region_diagnostic( /// with the other type. A TyVar inference type is compatible with any type, and an IntVar or /// FloatVar inference type are compatible with themselves or their concrete types (Int and /// Float types, respectively). When comparing two ADTs, these rules apply recursively. -pub fn same_type_modulo_infer(a: Ty<'tcx>, b: Ty<'ctx>) -> bool { +pub fn same_type_modulo_infer<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { match (&a.kind(), &b.kind()) { (&ty::Adt(did_a, substs_a), &ty::Adt(did_b, substs_b)) => { if did_a != did_b { @@ -384,6 +384,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { sub_r, sup_origin, sup_r, + _, ) => { if sub_r.is_placeholder() { self.report_placeholder_failure(sub_origin, sub_r, sup_r).emit(); @@ -464,7 +465,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { errors.sort_by_key(|u| match *u { RegionResolutionError::ConcreteFailure(ref sro, _, _) => sro.span(), RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(), - RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _) => rvo.span(), + RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _, _) => rvo.span(), RegionResolutionError::UpperBoundUniverseConflict(_, ref rvo, _, _, _) => rvo.span(), }); errors @@ -603,7 +604,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { exp_found: Option>>, terr: &TypeError<'tcx>, ) { - match cause.code { + match *cause.code() { ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => { let ty = self.resolve_vars_if_possible(root_ty); if ty.is_suggestable() { @@ -780,7 +781,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } _ => { if let ObligationCauseCode::BindingObligation(_, binding_span) = - cause.code.peel_derives() + cause.code().peel_derives() { if matches!(terr, TypeError::RegionsPlaceholderMismatch) { err.span_note(*binding_span, "the lifetime requirement is introduced here"); @@ -1429,6 +1430,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } + /// Extend a type error with extra labels pointing at "non-trivial" types, like closures and + /// the return type of `async fn`s. + /// + /// `secondary_span` gives the caller the opportunity to expand `diag` with a `span_label`. + /// + /// `swap_secondary_and_primary` is used to make projection errors in particular nicer by using + /// the message in `secondary_span` as the primary label, and apply the message that would + /// otherwise be used for the primary label on the `secondary_span` `Span`. This applies on + /// E0271, like `src/test/ui/issues/issue-39970.stderr`. pub fn note_type_err( &self, diag: &mut DiagnosticBuilder<'tcx>, @@ -1436,6 +1446,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { secondary_span: Option<(Span, String)>, mut values: Option>, terr: &TypeError<'tcx>, + swap_secondary_and_primary: bool, ) { let span = cause.span(self.tcx); debug!("note_type_err cause={:?} values={:?}, terr={:?}", cause, values, terr); @@ -1612,9 +1623,32 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { match terr { TypeError::ObjectUnsafeCoercion(_) => {} _ => { - diag.span_label(span, terr.to_string()); + let mut label_or_note = |span: Span, msg: &str| { + if &[span] == diag.span.primary_spans() { + diag.span_label(span, msg); + } else { + diag.span_note(span, msg); + } + }; if let Some((sp, msg)) = secondary_span { - diag.span_label(sp, msg); + if swap_secondary_and_primary { + let terr = if let Some(infer::ValuePairs::Types(infer::ExpectedFound { + expected, + .. + })) = values + { + format!("expected this to be `{}`", expected) + } else { + terr.to_string() + }; + label_or_note(sp, &terr); + label_or_note(span, &msg); + } else { + label_or_note(span, &terr.to_string()); + label_or_note(sp, &msg); + } + } else { + label_or_note(span, &terr.to_string()); } } }; @@ -1695,10 +1729,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } _ => exp_found, }; - debug!("exp_found {:?} terr {:?} cause.code {:?}", exp_found, terr, cause.code); + debug!("exp_found {:?} terr {:?} cause.code {:?}", exp_found, terr, cause.code()); if let Some(exp_found) = exp_found { let should_suggest_fixes = if let ObligationCauseCode::Pattern { root_ty, .. } = - &cause.code + cause.code() { // Skip if the root_ty of the pattern is not the same as the expected_ty. // If these types aren't equal then we've probably peeled off a layer of arrays. @@ -1793,7 +1827,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { exp_span, exp_found.expected, exp_found.found, ); - if let ObligationCauseCode::CompareImplMethodObligation { .. } = &cause.code { + if let ObligationCauseCode::CompareImplMethodObligation { .. } = cause.code() { return; } @@ -1801,7 +1835,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.get_impl_future_output_ty(exp_found.expected), self.get_impl_future_output_ty(exp_found.found), ) { - (Some(exp), Some(found)) if same_type_modulo_infer(exp, found) => match &cause.code { + (Some(exp), Some(found)) if same_type_modulo_infer(exp, found) => match cause.code() { ObligationCauseCode::IfExpression(box IfExpressionCause { then, .. }) => { diag.multipart_suggestion( "consider `await`ing on both `Future`s", @@ -1841,7 +1875,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { Applicability::MaybeIncorrect, ); } - (Some(ty), _) if same_type_modulo_infer(ty, exp_found.found) => match cause.code { + (Some(ty), _) if same_type_modulo_infer(ty, exp_found.found) => match cause.code() { ObligationCauseCode::Pattern { span: Some(span), .. } | ObligationCauseCode::IfExpression(box IfExpressionCause { then: span, .. }) => { diag.span_suggestion_verbose( @@ -1893,7 +1927,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .map(|field| (field.ident.name, field.ty(self.tcx, expected_substs))) .find(|(_, ty)| same_type_modulo_infer(ty, exp_found.found)) { - if let ObligationCauseCode::Pattern { span: Some(span), .. } = cause.code { + if let ObligationCauseCode::Pattern { span: Some(span), .. } = *cause.code() { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { let suggestion = if expected_def.is_struct() { format!("{}.{}", snippet, name) @@ -2007,11 +2041,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if let ValuePairs::Types(ty::error::ExpectedFound { expected, found }) = trace.values { - // If a tuple of length one was expected and the found expression has - // parentheses around it, perhaps the user meant to write `(expr,)` to - // build a tuple (issue #86100) match (expected.kind(), found.kind()) { (ty::Tuple(_), ty::Tuple(_)) => {} + // If a tuple of length one was expected and the found expression has + // parentheses around it, perhaps the user meant to write `(expr,)` to + // build a tuple (issue #86100) (ty::Tuple(_), _) if expected.tuple_fields().count() == 1 => { if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) { if let Some(code) = @@ -2026,11 +2060,46 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } } + // If a character was expected and the found expression is a string literal + // containing a single character, perhaps the user meant to write `'c'` to + // specify a character literal (issue #92479) + (ty::Char, ty::Ref(_, r, _)) if r.is_str() => { + if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) { + if let Some(code) = + code.strip_prefix('"').and_then(|s| s.strip_suffix('"')) + { + if code.chars().nth(1).is_none() { + err.span_suggestion( + span, + "if you meant to write a `char` literal, use single quotes", + format!("'{}'", code), + Applicability::MachineApplicable, + ); + } + } + } + } + // If a string was expected and the found expression is a character literal, + // perhaps the user meant to write `"s"` to specify a string literal. + (ty::Ref(_, r, _), ty::Char) if r.is_str() => { + if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) { + if let Some(code) = + code.strip_prefix('\'').and_then(|s| s.strip_suffix('\'')) + { + err.span_suggestion( + span, + "if you meant to write a `str` literal, use double quotes", + format!("\"{}\"", code), + Applicability::MachineApplicable, + ); + } + } + } _ => {} } } if let MatchExpressionArm(box MatchExpressionArmCause { source, .. }) = - trace.cause.code + *trace.cause.code() { if let hir::MatchSource::TryDesugar = source { if let Some((expected_ty, found_ty)) = self.values_str(trace.values) { @@ -2048,7 +2117,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { struct_span_err!(self.tcx.sess, span, E0644, "{}", failure_str) } }; - self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr); + self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr, false); diag } @@ -2218,8 +2287,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .map(|p| p.name.as_str()), ); } - let lts = lts_names.iter().map(|s| -> &str { &*s }).collect::>(); - possible.find(|candidate| !lts.contains(&candidate.as_str())) + possible.find(|candidate| !lts_names.contains(&&candidate[..])) }) .unwrap_or("'lt".to_string()); let add_lt_sugg = generics @@ -2626,7 +2694,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { fn as_failure_code(&self, terr: &TypeError<'tcx>) -> FailureCode { use self::FailureCode::*; use crate::traits::ObligationCauseCode::*; - match self.code { + match self.code() { CompareImplMethodObligation { .. } => Error0308("method not compatible with trait"), CompareImplTypeObligation { .. } => Error0308("type not compatible with trait"), MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => { @@ -2661,7 +2729,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { fn as_requirement_str(&self) -> &'static str { use crate::traits::ObligationCauseCode::*; - match self.code { + match self.code() { CompareImplMethodObligation { .. } => "method type is compatible with trait", CompareImplTypeObligation { .. } => "associated type is compatible with trait", ExprAssignable => "expression is assignable", diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index a7e019a53e..9cf6cde259 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -1,5 +1,5 @@ use crate::infer::type_variable::TypeVariableOriginKind; -use crate::infer::InferCtxt; +use crate::infer::{InferCtxt, Symbol}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace}; @@ -10,7 +10,7 @@ use rustc_middle::hir::map::Map; use rustc_middle::infer::unify_key::ConstVariableOriginKind; use rustc_middle::ty::print::Print; use rustc_middle::ty::subst::{GenericArg, GenericArgKind}; -use rustc_middle::ty::{self, DefIdTree, InferConst, Ty, TyCtxt}; +use rustc_middle::ty::{self, Const, DefIdTree, InferConst, Ty, TyCtxt, TypeFoldable, TypeFolder}; use rustc_span::symbol::kw; use rustc_span::Span; use std::borrow::Cow; @@ -305,6 +305,15 @@ pub enum UnderspecifiedArgKind { Const { is_parameter: bool }, } +impl UnderspecifiedArgKind { + fn descr(&self) -> &'static str { + match self { + Self::Type { .. } => "type", + Self::Const { .. } => "const", + } + } +} + impl InferenceDiagnosticsData { /// Generate a label for a generic argument which can't be inferred. When not /// much is known about the argument, `use_diag` may be used to describe the @@ -400,36 +409,75 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } GenericArgKind::Const(ct) => { - if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val { - let origin = - self.inner.borrow_mut().const_unification_table().probe_value(vid).origin; - if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) = - origin.kind - { - return InferenceDiagnosticsData { - name: name.to_string(), - span: Some(origin.span), - kind: UnderspecifiedArgKind::Const { is_parameter: true }, - parent: InferenceDiagnosticsParentData::for_def_id(self.tcx, def_id), - }; - } + match ct.val { + ty::ConstKind::Infer(InferConst::Var(vid)) => { + let origin = self + .inner + .borrow_mut() + .const_unification_table() + .probe_value(vid) + .origin; + if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) = + origin.kind + { + return InferenceDiagnosticsData { + name: name.to_string(), + span: Some(origin.span), + kind: UnderspecifiedArgKind::Const { is_parameter: true }, + parent: InferenceDiagnosticsParentData::for_def_id( + self.tcx, def_id, + ), + }; + } - debug_assert!(!origin.span.is_dummy()); - let mut s = String::new(); - let mut printer = - ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::ValueNS); - if let Some(highlight) = highlight { - printer.region_highlight_mode = highlight; + debug_assert!(!origin.span.is_dummy()); + let mut s = String::new(); + let mut printer = + ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::ValueNS); + if let Some(highlight) = highlight { + printer.region_highlight_mode = highlight; + } + let _ = ct.print(printer); + InferenceDiagnosticsData { + name: s, + span: Some(origin.span), + kind: UnderspecifiedArgKind::Const { is_parameter: false }, + parent: None, + } } - let _ = ct.print(printer); - InferenceDiagnosticsData { - name: s, - span: Some(origin.span), - kind: UnderspecifiedArgKind::Const { is_parameter: false }, - parent: None, + ty::ConstKind::Unevaluated(ty::Unevaluated { + substs_: Some(substs), .. + }) => { + assert!(substs.has_infer_types_or_consts()); + + // FIXME: We only use the first inference variable we encounter in + // `substs` here, this gives insufficiently informative diagnostics + // in case there are multiple inference variables + for s in substs.iter() { + match s.unpack() { + GenericArgKind::Type(t) => match t.kind() { + ty::Infer(_) => { + return self.extract_inference_diagnostics_data(s, None); + } + _ => {} + }, + GenericArgKind::Const(c) => match c.val { + ty::ConstKind::Infer(InferConst::Var(_)) => { + return self.extract_inference_diagnostics_data(s, None); + } + _ => {} + }, + _ => {} + } + } + bug!( + "expected an inference variable in substs of unevaluated const {:?}", + ct + ); + } + _ => { + bug!("unexpect const: {:?}", ct); } - } else { - bug!("unexpect const: {:?}", ct); } } GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"), @@ -548,6 +596,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } + let param_type = arg_data.kind.descr(); let suffix = match local_visitor.found_node_ty { Some(ty) if ty.is_closure() => { let substs = @@ -586,13 +635,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } Some(ty) if is_named_and_not_impl_trait(ty) && arg_data.name == "_" => { let ty = ty_to_string(ty); - format!("the explicit type `{}`, with the type parameters specified", ty) + format!("the explicit type `{}`, with the {} parameters specified", ty, param_type) } Some(ty) if is_named_and_not_impl_trait(ty) && ty.to_string() != arg_data.name => { + let ty = ResolvedTypeParamEraser::new(self.tcx).fold_ty(ty); + let ty = ErrTypeParamEraser(self.tcx).fold_ty(ty); let ty = ty_to_string(ty); format!( - "the explicit type `{}`, where the type parameter `{}` is specified", - ty, arg_data.name, + "the explicit type `{}`, where the {} parameter `{}` is specified", + ty, param_type, arg_data.name, ) } _ => "a type".to_string(), @@ -868,3 +919,117 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err } } + +/// Turn *resolved* type params into `[type error]` to signal we don't want to display them. After +/// performing that replacement, we'll turn all remaining infer type params to use their name from +/// their definition, and replace all the `[type error]`s back to being infer so they display in +/// the output as `_`. If we didn't go through `[type error]`, we would either show all type params +/// by their name *or* `_`, neither of which is desireable: we want to show all types that we could +/// infer as `_` to reduce verbosity and avoid telling the user about unnecessary type annotations. +struct ResolvedTypeParamEraser<'tcx> { + tcx: TyCtxt<'tcx>, + level: usize, +} + +impl<'tcx> ResolvedTypeParamEraser<'tcx> { + fn new(tcx: TyCtxt<'tcx>) -> Self { + ResolvedTypeParamEraser { tcx, level: 0 } + } + + /// Replace not yet inferred const params with their def name. + fn replace_infers(&self, c: &'tcx Const<'tcx>, index: u32, name: Symbol) -> &'tcx Const<'tcx> { + match c.val { + ty::ConstKind::Infer(..) => self.tcx().mk_const_param(index, name, c.ty), + _ => c, + } + } +} + +impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> { + fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { + self.tcx + } + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + self.level += 1; + let t = match t.kind() { + // We'll hide this type only if all its type params are hidden as well. + ty::Adt(def, substs) => { + let generics = self.tcx().generics_of(def.did); + // Account for params with default values, like `Vec`, where we + // want to show `Vec`, not `Vec`. If we replaced that + // subst, then we'd get the incorrect output, so we passthrough. + let substs: Vec<_> = substs + .iter() + .zip(generics.params.iter()) + .map(|(subst, param)| match &(subst.unpack(), ¶m.kind) { + (_, ty::GenericParamDefKind::Type { has_default: true, .. }) => subst, + (crate::infer::GenericArgKind::Const(c), _) => { + self.replace_infers(c, param.index, param.name).into() + } + _ => subst.super_fold_with(self), + }) + .collect(); + let should_keep = |subst: &GenericArg<'_>| match subst.unpack() { + ty::subst::GenericArgKind::Type(t) => match t.kind() { + ty::Error(_) => false, + _ => true, + }, + // Account for `const` params here, otherwise `doesnt_infer.rs` + // shows `_` instead of `Foo<{ _: u32 }>` + ty::subst::GenericArgKind::Const(_) => true, + _ => false, + }; + if self.level == 1 || substs.iter().any(should_keep) { + let substs = self.tcx().intern_substs(&substs[..]); + self.tcx().mk_ty(ty::Adt(def, substs)) + } else { + self.tcx().ty_error() + } + } + ty::Ref(_, ty, _) => { + let ty = self.fold_ty(ty); + match ty.kind() { + // Avoid `&_`, these can be safely presented as `_`. + ty::Error(_) => self.tcx().ty_error(), + _ => t.super_fold_with(self), + } + } + // We could account for `()` if we wanted to replace it, but it's assured to be short. + ty::Tuple(_) + | ty::Slice(_) + | ty::RawPtr(_) + | ty::FnDef(..) + | ty::FnPtr(_) + | ty::Opaque(..) + | ty::Projection(_) + | ty::Never => t.super_fold_with(self), + ty::Array(ty, c) => self + .tcx() + .mk_ty(ty::Array(self.fold_ty(ty), self.replace_infers(c, 0, Symbol::intern("N")))), + // We don't want to hide type params that haven't been resolved yet. + // This would be the type that will be written out with the type param + // name in the output. + ty::Infer(_) => t, + // We don't want to hide the outermost type, only its type params. + _ if self.level == 1 => t.super_fold_with(self), + // Hide this type + _ => self.tcx().ty_error(), + }; + self.level -= 1; + t + } +} + +/// Replace `[type error]` with `ty::Infer(ty::Var)` to display `_`. +struct ErrTypeParamEraser<'tcx>(TyCtxt<'tcx>); +impl<'tcx> TypeFolder<'tcx> for ErrTypeParamEraser<'tcx> { + fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { + self.0 + } + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + match t.kind() { + ty::Error(_) => self.tcx().mk_ty_var(ty::TyVid::from_u32(0)), + _ => t.super_fold_with(self), + } + } +} diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs index 58eb1e9aa1..89023101f3 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -20,7 +20,7 @@ use rustc_middle::ty::{self, Region, TyCtxt}; /// ``` /// The function returns the nested type corresponding to the anonymous region /// for e.g., `&u8` and `Vec<&u8>`. -pub(crate) fn find_anon_type( +pub(crate) fn find_anon_type<'tcx>( tcx: TyCtxt<'tcx>, region: Region<'tcx>, br: &ty::BoundRegionKind, @@ -50,7 +50,7 @@ pub(crate) fn find_anon_type( // This method creates a FindNestedTypeVisitor which returns the type corresponding // to the anonymous region. -fn find_component_for_bound_region( +fn find_component_for_bound_region<'tcx>( tcx: TyCtxt<'tcx>, arg: &'tcx hir::Ty<'tcx>, br: &ty::BoundRegionKind, @@ -83,7 +83,7 @@ struct FindNestedTypeVisitor<'tcx> { current_index: ty::DebruijnIndex, } -impl Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { type Map = Map<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -207,7 +207,7 @@ struct TyPathVisitor<'tcx> { current_index: ty::DebruijnIndex, } -impl Visitor<'tcx> for TyPathVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> { type Map = Map<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap> { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs index 35c8786dcd..d3b47e396e 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs @@ -31,15 +31,15 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { }; // If we added a "points at argument expression" obligation, we remove it here, we care // about the original obligation only. - let code = match &cause.code { + let code = match cause.code() { ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => &*parent_code, - _ => &cause.code, + _ => cause.code(), }; let (parent, impl_def_id) = match code { ObligationCauseCode::MatchImpl(parent, impl_def_id) => (parent, impl_def_id), _ => return None, }; - let binding_span = match parent.code { + let binding_span = match *parent.code() { ObligationCauseCode::BindingObligation(_def_id, binding_span) => binding_span, _ => return None, }; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs index 6a33097700..fd295b7434 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs @@ -67,7 +67,7 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> { pub fn regions(&self) -> Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)> { match (&self.error, self.regions) { (Some(ConcreteFailure(origin, sub, sup)), None) => Some((origin.span(), sub, sup)), - (Some(SubSupConflict(_, _, origin, sub, _, sup)), None) => { + (Some(SubSupConflict(_, _, origin, sub, _, sup, _)), None) => { Some((origin.span(), sub, sup)) } (None, Some((span, sub, sup))) => Some((span, sub, sup)), diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index 4aecc2f40b..7178bfa525 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -13,7 +13,7 @@ use rustc_middle::ty::{self, TyCtxt}; use std::fmt::{self, Write}; -impl NiceRegionError<'me, 'tcx> { +impl<'tcx> NiceRegionError<'_, 'tcx> { /// When given a `ConcreteFailure` for a function with arguments containing a named region and /// an anonymous region, emit a descriptive diagnostic error. pub(super) fn try_report_placeholder_conflict(&self) -> Option> { @@ -34,6 +34,7 @@ impl NiceRegionError<'me, 'tcx> { sub_placeholder @ ty::RePlaceholder(_), _, sup_placeholder @ ty::RePlaceholder(_), + _, )) => self.try_report_trait_placeholder_mismatch( Some(self.tcx().mk_region(ty::ReVar(*vid))), cause, @@ -49,6 +50,7 @@ impl NiceRegionError<'me, 'tcx> { sub_placeholder @ ty::RePlaceholder(_), _, _, + _, )) => self.try_report_trait_placeholder_mismatch( Some(self.tcx().mk_region(ty::ReVar(*vid))), cause, @@ -64,6 +66,7 @@ impl NiceRegionError<'me, 'tcx> { _, _, sup_placeholder @ ty::RePlaceholder(_), + _, )) => self.try_report_trait_placeholder_mismatch( Some(self.tcx().mk_region(ty::ReVar(*vid))), cause, @@ -79,6 +82,7 @@ impl NiceRegionError<'me, 'tcx> { _, SubregionOrigin::Subtype(box TypeTrace { cause, values }), sup_placeholder @ ty::RePlaceholder(_), + _, )) => self.try_report_trait_placeholder_mismatch( Some(self.tcx().mk_region(ty::ReVar(*vid))), cause, @@ -204,7 +208,7 @@ impl NiceRegionError<'me, 'tcx> { ); let mut err = self.tcx().sess.struct_span_err(span, &msg); - let leading_ellipsis = if let ObligationCauseCode::ItemObligation(def_id) = cause.code { + let leading_ellipsis = if let ObligationCauseCode::ItemObligation(def_id) = *cause.code() { err.span_label(span, "doesn't satisfy where-clause"); err.span_label( self.tcx().def_span(def_id), diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index 2aaebed28c..b6dff2e53e 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -10,7 +10,8 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_ty, ErasedMap, NestedVisitorMap, Visitor}; use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind}; use rustc_middle::ty::{ - self, AssocItemContainer, RegionKind, Ty, TyCtxt, TypeFoldable, TypeVisitor, + self, AssocItemContainer, RegionKind, StaticLifetimeVisitor, Ty, TyCtxt, TypeFoldable, + TypeVisitor, }; use rustc_span::symbol::Ident; use rustc_span::{MultiSpan, Span}; @@ -23,7 +24,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { pub(super) fn try_report_static_impl_trait(&self) -> Option { debug!("try_report_static_impl_trait(error={:?})", self.error); let tcx = self.tcx(); - let (var_origin, sub_origin, sub_r, sup_origin, sup_r) = match self.error.as_ref()? { + let (var_origin, sub_origin, sub_r, sup_origin, sup_r, spans) = match self.error.as_ref()? { RegionResolutionError::SubSupConflict( _, var_origin, @@ -31,8 +32,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { sub_r, sup_origin, sup_r, + spans, ) if **sub_r == RegionKind::ReStatic => { - (var_origin, sub_origin, sub_r, sup_origin, sup_r) + (var_origin, sub_origin, sub_r, sup_origin, sup_r, spans) } RegionResolutionError::ConcreteFailure( SubregionOrigin::Subtype(box TypeTrace { cause, .. }), @@ -40,7 +42,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { sup_r, ) if **sub_r == RegionKind::ReStatic => { // This is for an implicit `'static` requirement coming from `impl dyn Trait {}`. - if let ObligationCauseCode::UnifyReceiver(ctxt) = &cause.code { + if let ObligationCauseCode::UnifyReceiver(ctxt) = cause.code() { // This may have a closure and it would cause ICE // through `find_param_with_region` (#78262). let anon_reg_sup = tcx.is_suitable_region(sup_r)?; @@ -74,7 +76,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { err.span_label( cause.span, &format!( - "...is captured and required to live as long as `'static` here \ + "...is used and required to live as long as `'static` here \ because of an implicit lifetime bound on the {}", match ctxt.assoc_item.container { AssocItemContainer::TraitContainer(id) => @@ -123,63 +125,108 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { param_name, lifetime, ); - err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime)); + + let (mention_influencer, influencer_point) = + if sup_origin.span().overlaps(param.param_ty_span) { + // Account for `async fn` like in `async-await/issues/issue-62097.rs`. + // The desugaring of `async `fn`s causes `sup_origin` and `param` to point at the same + // place (but with different `ctxt`, hence `overlaps` instead of `==` above). + // + // This avoids the following: + // + // LL | pub async fn run_dummy_fn(&self) { + // | ^^^^^ + // | | + // | this data with an anonymous lifetime `'_`... + // | ...is captured here... + (false, sup_origin.span()) + } else { + (!sup_origin.span().overlaps(return_sp), param.param_ty_span) + }; + err.span_label(influencer_point, &format!("this data with {}...", lifetime)); + debug!("try_report_static_impl_trait: param_info={:?}", param); - // We try to make the output have fewer overlapping spans if possible. - if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span())) - && sup_origin.span() != return_sp - { - // FIXME: account for `async fn` like in `async-await/issues/issue-62097.rs` + let mut spans = spans.clone(); - // Customize the spans and labels depending on their relative order so - // that split sentences flow correctly. - if sup_origin.span().overlaps(return_sp) && sp == sup_origin.span() { - // Avoid the following: - // - // error: cannot infer an appropriate lifetime - // --> $DIR/must_outlive_least_region_or_bound.rs:18:50 - // | - // LL | fn foo(x: &i32) -> Box { Box::new(x) } - // | ---- ---------^- - // - // and instead show: - // - // error: cannot infer an appropriate lifetime - // --> $DIR/must_outlive_least_region_or_bound.rs:18:50 - // | - // LL | fn foo(x: &i32) -> Box { Box::new(x) } - // | ---- ^ - err.span_label( - sup_origin.span(), - "...is captured here, requiring it to live as long as `'static`", - ); - } else { - err.span_label(sup_origin.span(), "...is captured here..."); - if return_sp < sup_origin.span() { - err.span_note( - return_sp, - "...and is required to live as long as `'static` here", + if mention_influencer { + spans.push(sup_origin.span()); + } + // We dedup the spans *ignoring* expansion context. + spans.sort(); + spans.dedup_by_key(|span| (span.lo(), span.hi())); + + // We try to make the output have fewer overlapping spans if possible. + let require_msg = if spans.is_empty() { + "...is used and required to live as long as `'static` here" + } else { + "...and is required to live as long as `'static` here" + }; + let require_span = + if sup_origin.span().overlaps(return_sp) { sup_origin.span() } else { return_sp }; + + for span in &spans { + err.span_label(*span, "...is used here..."); + } + + if spans.iter().any(|sp| sp.overlaps(return_sp) || *sp > return_sp) { + // If any of the "captured here" labels appears on the same line or after + // `require_span`, we put it on a note to ensure the text flows by appearing + // always at the end. + err.span_note(require_span, require_msg); + } else { + // We don't need a note, it's already at the end, it can be shown as a `span_label`. + err.span_label(require_span, require_msg); + } + + if let SubregionOrigin::RelateParamBound(_, _, Some(bound)) = sub_origin { + err.span_note(*bound, "`'static` lifetime requirement introduced by this bound"); + } + if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = sub_origin { + if let ObligationCauseCode::ReturnValue(hir_id) + | ObligationCauseCode::BlockTailExpression(hir_id) = cause.code() + { + let parent_id = tcx.hir().get_parent_item(*hir_id); + if let Some(fn_decl) = tcx.hir().fn_decl_by_hir_id(parent_id) { + let mut span: MultiSpan = fn_decl.output.span().into(); + let mut add_label = true; + if let hir::FnRetTy::Return(ty) = fn_decl.output { + let mut v = StaticLifetimeVisitor(vec![], tcx.hir()); + v.visit_ty(ty); + if !v.0.is_empty() { + span = v.0.clone().into(); + for sp in v.0 { + span.push_span_label( + sp, + "`'static` requirement introduced here".to_string(), + ); + } + add_label = false; + } + } + if add_label { + span.push_span_label( + fn_decl.output.span(), + "requirement introduced by this return type".to_string(), + ); + } + span.push_span_label( + cause.span, + "because of this returned expression".to_string(), ); - } else { - err.span_label( - return_sp, - "...and is required to live as long as `'static` here", + err.span_note( + span, + "`'static` lifetime requirement introduced by the return type", ); } } - } else { - err.span_label( - return_sp, - "...is captured and required to live as long as `'static` here", - ); } let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id); let mut override_error_code = None; if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin { - if let ObligationCauseCode::UnifyReceiver(ctxt) = &cause.code { + if let ObligationCauseCode::UnifyReceiver(ctxt) = cause.code() { // Handle case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a // `'static` lifetime when called as a method on a binding: `bar.qux()`. if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) { @@ -188,9 +235,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } } if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sub_origin { - let code = match &cause.code { - ObligationCauseCode::MatchImpl(parent, ..) => &parent.code, - _ => &cause.code, + let code = match cause.code() { + ObligationCauseCode::MatchImpl(parent, ..) => parent.code(), + _ => cause.code(), }; if let (ObligationCauseCode::ItemObligation(item_def_id), None) = (code, override_error_code) @@ -240,7 +287,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } pub fn suggest_new_region_bound( - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, err: &mut DiagnosticBuilder<'_>, fn_returns: Vec<&rustc_hir::Ty<'_>>, lifetime_name: String, diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs index cfa79213c8..f5fb82dbf3 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -28,6 +28,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { _sub, sup_origin, _sup, + _, ) = error.clone() { if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin) { @@ -35,7 +36,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ValuePairs::Types(sub_expected_found), ValuePairs::Types(sup_expected_found), CompareImplMethodObligation { trait_item_def_id, .. }, - ) = (&sub_trace.values, &sup_trace.values, &sub_trace.cause.code) + ) = (&sub_trace.values, &sup_trace.values, sub_trace.cause.code()) { if sup_expected_found == sub_expected_found { self.emit_err( @@ -85,7 +86,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { counter: usize, } - impl HighlightBuilder<'tcx> { + impl<'tcx> HighlightBuilder<'tcx> { fn build(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> RegionHighlightMode { let mut builder = HighlightBuilder { highlight: RegionHighlightMode::default(), counter: 1, tcx }; @@ -185,7 +186,7 @@ struct TypeParamSpanVisitor<'tcx> { types: Vec, } -impl Visitor<'tcx> for TypeParamSpanVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for TypeParamSpanVisitor<'tcx> { type Map = rustc_middle::hir::map::Map<'tcx>; fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs index 90bc5b3b2f..04eceecc5f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs @@ -107,7 +107,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, - origin: hir::OpaqueTyOrigin::AsyncFn, + origin: hir::OpaqueTyOrigin::AsyncFn(..), .. }), .. diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index 6600c18351..82bd8890dd 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -359,13 +359,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { match placeholder_origin { infer::Subtype(box ref trace) if matches!( - &trace.cause.code.peel_derives(), + &trace.cause.code().peel_derives(), ObligationCauseCode::BindingObligation(..) ) => { // Hack to get around the borrow checker because trace.cause has an `Rc`. if let ObligationCauseCode::BindingObligation(_, span) = - &trace.cause.code.peel_derives() + &trace.cause.code().peel_derives() { let span = *span; let mut err = self.report_concrete_failure(placeholder_origin, sub, sup); diff --git a/compiler/rustc_infer/src/infer/free_regions.rs b/compiler/rustc_infer/src/infer/free_regions.rs index 4814b65e32..e93cdf7942 100644 --- a/compiler/rustc_infer/src/infer/free_regions.rs +++ b/compiler/rustc_infer/src/infer/free_regions.rs @@ -11,7 +11,7 @@ use rustc_middle::ty::{self, Lift, Region, TyCtxt}; /// /// This stuff is a bit convoluted and should be refactored, but as we /// transition to NLL, it'll all go away anyhow. -pub struct RegionRelations<'a, 'tcx> { +pub(crate) struct RegionRelations<'a, 'tcx> { pub tcx: TyCtxt<'tcx>, /// The context used for debug messages diff --git a/compiler/rustc_infer/src/infer/glb.rs b/compiler/rustc_infer/src/infer/glb.rs index d769667c2f..862f5a5fbb 100644 --- a/compiler/rustc_infer/src/infer/glb.rs +++ b/compiler/rustc_infer/src/infer/glb.rs @@ -23,7 +23,7 @@ impl<'combine, 'infcx, 'tcx> Glb<'combine, 'infcx, 'tcx> { } } -impl TypeRelation<'tcx> for Glb<'combine, 'infcx, 'tcx> { +impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> { fn tag(&self) -> &'static str { "Glb" } diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index 4c9dcab26b..a5ec84a4f1 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -19,6 +19,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic}; use rustc_middle::ty::{ReLateBound, RePlaceholder, ReVar}; use rustc_middle::ty::{Region, RegionVid}; +use rustc_span::Span; use std::fmt; /// This function performs lexical region resolution given a complete @@ -27,7 +28,7 @@ use std::fmt; /// assuming such values can be found. It returns the final values of /// all the variables as well as a set of errors that must be reported. #[instrument(level = "debug", skip(region_rels, var_infos, data))] -pub fn resolve<'tcx>( +pub(crate) fn resolve<'tcx>( region_rels: &RegionRelations<'_, 'tcx>, var_infos: VarInfos, data: RegionConstraintData<'tcx>, @@ -96,6 +97,7 @@ pub enum RegionResolutionError<'tcx> { Region<'tcx>, SubregionOrigin<'tcx>, Region<'tcx>, + Vec, // All the influences on a given value that didn't meet its constraints. ), /// Indicates a `'b: 'a` constraint where `'a` is in a universe that @@ -567,7 +569,30 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { // if this rule starts to create problems we'll // have to revisit this portion of the code and // think hard about it. =) -- nikomatsakis - self.collect_error_for_expanding_node(graph, &mut dup_vec, node_vid, errors); + + // Obtain the spans for all the places that can + // influence the constraints on this value for + // richer diagnostics in `static_impl_trait`. + let influences: Vec = self + .data + .constraints + .iter() + .filter_map(|(constraint, origin)| match (constraint, origin) { + ( + Constraint::VarSubVar(_, sup), + SubregionOrigin::DataBorrowed(_, sp), + ) if sup == &node_vid => Some(*sp), + _ => None, + }) + .collect(); + + self.collect_error_for_expanding_node( + graph, + &mut dup_vec, + node_vid, + errors, + influences, + ); } } } @@ -621,6 +646,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { dup_vec: &mut IndexVec>, node_idx: RegionVid, errors: &mut Vec>, + influences: Vec, ) { // Errors in expanding nodes result from a lower-bound that is // not contained by an upper-bound. @@ -667,6 +693,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { sup: {:?}", origin, node_idx, lower_bound.region, upper_bound.region ); + errors.push(RegionResolutionError::SubSupConflict( node_idx, origin, @@ -674,6 +701,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { lower_bound.region, upper_bound.origin.clone(), upper_bound.region, + influences, )); return; } diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/lub.rs index cbad66397f..5191d1c1cc 100644 --- a/compiler/rustc_infer/src/infer/lub.rs +++ b/compiler/rustc_infer/src/infer/lub.rs @@ -23,7 +23,7 @@ impl<'combine, 'infcx, 'tcx> Lub<'combine, 'infcx, 'tcx> { } } -impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> { +impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> { fn tag(&self) -> &'static str { "Lub" } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 2fd01c2d59..04e04e297c 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -21,6 +21,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType}; +use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::mir::interpret::EvalToConstValueResult; use rustc_middle::traits::select; use rustc_middle::ty::error::{ExpectedFound, TypeError}; @@ -553,7 +554,7 @@ pub trait TyCtxtInferExt<'tcx> { fn infer_ctxt(self) -> InferCtxtBuilder<'tcx>; } -impl TyCtxtInferExt<'tcx> for TyCtxt<'tcx> { +impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> { fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> { InferCtxtBuilder { tcx: self, @@ -1584,13 +1585,27 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { unevaluated: ty::Unevaluated<'tcx>, span: Option, ) -> EvalToConstValueResult<'tcx> { - let mut original_values = OriginalQueryValues::default(); - let canonical = self.canonicalize_query((param_env, unevaluated), &mut original_values); + let mut substs = unevaluated.substs(self.tcx); + substs = self.resolve_vars_if_possible(substs); + + // Postpone the evaluation of constants whose substs depend on inference + // variables + if substs.has_infer_types_or_consts() { + return Err(ErrorHandled::TooGeneric); + } + + let param_env_erased = self.tcx.erase_regions(param_env); + let substs_erased = self.tcx.erase_regions(substs); + + let unevaluated = ty::Unevaluated { + def: unevaluated.def, + substs_: Some(substs_erased), + promoted: unevaluated.promoted, + }; - let (param_env, unevaluated) = canonical.value; // The return value is the evaluated value which doesn't contain any reference to inference // variables, thus we don't need to substitute back the original values. - self.tcx.const_eval_resolve(param_env, unevaluated, span) + self.tcx.const_eval_resolve(param_env_erased, unevaluated, span) } /// If `typ` is a type variable of some kind, resolve it one level @@ -1703,7 +1718,7 @@ pub enum TyOrConstInferVar<'tcx> { Const(ConstVid<'tcx>), } -impl TyOrConstInferVar<'tcx> { +impl<'tcx> TyOrConstInferVar<'tcx> { /// Tries to extract an inference variable from a type or a constant, returns `None` /// for types other than `ty::Infer(_)` (or `InferTy::Fresh*`) and /// for constants other than `ty::ConstKind::Infer(_)` (or `InferConst::Fresh`). @@ -1809,7 +1824,7 @@ impl<'tcx> SubregionOrigin<'tcx> { where F: FnOnce() -> Self, { - match cause.code { + match *cause.code() { traits::ObligationCauseCode::ReferenceOutlivesReferent(ref_type) => { SubregionOrigin::ReferenceOutlivesReferent(ref_type, cause.span) } diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index 29a9cbc7a9..ebc0e80cdf 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -407,7 +407,7 @@ trait VidValuePair<'tcx>: Debug { /// Extract the scopes that apply to whichever side of the tuple /// the vid was found on. See the comment where this is called /// for more details on why we want them. - fn vid_scopes>( + fn vid_scopes<'r, D: TypeRelatingDelegate<'tcx>>( &self, relate: &'r mut TypeRelating<'_, 'tcx, D>, ) -> &'r mut Vec>; @@ -424,7 +424,7 @@ trait VidValuePair<'tcx>: Debug { D: TypeRelatingDelegate<'tcx>; } -impl VidValuePair<'tcx> for (ty::TyVid, Ty<'tcx>) { +impl<'tcx> VidValuePair<'tcx> for (ty::TyVid, Ty<'tcx>) { fn vid(&self) -> ty::TyVid { self.0 } @@ -433,7 +433,7 @@ impl VidValuePair<'tcx> for (ty::TyVid, Ty<'tcx>) { self.1 } - fn vid_scopes( + fn vid_scopes<'r, D>( &self, relate: &'r mut TypeRelating<'_, 'tcx, D>, ) -> &'r mut Vec> @@ -456,7 +456,7 @@ impl VidValuePair<'tcx> for (ty::TyVid, Ty<'tcx>) { } // In this case, the "vid" is the "b" type. -impl VidValuePair<'tcx> for (Ty<'tcx>, ty::TyVid) { +impl<'tcx> VidValuePair<'tcx> for (Ty<'tcx>, ty::TyVid) { fn vid(&self) -> ty::TyVid { self.1 } @@ -465,7 +465,7 @@ impl VidValuePair<'tcx> for (Ty<'tcx>, ty::TyVid) { self.0 } - fn vid_scopes( + fn vid_scopes<'r, D>( &self, relate: &'r mut TypeRelating<'_, 'tcx, D>, ) -> &'r mut Vec> @@ -487,7 +487,7 @@ impl VidValuePair<'tcx> for (Ty<'tcx>, ty::TyVid) { } } -impl TypeRelation<'tcx> for TypeRelating<'me, 'tcx, D> +impl<'tcx, D> TypeRelation<'tcx> for TypeRelating<'_, 'tcx, D> where D: TypeRelatingDelegate<'tcx>, { @@ -841,7 +841,7 @@ where universe: ty::UniverseIndex, } -impl TypeRelation<'tcx> for TypeGeneralizer<'me, 'tcx, D> +impl<'tcx, D> TypeRelation<'tcx> for TypeGeneralizer<'_, 'tcx, D> where D: TypeRelatingDelegate<'tcx>, { diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index e2e07f2072..c2ef0b41e2 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -276,7 +276,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { debug!(?concrete_ty); let first_own_region = match opaque_defn.origin { - hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => { + hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => { // We lower // // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm> @@ -461,33 +461,29 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { if let Some(def_id) = def_id.as_local() { let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let parent_def_id = self.infcx.defining_use_anchor; - let def_scope_default = || { - let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id); - parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id) + let item_kind = &tcx.hir().expect_item(def_id).kind; + let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item_kind else { + span_bug!( + self.value_span, + "weird opaque type: {:#?}, {:#?}", + ty.kind(), + item_kind + ) + }; + let in_definition_scope = match *origin { + // Async `impl Trait` + hir::OpaqueTyOrigin::AsyncFn(parent) => parent == parent_def_id, + // Anonymous `impl Trait` + hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id, + // Named `type Foo = impl Bar;` + hir::OpaqueTyOrigin::TyAlias => { + may_define_opaque_type(tcx, parent_def_id, opaque_hir_id) + } }; - let (in_definition_scope, origin) = - match tcx.hir().expect_item(opaque_hir_id).kind { - // Anonymous `impl Trait` - hir::ItemKind::OpaqueTy(hir::OpaqueTy { - impl_trait_fn: Some(parent), - origin, - .. - }) => (parent == parent_def_id.to_def_id(), origin), - // Named `type Foo = impl Bar;` - hir::ItemKind::OpaqueTy(hir::OpaqueTy { - impl_trait_fn: None, - origin, - .. - }) => ( - may_define_opaque_type(tcx, parent_def_id, opaque_hir_id), - origin, - ), - _ => (def_scope_default(), hir::OpaqueTyOrigin::TyAlias), - }; if in_definition_scope { let opaque_type_key = OpaqueTypeKey { def_id: def_id.to_def_id(), substs }; - return self.fold_opaque_ty(ty, opaque_type_key, origin); + return self.fold_opaque_ty(ty, opaque_type_key, *origin); } debug!( diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs index 98f926e9d7..22e18deac2 100644 --- a/compiler/rustc_infer/src/infer/outlives/components.rs +++ b/compiler/rustc_infer/src/infer/outlives/components.rs @@ -49,7 +49,7 @@ pub enum Component<'tcx> { /// Push onto `out` all the things that must outlive `'a` for the condition /// `ty0: 'a` to hold. Note that `ty0` must be a **fully resolved type**. -pub fn push_outlives_components( +pub fn push_outlives_components<'tcx>( tcx: TyCtxt<'tcx>, ty0: Ty<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>, @@ -59,7 +59,7 @@ pub fn push_outlives_components( debug!("components({:?}) = {:?}", ty0, out); } -fn compute_components( +fn compute_components<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>, @@ -190,7 +190,7 @@ fn compute_components( } } -fn compute_components_recursive( +fn compute_components_recursive<'tcx>( tcx: TyCtxt<'tcx>, parent: GenericArg<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>, diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 91a22ecc5a..74eb263a63 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -102,7 +102,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { infer::RelateParamBound( cause.span, sup_type, - match cause.code.peel_derives() { + match cause.code().peel_derives() { ObligationCauseCode::BindingObligation(_, span) => Some(*span), _ => None, }, diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index df4fdb3a98..29775a9668 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -65,7 +65,7 @@ pub struct RegionConstraintCollector<'a, 'tcx> { undo_log: &'a mut InferCtxtUndoLogs<'tcx>, } -impl std::ops::Deref for RegionConstraintCollector<'_, 'tcx> { +impl<'tcx> std::ops::Deref for RegionConstraintCollector<'_, 'tcx> { type Target = RegionConstraintStorage<'tcx>; #[inline] fn deref(&self) -> &RegionConstraintStorage<'tcx> { @@ -73,7 +73,7 @@ impl std::ops::Deref for RegionConstraintCollector<'_, 'tcx> { } } -impl std::ops::DerefMut for RegionConstraintCollector<'_, 'tcx> { +impl<'tcx> std::ops::DerefMut for RegionConstraintCollector<'_, 'tcx> { #[inline] fn deref_mut(&mut self) -> &mut RegionConstraintStorage<'tcx> { self.storage diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 4b08c2eb9c..f036e1214a 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -1,7 +1,7 @@ use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use super::{FixupError, FixupResult, InferCtxt, Span}; use rustc_middle::mir; -use rustc_middle::ty::fold::{TypeFolder, TypeVisitor}; +use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFolder, TypeVisitor}; use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable}; use std::ops::ControlFlow; @@ -175,81 +175,72 @@ pub fn fully_resolve<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>, value: T) -> Fixu where T: TypeFoldable<'tcx>, { - let mut full_resolver = FullTypeResolver { infcx, err: None }; - let result = value.fold_with(&mut full_resolver); - match full_resolver.err { - None => Ok(result), - Some(e) => Err(e), - } + value.try_fold_with(&mut FullTypeResolver { infcx }) } // N.B. This type is not public because the protocol around checking the // `err` field is not enforceable otherwise. struct FullTypeResolver<'a, 'tcx> { infcx: &'a InferCtxt<'a, 'tcx>, - err: Option>, } impl<'a, 'tcx> TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> { + type Error = FixupError<'tcx>; + fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { self.infcx.tcx } +} - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { +impl<'a, 'tcx> FallibleTypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> { + fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result, Self::Error> { if !t.needs_infer() { - t // micro-optimize -- if there is nothing in this type that this fold affects... + Ok(t) // micro-optimize -- if there is nothing in this type that this fold affects... } else { let t = self.infcx.shallow_resolve(t); match *t.kind() { - ty::Infer(ty::TyVar(vid)) => { - self.err = Some(FixupError::UnresolvedTy(vid)); - self.tcx().ty_error() - } - ty::Infer(ty::IntVar(vid)) => { - self.err = Some(FixupError::UnresolvedIntTy(vid)); - self.tcx().ty_error() - } - ty::Infer(ty::FloatVar(vid)) => { - self.err = Some(FixupError::UnresolvedFloatTy(vid)); - self.tcx().ty_error() - } + ty::Infer(ty::TyVar(vid)) => Err(FixupError::UnresolvedTy(vid)), + ty::Infer(ty::IntVar(vid)) => Err(FixupError::UnresolvedIntTy(vid)), + ty::Infer(ty::FloatVar(vid)) => Err(FixupError::UnresolvedFloatTy(vid)), ty::Infer(_) => { bug!("Unexpected type in full type resolver: {:?}", t); } - _ => t.super_fold_with(self), + _ => t.try_super_fold_with(self), } } } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result, Self::Error> { match *r { - ty::ReVar(rid) => self + ty::ReVar(rid) => Ok(self .infcx .lexical_region_resolutions .borrow() .as_ref() .expect("region resolution not performed") - .resolve_var(rid), - _ => r, + .resolve_var(rid)), + _ => Ok(r), } } - fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + fn try_fold_const( + &mut self, + c: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { if !c.needs_infer() { - c // micro-optimize -- if there is nothing in this const that this fold affects... + Ok(c) // micro-optimize -- if there is nothing in this const that this fold affects... } else { let c = self.infcx.shallow_resolve(c); match c.val { ty::ConstKind::Infer(InferConst::Var(vid)) => { - self.err = Some(FixupError::UnresolvedConst(vid)); - return self.tcx().const_error(c.ty); + return Err(FixupError::UnresolvedConst(vid)); } ty::ConstKind::Infer(InferConst::Fresh(_)) => { bug!("Unexpected const in full const resolver: {:?}", c); } _ => {} } - c.super_fold_with(self) + c.try_super_fold_with(self) } } } diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index 8ef0d132cf..ccac0efd6c 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -31,7 +31,7 @@ impl<'combine, 'infcx, 'tcx> Sub<'combine, 'infcx, 'tcx> { } } -impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> { +impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { fn tag(&self) -> &'static str { "Sub" } diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index e4b407e7c1..5f228d1e20 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -17,10 +17,8 @@ #![feature(box_patterns)] #![feature(derive_default_enum)] #![feature(extend_one)] -#![feature(iter_zip)] #![feature(let_else)] #![feature(never_type)] -#![feature(in_band_lifetimes)] #![feature(control_flow_enum)] #![feature(min_specialization)] #![feature(label_break_value)] diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index 152a395c87..736278ba0d 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -1,9 +1,8 @@ use crate::infer::InferCtxt; use crate::traits::Obligation; use rustc_data_structures::fx::FxHashMap; -use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_middle::ty::{self, ToPredicate, Ty, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty}; use super::FulfillmentError; use super::{ObligationCause, PredicateObligation}; @@ -48,26 +47,9 @@ pub trait TraitEngine<'tcx>: 'tcx { fn select_all_or_error(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec>; - fn select_all_with_constness_or_error( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - _constness: hir::Constness, - ) -> Vec> { - self.select_all_or_error(infcx) - } - fn select_where_possible(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec>; - // FIXME(fee1-dead) this should not provide a default body for chalk as chalk should be updated - fn select_with_constness_where_possible( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - _constness: hir::Constness, - ) -> Vec> { - self.select_where_possible(infcx) - } - fn pending_obligations(&self) -> Vec>; fn relationships(&mut self) -> &mut FxHashMap; @@ -81,7 +63,7 @@ pub trait TraitEngineExt<'tcx> { ); } -impl> TraitEngineExt<'tcx> for T { +impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T { fn register_predicate_obligations( &mut self, infcx: &InferCtxt<'_, 'tcx>, diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index c1f302e665..1a5ffd9370 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -35,7 +35,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } -pub fn report_object_safety_error( +pub fn report_object_safety_error<'tcx>( tcx: TyCtxt<'tcx>, span: Span, trait_def_id: DefId, diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index e8622b3c81..e1f3b548e9 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -55,7 +55,7 @@ pub struct Obligation<'tcx, T> { pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>; pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>; -impl PredicateObligation<'tcx> { +impl<'tcx> PredicateObligation<'tcx> { /// Flips the polarity of the inner predicate. /// /// Given `T: Trait` predicate it returns `T: !Trait` and given `T: !Trait` returns `T: Trait`. @@ -69,9 +69,19 @@ impl PredicateObligation<'tcx> { } } +impl TraitObligation<'_> { + /// Returns `true` if the trait predicate is considered `const` in its ParamEnv. + pub fn is_const(&self) -> bool { + match (self.predicate.skip_binder().constness, self.param_env.constness()) { + (ty::BoundConstness::ConstIfConst, hir::Constness::Const) => true, + _ => false, + } + } +} + // `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(PredicateObligation<'_>, 32); +static_assert_size!(PredicateObligation<'_>, 48); pub type PredicateObligations<'tcx> = Vec>; diff --git a/compiler/rustc_infer/src/traits/project.rs b/compiler/rustc_infer/src/traits/project.rs index e2c13d20a9..96af16c668 100644 --- a/compiler/rustc_infer/src/traits/project.rs +++ b/compiler/rustc_infer/src/traits/project.rs @@ -10,7 +10,7 @@ use rustc_data_structures::{ }; use rustc_middle::ty::{self, Ty}; -pub use rustc_middle::traits::Reveal; +pub use rustc_middle::traits::{EvaluationResult, Reveal}; pub(crate) type UndoLog<'tcx> = snapshot_map::UndoLog, ProjectionCacheEntry<'tcx>>; @@ -80,7 +80,7 @@ pub struct ProjectionCacheKey<'tcx> { ty: ty::ProjectionTy<'tcx>, } -impl ProjectionCacheKey<'tcx> { +impl<'tcx> ProjectionCacheKey<'tcx> { pub fn new(ty: ty::ProjectionTy<'tcx>) -> Self { Self { ty } } @@ -92,7 +92,42 @@ pub enum ProjectionCacheEntry<'tcx> { Ambiguous, Recur, Error, - NormalizedTy(NormalizedTy<'tcx>), + NormalizedTy { + ty: NormalizedTy<'tcx>, + /// If we were able to successfully evaluate the + /// corresponding cache entry key during predicate + /// evaluation, then this field stores the final + /// result obtained from evaluating all of the projection + /// sub-obligations. During evaluation, we will skip + /// evaluating the cached sub-obligations in `ty` + /// if this field is set. Evaluation only + /// cares about the final result, so we don't + /// care about any region constraint side-effects + /// produced by evaluating the sub-boligations. + /// + /// Additionally, we will clear out the sub-obligations + /// entirely if we ever evaluate the cache entry (along + /// with all its sub obligations) to `EvaluatedToOk`. + /// This affects all users of the cache, not just evaluation. + /// Since a result of `EvaluatedToOk` means that there were + /// no region obligations that need to be tracked, it's + /// fine to forget about the sub-obligations - they + /// don't provide any additional information. However, + /// we do *not* discard any obligations when we see + /// `EvaluatedToOkModuloRegions` - we don't know + /// which sub-obligations may introduce region constraints, + /// so we keep them all to be safe. + /// + /// When we are not performing evaluation + /// (e.g. in `FulfillmentContext`), we ignore this field, + /// and always re-process the cached sub-obligations + /// (which may have been cleared out - see the above + /// paragraph). + /// This ensures that we do not lose any regions + /// constraints that arise from processing the + /// sub-obligations. + complete: Option, + }, } impl<'tcx> ProjectionCacheStorage<'tcx> { @@ -149,10 +184,41 @@ impl<'tcx> ProjectionCache<'_, 'tcx> { debug!("Not overwriting Recur"); return; } - let fresh_key = map.insert(key, ProjectionCacheEntry::NormalizedTy(value)); + let fresh_key = + map.insert(key, ProjectionCacheEntry::NormalizedTy { ty: value, complete: None }); assert!(!fresh_key, "never started projecting `{:?}`", key); } + /// Mark the relevant projection cache key as having its derived obligations + /// complete, so they won't have to be re-computed (this is OK to do in a + /// snapshot - if the snapshot is rolled back, the obligations will be + /// marked as incomplete again). + pub fn complete(&mut self, key: ProjectionCacheKey<'tcx>, result: EvaluationResult) { + let mut map = self.map(); + match map.get(&key) { + Some(&ProjectionCacheEntry::NormalizedTy { ref ty, complete: _ }) => { + info!("ProjectionCacheEntry::complete({:?}) - completing {:?}", key, ty); + let mut ty = ty.clone(); + if result == EvaluationResult::EvaluatedToOk { + ty.obligations = vec![]; + } + map.insert(key, ProjectionCacheEntry::NormalizedTy { ty, complete: Some(result) }); + } + ref value => { + // Type inference could "strand behind" old cache entries. Leave + // them alone for now. + info!("ProjectionCacheEntry::complete({:?}) - ignoring {:?}", key, value); + } + }; + } + + pub fn is_complete(&mut self, key: ProjectionCacheKey<'tcx>) -> Option { + self.map().get(&key).and_then(|res| match res { + ProjectionCacheEntry::NormalizedTy { ty: _, complete } => *complete, + _ => None, + }) + } + /// Indicates that trying to normalize `key` resulted in /// ambiguity. No point in trying it again then until we gain more /// type information (in which case, the "fully resolved" key will diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs index b48ca3bd0c..20453eeb14 100644 --- a/compiler/rustc_infer/src/traits/structural_impls.rs +++ b/compiler/rustc_infer/src/traits/structural_impls.rs @@ -1,7 +1,7 @@ use crate::traits; use crate::traits::project::Normalized; use rustc_middle::ty; -use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; +use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeVisitor}; use std::fmt; use std::ops::ControlFlow; @@ -60,13 +60,16 @@ impl<'tcx> fmt::Debug for traits::MismatchedProjectionTypes<'tcx> { // TypeFoldable implementations. impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx, O> { - fn super_fold_with>(self, folder: &mut F) -> Self { - traits::Obligation { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + Ok(traits::Obligation { cause: self.cause, recursion_depth: self.recursion_depth, - predicate: self.predicate.fold_with(folder), - param_env: self.param_env.fold_with(folder), - } + predicate: self.predicate.try_fold_with(folder)?, + param_env: self.param_env.try_fold_with(folder)?, + }) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 92f74af4eb..8f5d6c8509 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -3,7 +3,7 @@ use smallvec::smallvec; use crate::infer::outlives::components::{push_outlives_components, Component}; use crate::traits::{Obligation, ObligationCause, PredicateObligation}; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; -use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, TyCtxt}; use rustc_span::symbol::Ident; use rustc_span::Span; @@ -20,7 +20,7 @@ pub struct PredicateSet<'tcx> { set: FxHashSet>, } -impl PredicateSet<'tcx> { +impl<'tcx> PredicateSet<'tcx> { pub fn new(tcx: TyCtxt<'tcx>) -> Self { Self { tcx, set: Default::default() } } @@ -40,7 +40,7 @@ impl PredicateSet<'tcx> { } } -impl Extend> for PredicateSet<'tcx> { +impl<'tcx> Extend> for PredicateSet<'tcx> { fn extend>>(&mut self, iter: I) { for pred in iter { self.insert(pred); @@ -131,7 +131,7 @@ fn predicate_obligation<'tcx>( Obligation { cause, param_env, recursion_depth: 0, predicate } } -impl Elaborator<'tcx> { +impl<'tcx> Elaborator<'tcx> { pub fn filter_to_traits(self) -> FilterToTraits { FilterToTraits::new(self) } @@ -267,7 +267,7 @@ impl Elaborator<'tcx> { } } -impl Iterator for Elaborator<'tcx> { +impl<'tcx> Iterator for Elaborator<'tcx> { type Item = PredicateObligation<'tcx>; fn size_hint(&self) -> (usize, Option) { @@ -328,8 +328,8 @@ pub fn transitive_bounds_that_define_assoc_type<'tcx>( )); for (super_predicate, _) in super_predicates.predicates { let subst_predicate = super_predicate.subst_supertrait(tcx, &trait_ref); - if let Some(binder) = subst_predicate.to_opt_poly_trait_ref() { - stack.push(binder.value); + if let Some(binder) = subst_predicate.to_opt_poly_trait_pred() { + stack.push(binder.map_bound(|t| t.trait_ref)); } } @@ -362,8 +362,8 @@ impl<'tcx, I: Iterator>> Iterator for FilterToT fn next(&mut self) -> Option> { while let Some(obligation) = self.base_iterator.next() { - if let Some(data) = obligation.predicate.to_opt_poly_trait_ref() { - return Some(data.value); + if let Some(data) = obligation.predicate.to_opt_poly_trait_pred() { + return Some(data.map_bound(|t| t.trait_ref)); } } None diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index 07af2201f5..f5823e521b 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -8,6 +8,7 @@ doctest = false [dependencies] libc = "0.2" +libloading = "0.7.1" tracing = "0.1" rustc-rayon-core = "0.3.1" rayon = { version = "0.3.1", package = "rustc-rayon" } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 2904b3f5b7..3804e10030 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -11,7 +11,7 @@ use rustc_errors::registry::Registry; use rustc_errors::{ErrorReported, Handler}; use rustc_lint::LintStore; use rustc_middle::ty; -use rustc_parse::new_parser_from_source_str; +use rustc_parse::maybe_new_parser_from_source_str; use rustc_query_impl::QueryCtxt; use rustc_session::config::{self, ErrorOutputType, Input, OutputFilenames}; use rustc_session::early_error; @@ -91,7 +91,6 @@ pub fn parse_cfgspecs(cfgspecs: Vec) -> FxHashSet<(String, Option { @@ -102,26 +101,27 @@ pub fn parse_cfgspecs(cfgspecs: Vec) -> FxHashSet<(String, Option { - if meta_item.path.segments.len() != 1 { - error!("argument key must be an identifier"); - } - match &meta_item.kind { - MetaItemKind::List(..) => { - error!(r#"expected `key` or `key="value"`"#); + match maybe_new_parser_from_source_str(&sess, filename, s.to_string()) { + Ok(mut parser) => match &mut parser.parse_meta_item() { + Ok(meta_item) if parser.token == token::Eof => { + if meta_item.path.segments.len() != 1 { + error!("argument key must be an identifier"); } - MetaItemKind::NameValue(lit) if !lit.kind.is_str() => { - error!("argument value must be a string"); - } - MetaItemKind::NameValue(..) | MetaItemKind::Word => { - let ident = meta_item.ident().expect("multi-segment cfg key"); - return (ident.name, meta_item.value_str()); + match &meta_item.kind { + MetaItemKind::List(..) => {} + MetaItemKind::NameValue(lit) if !lit.kind.is_str() => { + error!("argument value must be a string"); + } + MetaItemKind::NameValue(..) | MetaItemKind::Word => { + let ident = meta_item.ident().expect("multi-segment cfg key"); + return (ident.name, meta_item.value_str()); + } } } - } - Ok(..) => {} - Err(err) => err.cancel(), + Ok(..) => {} + Err(err) => err.cancel(), + }, + Err(errs) => errs.into_iter().for_each(|mut err| err.cancel()), } error!(r#"expected `key` or `key="value"`"#); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index d3917dfb14..33bf670f57 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -3,14 +3,14 @@ use crate::proc_macro_decls; use crate::util; use rustc_ast::mut_visit::MutVisitor; -use rustc_ast::{self as ast, visit}; +use rustc_ast::{self as ast, visit, DUMMY_NODE_ID}; use rustc_borrowck as mir_borrowck; use rustc_codegen_ssa::back::link::emit_metadata; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::parallel; use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal}; use rustc_data_structures::temp_dir::MaybeTempDir; -use rustc_errors::{ErrorReported, PResult}; +use rustc_errors::{Applicability, ErrorReported, PResult}; use rustc_expand::base::ExtCtxt; use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE}; use rustc_hir::Crate; @@ -323,8 +323,8 @@ pub fn configure_and_expand( let crate_attrs = krate.attrs.clone(); let extern_mod_loaded = |ident: Ident, attrs, items, span| { - let krate = ast::Crate { attrs, items, span }; - pre_expansion_lint(sess, lint_store, &krate, &crate_attrs, &ident.name.as_str()); + let krate = ast::Crate { attrs, items, span, id: DUMMY_NODE_ID, is_placeholder: false }; + pre_expansion_lint(sess, lint_store, &krate, &crate_attrs, ident.name.as_str()); (krate.attrs, krate.items) }; let mut ecx = ExtCtxt::new(sess, cfg, resolver, Some(&extern_mod_loaded)); @@ -456,10 +456,26 @@ pub fn configure_and_expand( identifiers.sort_by_key(|&(key, _)| key); for (ident, mut spans) in identifiers.into_iter() { spans.sort(); - sess.diagnostic().span_err( - MultiSpan::from(spans), - &format!("identifiers cannot contain emoji: `{}`", ident), - ); + if ident == sym::ferris { + let first_span = spans[0]; + sess.diagnostic() + .struct_span_err( + MultiSpan::from(spans), + "Ferris cannot be used as an identifier", + ) + .span_suggestion( + first_span, + "try using their name instead", + "ferris".to_string(), + Applicability::MaybeIncorrect, + ) + .emit(); + } else { + sess.diagnostic().span_err( + MultiSpan::from(spans), + &format!("identifiers cannot contain emoji: `{}`", ident), + ); + } } }); @@ -568,7 +584,7 @@ fn output_conflicts_with_dir(output_paths: &[PathBuf]) -> Option { fn escape_dep_filename(filename: &str) -> String { // Apparently clang and gcc *only* escape spaces: // https://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4 - filename.replace(" ", "\\ ") + filename.replace(' ', "\\ ") } // Makefile comments only need escaping newlines and `\`. @@ -615,7 +631,7 @@ fn write_out_deps( // (e.g. accessed in proc macros). let file_depinfo = sess.parse_sess.file_depinfo.borrow(); let extra_tracked_files = file_depinfo.iter().map(|path_sym| { - let path = PathBuf::from(&*path_sym.as_str()); + let path = PathBuf::from(path_sym.as_str()); let file = FileName::from(path); escape_dep_filename(&file.prefer_local().to_string()) }); @@ -1033,8 +1049,8 @@ fn encode_and_write_metadata( let need_metadata_file = tcx.sess.opts.output_types.contains_key(&OutputType::Metadata); if need_metadata_file { - let crate_name = &tcx.crate_name(LOCAL_CRATE).as_str(); - let out_filename = filename_for_metadata(tcx.sess, crate_name, outputs); + let crate_name = tcx.crate_name(LOCAL_CRATE); + let out_filename = filename_for_metadata(tcx.sess, crate_name.as_str(), outputs); // To avoid races with another rustc process scanning the output directory, // we need to write the file somewhere else and atomically move it to its // final destination, with an `fs::rename` call. In order for the rename to diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index f188ad3560..e635ee1e0e 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -335,8 +335,11 @@ pub struct Linker { impl Linker { pub fn link(self) -> Result<()> { - let (codegen_results, work_products) = - self.codegen_backend.join_codegen(self.ongoing_codegen, &self.sess)?; + let (codegen_results, work_products) = self.codegen_backend.join_codegen( + self.ongoing_codegen, + &self.sess, + &self.prepare_outputs, + )?; self.sess.compile_status()?; diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 6147311af6..30e319c475 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -593,6 +593,7 @@ fn test_codegen_options_tracking_hash() { tracked!(relocation_model, Some(RelocModel::Pic)); tracked!(soft_float, true); tracked!(split_debuginfo, Some(SplitDebuginfo::Packed)); + tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0)); tracked!(target_cpu, Some(String::from("abc"))); tracked!(target_feature, String::from("all the features, all of them")); } @@ -651,7 +652,6 @@ fn test_debugging_options_tracking_hash() { untracked!(dump_mir_dir, String::from("abc")); untracked!(dump_mir_exclude_pass_number, true); untracked!(dump_mir_graphviz, true); - untracked!(emit_future_incompat_report, true); untracked!(emit_stack_sizes, true); untracked!(future_incompat_test, true); untracked!(hir_stats, true); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 04e183a9ba..cb51555f5c 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -1,3 +1,4 @@ +use libloading::Library; use rustc_ast::mut_visit::{visit_clobber, MutVisitor, *}; use rustc_ast::ptr::P; use rustc_ast::{self as ast, AttrVec, BlockCheckMode}; @@ -7,7 +8,6 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::jobserver; use rustc_data_structures::sync::Lrc; use rustc_errors::registry::Registry; -use rustc_metadata::dynamic_lib::DynamicLibrary; #[cfg(parallel_compiler)] use rustc_middle::ty::tls; use rustc_parse::validate_attr; @@ -39,6 +39,9 @@ use std::sync::{Arc, Mutex}; use std::thread; use tracing::info; +/// Function pointer type that constructs a new CodegenBackend. +pub type MakeBackendFn = fn() -> Box; + /// Adds `target_feature = "..."` cfgs for a variety of platform /// specific features (SSE, NEON etc.). /// @@ -211,28 +214,24 @@ pub fn setup_callbacks_and_run_in_thread_pool_with_globals R + Se }) } -fn load_backend_from_dylib(path: &Path) -> fn() -> Box { - let lib = DynamicLibrary::open(path).unwrap_or_else(|err| { - let err = format!("couldn't load codegen backend {:?}: {:?}", path, err); +fn load_backend_from_dylib(path: &Path) -> MakeBackendFn { + let lib = unsafe { Library::new(path) }.unwrap_or_else(|err| { + let err = format!("couldn't load codegen backend {:?}: {}", path, err); early_error(ErrorOutputType::default(), &err); }); - unsafe { - match lib.symbol("__rustc_codegen_backend") { - Ok(f) => { - mem::forget(lib); - mem::transmute::<*mut u8, _>(f) - } - Err(e) => { - let err = format!( - "couldn't load codegen backend as it \ - doesn't export the `__rustc_codegen_backend` \ - symbol: {:?}", - e - ); - early_error(ErrorOutputType::default(), &err); - } - } - } + + let backend_sym = unsafe { lib.get::(b"__rustc_codegen_backend") } + .unwrap_or_else(|e| { + let err = format!("couldn't load codegen backend: {}", e); + early_error(ErrorOutputType::default(), &err); + }); + + // Intentionally leak the dynamic library. We can't ever unload it + // since the library can make things that will live arbitrarily long. + let backend_sym = unsafe { backend_sym.into_raw() }; + mem::forget(lib); + + *backend_sym } /// Get the codegen backend based on the name and specified sysroot. @@ -380,10 +379,7 @@ fn sysroot_candidates() -> Vec { } } -pub fn get_codegen_sysroot( - maybe_sysroot: &Option, - backend_name: &str, -) -> fn() -> Box { +pub fn get_codegen_sysroot(maybe_sysroot: &Option, backend_name: &str) -> MakeBackendFn { // For now we only allow this function to be called once as it'll dlopen a // few things, which seems to work best if we only do that once. In // general this assertion never trips due to the once guard in `get_codegen_backend`, @@ -488,7 +484,7 @@ pub(crate) fn check_attr_crate_type( return; } - if let ast::MetaItemKind::NameValue(spanned) = a.meta().unwrap().kind { + if let ast::MetaItemKind::NameValue(spanned) = a.meta_kind().unwrap() { let span = spanned.span; let lev_candidate = find_best_match_for_name( &CRATE_TYPES.iter().map(|(k, _)| *k).collect::>(), diff --git a/compiler/rustc_lexer/src/cursor.rs b/compiler/rustc_lexer/src/cursor.rs index 297f3d19ca..0ba6c56dbb 100644 --- a/compiler/rustc_lexer/src/cursor.rs +++ b/compiler/rustc_lexer/src/cursor.rs @@ -2,10 +2,11 @@ use std::str::Chars; /// Peekable iterator over a char sequence. /// -/// Next characters can be peeked via `nth_char` method, +/// Next characters can be peeked via `first` method, /// and position can be shifted forward via `bump` method. pub(crate) struct Cursor<'a> { initial_len: usize, + /// Iterator over chars. Slightly faster than a &str. chars: Chars<'a>, #[cfg(debug_assertions)] prev: char, @@ -37,22 +38,21 @@ impl<'a> Cursor<'a> { } } - /// Returns nth character relative to the current cursor position. + /// Peeks the next symbol from the input stream without consuming it. /// If requested position doesn't exist, `EOF_CHAR` is returned. /// However, getting `EOF_CHAR` doesn't always mean actual end of file, /// it should be checked with `is_eof` method. - fn nth_char(&self, n: usize) -> char { - self.chars().nth(n).unwrap_or(EOF_CHAR) - } - - /// Peeks the next symbol from the input stream without consuming it. pub(crate) fn first(&self) -> char { - self.nth_char(0) + // `.next()` optimizes better than `.nth(0)` + self.chars.clone().next().unwrap_or(EOF_CHAR) } /// Peeks the second symbol from the input stream without consuming it. pub(crate) fn second(&self) -> char { - self.nth_char(1) + // `.next()` optimizes better than `.nth(1)` + let mut iter = self.chars.clone(); + iter.next(); + iter.next().unwrap_or(EOF_CHAR) } /// Checks if there is nothing more to consume. @@ -65,9 +65,9 @@ impl<'a> Cursor<'a> { self.initial_len - self.chars.as_str().len() } - /// Returns a `Chars` iterator over the remaining characters. - fn chars(&self) -> Chars<'a> { - self.chars.clone() + /// Resets the number of bytes consumed to 0. + pub(crate) fn reset_len_consumed(&mut self) { + self.initial_len = self.chars.as_str().len(); } /// Moves to the next character. @@ -81,4 +81,13 @@ impl<'a> Cursor<'a> { Some(c) } + + /// Eats symbols while predicate returns true or until the end of file is reached. + pub(crate) fn eat_while(&mut self, mut predicate: impl FnMut(char) -> bool) { + // It was tried making optimized version of this for eg. line comments, but + // LLVM can inline all of this and compile it down to fast iteration over bytes. + while predicate(self.first()) && !self.is_eof() { + self.bump(); + } + } } diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 44b002fa93..5b8300ab53 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -227,14 +227,15 @@ pub fn first_token(input: &str) -> Token { } /// Creates an iterator that produces tokens from the input string. -pub fn tokenize(mut input: &str) -> impl Iterator + '_ { +pub fn tokenize(input: &str) -> impl Iterator + '_ { + let mut cursor = Cursor::new(input); std::iter::from_fn(move || { - if input.is_empty() { - return None; + if cursor.is_eof() { + None + } else { + cursor.reset_len_consumed(); + Some(cursor.advance_token()) } - let token = first_token(input); - input = &input[token.len..]; - Some(token) }) } @@ -832,11 +833,4 @@ impl Cursor<'_> { self.eat_while(is_id_continue); } - - /// Eats symbols while predicate returns true or until the end of file is reached. - fn eat_while(&mut self, mut predicate: impl FnMut(char) -> bool) { - while predicate(self.first()) && !self.is_eof() { - self.bump(); - } - } } diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs index d8883b0e66..b615175758 100644 --- a/compiler/rustc_lint/src/array_into_iter.rs +++ b/compiler/rustc_lint/src/array_into_iter.rs @@ -52,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter { if let hir::ExprKind::Call(path, [arg]) = &arg.kind { if let hir::ExprKind::Path(hir::QPath::LangItem( hir::LangItem::IntoIterIntoIter, - _, + .., )) = &path.kind { self.for_expr_span = arg.span; @@ -79,9 +79,8 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter { let receiver_ty = cx.typeck_results().expr_ty(receiver_arg); let adjustments = cx.typeck_results().expr_adjustments(receiver_arg); - let target = match adjustments.last() { - Some(Adjustment { kind: Adjust::Borrow(_), target }) => target, - _ => return, + let Some(Adjustment { kind: Adjust::Borrow(_), target }) = adjustments.last() else { + return }; let types = diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index f2e4e70a19..1fd6379b6e 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -609,14 +609,12 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { // If the trait is private, add the impl items to `private_traits` so they don't get // reported for missing docs. let real_trait = trait_ref.path.res.def_id(); - if let Some(def_id) = real_trait.as_local() { - let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id); - if let Some(Node::Item(item)) = cx.tcx.hir().find(hir_id) { - if let hir::VisibilityKind::Inherited = item.vis.node { - for impl_item_ref in items { - self.private_traits.insert(impl_item_ref.id.hir_id()); - } - } + let Some(def_id) = real_trait.as_local() else { return }; + let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id); + let Some(Node::Item(item)) = cx.tcx.hir().find(hir_id) else { return }; + if let hir::VisibilityKind::Inherited = item.vis.node { + for impl_item_ref in items { + self.private_traits.insert(impl_item_ref.id.hir_id()); } } return; @@ -829,9 +827,8 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations { _ => return, } - let debug = match cx.tcx.get_diagnostic_item(sym::Debug) { - Some(debug) => debug, - None => return, + let Some(debug) = cx.tcx.get_diagnostic_item(sym::Debug) else { + return }; if self.impling_types.is_none() { @@ -1079,6 +1076,10 @@ impl EarlyLintPass for UnusedDocComment { fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { warn_if_doc(cx, expr.span, "expressions", &expr.attrs); } + + fn check_generic_param(&mut self, cx: &EarlyContext<'_>, param: &ast::GenericParam) { + warn_if_doc(cx, param.ident.span, "generic parameters", ¶m.attrs); + } } declare_lint! { @@ -1505,9 +1506,8 @@ impl TypeAliasBounds { impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { - let (ty, type_alias_generics) = match item.kind { - hir::ItemKind::TyAlias(ref ty, ref generics) => (&*ty, generics), - _ => return, + let hir::ItemKind::TyAlias(ty, type_alias_generics) = &item.kind else { + return }; if let hir::TyKind::OpaqueDef(..) = ty.kind { // Bounds are respected for `type X = impl Trait` @@ -2262,16 +2262,15 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { // and should check for them here. match predicate.bounded_ty.kind { hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => { - if let Res::Def(DefKind::TyParam, def_id) = path.res { - let index = ty_generics.param_def_id_to_index[&def_id]; - ( - Self::lifetimes_outliving_type(inferred_outlives, index), - &predicate.bounds, - predicate.span, - ) - } else { - continue; - } + let Res::Def(DefKind::TyParam, def_id) = path.res else { + continue + }; + let index = ty_generics.param_def_id_to_index[&def_id]; + ( + Self::lifetimes_outliving_type(inferred_outlives, index), + &predicate.bounds, + predicate.span, + ) } _ => { continue; @@ -3011,7 +3010,7 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations { this_decl_ty, CItemKind::Declaration, ) { - let orig_fi = tcx.hir().expect_foreign_item(existing_hid); + let orig_fi = tcx.hir().expect_foreign_item(existing_hid.expect_owner()); let orig = Self::name_of_extern_decl(tcx, orig_fi); // We want to ensure that we use spans for both decls that include where the @@ -3148,7 +3147,8 @@ declare_lint! { /// ### Example /// /// ```rust,compile_fail - /// #![feature(asm)] + /// use std::arch::asm; + /// /// fn main() { /// unsafe { /// asm!("foo: bar"); @@ -3165,10 +3165,10 @@ declare_lint! { /// of this, GNU assembler [local labels] *must* be used instead of labels /// with a name. Using named labels might cause assembler or linker errors. /// - /// See the [unstable book] for more details. + /// See the explanation in [Rust By Example] for more details. /// /// [local labels]: https://sourceware.org/binutils/docs/as/Symbol-Names.html#Local-Labels - /// [unstable book]: https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels + /// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels pub NAMED_ASM_LABELS, Deny, "named labels in inline assembly", @@ -3184,7 +3184,7 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels { } = expr { for (template_sym, template_snippet, template_span) in template_strs.iter() { - let template_str = &template_sym.as_str(); + let template_str = template_sym.as_str(); let find_label_span = |needle: &str| -> Option { if let Some(template_snippet) = template_snippet { let snippet = template_snippet.as_str(); @@ -3212,18 +3212,17 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels { for (idx, _) in statement.match_indices(':') { let possible_label = statement[start_idx..idx].trim(); let mut chars = possible_label.chars(); - if let Some(c) = chars.next() { - // A label starts with an alphabetic character or . or _ and continues with alphanumeric characters, _, or $ - if (c.is_alphabetic() || matches!(c, '.' | '_')) - && chars.all(|c| c.is_alphanumeric() || matches!(c, '_' | '$')) - { - found_labels.push(possible_label); - } else { - // If we encounter a non-label, there cannot be any further labels, so stop checking - break; - } - } else { + let Some(c) = chars.next() else { // Empty string means a leading ':' in this section, which is not a label + break + }; + // A label starts with an alphabetic character or . or _ and continues with alphanumeric characters, _, or $ + if (c.is_alphabetic() || matches!(c, '.' | '_')) + && chars.all(|c| c.is_alphanumeric() || matches!(c, '_' | '$')) + { + found_labels.push(possible_label); + } else { + // If we encounter a non-label, there cannot be any further labels, so stop checking break; } diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 4c936dec6f..d93866443a 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -22,9 +22,7 @@ use ast::util::unicode::TEXT_FLOW_CONTROL_CHARS; use rustc_ast as ast; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync; -use rustc_errors::{ - add_elided_lifetime_in_path_suggestion, struct_span_err, Applicability, SuggestionStyle, -}; +use rustc_errors::{struct_span_err, Applicability, SuggestionStyle}; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def_id::{CrateNum, DefId}; @@ -383,10 +381,10 @@ impl LintStore { lint_name, self.lint_groups.keys().collect::>() ); - let lint_name_str = &*lint_name.as_str(); - self.lint_groups.contains_key(&lint_name_str) || { + let lint_name_str = lint_name.as_str(); + self.lint_groups.contains_key(lint_name_str) || { let warnings_name_str = crate::WARNINGS.name_lower(); - lint_name_str == &*warnings_name_str + lint_name_str == warnings_name_str } } @@ -635,16 +633,6 @@ pub trait LintContext: Sized { } }, BuiltinLintDiagnostics::Normal => (), - BuiltinLintDiagnostics::BareTraitObject(span, is_global) => { - let (sugg, app) = match sess.source_map().span_to_snippet(span) { - Ok(s) if is_global => { - (format!("dyn ({})", s), Applicability::MachineApplicable) - } - Ok(s) => (format!("dyn {}", s), Applicability::MachineApplicable), - Err(_) => ("dyn ".to_string(), Applicability::HasPlaceholders), - }; - db.span_suggestion(span, "use `dyn`", sugg, app); - } BuiltinLintDiagnostics::AbsPathWithModule(span) => { let (sugg, app) = match sess.source_map().span_to_snippet(span) { Ok(ref s) => { @@ -670,27 +658,10 @@ pub trait LintContext: Sized { ) => { db.span_note(span_def, "the macro is defined here"); } - BuiltinLintDiagnostics::ElidedLifetimesInPaths( - n, - path_span, - incl_angl_brckt, - insertion_span, - anon_lts, - ) => { - add_elided_lifetime_in_path_suggestion( - sess.source_map(), - &mut db, - n, - path_span, - incl_angl_brckt, - insertion_span, - anon_lts, - ); - } BuiltinLintDiagnostics::UnknownCrateTypes(span, note, sugg) => { db.span_suggestion(span, ¬e, sugg, Applicability::MaybeIncorrect); } - BuiltinLintDiagnostics::UnusedImports(message, replaces) => { + BuiltinLintDiagnostics::UnusedImports(message, replaces, in_test_module) => { if !replaces.is_empty() { db.tool_only_multipart_suggestion( &message, @@ -698,6 +669,14 @@ pub trait LintContext: Sized { Applicability::MachineApplicable, ); } + + if let Some(span) = in_test_module { + let def_span = self.sess().source_map().guess_head_span(span); + db.span_help( + span.shrink_to_lo().to(def_span), + "consider adding a `#[cfg(test)]` to the containing module", + ); + } } BuiltinLintDiagnostics::RedundantImport(spans, ident) => { for (span, is_imported) in spans { @@ -791,7 +770,7 @@ pub trait LintContext: Sized { } BuiltinLintDiagnostics::NamedAsmLabel(help) => { db.help(&help); - db.note("see the asm section of the unstable book for more information"); + db.note("see the asm section of Rust By Example for more information"); } } // Rewrap `db`, and pass control to the user. @@ -1060,8 +1039,8 @@ impl<'tcx> LateContext<'tcx> { ) -> Result { let mut path = print_prefix(self)?; - // Skip `::{{constructor}}` on tuple/unit structs. - if let DefPathData::Ctor = disambiguated_data.data { + // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs. + if let DefPathData::ForeignMod | DefPathData::Ctor = disambiguated_data.data { return Ok(path); } diff --git a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs index 876245747f..65772d0237 100644 --- a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs +++ b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs @@ -91,16 +91,14 @@ fn enforce_mem_variant_count(cx: &LateContext<'_>, func_expr: &hir::Expr<'_>, sp impl<'tcx> LateLintPass<'tcx> for EnumIntrinsicsNonEnums { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) { - if let hir::ExprKind::Call(ref func, ref args) = expr.kind { - if let hir::ExprKind::Path(ref qpath) = func.kind { - if let Some(def_id) = cx.qpath_res(qpath, func.hir_id).opt_def_id() { - if cx.tcx.is_diagnostic_item(sym::mem_discriminant, def_id) { - enforce_mem_discriminant(cx, func, expr.span, args[0].span); - } else if cx.tcx.is_diagnostic_item(sym::mem_variant_count, def_id) { - enforce_mem_variant_count(cx, func, expr.span); - } - } - } + let hir::ExprKind::Call(func, args) = &expr.kind else { return }; + let hir::ExprKind::Path(qpath) = &func.kind else { return }; + let Some(def_id) = cx.qpath_res(qpath, func.hir_id).opt_def_id() else { return }; + let Some(name) = cx.tcx.get_diagnostic_name(def_id) else { return }; + match name { + sym::mem_discriminant => enforce_mem_discriminant(cx, func, expr.span, args[0].span), + sym::mem_variant_count => enforce_mem_variant_count(cx, func, expr.span), + _ => {} } } } diff --git a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs index fde84be9a7..fc99d759a0 100644 --- a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs +++ b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs @@ -127,7 +127,7 @@ impl HiddenUnicodeCodepoints { impl EarlyLintPass for HiddenUnicodeCodepoints { fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) { if let ast::AttrKind::DocComment(_, comment) = attr.kind { - if contains_text_flow_control_chars(&comment.as_str()) { + if contains_text_flow_control_chars(comment.as_str()) { self.lint_text_direction_codepoint(cx, comment, attr.span, 0, false, "doc comment"); } } @@ -138,7 +138,7 @@ impl EarlyLintPass for HiddenUnicodeCodepoints { let (text, span, padding) = match &expr.kind { ast::ExprKind::Lit(ast::Lit { token, kind, span }) => { let text = token.symbol; - if !contains_text_flow_control_chars(&text.as_str()) { + if !contains_text_flow_control_chars(text.as_str()) { return; } let padding = match kind { diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index b6d66eb12d..d3fa08650d 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -154,7 +154,7 @@ impl<'s> LintLevelsBuilder<'s> { LintLevelSource::Node(_, forbid_source_span, reason) => { diag_builder.span_label(forbid_source_span, "`forbid` level set here"); if let Some(rationale) = reason { - diag_builder.note(&rationale.as_str()); + diag_builder.note(rationale.as_str()); } } LintLevelSource::CommandLine(_, _) => { @@ -227,14 +227,12 @@ impl<'s> LintLevelsBuilder<'s> { let sess = self.sess; let bad_attr = |span| struct_span_err!(sess, span, E0452, "malformed lint attribute input"); for attr in attrs { - let level = match Level::from_symbol(attr.name_or_empty()) { - None => continue, - Some(lvl) => lvl, + let Some(level) = Level::from_symbol(attr.name_or_empty()) else { + continue }; - let mut metas = match attr.meta_item_list() { - Some(x) => x, - None => continue, + let Some(mut metas) = attr.meta_item_list() else { + continue }; if metas.is_empty() { @@ -481,9 +479,8 @@ impl<'s> LintLevelsBuilder<'s> { continue; } - let (lint_attr_name, lint_attr_span) = match *src { - LintLevelSource::Node(name, span, _) => (name, span), - _ => continue, + let LintLevelSource::Node(lint_attr_name, lint_attr_span, _) = *src else { + continue }; let lint = builtin::UNUSED_ATTRIBUTES; diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 507b4421fa..c7823032b0 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -30,9 +30,8 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(crate_visibility_modifier)] -#![cfg_attr(bootstrap, feature(format_args_capture))] #![feature(iter_order_by)] -#![feature(iter_zip)] +#![feature(let_else)] #![feature(never_type)] #![feature(nll)] #![feature(control_flow_enum)] diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs index 9b4ee148df..a570206f1e 100644 --- a/compiler/rustc_lint/src/non_ascii_idents.rs +++ b/compiler/rustc_lint/src/non_ascii_idents.rs @@ -218,8 +218,7 @@ impl EarlyLintPass for NonAsciiIdents { cx.struct_span_lint(CONFUSABLE_IDENTS, sp, |lint| { lint.build(&format!( "identifier pair considered confusable between `{}` and `{}`", - existing_symbol.as_str(), - symbol.as_str() + existing_symbol, symbol )) .span_label( *existing_span, diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index f2ad72f97e..f2fee67115 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -9,7 +9,7 @@ use rustc_middle::ty::subst::InternalSubsts; use rustc_parse_format::{ParseMode, Parser, Piece}; use rustc_session::lint::FutureIncompatibilityReason; use rustc_span::edition::Edition; -use rustc_span::{hygiene, sym, symbol::kw, symbol::SymbolStr, InnerSpan, Span, Symbol}; +use rustc_span::{hygiene, sym, symbol::kw, InnerSpan, Span, Symbol}; use rustc_trait_selection::infer::InferCtxtExt; declare_lint! { @@ -49,9 +49,11 @@ impl<'tcx> LateLintPass<'tcx> for NonPanicFmt { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { if let hir::ExprKind::Call(f, [arg]) = &expr.kind { if let &ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(f).kind() { + let f_diagnostic_name = cx.tcx.get_diagnostic_name(def_id); + if Some(def_id) == cx.tcx.lang_items().begin_panic_fn() || Some(def_id) == cx.tcx.lang_items().panic_fn() - || Some(def_id) == cx.tcx.lang_items().panic_str() + || f_diagnostic_name == Some(sym::panic_str) { if let Some(id) = f.span.ctxt().outer_expn_data().macro_def_id { if matches!( @@ -61,6 +63,22 @@ impl<'tcx> LateLintPass<'tcx> for NonPanicFmt { check_panic(cx, f, arg); } } + } else if f_diagnostic_name == Some(sym::unreachable_display) { + if let Some(id) = f.span.ctxt().outer_expn_data().macro_def_id { + if cx.tcx.is_diagnostic_item(sym::unreachable_2015_macro, id) { + check_panic( + cx, + f, + // This is safe because we checked above that the callee is indeed + // unreachable_display + match &arg.kind { + // Get the borrowed arg not the borrow + hir::ExprKind::AddrOf(ast::BorrowKind::Ref, _, arg) => arg, + _ => bug!("call to unreachable_display without borrow"), + }, + ); + } + } } } } @@ -71,22 +89,22 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc if let hir::ExprKind::Lit(lit) = &arg.kind { if let ast::LitKind::Str(sym, _) = lit.node { // The argument is a string literal. - check_panic_str(cx, f, arg, &sym.as_str()); + check_panic_str(cx, f, arg, sym.as_str()); return; } } // The argument is *not* a string literal. - let (span, panic, symbol_str) = panic_call(cx, f); + let (span, panic, symbol) = panic_call(cx, f); if in_external_macro(cx.sess(), span) { // Nothing that can be done about it in the current crate. return; } - // Find the span of the argument to `panic!()`, before expansion in the - // case of `panic!(some_macro!())`. + // Find the span of the argument to `panic!()` or `unreachable!`, before expansion in the + // case of `panic!(some_macro!())` or `unreachable!(some_macro!())`. // We don't use source_callsite(), because this `panic!(..)` might itself // be expanded from another macro, in which case we want to stop at that // expansion. @@ -103,7 +121,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc cx.struct_span_lint(NON_FMT_PANICS, arg_span, |lint| { let mut l = lint.build("panic message is not a string literal"); - l.note(&format!("this usage of {}!() is deprecated; it will be a hard error in Rust 2021", symbol_str)); + l.note(&format!("this usage of {}!() is deprecated; it will be a hard error in Rust 2021", symbol)); l.note("for more information, see "); if !is_arg_inside_call(arg_span, span) { // No clue where this argument is coming from. @@ -112,7 +130,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc } if arg_macro.map_or(false, |id| cx.tcx.is_diagnostic_item(sym::format_macro, id)) { // A case of `panic!(format!(..))`. - l.note(format!("the {}!() macro supports formatting, so there's no need for the format!() macro here", symbol_str).as_str()); + l.note(format!("the {}!() macro supports formatting, so there's no need for the format!() macro here", symbol).as_str()); if let Some((open, close, _)) = find_delimiters(cx, arg_span) { l.multipart_suggestion( "remove the `format!(..)` macro call", @@ -207,7 +225,7 @@ fn check_panic_str<'tcx>( arg: &'tcx hir::Expr<'tcx>, fmt: &str, ) { - if !fmt.contains(&['{', '}'][..]) { + if !fmt.contains(&['{', '}']) { // No brace, no problem. return; } @@ -301,7 +319,7 @@ fn find_delimiters<'tcx>(cx: &LateContext<'tcx>, span: Span) -> Option<(Span, Sp )) } -fn panic_call<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>) -> (Span, Symbol, SymbolStr) { +fn panic_call<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>) -> (Span, Symbol, Symbol) { let mut expn = f.span.ctxt().outer_expn_data(); let mut panic_macro = kw::Empty; @@ -309,19 +327,27 @@ fn panic_call<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>) -> (Span, // Unwrap more levels of macro expansion, as panic_2015!() // was likely expanded from panic!() and possibly from // [debug_]assert!(). - for &i in - &[sym::std_panic_macro, sym::core_panic_macro, sym::assert_macro, sym::debug_assert_macro] - { + loop { let parent = expn.call_site.ctxt().outer_expn_data(); - if parent.macro_def_id.map_or(false, |id| cx.tcx.is_diagnostic_item(i, id)) { - expn = parent; - panic_macro = i; + let Some(id) = parent.macro_def_id else { break }; + let Some(name) = cx.tcx.get_diagnostic_name(id) else { break }; + if !matches!( + name, + sym::core_panic_macro + | sym::std_panic_macro + | sym::assert_macro + | sym::debug_assert_macro + | sym::unreachable_macro + ) { + break; } + expn = parent; + panic_macro = name; } let macro_symbol = if let hygiene::ExpnKind::Macro(_, symbol) = expn.kind { symbol } else { sym::panic }; - (expn.call_site, panic_macro, macro_symbol.as_str()) + (expn.call_site, panic_macro, macro_symbol) } fn is_arg_inside_call(arg: Span, call: Span) -> bool { diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index bcddc4f3d7..be7756b0f2 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -133,7 +133,7 @@ fn to_camel_case(s: &str) -> String { impl NonCamelCaseTypes { fn check_case(&self, cx: &EarlyContext<'_>, sort: &str, ident: &Ident) { - let name = &ident.name.as_str(); + let name = ident.name.as_str(); if !is_camel_case(name) { cx.struct_span_lint(NON_CAMEL_CASE_TYPES, ident.span, |lint| { @@ -276,7 +276,7 @@ impl NonSnakeCase { }) } - let name = &ident.name.as_str(); + let name = ident.name.as_str(); if !is_snake_case(name) { cx.struct_span_lint(NON_SNAKE_CASE, ident.span, |lint| { @@ -484,7 +484,7 @@ declare_lint_pass!(NonUpperCaseGlobals => [NON_UPPER_CASE_GLOBALS]); impl NonUpperCaseGlobals { fn check_upper_case(cx: &LateContext<'_>, sort: &str, ident: &Ident) { - let name = &ident.name.as_str(); + let name = ident.name.as_str(); if name.chars().any(|c| c.is_lowercase()) { cx.struct_span_lint(NON_UPPER_CASE_GLOBALS, ident.span, |lint| { let uc = NonSnakeCase::to_snake_case(&name).to_uppercase(); diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs index d2c970468a..600504f7c1 100644 --- a/compiler/rustc_lint/src/noop_method_call.rs +++ b/compiler/rustc_lint/src/noop_method_call.rs @@ -40,9 +40,8 @@ declare_lint_pass!(NoopMethodCall => [NOOP_METHOD_CALL]); impl<'tcx> LateLintPass<'tcx> for NoopMethodCall { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { // We only care about method calls. - let (call, elements) = match expr.kind { - ExprKind::MethodCall(call, _, elements, _) => (call, elements), - _ => return, + let ExprKind::MethodCall(call, _, elements, _) = &expr.kind else { + return }; // We only care about method calls corresponding to the `Clone`, `Deref` and `Borrow` // traits and ignore any other method call. @@ -70,43 +69,40 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall { } let param_env = cx.tcx.param_env(trait_id); // Resolve the trait method instance. - let i = match ty::Instance::resolve(cx.tcx, param_env, did, substs) { - Ok(Some(i)) => i, - _ => return, + let Ok(Some(i)) = ty::Instance::resolve(cx.tcx, param_env, did, substs) else { + return }; // (Re)check that it implements the noop diagnostic. - for s in [sym::noop_method_clone, sym::noop_method_deref, sym::noop_method_borrow].iter() { - if cx.tcx.is_diagnostic_item(*s, i.def_id()) { - let method = &call.ident.name; - let receiver = &elements[0]; - let receiver_ty = cx.typeck_results().expr_ty(receiver); - let expr_ty = cx.typeck_results().expr_ty_adjusted(expr); - if receiver_ty != expr_ty { - // This lint will only trigger if the receiver type and resulting expression \ - // type are the same, implying that the method call is unnecessary. - return; - } - let expr_span = expr.span; - let note = format!( - "the type `{:?}` which `{}` is being called on is the same as \ - the type returned from `{}`, so the method call does not do \ - anything and can be removed", - receiver_ty, method, method, - ); - - let span = expr_span.with_lo(receiver.span.hi()); - cx.struct_span_lint(NOOP_METHOD_CALL, span, |lint| { - let method = &call.ident.name; - let message = format!( - "call to `.{}()` on a reference in this situation does nothing", - &method, - ); - lint.build(&message) - .span_label(span, "unnecessary method call") - .note(¬e) - .emit() - }); - } + let Some(name) = cx.tcx.get_diagnostic_name(i.def_id()) else { return }; + if !matches!( + name, + sym::noop_method_borrow | sym::noop_method_clone | sym::noop_method_deref + ) { + return; } + let method = &call.ident.name; + let receiver = &elements[0]; + let receiver_ty = cx.typeck_results().expr_ty(receiver); + let expr_ty = cx.typeck_results().expr_ty_adjusted(expr); + if receiver_ty != expr_ty { + // This lint will only trigger if the receiver type and resulting expression \ + // type are the same, implying that the method call is unnecessary. + return; + } + let expr_span = expr.span; + let note = format!( + "the type `{:?}` which `{}` is being called on is the same as \ + the type returned from `{}`, so the method call does not do \ + anything and can be removed", + receiver_ty, method, method, + ); + + let span = expr_span.with_lo(receiver.span.hi()); + cx.struct_span_lint(NOOP_METHOD_CALL, span, |lint| { + let method = &call.ident.name; + let message = + format!("call to `.{}()` on a reference in this situation does nothing", &method,); + lint.build(&message).span_label(span, "unnecessary method call").note(¬e).emit() + }); } } diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs index 5435ff1396..dafff640b3 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -91,9 +91,8 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { let predicates = cx.tcx.explicit_predicates_of(item.def_id); for &(predicate, span) in predicates.predicates { - let trait_predicate = match predicate.kind().skip_binder() { - Trait(trait_predicate) => trait_predicate, - _ => continue, + let Trait(trait_predicate) = predicate.kind().skip_binder() else { + continue }; if trait_predicate.constness == ty::BoundConstness::ConstIfConst { // `~const Drop` definitely have meanings so avoid linting here. @@ -106,9 +105,8 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { continue; } cx.struct_span_lint(DROP_BOUNDS, span, |lint| { - let needs_drop = match cx.tcx.get_diagnostic_item(sym::needs_drop) { - Some(needs_drop) => needs_drop, - None => return, + let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { + return }; let msg = format!( "bounds on `{}` are most likely incorrect, consider instead \ @@ -123,17 +121,15 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { } fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) { - let bounds = match &ty.kind { - hir::TyKind::TraitObject(bounds, _lifetime, _syntax) => bounds, - _ => return, + let hir::TyKind::TraitObject(bounds, _lifetime, _syntax) = &ty.kind else { + return }; for bound in &bounds[..] { let def_id = bound.trait_ref.trait_def_id(); if cx.tcx.lang_items().drop_trait() == def_id { cx.struct_span_lint(DYN_DROP, bound.span, |lint| { - let needs_drop = match cx.tcx.get_diagnostic_item(sym::needs_drop) { - Some(needs_drop) => needs_drop, - None => return, + let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { + return }; let msg = format!( "types that do not implement `Drop` can still have drop glue, consider \ diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 708cd56e06..32ed6dad7f 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1337,14 +1337,15 @@ impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences { let layout = match cx.layout_of(ty) { Ok(layout) => layout, Err( - ty::layout::LayoutError::Unknown(_) | ty::layout::LayoutError::SizeOverflow(_), + ty::layout::LayoutError::Unknown(_) + | ty::layout::LayoutError::SizeOverflow(_) + | ty::layout::LayoutError::NormalizationFailure(_, _), ) => return, }; - let (variants, tag) = match layout.variants { - Variants::Multiple { + let Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, ref variants, .. - } => (variants, tag), - _ => return, + } = &layout.variants else { + return }; let tag_size = tag.value.size(&cx.tcx).bytes(); diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index da1edcf6fe..755e24d541 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -169,7 +169,9 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { } if !(type_permits_lack_of_use || fn_warned || op_warned) { - cx.struct_span_lint(UNUSED_RESULTS, s.span, |lint| lint.build("unused result").emit()); + cx.struct_span_lint(UNUSED_RESULTS, s.span, |lint| { + lint.build(&format!("unused result of type `{}`", ty)).emit() + }); } // Returns whether an error has been emitted (and thus another does not need to be later). @@ -313,7 +315,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { let mut err = lint.build(&msg); // check for #[must_use = "..."] if let Some(note) = attr.value_str() { - err.note(¬e.as_str()); + err.note(note.as_str()); } err.emit(); }); @@ -476,8 +478,11 @@ trait UnusedDelimLint { lhs_needs_parens || (followed_by_block - && match inner.kind { + && match &inner.kind { ExprKind::Ret(_) | ExprKind::Break(..) | ExprKind::Yield(..) => true, + ExprKind::Range(_lhs, Some(rhs), _limits) => { + matches!(rhs.kind, ExprKind::Block(..)) + } _ => parser::contains_exterior_struct_lit(&inner), }) } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index c1a53c34b7..6b89fd657b 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2419,8 +2419,9 @@ declare_lint! { /// /// ### Example /// - /// ```rust,ignore (fails on system llvm) - /// #![feature(asm)] + /// ```rust,ignore (fails on non-x86_64) + /// #[cfg(target_arch="x86_64")] + /// use std::arch::asm; /// /// fn main() { /// #[cfg(target_arch="x86_64")] @@ -2430,19 +2431,7 @@ declare_lint! { /// } /// ``` /// - /// This will produce: - /// - /// ```text - /// warning: formatting may not be suitable for sub-register argument - /// --> src/main.rs:6:19 - /// | - /// 6 | asm!("mov {0}, {0}", in(reg) 0i16); - /// | ^^^ ^^^ ---- for this argument - /// | - /// = note: `#[warn(asm_sub_register)]` on by default - /// = help: use the `x` modifier to have the register formatted as `ax` - /// = help: or use the `r` modifier to keep the default formatting of `rax` - /// ``` + /// {{produces}} /// /// ### Explanation /// @@ -2456,9 +2445,9 @@ declare_lint! { /// fix this, add the suggested modifier to the template, or cast the /// value to the correct size. /// - /// See [register template modifiers] for more details. + /// See [register template modifiers] in the reference for more details. /// - /// [register template modifiers]: https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#register-template-modifiers + /// [register template modifiers]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html#template-modifiers pub ASM_SUB_REGISTER, Warn, "using only a subset of a register for inline asm inputs", @@ -2470,34 +2459,22 @@ declare_lint! { /// /// ### Example /// - /// ```rust,ignore (fails on system llvm) - /// #![feature(asm)] + /// ```rust,ignore (fails on non-x86_64) + /// #[cfg(target_arch="x86_64")] + /// use std::arch::asm; /// /// fn main() { /// #[cfg(target_arch="x86_64")] /// unsafe { /// asm!( /// ".att_syntax", - /// "movl {0}, {0}", in(reg) 0usize + /// "movq %{0}, %{0}", in(reg) 0usize /// ); /// } /// } /// ``` /// - /// This will produce: - /// - /// ```text - /// warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead - /// --> test.rs:7:14 - /// | - /// 7 | ".att_syntax", - /// | ^^^^^^^^^^^ - /// 8 | "movq {0}, {0}", out(reg) _, - /// 9 | ); - /// | - help: add option: `, options(att_syntax)` - /// | - /// = note: `#[warn(bad_asm_style)]` on by default - /// ``` + /// {{produces}} /// /// ### Explanation /// @@ -2739,7 +2716,8 @@ declare_lint! { /// /// ```rust /// #![feature(naked_functions)] - /// #![feature(asm)] + /// + /// use std::arch::asm; /// /// #[naked] /// pub fn default_abi() -> u32 { @@ -2960,6 +2938,41 @@ declare_lint! { "detects large moves or copies", } +declare_lint! { + /// The `deprecated_cfg_attr_crate_type_name` lint detects uses of the + /// `#![cfg_attr(..., crate_type = "...")]` and + /// `#![cfg_attr(..., crate_name = "...")]` attributes to conditionally + /// specify the crate type and name in the source code. + /// + /// ### Example + /// + /// ```rust + /// #![cfg_attr(debug_assertions, crate_type = "lib")] + /// ``` + /// + /// {{produces}} + /// + /// + /// ### Explanation + /// + /// The `#![crate_type]` and `#![crate_name]` attributes require a hack in + /// the compiler to be able to change the used crate type and crate name + /// after macros have been expanded. Neither attribute works in combination + /// with Cargo as it explicitly passes `--crate-type` and `--crate-name` on + /// the commandline. These values must match the value used in the source + /// code to prevent an error. + /// + /// To fix the warning use `--crate-type` on the commandline when running + /// rustc instead of `#![cfg_attr(..., crate_type = "...")]` and + /// `--crate-name` instead of `#![cfg_attr(..., crate_name = "...")]`. + pub DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, + Warn, + "detects usage of `#![cfg_attr(..., crate_type/crate_name = \"...\")]`", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #91632 ", + }; +} + declare_lint_pass! { /// Does nothing as a lint pass, but registers some `Lint`s /// that are used by other parts of the compiler. @@ -3056,6 +3069,8 @@ declare_lint_pass! { NON_EXHAUSTIVE_OMITTED_PATTERNS, TEXT_DIRECTION_CODEPOINT_IN_COMMENT, DEREF_INTO_DYN_SUPERTRAIT, + DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, + DUPLICATE_MACRO_ATTRIBUTES, ] } @@ -3593,3 +3608,32 @@ declare_lint! { reference: "issue #89460 ", }; } + +declare_lint! { + /// The `duplicate_macro_attributes` lint detects when a `#[test]`-like built-in macro + /// attribute is duplicated on an item. This lint may trigger on `bench`, `cfg_eval`, `test` + /// and `test_case`. + /// + /// ### Example + /// + /// ```rust,ignore (needs --test) + /// #[test] + /// #[test] + /// fn foo() {} + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// A duplicated attribute may erroneously originate from a copy-paste and the effect of it + /// being duplicated may not be obvious or desireable. + /// + /// For instance, doubling the `#[test]` attributes registers the test to be run twice with no + /// change to its environment. + /// + /// [issue #90979]: https://github.com/rust-lang/rust/issues/90979 + pub DUPLICATE_MACRO_ATTRIBUTES, + Warn, + "duplicated attribute" +} diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index feac2a7cfa..97f6df51f8 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -285,13 +285,11 @@ pub enum ExternDepSpec { #[derive(PartialEq, Debug)] pub enum BuiltinLintDiagnostics { Normal, - BareTraitObject(Span, /* is_global */ bool), AbsPathWithModule(Span), ProcMacroDeriveResolutionFallback(Span), MacroExpandedMacroExportsAccessedByAbsolutePaths(Span), - ElidedLifetimesInPaths(usize, Span, bool, Span, String), UnknownCrateTypes(Span, String, String), - UnusedImports(String, Vec<(Span, String)>), + UnusedImports(String, Vec<(Span, String)>, Option), RedundantImport(Vec<(Span, bool)>, Ident), DeprecatedMacro(Option, Span), MissingAbi(Span, Abi), diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index 943ce589c4..3b6808d693 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -276,8 +276,11 @@ fn main() { "stdc++" }; - // RISC-V requires libatomic for sub-word atomic operations - if target.starts_with("riscv") { + // RISC-V GCC erroneously requires libatomic for sub-word + // atomic operations. FreeBSD uses Clang as its system + // compiler and provides no libatomic in its base system so + // does not want this. + if !target.contains("freebsd") && target.starts_with("riscv") { println!("cargo:rustc-link-lib=atomic"); } diff --git a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp index 8cd2bd1245..154f554d60 100644 --- a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp @@ -10,6 +10,7 @@ using namespace llvm; struct LLVMRustCounterMappingRegion { coverage::Counter Count; + coverage::Counter FalseCount; uint32_t FileID; uint32_t ExpandedFileID; uint32_t LineStart; @@ -53,7 +54,7 @@ extern "C" void LLVMRustCoverageWriteMappingToBuffer( MappingRegions.reserve(NumMappingRegions); for (const auto &Region : makeArrayRef(RustMappingRegions, NumMappingRegions)) { MappingRegions.emplace_back( - Region.Count, Region.FileID, Region.ExpandedFileID, + Region.Count, Region.FalseCount, Region.FileID, Region.ExpandedFileID, Region.LineStart, Region.ColumnStart, Region.LineEnd, Region.ColumnEnd, Region.Kind); } @@ -108,5 +109,9 @@ extern "C" void LLVMRustCoverageWriteMappingVarNameToString(RustStringRef Str) { } extern "C" uint32_t LLVMRustCoverageMappingVersion() { - return coverage::CovMapVersion::Version4; +#if LLVM_VERSION_GE(13, 0) + return coverage::CovMapVersion::Version6; +#else + return coverage::CovMapVersion::Version5; +#endif } diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 4f77db8a24..f06fc3edf5 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -17,6 +17,7 @@ #include "llvm/Object/ObjectFile.h" #include "llvm/Object/IRObjectFile.h" #include "llvm/Passes/PassBuilder.h" +#include "llvm/Passes/PassPlugin.h" #include "llvm/Passes/StandardInstrumentations.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/FileSystem.h" @@ -753,7 +754,8 @@ LLVMRustOptimizeWithNewPassManager( void* LlvmSelfProfiler, LLVMRustSelfProfileBeforePassCallback BeforePassCallback, LLVMRustSelfProfileAfterPassCallback AfterPassCallback, - const char *ExtraPasses, size_t ExtraPassesLen) { + const char *ExtraPasses, size_t ExtraPassesLen, + const char *LLVMPlugins, size_t LLVMPluginsLen) { Module *TheModule = unwrap(ModuleRef); TargetMachine *TM = unwrap(TMRef); OptimizationLevel OptLevel = fromRust(OptLevelRust); @@ -924,6 +926,20 @@ LLVMRustOptimizeWithNewPassManager( } } + if (LLVMPluginsLen) { + auto PluginsStr = StringRef(LLVMPlugins, LLVMPluginsLen); + SmallVector Plugins; + PluginsStr.split(Plugins, ',', -1, false); + for (auto PluginPath: Plugins) { + auto Plugin = PassPlugin::Load(PluginPath.str()); + if (!Plugin) { + LLVMRustSetLastError(("Failed to load pass plugin" + PluginPath.str()).c_str()); + continue; + } + Plugin->registerPassBuilderCallbacks(PB); + } + } + #if LLVM_VERSION_GE(13, 0) ModulePassManager MPM; #else diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index bb6d42c1a9..c21e4acbef 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1,5 +1,6 @@ #include "LLVMWrapper.h" #include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/DiagnosticHandler.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/GlobalVariable.h" @@ -340,14 +341,12 @@ extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn, unsigned Index, LLVMRustAttribute RustAttr) { Function *F = unwrap(Fn); - Attribute Attr = Attribute::get(F->getContext(), fromRust(RustAttr)); - AttrBuilder B(Attr); - auto PAL = F->getAttributes(); + AttributeList PAL = F->getAttributes(); AttributeList PALNew; #if LLVM_VERSION_LT(14, 0) - PALNew = PAL.removeAttributes(F->getContext(), Index, B); + PALNew = PAL.removeAttribute(F->getContext(), Index, fromRust(RustAttr)); #else - PALNew = PAL.removeAttributesAtIndex(F->getContext(), Index, B); + PALNew = PAL.removeAttributeAtIndex(F->getContext(), Index, fromRust(RustAttr)); #endif F->setAttributes(PALNew); } @@ -444,11 +443,20 @@ extern "C" LLVMValueRef LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen, char *Constraints, size_t ConstraintsLen, LLVMBool HasSideEffects, LLVMBool IsAlignStack, - LLVMRustAsmDialect Dialect) { + LLVMRustAsmDialect Dialect, LLVMBool CanThrow) { +#if LLVM_VERSION_GE(13, 0) return wrap(InlineAsm::get(unwrap(Ty), StringRef(AsmString, AsmStringLen), StringRef(Constraints, ConstraintsLen), - HasSideEffects, IsAlignStack, fromRust(Dialect))); + HasSideEffects, IsAlignStack, + fromRust(Dialect), CanThrow)); +#else + return wrap(InlineAsm::get(unwrap(Ty), + StringRef(AsmString, AsmStringLen), + StringRef(Constraints, ConstraintsLen), + HasSideEffects, IsAlignStack, + fromRust(Dialect))); +#endif } extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints, @@ -706,6 +714,14 @@ extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; } extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; } +extern "C" bool LLVMRustIsRustLLVM() { +#ifdef LLVM_RUSTLLVM + return true; +#else + return false; +#endif +} + extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *Name, uint32_t Value) { unwrap(M)->addModuleFlag(Module::Warning, Name, Value); @@ -961,11 +977,11 @@ LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder, extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd( LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo, - int64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL, + uint64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL, LLVMBasicBlockRef InsertAtEnd) { return wrap(Builder->insertDeclare( unwrap(V), unwrap(VarInfo), - Builder->createExpression(llvm::ArrayRef(AddrOps, AddrOpsCount)), + Builder->createExpression(llvm::ArrayRef(AddrOps, AddrOpsCount)), DebugLoc(cast(unwrap(DL))), unwrap(InsertAtEnd))); } @@ -1039,11 +1055,11 @@ LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column, return wrap(Loc); } -extern "C" int64_t LLVMRustDIBuilderCreateOpDeref() { +extern "C" uint64_t LLVMRustDIBuilderCreateOpDeref() { return dwarf::DW_OP_deref; } -extern "C" int64_t LLVMRustDIBuilderCreateOpPlusUconst() { +extern "C" uint64_t LLVMRustDIBuilderCreateOpPlusUconst() { return dwarf::DW_OP_plus_uconst; } @@ -1177,10 +1193,13 @@ static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) { case DK_SampleProfile: return LLVMRustDiagnosticKind::SampleProfile; case DK_OptimizationRemark: + case DK_MachineOptimizationRemark: return LLVMRustDiagnosticKind::OptimizationRemark; case DK_OptimizationRemarkMissed: + case DK_MachineOptimizationRemarkMissed: return LLVMRustDiagnosticKind::OptimizationRemarkMissed; case DK_OptimizationRemarkAnalysis: + case DK_MachineOptimizationRemarkAnalysis: return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis; case DK_OptimizationRemarkAnalysisFPCommute: return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute; @@ -1783,3 +1802,92 @@ extern "C" LLVMRustResult LLVMRustWriteImportLibrary( return LLVMRustResult::Success; } } + +// Transfers ownership of DiagnosticHandler unique_ptr to the caller. +extern "C" DiagnosticHandler * +LLVMRustContextGetDiagnosticHandler(LLVMContextRef C) { + std::unique_ptr DH = unwrap(C)->getDiagnosticHandler(); + return DH.release(); +} + +// Sets unique_ptr to object of DiagnosticHandler to provide custom diagnostic +// handling. Ownership of the handler is moved to the LLVMContext. +extern "C" void LLVMRustContextSetDiagnosticHandler(LLVMContextRef C, + DiagnosticHandler *DH) { + unwrap(C)->setDiagnosticHandler(std::unique_ptr(DH)); +} + +using LLVMDiagnosticHandlerTy = DiagnosticHandler::DiagnosticHandlerTy; + +// Configures a diagnostic handler that invokes provided callback when a +// backend needs to emit a diagnostic. +// +// When RemarkAllPasses is true, remarks are enabled for all passes. Otherwise +// the RemarkPasses array specifies individual passes for which remarks will be +// enabled. +extern "C" void LLVMRustContextConfigureDiagnosticHandler( + LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback, + void *DiagnosticHandlerContext, bool RemarkAllPasses, + const char * const * RemarkPasses, size_t RemarkPassesLen) { + + class RustDiagnosticHandler final : public DiagnosticHandler { + public: + RustDiagnosticHandler(LLVMDiagnosticHandlerTy DiagnosticHandlerCallback, + void *DiagnosticHandlerContext, + bool RemarkAllPasses, + std::vector RemarkPasses) + : DiagnosticHandlerCallback(DiagnosticHandlerCallback), + DiagnosticHandlerContext(DiagnosticHandlerContext), + RemarkAllPasses(RemarkAllPasses), + RemarkPasses(RemarkPasses) {} + + virtual bool handleDiagnostics(const DiagnosticInfo &DI) override { + if (DiagnosticHandlerCallback) { + DiagnosticHandlerCallback(DI, DiagnosticHandlerContext); + return true; + } + return false; + } + + bool isAnalysisRemarkEnabled(StringRef PassName) const override { + return isRemarkEnabled(PassName); + } + + bool isMissedOptRemarkEnabled(StringRef PassName) const override { + return isRemarkEnabled(PassName); + } + + bool isPassedOptRemarkEnabled(StringRef PassName) const override { + return isRemarkEnabled(PassName); + } + + bool isAnyRemarkEnabled() const override { + return RemarkAllPasses || !RemarkPasses.empty(); + } + + private: + bool isRemarkEnabled(StringRef PassName) const { + if (RemarkAllPasses) + return true; + + for (auto &Pass : RemarkPasses) + if (Pass == PassName) + return true; + + return false; + } + + LLVMDiagnosticHandlerTy DiagnosticHandlerCallback = nullptr; + void *DiagnosticHandlerContext = nullptr; + + bool RemarkAllPasses = false; + std::vector RemarkPasses; + }; + + std::vector Passes; + for (size_t I = 0; I != RemarkPassesLen; ++I) + Passes.push_back(RemarkPasses[I]); + + unwrap(C)->setDiagnosticHandler(std::make_unique( + DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes)); +} diff --git a/compiler/rustc_log/Cargo.toml b/compiler/rustc_log/Cargo.toml new file mode 100644 index 0000000000..1b2cde6055 --- /dev/null +++ b/compiler/rustc_log/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "rustc_log" +version = "0.0.0" +edition = "2021" + +[dependencies] +atty = "0.2" +tracing = "0.1.28" +tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] } +tracing-tree = "0.2.0" + +[dev-dependencies] +rustc_span = { path = "../rustc_span" } + +[features] +max_level_info = ['tracing/max_level_info'] diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs new file mode 100644 index 0000000000..f5e7435d36 --- /dev/null +++ b/compiler/rustc_log/src/lib.rs @@ -0,0 +1,115 @@ +//! This crate allows tools to enable rust logging without having to magically +//! match rustc's tracing crate version. +//! +//! For example if someone is working on rustc_ast and wants to write some +//! minimal code against it to run in a debugger, with access to the `debug!` +//! logs emitted by rustc_ast, that can be done by writing: +//! +//! ```toml +//! [dependencies] +//! rustc_ast = { path = "../rust/compiler/rustc_ast" } +//! rustc_log = { path = "../rust/compiler/rustc_log" } +//! rustc_span = { path = "../rust/compiler/rustc_span" } +//! ``` +//! +//! ``` +//! fn main() { +//! rustc_log::init_rustc_env_logger().unwrap(); +//! +//! let edition = rustc_span::edition::Edition::Edition2021; +//! rustc_span::create_session_globals_then(edition, || { +//! /* ... */ +//! }); +//! } +//! ``` +//! +//! Now `RUSTC_LOG=debug cargo run` will run your minimal main.rs and show +//! rustc's debug logging. In a workflow like this, one might also add +//! `std::env::set_var("RUSTC_LOG", "debug")` to the top of main so that `cargo +//! run` by itself is sufficient to get logs. +//! +//! The reason rustc_log is a tiny separate crate, as opposed to exposing the +//! same things in rustc_driver only, is to enable the above workflow. If you +//! had to depend on rustc_driver in order to turn on rustc's debug logs, that's +//! an enormously bigger dependency tree; every change you make to rustc_ast (or +//! whichever piece of the compiler you are interested in) would involve +//! rebuilding all the rest of rustc up to rustc_driver in order to run your +//! main.rs. Whereas by depending only on rustc_log and the few crates you are +//! debugging, you can make changes inside those crates and quickly run main.rs +//! to read the debug logs. + +use std::env::{self, VarError}; +use std::fmt::{self, Display}; +use std::io; +use tracing_subscriber::filter::{Directive, EnvFilter, LevelFilter}; +use tracing_subscriber::layer::SubscriberExt; + +pub fn init_rustc_env_logger() -> Result<(), Error> { + init_env_logger("RUSTC_LOG") +} + +/// In contrast to `init_rustc_env_logger` this allows you to choose an env var +/// other than `RUSTC_LOG`. +pub fn init_env_logger(env: &str) -> Result<(), Error> { + let filter = match env::var(env) { + Ok(env) => EnvFilter::new(env), + _ => EnvFilter::default().add_directive(Directive::from(LevelFilter::WARN)), + }; + + let color_logs = match env::var(String::from(env) + "_COLOR") { + Ok(value) => match value.as_ref() { + "always" => true, + "never" => false, + "auto" => stderr_isatty(), + _ => return Err(Error::InvalidColorValue(value)), + }, + Err(VarError::NotPresent) => stderr_isatty(), + Err(VarError::NotUnicode(_value)) => return Err(Error::NonUnicodeColorValue), + }; + + let layer = tracing_tree::HierarchicalLayer::default() + .with_writer(io::stderr) + .with_indent_lines(true) + .with_ansi(color_logs) + .with_targets(true) + .with_indent_amount(2); + #[cfg(parallel_compiler)] + let layer = layer.with_thread_ids(true).with_thread_names(true); + + let subscriber = tracing_subscriber::Registry::default().with(filter).with(layer); + tracing::subscriber::set_global_default(subscriber).unwrap(); + + Ok(()) +} + +pub fn stdout_isatty() -> bool { + atty::is(atty::Stream::Stdout) +} + +pub fn stderr_isatty() -> bool { + atty::is(atty::Stream::Stderr) +} + +#[derive(Debug)] +pub enum Error { + InvalidColorValue(String), + NonUnicodeColorValue, +} + +impl std::error::Error for Error {} + +impl Display for Error { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Error::InvalidColorValue(value) => write!( + formatter, + "invalid log color value '{}': expected one of always, never, or auto", + value, + ), + Error::NonUnicodeColorValue => write!( + formatter, + "non-Unicode log color value: expected one of always, never, or auto", + ), + } + } +} diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 6dbba27436..478159147a 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -58,6 +58,9 @@ enum QueryModifier { /// Use a separate query provider for local and extern crates SeparateProvideExtern(Ident), + + /// Always remap the ParamEnv's constness before hashing and passing to the query provider + RemapEnvConstness(Ident), } impl Parse for QueryModifier { @@ -123,6 +126,8 @@ impl Parse for QueryModifier { Ok(QueryModifier::EvalAlways(modifier)) } else if modifier == "separate_provide_extern" { Ok(QueryModifier::SeparateProvideExtern(modifier)) + } else if modifier == "remap_env_constness" { + Ok(QueryModifier::RemapEnvConstness(modifier)) } else { Err(Error::new(modifier.span(), "unknown query modifier")) } @@ -222,6 +227,9 @@ struct QueryModifiers { /// Use a separate query provider for local and extern crates separate_provide_extern: Option, + + /// Always remap the ParamEnv's constness before hashing. + remap_env_constness: Option, } /// Process query modifiers into a struct, erroring on duplicates @@ -236,6 +244,7 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers { let mut anon = None; let mut eval_always = None; let mut separate_provide_extern = None; + let mut remap_env_constness = None; for modifier in query.modifiers.0.drain(..) { match modifier { QueryModifier::LoadCached(tcx, id, block) => { @@ -335,6 +344,12 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers { } separate_provide_extern = Some(ident); } + QueryModifier::RemapEnvConstness(ident) => { + if remap_env_constness.is_some() { + panic!("duplicate modifier `remap_env_constness` for query `{}`", query.name); + } + remap_env_constness = Some(ident) + } } } let desc = desc.unwrap_or_else(|| { @@ -351,6 +366,7 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers { anon, eval_always, separate_provide_extern, + remap_env_constness, } } @@ -485,6 +501,10 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { if let Some(separate_provide_extern) = &modifiers.separate_provide_extern { attributes.push(quote! { (#separate_provide_extern) }); } + // Pass on the remap_env_constness modifier + if let Some(remap_env_constness) = &modifiers.remap_env_constness { + attributes.push(quote! { (#remap_env_constness) }); + } // This uses the span of the query definition for the commas, // which can be important if we later encounter any ambiguity diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs index 66e6b571be..3351564299 100644 --- a/compiler/rustc_macros/src/serialize.rs +++ b/compiler/rustc_macros/src/serialize.rs @@ -1,6 +1,7 @@ use proc_macro2::TokenStream; -use quote::quote; +use quote::{quote, quote_spanned}; use syn::parse_quote; +use syn::spanned::Spanned; pub fn type_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { let decoder_ty = quote! { __D }; @@ -104,6 +105,8 @@ fn decodable_body( } fn decode_field(field: &syn::Field, index: usize, is_struct: bool) -> proc_macro2::TokenStream { + let field_span = field.ident.as_ref().map_or(field.ty.span(), |ident| ident.span()); + let decode_inner_method = if let syn::Type::Reference(_) = field.ty { quote! { ::rustc_middle::ty::codec::RefDecodable::decode } } else { @@ -111,20 +114,21 @@ fn decode_field(field: &syn::Field, index: usize, is_struct: bool) -> proc_macro }; let (decode_method, opt_field_name) = if is_struct { let field_name = field.ident.as_ref().map_or_else(|| index.to_string(), |i| i.to_string()); - ( - proc_macro2::Ident::new("read_struct_field", proc_macro2::Span::call_site()), - quote! { #field_name, }, - ) + (proc_macro2::Ident::new("read_struct_field", field_span), quote! { #field_name, }) } else { - ( - proc_macro2::Ident::new("read_enum_variant_arg", proc_macro2::Span::call_site()), - quote! {}, - ) + (proc_macro2::Ident::new("read_enum_variant_arg", field_span), quote! {}) + }; + + let __decoder = quote! { __decoder }; + // Use the span of the field for the method call, so + // that backtraces will point to the field. + let decode_call = quote_spanned! {field_span=> + ::rustc_serialize::Decoder::#decode_method( + #__decoder, #opt_field_name #decode_inner_method) }; quote! { - match ::rustc_serialize::Decoder::#decode_method( - __decoder, #opt_field_name #decode_inner_method) { + match #decode_call { ::std::result::Result::Ok(__res) => __res, ::std::result::Result::Err(__err) => return ::std::result::Result::Err(__err), } diff --git a/compiler/rustc_macros/src/type_foldable.rs b/compiler/rustc_macros/src/type_foldable.rs index 082af087bf..bc8213a18e 100644 --- a/compiler/rustc_macros/src/type_foldable.rs +++ b/compiler/rustc_macros/src/type_foldable.rs @@ -1,10 +1,15 @@ use quote::quote; +use syn::parse_quote; pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { if let syn::Data::Union(_) = s.ast().data { panic!("cannot derive on union") } + if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { + s.add_impl_generic(parse_quote! { 'tcx }); + } + s.add_bounds(synstructure::AddBounds::Generics); let body_visit = s.each(|bind| { quote! { @@ -17,7 +22,7 @@ pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2:: vi.construct(|_, index| { let bind = &bindings[index]; quote! { - ::rustc_middle::ty::fold::TypeFoldable::fold_with(#bind, __folder) + ::rustc_middle::ty::fold::TypeFoldable::try_fold_with(#bind, __folder)? } }) }); @@ -25,11 +30,11 @@ pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2:: s.bound_impl( quote!(::rustc_middle::ty::fold::TypeFoldable<'tcx>), quote! { - fn super_fold_with<__F: ::rustc_middle::ty::fold::TypeFolder<'tcx>>( + fn try_super_fold_with<__F: ::rustc_middle::ty::fold::FallibleTypeFolder<'tcx>>( self, __folder: &mut __F - ) -> Self { - match self { #body_fold } + ) -> Result { + Ok(match self { #body_fold }) } fn super_visit_with<__F: ::rustc_middle::ty::fold::TypeVisitor<'tcx>>( diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index dec77d996f..59796dd652 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" doctest = false [dependencies] -libc = "0.2" +libloading = "0.7.1" odht = { version = "0.3.1", features = ["nightly"] } snap = "1" tracing = "0.1" @@ -27,6 +27,3 @@ rustc_ast = { path = "../rustc_ast" } rustc_expand = { path = "../rustc_expand" } rustc_span = { path = "../rustc_span" } rustc_session = { path = "../rustc_session" } - -[target.'cfg(windows)'.dependencies] -winapi = { version = "0.3", features = ["errhandlingapi", "libloaderapi"] } diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index eb0a693226..36a1798cd6 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -1,6 +1,5 @@ //! Validates all used crates and extern libraries and loads their metadata -use crate::dynamic_lib::DynamicLibrary; use crate::locator::{CrateError, CrateLocator, CratePaths}; use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob}; @@ -103,30 +102,23 @@ struct CrateDump<'a>(&'a CStore); impl<'a> std::fmt::Debug for CrateDump<'a> { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(fmt, "resolved crates:")?; - // `iter_crate_data` does not allow returning values. Thus we use a mutable variable here - // that aggregates the value (and any errors that could happen). - let mut res = Ok(()); - self.0.iter_crate_data(|cnum, data| { - res = res.and( - try { - writeln!(fmt, " name: {}", data.name())?; - writeln!(fmt, " cnum: {}", cnum)?; - writeln!(fmt, " hash: {}", data.hash())?; - writeln!(fmt, " reqd: {:?}", data.dep_kind())?; - let CrateSource { dylib, rlib, rmeta } = data.source(); - if let Some(dylib) = dylib { - writeln!(fmt, " dylib: {}", dylib.0.display())?; - } - if let Some(rlib) = rlib { - writeln!(fmt, " rlib: {}", rlib.0.display())?; - } - if let Some(rmeta) = rmeta { - writeln!(fmt, " rmeta: {}", rmeta.0.display())?; - } - }, - ); - }); - res + for (cnum, data) in self.0.iter_crate_data() { + writeln!(fmt, " name: {}", data.name())?; + writeln!(fmt, " cnum: {}", cnum)?; + writeln!(fmt, " hash: {}", data.hash())?; + writeln!(fmt, " reqd: {:?}", data.dep_kind())?; + let CrateSource { dylib, rlib, rmeta } = data.source(); + if let Some(dylib) = dylib { + writeln!(fmt, " dylib: {}", dylib.0.display())?; + } + if let Some(rlib) = rlib { + writeln!(fmt, " rlib: {}", rlib.0.display())?; + } + if let Some(rmeta) = rmeta { + writeln!(fmt, " rmeta: {}", rmeta.0.display())?; + } + } + Ok(()) } } @@ -155,12 +147,10 @@ impl CStore { self.metas[cnum] = Some(Lrc::new(data)); } - crate fn iter_crate_data(&self, mut f: impl FnMut(CrateNum, &CrateMetadata)) { - for (cnum, data) in self.metas.iter_enumerated() { - if let Some(data) = data { - f(cnum, data); - } - } + crate fn iter_crate_data(&self) -> impl Iterator { + self.metas + .iter_enumerated() + .filter_map(|(cnum, data)| data.as_ref().map(|data| (cnum, &**data))) } fn push_dependencies_in_postorder(&self, deps: &mut Vec, cnum: CrateNum) { @@ -179,7 +169,9 @@ impl CStore { crate fn crate_dependencies_in_postorder(&self, cnum: CrateNum) -> Vec { let mut deps = Vec::new(); if cnum == LOCAL_CRATE { - self.iter_crate_data(|cnum, _| self.push_dependencies_in_postorder(&mut deps, cnum)); + for (cnum, _) in self.iter_crate_data() { + self.push_dependencies_in_postorder(&mut deps, cnum); + } } else { self.push_dependencies_in_postorder(&mut deps, cnum); } @@ -264,21 +256,17 @@ impl<'a> CrateLoader<'a> { } fn existing_match(&self, name: Symbol, hash: Option, kind: PathKind) -> Option { - let mut ret = None; - self.cstore.iter_crate_data(|cnum, data| { + for (cnum, data) in self.cstore.iter_crate_data() { if data.name() != name { tracing::trace!("{} did not match {}", data.name(), name); - return; + continue; } match hash { - Some(hash) if hash == data.hash() => { - ret = Some(cnum); - return; - } + Some(hash) if hash == data.hash() => return Some(cnum), Some(hash) => { debug!("actual hash {} did not match expected {}", hash, data.hash()); - return; + continue; } None => {} } @@ -293,7 +281,7 @@ impl<'a> CrateLoader<'a> { // `source` stores paths which are normalized which may be different // from the strings on the command line. let source = self.cstore.get_crate_data(cnum).cdata.source(); - if let Some(entry) = self.sess.opts.externs.get(&name.as_str()) { + if let Some(entry) = self.sess.opts.externs.get(name.as_str()) { // Only use `--extern crate_name=path` here, not `--extern crate_name`. if let Some(mut files) = entry.files() { if files.any(|l| { @@ -302,10 +290,10 @@ impl<'a> CrateLoader<'a> { || source.rlib.as_ref().map(|(p, _)| p) == Some(l) || source.rmeta.as_ref().map(|(p, _)| p) == Some(l) }) { - ret = Some(cnum); + return Some(cnum); } } - return; + continue; } // Alright, so we've gotten this far which means that `data` has the @@ -322,15 +310,16 @@ impl<'a> CrateLoader<'a> { .expect("No sources for crate") .1; if kind.matches(prev_kind) { - ret = Some(cnum); + return Some(cnum); } else { debug!( "failed to load existing crate {}; kind {:?} did not match prev_kind {:?}", name, kind, prev_kind ); } - }); - ret + } + + None } fn verify_no_symbol_conflicts(&self, root: &CrateRoot<'_>) -> Result<(), CrateError> { @@ -340,17 +329,14 @@ impl<'a> CrateLoader<'a> { } // Check for conflicts with any crate loaded so far - let mut res = Ok(()); - self.cstore.iter_crate_data(|_, other| { - if other.stable_crate_id() == root.stable_crate_id() && // same stable crate id - other.hash() != root.hash() - { - // but different SVH - res = Err(CrateError::SymbolConflictsOthers(root.name())); + for (_, other) in self.cstore.iter_crate_data() { + // Same stable crate id but different SVH + if other.stable_crate_id() == root.stable_crate_id() && other.hash() != root.hash() { + return Err(CrateError::SymbolConflictsOthers(root.name())); } - }); + } - res + Ok(()) } fn verify_no_stable_crate_id_hash_conflicts( @@ -382,7 +368,7 @@ impl<'a> CrateLoader<'a> { let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash()); let private_dep = - self.sess.opts.externs.get(&name.as_str()).map_or(false, |e| e.is_private_dep); + self.sess.opts.externs.get(name.as_str()).map_or(false, |e| e.is_private_dep); // Claim this crate number and cache it let cnum = self.cstore.alloc_new_crate_num(); @@ -512,13 +498,17 @@ impl<'a> CrateLoader<'a> { name: Symbol, span: Span, dep_kind: CrateDepKind, - ) -> CrateNum { + ) -> Option { self.used_extern_options.insert(name); - self.maybe_resolve_crate(name, dep_kind, None).unwrap_or_else(|err| { - let missing_core = - self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err(); - err.report(&self.sess, span, missing_core) - }) + match self.maybe_resolve_crate(name, dep_kind, None) { + Ok(cnum) => Some(cnum), + Err(err) => { + let missing_core = + self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err(); + err.report(&self.sess, span, missing_core); + None + } + } } fn maybe_resolve_crate<'b>( @@ -604,13 +594,14 @@ impl<'a> CrateLoader<'a> { locator.triple == self.sess.opts.target_triple || locator.is_proc_macro; Ok(Some(if can_reuse_cratenum { let mut result = LoadResult::Loaded(library); - self.cstore.iter_crate_data(|cnum, data| { + for (cnum, data) in self.cstore.iter_crate_data() { if data.name() == root.name() && root.hash() == data.hash() { assert!(locator.hash.is_none()); info!("load success, going to previous cnum: {}", cnum); result = LoadResult::Previous(cnum); + break; } - }); + } result } else { LoadResult::Loaded(library) @@ -672,25 +663,19 @@ impl<'a> CrateLoader<'a> { ) -> Result<&'static [ProcMacro], CrateError> { // Make sure the path contains a / or the linker will search for it. let path = env::current_dir().unwrap().join(path); - let lib = match DynamicLibrary::open(&path) { - Ok(lib) => lib, - Err(s) => return Err(CrateError::DlOpen(s)), - }; + let lib = unsafe { libloading::Library::new(path) } + .map_err(|err| CrateError::DlOpen(err.to_string()))?; - let sym = self.sess.generate_proc_macro_decls_symbol(stable_crate_id); - let decls = unsafe { - let sym = match lib.symbol(&sym) { - Ok(f) => f, - Err(s) => return Err(CrateError::DlSym(s)), - }; - *(sym as *const &[ProcMacro]) - }; + let sym_name = self.sess.generate_proc_macro_decls_symbol(stable_crate_id); + let sym = unsafe { lib.get::<*const &[ProcMacro]>(sym_name.as_bytes()) } + .map_err(|err| CrateError::DlSym(err.to_string()))?; // Intentionally leak the dynamic library. We can't ever unload it // since the library can make things that will live arbitrarily long. + let sym = unsafe { sym.into_raw() }; std::mem::forget(lib); - Ok(decls) + Ok(unsafe { **sym }) } fn inject_panic_runtime(&mut self, krate: &ast::Crate) { @@ -714,7 +699,7 @@ impl<'a> CrateLoader<'a> { let mut needs_panic_runtime = self.sess.contains_name(&krate.attrs, sym::needs_panic_runtime); - self.cstore.iter_crate_data(|cnum, data| { + for (cnum, data) in self.cstore.iter_crate_data() { needs_panic_runtime = needs_panic_runtime || data.needs_panic_runtime(); if data.is_panic_runtime() { // Inject a dependency from all #![needs_panic_runtime] to this @@ -724,7 +709,7 @@ impl<'a> CrateLoader<'a> { }); runtime_found = runtime_found || data.dep_kind() == CrateDepKind::Explicit; } - }); + } // If an explicitly linked and matching panic runtime was found, or if // we just don't need one at all, then we're done here and there's @@ -751,7 +736,7 @@ impl<'a> CrateLoader<'a> { }; info!("panic runtime not found -- loading {}", name); - let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit); + let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; }; let data = self.cstore.get_crate_data(cnum); // Sanity check the loaded crate to ensure it is indeed a panic runtime @@ -791,7 +776,7 @@ impl<'a> CrateLoader<'a> { ); } - let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit); + let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; }; let data = self.cstore.get_crate_data(cnum); // Sanity check the loaded crate to ensure it is indeed a profiler runtime @@ -816,11 +801,9 @@ impl<'a> CrateLoader<'a> { // Check to see if we actually need an allocator. This desire comes // about through the `#![needs_allocator]` attribute and is typically // written down in liballoc. - let mut needs_allocator = self.sess.contains_name(&krate.attrs, sym::needs_allocator); - self.cstore.iter_crate_data(|_, data| { - needs_allocator = needs_allocator || data.needs_allocator(); - }); - if !needs_allocator { + if !self.sess.contains_name(&krate.attrs, sym::needs_allocator) + && !self.cstore.iter_crate_data().any(|(_, data)| data.needs_allocator()) + { return; } @@ -841,23 +824,19 @@ impl<'a> CrateLoader<'a> { // global allocator. let mut global_allocator = self.cstore.has_global_allocator.then(|| Symbol::intern("this crate")); - self.cstore.iter_crate_data(|_, data| { - if !data.has_global_allocator() { - return; - } - match global_allocator { - Some(other_crate) => { - self.sess.err(&format!( - "the `#[global_allocator]` in {} \ - conflicts with global \ - allocator in: {}", + for (_, data) in self.cstore.iter_crate_data() { + if data.has_global_allocator() { + match global_allocator { + Some(other_crate) => self.sess.err(&format!( + "the `#[global_allocator]` in {} conflicts with global allocator in: {}", other_crate, data.name() - )); + )), + None => global_allocator = Some(data.name()), } - None => global_allocator = Some(data.name()), } - }); + } + if global_allocator.is_some() { self.cstore.allocator_kind = Some(AllocatorKind::Global); return; @@ -867,19 +846,12 @@ impl<'a> CrateLoader<'a> { // allocator. At this point our allocator request is typically fulfilled // by the standard library, denoted by the `#![default_lib_allocator]` // attribute. - let mut has_default = self.sess.contains_name(&krate.attrs, sym::default_lib_allocator); - self.cstore.iter_crate_data(|_, data| { - if data.has_default_lib_allocator() { - has_default = true; - } - }); - - if !has_default { + if !self.sess.contains_name(&krate.attrs, sym::default_lib_allocator) + && !self.cstore.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator()) + { self.sess.err( - "no global memory allocator found but one is \ - required; link to std or \ - add `#[global_allocator]` to a static item \ - that implements the GlobalAlloc trait", + "no global memory allocator found but one is required; link to std or add \ + `#[global_allocator]` to a static item that implements the GlobalAlloc trait", ); } self.cstore.allocator_kind = Some(AllocatorKind::Default); @@ -919,14 +891,12 @@ impl<'a> CrateLoader<'a> { // crate provided for this compile, but in order for this compilation to // be successfully linked we need to inject a dependency (to order the // crates on the command line correctly). - self.cstore.iter_crate_data(|cnum, data| { - if !needs_dep(data) { - return; + for (cnum, data) in self.cstore.iter_crate_data() { + if needs_dep(data) { + info!("injecting a dep from {} to {}", cnum, krate); + data.add_dependency(krate); } - - info!("injecting a dep from {} to {}", cnum, krate); - data.add_dependency(krate); - }); + } } fn report_unused_deps(&mut self, krate: &ast::Crate) { @@ -991,7 +961,7 @@ impl<'a> CrateLoader<'a> { item: &ast::Item, definitions: &Definitions, def_id: LocalDefId, - ) -> CrateNum { + ) -> Option { match item.kind { ast::ItemKind::ExternCrate(orig_name) => { debug!( @@ -1000,7 +970,7 @@ impl<'a> CrateLoader<'a> { ); let name = match orig_name { Some(orig_name) => { - validate_crate_name(self.sess, &orig_name.as_str(), Some(item.span)); + validate_crate_name(self.sess, orig_name.as_str(), Some(item.span)); orig_name } None => item.ident.name, @@ -1011,7 +981,7 @@ impl<'a> CrateLoader<'a> { CrateDepKind::Explicit }; - let cnum = self.resolve_crate(name, item.span, dep_kind); + let cnum = self.resolve_crate(name, item.span, dep_kind)?; let path_len = definitions.def_path(def_id).data.len(); self.update_extern_crate( @@ -1023,14 +993,14 @@ impl<'a> CrateLoader<'a> { dependency_of: LOCAL_CRATE, }, ); - cnum + Some(cnum) } _ => bug!(), } } - pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> CrateNum { - let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit); + pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> Option { + let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit)?; self.update_extern_crate( cnum, @@ -1043,7 +1013,7 @@ impl<'a> CrateLoader<'a> { }, ); - cnum + Some(cnum) } pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option { diff --git a/compiler/rustc_metadata/src/dynamic_lib.rs b/compiler/rustc_metadata/src/dynamic_lib.rs deleted file mode 100644 index e8929cd5c0..0000000000 --- a/compiler/rustc_metadata/src/dynamic_lib.rs +++ /dev/null @@ -1,194 +0,0 @@ -//! Dynamic library facilities. -//! -//! A simple wrapper over the platform's dynamic library facilities - -use std::ffi::CString; -use std::path::Path; - -pub struct DynamicLibrary { - handle: *mut u8, -} - -impl Drop for DynamicLibrary { - fn drop(&mut self) { - unsafe { dl::close(self.handle) } - } -} - -impl DynamicLibrary { - /// Lazily open a dynamic library. - pub fn open(filename: &Path) -> Result { - let maybe_library = dl::open(filename.as_os_str()); - - // The dynamic library must not be constructed if there is - // an error opening the library so the destructor does not - // run. - match maybe_library { - Err(err) => Err(err), - Ok(handle) => Ok(DynamicLibrary { handle }), - } - } - - /// Accesses the value at the symbol of the dynamic library. - pub unsafe fn symbol(&self, symbol: &str) -> Result<*mut T, String> { - // This function should have a lifetime constraint of 'a on - // T but that feature is still unimplemented - - let raw_string = CString::new(symbol).unwrap(); - let maybe_symbol_value = dl::symbol(self.handle, raw_string.as_ptr()); - - // The value must not be constructed if there is an error so - // the destructor does not run. - match maybe_symbol_value { - Err(err) => Err(err), - Ok(symbol_value) => Ok(symbol_value as *mut T), - } - } -} - -#[cfg(test)] -mod tests; - -#[cfg(unix)] -mod dl { - use std::ffi::{CString, OsStr}; - use std::os::unix::prelude::*; - - // As of the 2017 revision of the POSIX standard (IEEE 1003.1-2017), it is - // implementation-defined whether `dlerror` is thread-safe (in which case it returns the most - // recent error in the calling thread) or not thread-safe (in which case it returns the most - // recent error in *any* thread). - // - // There's no easy way to tell what strategy is used by a given POSIX implementation, so we - // lock around all calls that can modify `dlerror` in this module lest we accidentally read an - // error from a different thread. This is bulletproof when we are the *only* code using the - // dynamic library APIs at a given point in time. However, it's still possible for us to race - // with other code (see #74469) on platforms where `dlerror` is not thread-safe. - mod error { - use std::ffi::CStr; - use std::lazy::SyncLazy; - use std::sync::{Mutex, MutexGuard}; - - pub fn lock() -> MutexGuard<'static, Guard> { - static LOCK: SyncLazy> = SyncLazy::new(|| Mutex::new(Guard)); - LOCK.lock().unwrap() - } - - #[non_exhaustive] - pub struct Guard; - - impl Guard { - pub fn get(&mut self) -> Result<(), String> { - let msg = unsafe { libc::dlerror() }; - if msg.is_null() { - Ok(()) - } else { - let msg = unsafe { CStr::from_ptr(msg as *const _) }; - Err(msg.to_string_lossy().into_owned()) - } - } - - pub fn clear(&mut self) { - let _ = unsafe { libc::dlerror() }; - } - } - } - - pub(super) fn open(filename: &OsStr) -> Result<*mut u8, String> { - let s = CString::new(filename.as_bytes()).unwrap(); - - let mut dlerror = error::lock(); - let ret = unsafe { libc::dlopen(s.as_ptr(), libc::RTLD_LAZY | libc::RTLD_LOCAL) }; - - if !ret.is_null() { - return Ok(ret.cast()); - } - - // A null return from `dlopen` indicates that an error has definitely occurred, so if - // nothing is in `dlerror`, we are racing with another thread that has stolen our error - // message. See the explanation on the `dl::error` module for more information. - dlerror.get().and_then(|()| Err("Unknown error".to_string())) - } - - pub(super) unsafe fn symbol( - handle: *mut u8, - symbol: *const libc::c_char, - ) -> Result<*mut u8, String> { - let mut dlerror = error::lock(); - - // Unlike `dlopen`, it's possible for `dlsym` to return null without overwriting `dlerror`. - // Because of this, we clear `dlerror` before calling `dlsym` to avoid picking up a stale - // error message by accident. - dlerror.clear(); - - let ret = libc::dlsym(handle as *mut libc::c_void, symbol); - - if !ret.is_null() { - return Ok(ret.cast()); - } - - // If `dlsym` returns null but there is nothing in `dlerror` it means one of two things: - // - We tried to load a symbol mapped to address 0. This is not technically an error but is - // unlikely to occur in practice and equally unlikely to be handled correctly by calling - // code. Therefore we treat it as an error anyway. - // - An error has occurred, but we are racing with another thread that has stolen our error - // message. See the explanation on the `dl::error` module for more information. - dlerror.get().and_then(|()| Err("Tried to load symbol mapped to address 0".to_string())) - } - - pub(super) unsafe fn close(handle: *mut u8) { - libc::dlclose(handle as *mut libc::c_void); - } -} - -#[cfg(windows)] -mod dl { - use std::ffi::OsStr; - use std::io; - use std::os::windows::prelude::*; - use std::ptr; - - use winapi::shared::minwindef::HMODULE; - use winapi::um::errhandlingapi::SetThreadErrorMode; - use winapi::um::libloaderapi::{FreeLibrary, GetProcAddress, LoadLibraryW}; - use winapi::um::winbase::SEM_FAILCRITICALERRORS; - - pub(super) fn open(filename: &OsStr) -> Result<*mut u8, String> { - // disable "dll load failed" error dialog. - let prev_error_mode = unsafe { - let new_error_mode = SEM_FAILCRITICALERRORS; - let mut prev_error_mode = 0; - let result = SetThreadErrorMode(new_error_mode, &mut prev_error_mode); - if result == 0 { - return Err(io::Error::last_os_error().to_string()); - } - prev_error_mode - }; - - let filename_str: Vec<_> = filename.encode_wide().chain(Some(0)).collect(); - let result = unsafe { LoadLibraryW(filename_str.as_ptr()) } as *mut u8; - let result = ptr_result(result); - - unsafe { - SetThreadErrorMode(prev_error_mode, ptr::null_mut()); - } - - result - } - - pub(super) unsafe fn symbol( - handle: *mut u8, - symbol: *const libc::c_char, - ) -> Result<*mut u8, String> { - let ptr = GetProcAddress(handle as HMODULE, symbol) as *mut u8; - ptr_result(ptr) - } - - pub(super) unsafe fn close(handle: *mut u8) { - FreeLibrary(handle as HMODULE); - } - - fn ptr_result(ptr: *mut T) -> Result<*mut T, String> { - if ptr.is_null() { Err(io::Error::last_os_error().to_string()) } else { Ok(ptr) } - } -} diff --git a/compiler/rustc_metadata/src/dynamic_lib/tests.rs b/compiler/rustc_metadata/src/dynamic_lib/tests.rs deleted file mode 100644 index 7090bbf61c..0000000000 --- a/compiler/rustc_metadata/src/dynamic_lib/tests.rs +++ /dev/null @@ -1,18 +0,0 @@ -use super::*; - -#[test] -fn test_errors_do_not_crash() { - use std::path::Path; - - if !cfg!(unix) { - return; - } - - // Open /dev/null as a library to get an error, and make sure - // that only causes an error, and not a crash. - let path = Path::new("/dev/null"); - match DynamicLibrary::open(&path) { - Err(_) => {} - Ok(_) => panic!("Successfully opened the empty library."), - } -} diff --git a/compiler/rustc_metadata/src/foreign_modules.rs b/compiler/rustc_metadata/src/foreign_modules.rs index 5b42f48a7d..c70a691452 100644 --- a/compiler/rustc_metadata/src/foreign_modules.rs +++ b/compiler/rustc_metadata/src/foreign_modules.rs @@ -13,7 +13,7 @@ struct Collector { modules: Vec, } -impl ItemLikeVisitor<'tcx> for Collector { +impl<'tcx> ItemLikeVisitor<'tcx> for Collector { fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) { let items = match it.kind { hir::ItemKind::ForeignMod { items, .. } => items, diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 6cf0dd8b1a..918c3b9daf 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -1,7 +1,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(crate_visibility_modifier)] #![feature(drain_filter)] -#![feature(in_band_lifetimes)] #![feature(let_else)] #![feature(nll)] #![feature(once_cell)] @@ -28,7 +27,6 @@ mod native_libs; mod rmeta; pub mod creader; -pub mod dynamic_lib; pub mod locator; pub use rmeta::{encode_metadata, EncodedMetadata, METADATA_HEADER}; diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 7cba16e0a9..13ea089e24 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -220,7 +220,7 @@ use rustc_data_structures::memmap::Mmap; use rustc_data_structures::owning_ref::OwningRef; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::MetadataRef; -use rustc_errors::struct_span_err; +use rustc_errors::{struct_span_err, FatalError}; use rustc_session::config::{self, CrateType}; use rustc_session::cstore::{CrateSource, MetadataLoader}; use rustc_session::filesearch::{FileDoesntMatch, FileMatches, FileSearch}; @@ -315,7 +315,7 @@ impl<'a> CrateLocator<'a> { exact_paths: if hash.is_none() { sess.opts .externs - .get(&crate_name.as_str()) + .get(crate_name.as_str()) .into_iter() .filter_map(|entry| entry.files()) .flatten() @@ -734,7 +734,7 @@ impl<'a> CrateLocator<'a> { } } -fn get_metadata_section( +fn get_metadata_section<'p>( target: &Target, flavor: CrateFlavor, filename: &'p Path, @@ -814,11 +814,11 @@ pub fn find_plugin_registrar( span: Span, name: Symbol, ) -> PathBuf { - match find_plugin_registrar_impl(sess, metadata_loader, name) { - Ok(res) => res, + find_plugin_registrar_impl(sess, metadata_loader, name).unwrap_or_else(|err| { // `core` is always available if we got as far as loading plugins. - Err(err) => err.report(sess, span, false), - } + err.report(sess, span, false); + FatalError.raise() + }) } fn find_plugin_registrar_impl<'a>( @@ -931,8 +931,8 @@ impl fmt::Display for MetadataError<'_> { } impl CrateError { - crate fn report(self, sess: &Session, span: Span, missing_core: bool) -> ! { - let mut err = match self { + crate fn report(self, sess: &Session, span: Span, missing_core: bool) { + let mut diag = match self { CrateError::NonAsciiName(crate_name) => sess.struct_span_err( span, &format!("cannot load a crate with a non-ascii name `{}`", crate_name), @@ -976,7 +976,8 @@ impl CrateError { let candidates = libraries .iter() .map(|lib| { - let crate_name = &lib.metadata.get_root().name().as_str(); + let crate_name = lib.metadata.get_root().name(); + let crate_name = crate_name.as_str(); let mut paths = lib.source.paths(); // This `unwrap()` should be okay because there has to be at least one @@ -1174,7 +1175,7 @@ impl CrateError { } else if crate_name == Symbol::intern(&sess.opts.debugging_opts.profiler_runtime) { - err.note(&"the compiler may have been built without the profiler runtime"); + err.note("the compiler may have been built without the profiler runtime"); } else if crate_name.as_str().starts_with("rustc_") { err.help( "maybe you need to install the missing components with: \ @@ -1210,8 +1211,6 @@ impl CrateError { ), }; - err.emit(); - sess.abort_if_errors(); - unreachable!(); + diag.emit(); } } diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index bd5cda15b9..639d2e617c 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -31,7 +31,7 @@ struct Collector<'tcx> { libs: Vec, } -impl ItemLikeVisitor<'tcx> for Collector<'tcx> { +impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> { fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) { let (abi, foreign_mod_items) = match it.kind { hir::ItemKind::ForeignMod { abi, items } => (abi, items), @@ -67,7 +67,7 @@ impl ItemLikeVisitor<'tcx> for Collector<'tcx> { Some(name) => name, None => continue, // skip like historical compilers }; - lib.kind = match &*kind.as_str() { + lib.kind = match kind.as_str() { "static" => NativeLibKind::Static { bundle: None, whole_archive: None }, "static-nobundle" => { sess.struct_span_warn( @@ -132,7 +132,7 @@ impl ItemLikeVisitor<'tcx> for Collector<'tcx> { if let Some(modifiers) = item.value_str() { let span = item.name_value_literal_span().unwrap(); for modifier in modifiers.as_str().split(',') { - let (modifier, value) = match modifier.strip_prefix(&['+', '-'][..]) { + let (modifier, value) = match modifier.strip_prefix(&['+', '-']) { Some(m) => (m, modifier.starts_with('+')), None => { sess.span_err( @@ -223,7 +223,7 @@ impl ItemLikeVisitor<'tcx> for Collector<'tcx> { fn visit_foreign_item(&mut self, _it: &'tcx hir::ForeignItem<'tcx>) {} } -impl Collector<'tcx> { +impl Collector<'_> { fn register_native_lib(&mut self, span: Option, lib: NativeLib) { if lib.name.as_ref().map_or(false, |&s| s == kw::Empty) { match span { diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index b2c7818a54..bb9a58a0b6 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -27,6 +27,7 @@ use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use rustc_middle::mir::{self, Body, Promoted}; use rustc_middle::thir; use rustc_middle::ty::codec::TyDecoder; +use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::{self, Ty, TyCtxt, Visibility}; use rustc_serialize::{opaque, Decodable, Decoder}; use rustc_session::cstore::{ @@ -45,7 +46,8 @@ use std::num::NonZeroUsize; use std::path::Path; use tracing::debug; -pub use cstore_impl::{provide, provide_extern}; +pub(super) use cstore_impl::provide; +pub use cstore_impl::provide_extern; use rustc_span::hygiene::HygieneDecodeContext; mod cstore_impl; @@ -91,8 +93,7 @@ crate struct CrateMetadata { /// Trait impl data. /// FIXME: Used only from queries and can use query cache, /// so pre-decoding can probably be avoided. - trait_impls: - FxHashMap<(u32, DefIndex), Lazy<[(DefIndex, Option)]>>, + trait_impls: FxHashMap<(u32, DefIndex), Lazy<[(DefIndex, Option)]>>, /// Proc macro descriptions for this crate, if it's a proc macro crate. raw_proc_macros: Option<&'static [ProcMacro]>, /// Source maps for code from the crate. @@ -628,7 +629,7 @@ where implement_ty_decoder!(DecodeContext<'a, 'tcx>); -impl MetadataBlob { +impl<'tcx> MetadataBlob { crate fn new(metadata_ref: MetadataRef) -> MetadataBlob { MetadataBlob(Lrc::new(metadata_ref)) } @@ -697,7 +698,7 @@ impl CrateRoot<'_> { &self.triple } - crate fn decode_crate_deps( + crate fn decode_crate_deps<'a>( &self, metadata: &'a MetadataBlob, ) -> impl ExactSizeIterator + Captures<'a> { @@ -721,25 +722,24 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { &self.raw_proc_macros.unwrap()[pos] } - fn try_item_ident(&self, item_index: DefIndex, sess: &Session) -> Result { - let name = self - .def_key(item_index) - .disambiguated_data - .data - .get_opt_name() - .ok_or_else(|| format!("Missing opt name for {:?}", item_index))?; - let span = self - .root - .tables - .ident_span - .get(self, item_index) - .ok_or_else(|| format!("Missing ident span for {:?} ({:?})", name, item_index))? - .decode((self, sess)); - Ok(Ident::new(name, span)) + fn opt_item_ident(&self, item_index: DefIndex, sess: &Session) -> Option { + let name = self.def_key(item_index).disambiguated_data.data.get_opt_name()?; + let span = match self.root.tables.ident_span.get(self, item_index) { + Some(lazy_span) => lazy_span.decode((self, sess)), + None => { + // FIXME: this weird case of a name with no span is specific to `extern crate` + // items, which are supposed to be treated like `use` items and only be encoded + // to metadata as `Export`s, return `None` because that's what all the callers + // expect in this case. + assert_eq!(self.def_kind(item_index), DefKind::ExternCrate); + return None; + } + }; + Some(Ident::new(name, span)) } fn item_ident(&self, item_index: DefIndex, sess: &Session) -> Ident { - self.try_item_ident(item_index, sess).unwrap() + self.opt_item_ident(item_index, sess).expect("no encoded ident for item") } fn maybe_kind(&self, item_id: DefIndex) -> Option { @@ -1099,70 +1099,29 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { }; // Iterate over all children. - let macros_only = self.dep_kind.lock().macros_only(); - if !macros_only { - let children = self.root.tables.children.get(self, id).unwrap_or_else(Lazy::empty); - + if let Some(children) = self.root.tables.children.get(self, id) { for child_index in children.decode((self, sess)) { - // Get the item. - let child_kind = match self.maybe_kind(child_index) { - Some(child_kind) => child_kind, - None => continue, - }; - - // Hand off the item to the callback. - match child_kind { - // FIXME(eddyb) Don't encode these in children. - EntryKind::ForeignMod => { - let child_children = self - .root - .tables - .children - .get(self, child_index) - .unwrap_or_else(Lazy::empty); - for child_index in child_children.decode((self, sess)) { - let kind = self.def_kind(child_index); - callback(Export { - res: Res::Def(kind, self.local_def_id(child_index)), - ident: self.item_ident(child_index, sess), - vis: self.get_visibility(child_index), - span: self - .root - .tables - .span - .get(self, child_index) - .unwrap() - .decode((self, sess)), - }); - } + if let Some(ident) = self.opt_item_ident(child_index, sess) { + let kind = self.def_kind(child_index); + if matches!(kind, DefKind::Macro(..)) { + // FIXME: Macros are currently encoded twice, once as items and once as + // reexports. We ignore the items here and only use the reexports. continue; } - EntryKind::Impl(_) => continue, - - _ => {} - } - - let def_key = self.def_key(child_index); - if def_key.disambiguated_data.data.get_opt_name().is_some() { - let span = self.get_span(child_index, sess); - let kind = self.def_kind(child_index); - let ident = self.item_ident(child_index, sess); - let vis = self.get_visibility(child_index); let def_id = self.local_def_id(child_index); let res = Res::Def(kind, def_id); + let vis = self.get_visibility(child_index); + let span = self.get_span(child_index, sess); - // FIXME: Macros are currently encoded twice, once as items and once as - // reexports. We ignore the items here and only use the reexports. - if !matches!(kind, DefKind::Macro(..)) { - callback(Export { res, ident, vis, span }); - } + callback(Export { ident, res, vis, span }); // For non-re-export structs and variants add their constructors to children. // Re-export lists automatically contain constructors when necessary. match kind { DefKind::Struct => { - if let Some(ctor_def_id) = self.get_ctor_def_id(child_index) { - let ctor_kind = self.get_ctor_kind(child_index); + if let Some((ctor_def_id, ctor_kind)) = + self.get_ctor_def_id_and_kind(child_index) + { let ctor_res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id); let vis = self.get_visibility(ctor_def_id.index); @@ -1174,8 +1133,9 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { // value namespace, they are reserved for possible future use. // It's ok to use the variant's id as a ctor id since an // error will be reported on any use of such resolution anyway. - let ctor_def_id = self.get_ctor_def_id(child_index).unwrap_or(def_id); - let ctor_kind = self.get_ctor_kind(child_index); + let (ctor_def_id, ctor_kind) = self + .get_ctor_def_id_and_kind(child_index) + .unwrap_or((def_id, CtorKind::Fictive)); let ctor_res = Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id); let mut vis = self.get_visibility(ctor_def_id.index); @@ -1200,11 +1160,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { if let EntryKind::Mod(exports) = kind { for exp in exports.decode((self, sess)) { - match exp.res { - Res::Def(DefKind::Macro(..), _) => {} - _ if macros_only => continue, - _ => {} - } callback(exp); } } @@ -1296,6 +1251,13 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } } + fn get_fn_has_self_parameter(&self, id: DefIndex) -> bool { + match self.kind(id) { + EntryKind::AssocFn(data) => data.decode(self).has_self, + _ => false, + } + } + fn get_associated_item(&self, id: DefIndex, sess: &Session) -> ty::AssocItem { let def_key = self.def_key(id); let parent = self.local_def_id(def_key.parent.unwrap()); @@ -1326,22 +1288,11 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.root.tables.variances.get(self, id).unwrap_or_else(Lazy::empty).decode(self) } - fn get_ctor_kind(&self, node_id: DefIndex) -> CtorKind { + fn get_ctor_def_id_and_kind(&self, node_id: DefIndex) -> Option<(DefId, CtorKind)> { match self.kind(node_id) { - EntryKind::Struct(data, _) | EntryKind::Union(data, _) | EntryKind::Variant(data) => { - data.decode(self).ctor_kind - } - _ => CtorKind::Fictive, - } - } - - fn get_ctor_def_id(&self, node_id: DefIndex) -> Option { - match self.kind(node_id) { - EntryKind::Struct(data, _) => { - data.decode(self).ctor.map(|index| self.local_def_id(index)) - } - EntryKind::Variant(data) => { - data.decode(self).ctor.map(|index| self.local_def_id(index)) + EntryKind::Struct(data, _) | EntryKind::Variant(data) => { + let vdata = data.decode(self); + vdata.ctor.map(|index| (self.local_def_id(index), vdata.ctor_kind)) } _ => None, } @@ -1349,24 +1300,26 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { fn get_item_attrs( &'a self, - node_id: DefIndex, + id: DefIndex, sess: &'a Session, ) -> impl Iterator + 'a { - // The attributes for a tuple struct/variant are attached to the definition, not the ctor; - // we assume that someone passing in a tuple struct ctor is actually wanting to - // look at the definition - let def_key = self.def_key(node_id); - let item_id = if def_key.disambiguated_data.data == DefPathData::Ctor { - def_key.parent.unwrap() - } else { - node_id - }; - self.root .tables .attributes - .get(self, item_id) - .unwrap_or_else(Lazy::empty) + .get(self, id) + .unwrap_or_else(|| { + // Structure and variant constructors don't have any attributes encoded for them, + // but we assume that someone passing a constructor ID actually wants to look at + // the attributes on the corresponding struct or variant. + let def_key = self.def_key(id); + assert_eq!(def_key.disambiguated_data.data, DefPathData::Ctor); + let parent_id = def_key.parent.expect("no parent for a constructor"); + self.root + .tables + .attributes + .get(self, parent_id) + .expect("no encoded attributes for a structure or variant") + }) .decode((self, sess)) } @@ -1408,39 +1361,43 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { ) } - fn get_implementations_for_trait( + fn get_traits(&'a self) -> impl Iterator + 'a { + self.root.traits.decode(self).map(|index| self.local_def_id(index)) + } + + fn get_trait_impls(&'a self) -> impl Iterator)> + 'a { + self.trait_impls.values().flat_map(move |impls| { + impls + .decode(self) + .map(|(idx, simplified_self_ty)| (self.local_def_id(idx), simplified_self_ty)) + }) + } + + fn get_implementations_of_trait( &self, tcx: TyCtxt<'tcx>, - filter: Option, - ) -> &'tcx [(DefId, Option)] { + trait_def_id: DefId, + ) -> &'tcx [(DefId, Option)] { if self.root.is_proc_macro_crate() { // proc-macro crates export no trait impls. return &[]; } - if let Some(def_id) = filter { - // Do a reverse lookup beforehand to avoid touching the crate_num - // hash map in the loop below. - let filter = match self.reverse_translate_def_id(def_id) { - Some(def_id) => (def_id.krate.as_u32(), def_id.index), - None => return &[], - }; + // Do a reverse lookup beforehand to avoid touching the crate_num + // hash map in the loop below. + let key = match self.reverse_translate_def_id(trait_def_id) { + Some(def_id) => (def_id.krate.as_u32(), def_id.index), + None => return &[], + }; - if let Some(impls) = self.trait_impls.get(&filter) { - tcx.arena.alloc_from_iter( - impls.decode(self).map(|(idx, simplified_self_ty)| { - (self.local_def_id(idx), simplified_self_ty) - }), - ) - } else { - &[] - } - } else { - tcx.arena.alloc_from_iter(self.trait_impls.values().flat_map(|impls| { + if let Some(impls) = self.trait_impls.get(&key) { + tcx.arena.alloc_from_iter( impls .decode(self) - .map(|(idx, simplified_self_ty)| (self.local_def_id(idx), simplified_self_ty)) - })) + .map(|(idx, simplified_self_ty)| (self.local_def_id(idx), simplified_self_ty)), + ) + } else { + &[] } } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index eeb0a77adc..aac0aa61ea 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -17,7 +17,7 @@ use rustc_session::utils::NativeLibKind; use rustc_session::{Session, StableCrateId}; use rustc_span::hygiene::{ExpnHash, ExpnId}; use rustc_span::source_map::{Span, Spanned}; -use rustc_span::symbol::Symbol; +use rustc_span::symbol::{kw, Symbol}; use rustc_data_structures::sync::Lrc; use smallvec::SmallVec; @@ -83,7 +83,7 @@ impl IntoArgs for (CrateNum, DefId) { } } -impl IntoArgs for ty::InstanceDef<'tcx> { +impl<'tcx> IntoArgs for ty::InstanceDef<'tcx> { fn into_args(self) -> (DefId, DefId) { (self.def_id(), self.def_id()) } @@ -133,9 +133,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, generator_kind => { cdata.generator_kind(def_id.index) } opt_def_kind => { Some(cdata.def_kind(def_id.index)) } def_span => { cdata.get_span(def_id.index, &tcx.sess) } - def_ident_span => { - cdata.try_item_ident(def_id.index, &tcx.sess).ok().map(|ident| ident.span) - } + def_ident_span => { cdata.opt_item_ident(def_id.index, &tcx.sess).map(|ident| ident.span) } lookup_stability => { cdata.get_stability(def_id.index).map(|s| tcx.intern_stability(s)) } @@ -145,9 +143,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, lookup_deprecation_entry => { cdata.get_deprecation(def_id.index).map(DeprecationEntry::external) } - item_attrs => { tcx.arena.alloc_from_iter( - cdata.get_item_attrs(def_id.index, tcx.sess) - ) } + item_attrs => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(def_id.index, tcx.sess)) } fn_arg_names => { cdata.get_fn_param_names(tcx, def_id.index) } rendered_const => { cdata.get_rendered_const(def_id.index) } impl_parent => { cdata.get_parent_impl(def_id.index) } @@ -195,13 +191,10 @@ provide! { <'tcx> tcx, def_id, other, cdata, extra_filename => { cdata.root.extra_filename.clone() } - implementations_of_trait => { - cdata.get_implementations_for_trait(tcx, Some(other)) - } + traits_in_crate => { tcx.arena.alloc_from_iter(cdata.get_traits()) } + all_trait_implementations => { tcx.arena.alloc_from_iter(cdata.get_trait_impls()) } - all_trait_implementations => { - cdata.get_implementations_for_trait(tcx, None) - } + implementations_of_trait => { cdata.get_implementations_of_trait(tcx, other) } visibility => { cdata.get_visibility(def_id.index) } dep_kind => { @@ -239,7 +232,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, expn_that_defined => { cdata.get_expn_that_defined(def_id.index, tcx.sess) } } -pub fn provide(providers: &mut Providers) { +pub(in crate::rmeta) fn provide(providers: &mut Providers) { // FIXME(#44234) - almost all of these queries have no sub-queries and // therefore no actual inputs, they're just reading tables calculated in // resolve! Does this work? Unsure! That's what the issue is about @@ -295,6 +288,10 @@ pub fn provide(providers: &mut Providers) { use std::collections::vec_deque::VecDeque; let mut visible_parent_map: DefIdMap = Default::default(); + // This is a secondary visible_parent_map, storing the DefId of parents that re-export + // the child as `_`. Since we prefer parents that don't do this, merge this map at the + // end, only if we're missing any keys from the former. + let mut fallback_map: DefIdMap = Default::default(); // Issue 46112: We want the map to prefer the shortest // paths when reporting the path to an item. Therefore we @@ -317,12 +314,17 @@ pub fn provide(providers: &mut Providers) { bfs_queue.push_back(DefId { krate: cnum, index: CRATE_DEF_INDEX }); } - let mut add_child = |bfs_queue: &mut VecDeque<_>, child: &Export, parent: DefId| { - if !child.vis.is_public() { + let mut add_child = |bfs_queue: &mut VecDeque<_>, export: &Export, parent: DefId| { + if !export.vis.is_public() { return; } - if let Some(child) = child.res.opt_def_id() { + if let Some(child) = export.res.opt_def_id() { + if export.ident.name == kw::Underscore { + fallback_map.insert(child, parent); + return; + } + match visible_parent_map.entry(child) { Entry::Occupied(mut entry) => { // If `child` is defined in crate `cnum`, ensure @@ -345,6 +347,12 @@ pub fn provide(providers: &mut Providers) { } } + // Fill in any missing entries with the (less preferable) path ending in `::_`. + // We still use this path in a diagnostic that suggests importing `::*`. + for (child, parent) in fallback_map { + visible_parent_map.entry(child).or_insert(parent); + } + visible_parent_map }, @@ -357,7 +365,7 @@ pub fn provide(providers: &mut Providers) { tcx.arena .alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE)) }, - crates: |tcx, ()| tcx.arena.alloc_slice(&CStore::from_tcx(tcx).crates_untracked()), + crates: |tcx, ()| tcx.arena.alloc_from_iter(CStore::from_tcx(tcx).crates_untracked()), ..*providers }; @@ -373,9 +381,7 @@ impl CStore { } pub fn ctor_def_id_and_kind_untracked(&self, def: DefId) -> Option<(DefId, CtorKind)> { - self.get_crate_data(def.krate).get_ctor_def_id(def.index).map(|ctor_def_id| { - (ctor_def_id, self.get_crate_data(def.krate).get_ctor_kind(def.index)) - }) + self.get_crate_data(def.krate).get_ctor_def_id_and_kind(def.index) } pub fn visibility_untracked(&self, def: DefId) -> Visibility { @@ -402,16 +408,12 @@ impl CStore { let span = data.get_span(id.index, sess); - let attrs = data.get_item_attrs(id.index, sess).collect(); - - let ident = data.item_ident(id.index, sess); - LoadedMacro::MacroDef( ast::Item { - ident, + ident: data.item_ident(id.index, sess), id: ast::DUMMY_NODE_ID, span, - attrs, + attrs: data.get_item_attrs(id.index, sess).collect(), kind: ast::ItemKind::MacroDef(data.get_macro(id.index, sess)), vis: ast::Visibility { span: span.shrink_to_lo(), @@ -424,8 +426,8 @@ impl CStore { ) } - pub fn associated_item_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::AssocItem { - self.get_crate_data(def.krate).get_associated_item(def.index, sess) + pub fn fn_has_self_parameter_untracked(&self, def: DefId) -> bool { + self.get_crate_data(def.krate).get_fn_has_self_parameter(def.index) } pub fn crate_source_untracked(&self, cnum: CrateNum) -> CrateSource { @@ -440,10 +442,8 @@ impl CStore { self.get_crate_data(def.krate).def_kind(def.index) } - pub fn crates_untracked(&self) -> Vec { - let mut result = vec![]; - self.iter_crate_data(|cnum, _| result.push(cnum)); - result + pub fn crates_untracked(&self) -> impl Iterator + '_ { + self.iter_crate_data().map(|(cnum, _)| cnum) } pub fn item_generics_num_lifetimes(&self, def_id: DefId, sess: &Session) -> usize { @@ -461,7 +461,7 @@ impl CStore { self.get_crate_data(cnum).num_def_ids() } - pub fn item_attrs(&self, def_id: DefId, sess: &Session) -> Vec { + pub fn item_attrs_untracked(&self, def_id: DefId, sess: &Session) -> Vec { self.get_crate_data(def_id.krate).get_item_attrs(def_id.index, sess).collect() } @@ -521,4 +521,8 @@ impl CrateStore for CStore { ) -> ExpnId { self.get_crate_data(cnum).expn_hash_to_expn_id(sess, index_guess, hash) } + + fn import_source_files(&self, sess: &Session, cnum: CrateNum) { + self.get_crate_data(cnum).imported_source_files(sess); + } } diff --git a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs index d6435bb649..054431169a 100644 --- a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs +++ b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs @@ -11,7 +11,7 @@ crate enum DefPathHashMapRef<'tcx> { BorrowedFromTcx(&'tcx DefPathHashMap), } -impl DefPathHashMapRef<'tcx> { +impl DefPathHashMapRef<'_> { #[inline] pub fn def_path_hash_to_def_index(&self, def_path_hash: &DefPathHash) -> DefIndex { match *self { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index d46829c2ce..12d66f4fc4 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -26,6 +26,8 @@ use rustc_middle::mir::interpret; use rustc_middle::thir; use rustc_middle::traits::specialization_graph; use rustc_middle::ty::codec::TyEncoder; +use rustc_middle::ty::fast_reject::{self, SimplifiedType, SimplifyParams, StripReferences}; +use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt}; use rustc_serialize::{opaque, Encodable, Encoder}; use rustc_session::config::CrateType; @@ -611,10 +613,15 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_def_path_table(); let def_path_table_bytes = self.position() - i; + // Encode the def IDs of traits, for rustdoc and diagnostics. + i = self.position(); + let traits = self.encode_traits(); + let traits_bytes = self.position() - i; + // Encode the def IDs of impls, for coherence checking. i = self.position(); let impls = self.encode_impls(); - let impl_bytes = self.position() - i; + let impls_bytes = self.position() - i; let tcx = self.tcx; @@ -714,7 +721,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { no_builtins: tcx.sess.contains_name(&attrs, sym::no_builtins), panic_runtime: tcx.sess.contains_name(&attrs, sym::panic_runtime), profiler_runtime: tcx.sess.contains_name(&attrs, sym::profiler_runtime), - symbol_mangling_version: tcx.sess.opts.debugging_opts.get_symbol_mangling_version(), + symbol_mangling_version: tcx.sess.opts.get_symbol_mangling_version(), crate_deps, dylib_dependency_formats, @@ -725,6 +732,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { native_libraries, foreign_modules, source_map, + traits, impls, exported_symbols, interpret_alloc_index, @@ -752,7 +760,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { eprintln!(" diagnostic item bytes: {}", diagnostic_item_bytes); eprintln!(" native bytes: {}", native_lib_bytes); eprintln!(" source_map bytes: {}", source_map_bytes); - eprintln!(" impl bytes: {}", impl_bytes); + eprintln!(" traits bytes: {}", traits_bytes); + eprintln!(" impls bytes: {}", impls_bytes); eprintln!(" exp. symbols bytes: {}", exported_symbols_bytes); eprintln!(" def-path table bytes: {}", def_path_table_bytes); eprintln!(" def-path hashes bytes: {}", def_path_hash_map_bytes); @@ -869,8 +878,9 @@ fn should_encode_mir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> (bool, bool) { let needs_inline = (generics.requires_monomorphization(tcx) || tcx.codegen_fn_attrs(def_id).requests_inline()) && tcx.sess.opts.output_types.should_codegen(); - // Only check the presence of the `const` modifier. - let is_const_fn = tcx.is_const_fn_raw(def_id.to_def_id()); + // The function has a `const` modifier or is annotated with `default_method_body_is_const`. + let is_const_fn = tcx.is_const_fn_raw(def_id.to_def_id()) + || tcx.has_attr(def_id.to_def_id(), sym::default_method_body_is_const); let always_encode_mir = tcx.sess.opts.debugging_opts.always_encode_mir; (is_const_fn, needs_inline || always_encode_mir) } @@ -962,7 +972,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool { } } -impl EncodeContext<'a, 'tcx> { +impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_def_ids(&mut self) { if self.is_proc_macro { return; @@ -1098,9 +1108,21 @@ impl EncodeContext<'a, 'tcx> { // Encode this here because we don't do it in encode_def_ids. record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id)); } else { - record!(self.tables.children[def_id] <- md.item_ids.iter().map(|item_id| { - item_id.def_id.local_def_index - })); + let direct_children = md.item_ids.iter().map(|item_id| item_id.def_id.local_def_index); + // Foreign items are planted into their parent modules from name resolution point of view. + let tcx = self.tcx; + let foreign_item_children = md + .item_ids + .iter() + .filter_map(|item_id| match tcx.hir().item(*item_id).kind { + hir::ItemKind::ForeignMod { items, .. } => { + Some(items.iter().map(|fi_ref| fi_ref.id.def_id.local_def_index)) + } + _ => None, + }) + .flatten(); + + record!(self.tables.children[def_id] <- direct_children.chain(foreign_item_children)); } } @@ -1152,8 +1174,7 @@ impl EncodeContext<'a, 'tcx> { debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id); let tcx = self.tcx; - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - let ast_item = tcx.hir().expect_trait_item(hir_id); + let ast_item = tcx.hir().expect_trait_item(def_id.expect_local()); let trait_item = tcx.associated_item(def_id); let container = match trait_item.defaultness { @@ -1221,8 +1242,7 @@ impl EncodeContext<'a, 'tcx> { debug!("EncodeContext::encode_info_for_impl_item({:?})", def_id); let tcx = self.tcx; - let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - let ast_item = self.tcx.hir().expect_impl_item(hir_id); + let ast_item = self.tcx.hir().expect_impl_item(def_id.expect_local()); let impl_item = self.tcx.associated_item(def_id); let container = match impl_item.defaultness { @@ -1306,7 +1326,7 @@ impl EncodeContext<'a, 'tcx> { }) .collect::>(); // Sort everything to ensure a stable order for diagnotics. - keys_and_jobs.sort_by_key(|&(def_id, _, _)| def_id); + keys_and_jobs.sort_by_key(|&(def_id, _, _)| def_id.index()); for (def_id, encode_const, encode_opt) in keys_and_jobs.into_iter() { debug_assert!(encode_const || encode_opt); @@ -1503,11 +1523,6 @@ impl EncodeContext<'a, 'tcx> { record!(self.tables.kind[def_id] <- entry_kind); // FIXME(eddyb) there should be a nicer way to do this. match item.kind { - hir::ItemKind::ForeignMod { items, .. } => record!(self.tables.children[def_id] <- - items - .iter() - .map(|foreign_item| foreign_item.id.def_id.local_def_index) - ), hir::ItemKind::Enum(..) => record!(self.tables.children[def_id] <- self.tcx.adt_def(def_id).variants.iter().map(|v| { assert!(v.def_id.is_local()); @@ -1751,7 +1766,7 @@ impl EncodeContext<'a, 'tcx> { fn encode_lib_features(&mut self) -> Lazy<[(Symbol, Option)]> { empty_proc_macro!(self); let tcx = self.tcx; - let lib_features = tcx.lib_features(); + let lib_features = tcx.lib_features(()); self.lazy(lib_features.to_vec()) } @@ -1783,12 +1798,17 @@ impl EncodeContext<'a, 'tcx> { self.lazy(&tcx.lang_items().missing) } + fn encode_traits(&mut self) -> Lazy<[DefIndex]> { + empty_proc_macro!(self); + self.lazy(self.tcx.traits_in_crate(LOCAL_CRATE).iter().map(|def_id| def_id.index)) + } + /// Encodes an index, mapping each trait to its (local) implementations. fn encode_impls(&mut self) -> Lazy<[TraitImpls]> { + debug!("EncodeContext::encode_traits_and_impls()"); empty_proc_macro!(self); - debug!("EncodeContext::encode_impls()"); let tcx = self.tcx; - let mut visitor = ImplVisitor { tcx, impls: FxHashMap::default() }; + let mut visitor = ImplsVisitor { tcx, impls: FxHashMap::default() }; tcx.hir().visit_all_item_likes(&mut visitor); let mut all_impls: Vec<_> = visitor.impls.into_iter().collect(); @@ -1894,7 +1914,7 @@ impl EncodeContext<'a, 'tcx> { } // FIXME(eddyb) make metadata encoding walk over all definitions, instead of HIR. -impl Visitor<'tcx> for EncodeContext<'a, 'tcx> { +impl<'a, 'tcx> Visitor<'tcx> for EncodeContext<'a, 'tcx> { type Map = Map<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -1927,7 +1947,7 @@ impl Visitor<'tcx> for EncodeContext<'a, 'tcx> { } } -impl EncodeContext<'a, 'tcx> { +impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_fields(&mut self, adt_def: &ty::AdtDef) { for (variant_index, variant) in adt_def.variants.iter_enumerated() { for (field_index, _field) in variant.fields.iter().enumerate() { @@ -2033,23 +2053,30 @@ impl EncodeContext<'a, 'tcx> { } } -struct ImplVisitor<'tcx> { +struct ImplsVisitor<'tcx> { tcx: TyCtxt<'tcx>, - impls: FxHashMap)>>, + impls: FxHashMap)>>, } -impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> { +impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplsVisitor<'tcx> { fn visit_item(&mut self, item: &hir::Item<'_>) { - if let hir::ItemKind::Impl { .. } = item.kind { - if let Some(trait_ref) = self.tcx.impl_trait_ref(item.def_id.to_def_id()) { - let simplified_self_ty = - ty::fast_reject::simplify_type(self.tcx, trait_ref.self_ty(), false); + match item.kind { + hir::ItemKind::Impl(..) => { + if let Some(trait_ref) = self.tcx.impl_trait_ref(item.def_id.to_def_id()) { + let simplified_self_ty = fast_reject::simplify_type( + self.tcx, + trait_ref.self_ty(), + SimplifyParams::No, + StripReferences::No, + ); - self.impls - .entry(trait_ref.def_id) - .or_default() - .push((item.def_id.local_def_index, simplified_self_ty)); + self.impls + .entry(trait_ref.def_id) + .or_default() + .push((item.def_id.local_def_index, simplified_self_ty)); + } } + _ => {} } } @@ -2121,7 +2148,7 @@ impl EncodedMetadata { #[inline] pub fn raw_data(&self) -> &[u8] { - &self.raw_data[..] + &self.raw_data } } @@ -2198,3 +2225,34 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata { EncodedMetadata { raw_data: result } } + +pub fn provide(providers: &mut Providers) { + *providers = Providers { + traits_in_crate: |tcx, cnum| { + assert_eq!(cnum, LOCAL_CRATE); + + #[derive(Default)] + struct TraitsVisitor { + traits: Vec, + } + impl ItemLikeVisitor<'_> for TraitsVisitor { + fn visit_item(&mut self, item: &hir::Item<'_>) { + if let hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) = item.kind { + self.traits.push(item.def_id.to_def_id()); + } + } + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {} + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {} + fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {} + } + + let mut visitor = TraitsVisitor::default(); + tcx.hir().visit_all_item_likes(&mut visitor); + // Bring everything into deterministic order. + visitor.traits.sort_by_cached_key(|&def_id| tcx.def_path_hash(def_id)); + tcx.arena.alloc_slice(&visitor.traits) + }, + + ..*providers + }; +} diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 4e09d23169..4076e0b9e0 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -16,6 +16,8 @@ use rustc_middle::hir::exports::Export; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc_middle::mir; use rustc_middle::thir; +use rustc_middle::ty::fast_reject::SimplifiedType; +use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, ReprOptions, Ty}; use rustc_serialize::opaque::Encoder; use rustc_session::config::SymbolManglingVersion; @@ -29,8 +31,8 @@ use rustc_target::spec::{PanicStrategy, TargetTriple}; use std::marker::PhantomData; use std::num::NonZeroUsize; +pub use decoder::provide_extern; use decoder::DecodeContext; -pub use decoder::{provide, provide_extern}; crate use decoder::{CrateMetadata, CrateNumMap, MetadataBlob}; use encoder::EncodeContext; pub use encoder::{encode_metadata, EncodedMetadata}; @@ -48,7 +50,7 @@ crate fn rustc_version() -> String { /// Metadata encoding version. /// N.B., increment this if you change the format of metadata such that /// the rustc version can't be found to compare with `rustc_version()`. -const METADATA_VERSION: u8 = 5; +const METADATA_VERSION: u8 = 6; /// Metadata header which includes `METADATA_VERSION`. /// @@ -222,6 +224,7 @@ crate struct CrateRoot<'tcx> { diagnostic_items: Lazy<[(Symbol, DefIndex)]>, native_libraries: Lazy<[NativeLib]>, foreign_modules: Lazy<[ForeignModule]>, + traits: Lazy<[DefIndex]>, impls: Lazy<[TraitImpls]>, interpret_alloc_index: Lazy<[u32]>, proc_macro_data: Option, @@ -259,7 +262,7 @@ crate struct CrateDep { #[derive(MetadataEncodable, MetadataDecodable)] crate struct TraitImpls { trait_id: (u32, DefIndex), - impls: Lazy<[(DefIndex, Option)]>, + impls: Lazy<[(DefIndex, Option)]>, } /// Define `LazyTables` and `TableBuilders` at the same time. @@ -275,7 +278,7 @@ macro_rules! define_tables { $($name: TableBuilder<$IDX, $T>),+ } - impl TableBuilders<'tcx> { + impl<'tcx> TableBuilders<'tcx> { fn encode(&self, buf: &mut Encoder) -> LazyTables<'tcx> { LazyTables { $($name: self.$name.encode(buf)),+ @@ -453,3 +456,8 @@ struct GeneratorData<'tcx> { const TAG_VALID_SPAN_LOCAL: u8 = 0; const TAG_VALID_SPAN_FOREIGN: u8 = 1; const TAG_PARTIAL_SPAN: u8 = 2; + +pub fn provide(providers: &mut Providers) { + encoder::provide(providers); + decoder::provide(providers); +} diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index daeccde602..a9db846938 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -29,7 +29,7 @@ rustc_index = { path = "../rustc_index" } rustc_serialize = { path = "../rustc_serialize" } rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } -chalk-ir = "0.55.0" +chalk-ir = "0.75.0" smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } rustc_session = { path = "../rustc_session" } rustc_type_ir = { path = "../rustc_type_ir" } diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index ee2e190e7c..a936852f4e 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -9,7 +9,7 @@ macro_rules! arena_types { [] layout: rustc_target::abi::Layout, [] fn_abi: rustc_target::abi::call::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>, // AdtDef are interned and compared by address - [] adt_def: rustc_middle::ty::AdtDef, + [decode] adt_def: rustc_middle::ty::AdtDef, [] steal_thir: rustc_data_structures::steal::Steal>, [] steal_mir: rustc_data_structures::steal::Steal>, [decode] mir: rustc_middle::mir::Body<'tcx>, diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index f310001077..5c7cdbe4c2 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -201,7 +201,7 @@ crate fn make_compile_codegen_unit(tcx: TyCtxt<'_>, name: Symbol) -> DepNode { // WARNING: `construct` is generic and does not know that `CompileMonoItem` takes `MonoItem`s as keys. // Be very careful changing this type signature! -crate fn make_compile_mono_item(tcx: TyCtxt<'tcx>, mono_item: &MonoItem<'tcx>) -> DepNode { +crate fn make_compile_mono_item<'tcx>(tcx: TyCtxt<'tcx>, mono_item: &MonoItem<'tcx>) -> DepNode { DepNode::construct(tcx, DepKind::CompileMonoItem, mono_item) } @@ -264,7 +264,7 @@ impl DepNodeExt for DepNode { /// DepNode. Condition (2) might not be fulfilled if a DepNode /// refers to something from the previous compilation session that /// has been removed. - fn extract_def_id(&self, tcx: TyCtxt<'tcx>) -> Option { + fn extract_def_id<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option { if self.kind.fingerprint_style(tcx) == FingerprintStyle::DefPathHash { Some(tcx.def_path_hash_to_def_id(DefPathHash(self.hash.into()))) } else { diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index d9d0781b37..394a1fc227 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -474,7 +474,8 @@ impl<'hir> Map<'hir> { /// Panics if `LocalDefId` does not have an associated body. /// /// This should only be used for determining the context of a body, a return - /// value of `Some` does not always suggest that the owner of the body is `const`. + /// value of `Some` does not always suggest that the owner of the body is `const`, + /// just that it has to be checked as if it were. pub fn body_const_context(&self, did: LocalDefId) -> Option { let hir_id = self.local_def_id_to_hir_id(did); let ccx = match self.body_owner_kind(hir_id) { @@ -869,24 +870,24 @@ impl<'hir> Map<'hir> { bug!("expected foreign mod or inlined parent, found {}", self.node_to_string(parent)) } - pub fn expect_item(&self, id: HirId) -> &'hir Item<'hir> { - match self.tcx.hir_owner(id.expect_owner()) { + pub fn expect_item(&self, id: LocalDefId) -> &'hir Item<'hir> { + match self.tcx.hir_owner(id) { Some(Owner { node: OwnerNode::Item(item), .. }) => item, - _ => bug!("expected item, found {}", self.node_to_string(id)), + _ => bug!("expected item, found {}", self.node_to_string(HirId::make_owner(id))), } } - pub fn expect_impl_item(&self, id: HirId) -> &'hir ImplItem<'hir> { - match self.tcx.hir_owner(id.expect_owner()) { + pub fn expect_impl_item(&self, id: LocalDefId) -> &'hir ImplItem<'hir> { + match self.tcx.hir_owner(id) { Some(Owner { node: OwnerNode::ImplItem(item), .. }) => item, - _ => bug!("expected impl item, found {}", self.node_to_string(id)), + _ => bug!("expected impl item, found {}", self.node_to_string(HirId::make_owner(id))), } } - pub fn expect_trait_item(&self, id: HirId) -> &'hir TraitItem<'hir> { - match self.tcx.hir_owner(id.expect_owner()) { + pub fn expect_trait_item(&self, id: LocalDefId) -> &'hir TraitItem<'hir> { + match self.tcx.hir_owner(id) { Some(Owner { node: OwnerNode::TraitItem(item), .. }) => item, - _ => bug!("expected trait item, found {}", self.node_to_string(id)), + _ => bug!("expected trait item, found {}", self.node_to_string(HirId::make_owner(id))), } } @@ -897,10 +898,12 @@ impl<'hir> Map<'hir> { } } - pub fn expect_foreign_item(&self, id: HirId) -> &'hir ForeignItem<'hir> { - match self.tcx.hir_owner(id.expect_owner()) { + pub fn expect_foreign_item(&self, id: LocalDefId) -> &'hir ForeignItem<'hir> { + match self.tcx.hir_owner(id) { Some(Owner { node: OwnerNode::ForeignItem(item), .. }) => item, - _ => bug!("expected foreign item, found {}", self.node_to_string(id)), + _ => { + bug!("expected foreign item, found {}", self.node_to_string(HirId::make_owner(id))) + } } } diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index d764d45ba7..605fff671d 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -75,7 +75,7 @@ pub struct OriginalQueryValues<'tcx> { pub var_values: SmallVec<[GenericArg<'tcx>; 8]>, } -impl Default for OriginalQueryValues<'tcx> { +impl<'tcx> Default for OriginalQueryValues<'tcx> { fn default() -> Self { let mut universe_map = SmallVec::default(); universe_map.push(ty::UniverseIndex::ROOT); @@ -246,6 +246,14 @@ impl<'tcx, R> Canonical<'tcx, QueryResponse<'tcx, R>> { } } +impl<'tcx, R> Canonical<'tcx, ty::ParamEnvAnd<'tcx, R>> { + #[inline] + pub fn without_const(mut self) -> Self { + self.value = self.value.without_const(); + self + } +} + impl<'tcx, V> Canonical<'tcx, V> { /// Allows you to map the `value` of a canonical while keeping the /// same set of bound variables. diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index 0b05dd5c0b..dcc49a5357 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -164,7 +164,7 @@ impl<'tcx> UnifyValue for ConstVarValue<'tcx> { impl<'tcx> EqUnifyValue for &'tcx ty::Const<'tcx> {} -pub fn replace_if_possible( +pub fn replace_if_possible<'tcx, V, L>( table: &mut UnificationTable, V, L>>, c: &'tcx ty::Const<'tcx>, ) -> &'tcx ty::Const<'tcx> diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 9ce9f65a49..e6dd4e484c 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -33,6 +33,7 @@ #![feature(derive_default_enum)] #![feature(discriminant_kind)] #![feature(exhaustive_patterns)] +#![feature(get_mut_unchecked)] #![feature(if_let_guard)] #![feature(map_first_last)] #![feature(never_type)] @@ -43,19 +44,17 @@ #![feature(let_else)] #![feature(min_specialization)] #![feature(trusted_len)] -#![feature(in_band_lifetimes)] #![feature(crate_visibility_modifier)] #![feature(associated_type_bounds)] #![feature(rustc_attrs)] #![feature(half_open_range_patterns)] #![feature(control_flow_enum)] #![feature(associated_type_defaults)] -#![feature(iter_zip)] -#![feature(thread_local_const_init)] #![feature(trusted_step)] #![feature(try_blocks)] #![feature(try_reserve_kind)] #![feature(nonzero_ops)] +#![feature(unwrap_infallible)] #![recursion_limit = "512"] #[macro_use] diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 881b14278e..eef10356ed 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -212,7 +212,7 @@ pub fn struct_lint_level<'s, 'd>( ) { // Avoid codegen bloat from monomorphization by immediately doing dyn dispatch of `decorate` to // the "real" work. - fn struct_lint_level_impl( + fn struct_lint_level_impl<'s, 'd>( sess: &'s Session, lint: &'static Lint, level: Level, @@ -295,7 +295,7 @@ pub fn struct_lint_level<'s, 'd>( Level::Allow => "-A", Level::ForceWarn => "--force-warn", }; - let hyphen_case_lint_name = name.replace("_", "-"); + let hyphen_case_lint_name = name.replace('_', "-"); if lint_flag_val.as_str() == name { sess.diag_note_once( &mut err, @@ -306,7 +306,7 @@ pub fn struct_lint_level<'s, 'd>( ), ); } else { - let hyphen_case_flag_val = lint_flag_val.as_str().replace("_", "-"); + let hyphen_case_flag_val = lint_flag_val.as_str().replace('_', "-"); sess.diag_note_once( &mut err, DiagnosticMessageId::from(lint), @@ -319,7 +319,7 @@ pub fn struct_lint_level<'s, 'd>( } LintLevelSource::Node(lint_attr_name, src, reason) => { if let Some(rationale) = reason { - err.note(&rationale.as_str()); + err.note(rationale.as_str()); } sess.diag_span_note_once( &mut err, diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs index c0f2a76c19..4e927f00ac 100644 --- a/compiler/rustc_middle/src/macros.rs +++ b/compiler/rustc_middle/src/macros.rs @@ -52,11 +52,11 @@ macro_rules! TrivialTypeFoldableImpls { (for <$tcx:lifetime> { $($ty:ty,)+ }) => { $( impl<$tcx> $crate::ty::fold::TypeFoldable<$tcx> for $ty { - fn super_fold_with>( + fn try_super_fold_with>( self, _: &mut F - ) -> $ty { - self + ) -> ::std::result::Result<$ty, F::Error> { + Ok(self) } fn super_visit_with>( @@ -95,10 +95,10 @@ macro_rules! EnumTypeFoldableImpl { impl<$($p),*> $crate::ty::fold::TypeFoldable<$tcx> for $s $(where $($wc)*)* { - fn super_fold_with>( + fn try_super_fold_with>( self, folder: &mut V, - ) -> Self { + ) -> ::std::result::Result { EnumTypeFoldableImpl!(@FoldVariants(self, folder) input($($variants)*) output()) } @@ -112,9 +112,9 @@ macro_rules! EnumTypeFoldableImpl { }; (@FoldVariants($this:expr, $folder:expr) input() output($($output:tt)*)) => { - match $this { + Ok(match $this { $($output)* - } + }) }; (@FoldVariants($this:expr, $folder:expr) @@ -126,7 +126,7 @@ macro_rules! EnumTypeFoldableImpl { output( $variant ( $($variant_arg),* ) => { $variant ( - $($crate::ty::fold::TypeFoldable::fold_with($variant_arg, $folder)),* + $($crate::ty::fold::TypeFoldable::try_fold_with($variant_arg, $folder)?),* ) } $($output)* @@ -145,7 +145,7 @@ macro_rules! EnumTypeFoldableImpl { $variant { $($variant_arg: $crate::ty::fold::TypeFoldable::fold_with( $variant_arg, $folder - )),* } + )?),* } } $($output)* ) diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs index 80a5407131..fc35cafcc7 100644 --- a/compiler/rustc_middle/src/middle/mod.rs +++ b/compiler/rustc_middle/src/middle/mod.rs @@ -21,7 +21,7 @@ pub mod lib_features { .map(|(f, s)| (*f, Some(*s))) .chain(self.unstable.iter().map(|f| (*f, None))) .collect(); - all_features.sort_unstable_by_key(|f| f.0.as_str()); + all_features.sort_unstable_by(|a, b| a.0.as_str().partial_cmp(b.0.as_str()).unwrap()); all_features } } diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index 605e0bc2e6..39ca41c92f 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -7,13 +7,12 @@ //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html use crate::ty::TyCtxt; -use rustc_hir as hir; -use rustc_hir::Node; -use rustc_query_system::ich::{NodeIdHashingMode, StableHashingContext}; - use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_hir as hir; +use rustc_hir::Node; use rustc_macros::HashStable; +use rustc_query_system::ich::{NodeIdHashingMode, StableHashingContext}; use rustc_span::{Span, DUMMY_SP}; use std::fmt; @@ -210,11 +209,6 @@ pub struct ScopeTree { /// If not empty, this body is the root of this region hierarchy. pub root_body: Option, - /// The parent of the root body owner, if the latter is an - /// an associated const or method, as impls/traits can also - /// have lifetime parameters free in this body. - pub root_parent: Option, - /// Maps from a scope ID to the enclosing scope id; /// this is usually corresponding to the lexical nesting, though /// in the case of closures the parent scope is the innermost @@ -445,7 +439,6 @@ impl<'a> HashStable> for ScopeTree { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let ScopeTree { root_body, - root_parent, ref body_expr_count, ref parent_map, ref var_map, @@ -455,8 +448,7 @@ impl<'a> HashStable> for ScopeTree { } = *self; hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { - root_body.hash_stable(hcx, hasher); - root_parent.hash_stable(hcx, hasher); + root_body.hash_stable(hcx, hasher) }); body_expr_count.hash_stable(hcx, hasher); diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 8a5fc5feeb..175d31d69d 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -131,8 +131,7 @@ pub fn report_unstable( /// deprecated (i.e., whether X is not greater than the current rustc version). pub fn deprecation_in_effect(depr: &Deprecation) -> bool { let is_since_rustc_version = depr.is_since_rustc_version; - let since = depr.since.map(Symbol::as_str); - let since = since.as_deref(); + let since = depr.since.as_ref().map(Symbol::as_str); fn parse_version(ver: &str) -> Vec { // We ignore non-integer components of the version (e.g., "nightly"). @@ -197,7 +196,7 @@ fn deprecation_message( let message = if is_in_effect { format!("use of deprecated {} `{}`", kind, path) } else { - let since = since.map(Symbol::as_str); + let since = since.as_ref().map(Symbol::as_str); if since.as_deref() == Some("TBD") { format!("use of {} `{}` that will be deprecated in a future Rust version", kind, path) @@ -229,7 +228,7 @@ pub fn deprecation_message_and_lint( ) } -pub fn early_report_deprecation( +pub fn early_report_deprecation<'a>( lint_buffer: &'a mut LintBuffer, message: &str, suggestion: Option, diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index ddb1a84fe7..640d3a5a02 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -21,9 +21,9 @@ rustc_index::newtype_index! { impl ExpressionOperandId { /// An expression operand for a "zero counter", as described in the following references: /// - /// * - /// * - /// * + /// * + /// * + /// * /// /// This operand can be used to count two or more separate code regions with a single counter, /// if they run sequentially with no branches, by injecting the `Counter` in a `BasicBlock` for diff --git a/compiler/rustc_middle/src/mir/generic_graphviz.rs b/compiler/rustc_middle/src/mir/generic_graphviz.rs index 21c18b28e2..c907680bda 100644 --- a/compiler/rustc_middle/src/mir/generic_graphviz.rs +++ b/compiler/rustc_middle/src/mir/generic_graphviz.rs @@ -126,7 +126,7 @@ impl< write!( w, r#"{}"#, - dot::escape_html(§ion).replace("\n", "
") + dot::escape_html(§ion).replace('\n', "
") )?; } @@ -147,7 +147,7 @@ impl< let src = self.node(source); let trg = self.node(target); let escaped_edge_label = if let Some(edge_label) = edge_labels.get(index) { - dot::escape_html(edge_label).replace("\n", r#"
"#) + dot::escape_html(edge_label).replace('\n', r#"
"#) } else { "".to_owned() }; diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 7a51bb4a1f..e9a857d091 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -8,7 +8,7 @@ use rustc_errors::{pluralize, struct_span_err, DiagnosticBuilder, ErrorReported} use rustc_macros::HashStable; use rustc_session::CtfeBacktrace; use rustc_span::def_id::DefId; -use rustc_target::abi::{Align, Size}; +use rustc_target::abi::{call, Align, Size}; use std::{any::Any, backtrace::Backtrace, fmt}; #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)] @@ -63,7 +63,7 @@ impl fmt::Display for InterpErrorInfo<'_> { } } -impl InterpErrorInfo<'tcx> { +impl<'tcx> InterpErrorInfo<'tcx> { pub fn print_backtrace(&self) { if let Some(backtrace) = self.0.backtrace.as_ref() { print_backtrace(backtrace); @@ -141,6 +141,10 @@ pub enum InvalidProgramInfo<'tcx> { AlreadyReported(ErrorReported), /// An error occurred during layout computation. Layout(layout::LayoutError<'tcx>), + /// An error occurred during FnAbi computation: the passed --target lacks FFI support + /// (which unfortunately typeck does not reject). + /// Not using `FnAbiError` as that contains a nested `LayoutError`. + FnAbiAdjustForForeignAbi(call::AdjustForForeignAbiError), /// An invalid transmute happened. TransmuteSizeDiff(Ty<'tcx>, Ty<'tcx>), /// SizeOf of unsized type was requested. @@ -157,6 +161,7 @@ impl fmt::Display for InvalidProgramInfo<'_> { write!(f, "encountered constants with type errors, stopping evaluation") } Layout(ref err) => write!(f, "{}", err), + FnAbiAdjustForForeignAbi(ref err) => write!(f, "{}", err), TransmuteSizeDiff(from_ty, to_ty) => write!( f, "transmuting `{}` to `{}` is not possible, because these types do not have the same size", @@ -492,9 +497,6 @@ impl dyn MachineStopType { } } -#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(InterpError<'_>, 64); - pub enum InterpError<'tcx> { /// The program caused undefined behavior. UndefinedBehavior(UndefinedBehaviorInfo<'tcx>), diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 4628c24292..b762a10da8 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -145,7 +145,7 @@ pub struct GlobalId<'tcx> { pub promoted: Option, } -impl GlobalId<'tcx> { +impl<'tcx> GlobalId<'tcx> { pub fn display(self, tcx: TyCtxt<'tcx>) -> String { let instance_name = with_no_trimmed_paths(|| tcx.def_path_str(self.instance.def.def_id())); if let Some(promoted) = self.promoted { @@ -273,7 +273,7 @@ pub struct AllocDecodingSession<'s> { impl<'s> AllocDecodingSession<'s> { /// Decodes an `AllocId` in a thread-safe way. - pub fn decode_alloc_id(&self, decoder: &mut D) -> Result + pub fn decode_alloc_id<'tcx, D>(&self, decoder: &mut D) -> Result where D: TyDecoder<'tcx>, { @@ -390,7 +390,7 @@ pub enum GlobalAlloc<'tcx> { Memory(&'tcx Allocation), } -impl GlobalAlloc<'tcx> { +impl<'tcx> GlobalAlloc<'tcx> { /// Panics if the `GlobalAlloc` does not refer to an `GlobalAlloc::Memory` #[track_caller] #[inline] diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index c63613ae3a..f983185563 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -64,6 +64,7 @@ impl<'tcx> TyCtxt<'tcx> { cid: GlobalId<'tcx>, span: Option, ) -> EvalToConstValueResult<'tcx> { + let param_env = param_env.with_const(); // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // improve caching of queries. let inputs = self.erase_regions(param_env.and(cid)); @@ -92,6 +93,7 @@ impl<'tcx> TyCtxt<'tcx> { gid: GlobalId<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Result<&'tcx mir::Allocation, ErrorHandled> { + let param_env = param_env.with_const(); trace!("eval_to_allocation: Need to compute {:?}", gid); let raw_const = self.eval_to_allocation_raw(param_env.and(gid))?; Ok(self.global_alloc(raw_const.alloc_id).unwrap_memory()) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 4210e07d27..52ef380001 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -7,15 +7,17 @@ use crate::mir::interpret::{Allocation, ConstValue, GlobalAlloc, Scalar}; use crate::mir::visit::MirVisitable; use crate::ty::adjustment::PointerCast; use crate::ty::codec::{TyDecoder, TyEncoder}; -use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; +use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeVisitor}; use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::subst::{Subst, SubstsRef}; use crate::ty::{self, List, Ty, TyCtxt}; use crate::ty::{AdtDef, InstanceDef, Region, ScalarInt, UserTypeAnnotationIndex}; + use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_hir::{self, GeneratorKind}; use rustc_hir::{self as hir, HirId}; +use rustc_session::Session; use rustc_target::abi::{Size, VariantIdx}; use polonius_engine::Atom; @@ -29,6 +31,9 @@ use rustc_serialize::{Decodable, Encodable}; use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; use rustc_target::asm::InlineAsmRegOrRegClass; + +use either::Either; + use std::borrow::Cow; use std::convert::TryInto; use std::fmt::{self, Debug, Display, Formatter, Write}; @@ -99,7 +104,21 @@ pub trait MirPass<'tcx> { } } + /// Returns `true` if this pass is enabled with the current combination of compiler flags. + fn is_enabled(&self, _sess: &Session) -> bool { + true + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>); + + /// If this pass causes the MIR to enter a new phase, return that phase. + fn phase_change(&self) -> Option { + None + } + + fn is_mir_dump_enabled(&self) -> bool { + true + } } /// The various "big phases" that MIR goes through. @@ -488,6 +507,16 @@ impl<'tcx> Body<'tcx> { Location { block: bb, statement_index: self[bb].statements.len() } } + pub fn stmt_at(&self, location: Location) -> Either<&Statement<'tcx>, &Terminator<'tcx>> { + let Location { block, statement_index } = location; + let block_data = &self.basic_blocks[block]; + block_data + .statements + .get(statement_index) + .map(Either::Left) + .unwrap_or_else(|| Either::Right(block_data.terminator())) + } + #[inline] pub fn predecessors(&self) -> &Predecessors { self.predecessor_cache.compute(&self.basic_blocks) @@ -1504,6 +1533,7 @@ impl Statement<'_> { } /// Changes a statement to a nop and returns the original statement. + #[must_use = "If you don't need the statement, use `make_nop` instead"] pub fn replace_nop(&mut self) -> Self { Statement { source_info: self.source_info, @@ -1803,6 +1833,16 @@ impl ProjectionElem { | Self::Downcast(_, _) => false, } } + + /// Returns `true` if this is a `Downcast` projection with the given `VariantIdx`. + pub fn is_downcast_to(&self, v: VariantIdx) -> bool { + matches!(*self, Self::Downcast(_, x) if x == v) + } + + /// Returns `true` if this is a `Field` projection with the given index. + pub fn is_field_to(&self, f: Field) -> bool { + matches!(*self, Self::Field(x, _) if x == f) + } } /// Alias for projections as they appear in places, where the base is a place @@ -1993,7 +2033,7 @@ impl SourceScope { /// Finds the original HirId this MIR item came from. /// This is necessary after MIR optimizations, as otherwise we get a HirId /// from the function that was inlined instead of the function call site. - pub fn lint_root( + pub fn lint_root<'tcx>( self, source_scopes: &IndexVec>, ) -> Option { @@ -2228,7 +2268,7 @@ pub enum AggregateKind<'tcx> { /// active field number and is present only for union expressions /// -- e.g., for a union expression `SomeUnion { c: .. }`, the /// active field index would identity the field `c` - Adt(&'tcx AdtDef, VariantIdx, SubstsRef<'tcx>, Option, Option), + Adt(DefId, VariantIdx, SubstsRef<'tcx>, Option, Option), Closure(DefId, SubstsRef<'tcx>), Generator(DefId, SubstsRef<'tcx>, hir::Movability), @@ -2296,8 +2336,6 @@ pub enum NullOp { SizeOf, /// Returns the minimum alignment of a type AlignOf, - /// Creates a new uninitialized box for a value of that type - Box, } #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] @@ -2387,28 +2425,26 @@ impl<'tcx> Debug for Rvalue<'tcx> { } } - AggregateKind::Adt(adt_def, variant, substs, _user_ty, _) => { - let variant_def = &adt_def.variants[variant]; - - let name = ty::tls::with(|tcx| { + AggregateKind::Adt(adt_did, variant, substs, _user_ty, _) => { + ty::tls::with(|tcx| { let mut name = String::new(); + let variant_def = &tcx.adt_def(adt_did).variants[variant]; let substs = tcx.lift(substs).expect("could not lift for printing"); FmtPrinter::new(tcx, &mut name, Namespace::ValueNS) .print_def_path(variant_def.def_id, substs)?; - Ok(name) - })?; - match variant_def.ctor_kind { - CtorKind::Const => fmt.write_str(&name), - CtorKind::Fn => fmt_tuple(fmt, &name), - CtorKind::Fictive => { - let mut struct_fmt = fmt.debug_struct(&name); - for (field, place) in iter::zip(&variant_def.fields, places) { - struct_fmt.field(&field.ident.as_str(), place); + match variant_def.ctor_kind { + CtorKind::Const => fmt.write_str(&name), + CtorKind::Fn => fmt_tuple(fmt, &name), + CtorKind::Fictive => { + let mut struct_fmt = fmt.debug_struct(&name); + for (field, place) in iter::zip(&variant_def.fields, places) { + struct_fmt.field(field.ident.as_str(), place); + } + struct_fmt.finish() } - struct_fmt.finish() } - } + }) } AggregateKind::Closure(def_id, substs) => ty::tls::with(|tcx| { @@ -2433,7 +2469,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { if let Some(upvars) = tcx.upvars_mentioned(def_id) { for (&var_id, place) in iter::zip(upvars.keys(), places) { let var_name = tcx.hir().name(var_id); - struct_fmt.field(&var_name.as_str(), place); + struct_fmt.field(var_name.as_str(), place); } } @@ -2453,7 +2489,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { if let Some(upvars) = tcx.upvars_mentioned(def_id) { for (&var_id, place) in iter::zip(upvars.keys(), places) { let var_name = tcx.hir().name(var_id); - struct_fmt.field(&var_name.as_str(), place); + struct_fmt.field(var_name.as_str(), place); } } @@ -2503,7 +2539,7 @@ pub enum ConstantKind<'tcx> { Val(interpret::ConstValue<'tcx>, Ty<'tcx>), } -impl Constant<'tcx> { +impl<'tcx> Constant<'tcx> { pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option { match self.literal.const_for_ty()?.val.try_to_scalar() { Some(Scalar::Ptr(ptr, _size)) => match tcx.global_alloc(ptr.provenance) { @@ -2522,14 +2558,14 @@ impl Constant<'tcx> { } } -impl From<&'tcx ty::Const<'tcx>> for ConstantKind<'tcx> { +impl<'tcx> From<&'tcx ty::Const<'tcx>> for ConstantKind<'tcx> { #[inline] fn from(ct: &'tcx ty::Const<'tcx>) -> Self { Self::Ty(ct) } } -impl ConstantKind<'tcx> { +impl<'tcx> ConstantKind<'tcx> { /// Returns `None` if the constant is not trivially safe for use in the type system. pub fn const_for_ty(&self) -> Option<&'tcx ty::Const<'tcx>> { match self { @@ -2760,11 +2796,14 @@ impl UserTypeProjection { TrivialTypeFoldableAndLiftImpls! { ProjectionKind, } impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection { - fn super_fold_with>(self, folder: &mut F) -> Self { - UserTypeProjection { - base: self.base.fold_with(folder), - projs: self.projs.fold_with(folder), - } + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + Ok(UserTypeProjection { + base: self.base.try_fold_with(folder)?, + projs: self.projs.try_fold_with(folder)?, + }) } fn super_visit_with>( @@ -2808,7 +2847,7 @@ impl<'tcx> Display for ConstantKind<'tcx> { } } -fn pretty_print_const( +fn pretty_print_const<'tcx>( c: &ty::Const<'tcx>, fmt: &mut Formatter<'_>, print_types: bool, @@ -2823,7 +2862,7 @@ fn pretty_print_const( }) } -fn pretty_print_const_value( +fn pretty_print_const_value<'tcx>( val: interpret::ConstValue<'tcx>, ty: Ty<'tcx>, fmt: &mut Formatter<'_>, @@ -2870,12 +2909,12 @@ impl<'a, 'b> graph::GraphSuccessors<'b> for Body<'a> { type Iter = iter::Cloned>; } -impl graph::GraphPredecessors<'graph> for Body<'tcx> { +impl<'tcx, 'graph> graph::GraphPredecessors<'graph> for Body<'tcx> { type Item = BasicBlock; type Iter = std::iter::Copied>; } -impl graph::WithPredecessors for Body<'tcx> { +impl<'tcx> graph::WithPredecessors for Body<'tcx> { #[inline] fn predecessors(&self, node: Self::Node) -> >::Iter { self.predecessors()[node].iter().copied() diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 06b4232004..1422537cd5 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; -use rustc_hir::{HirId, ItemId}; +use rustc_hir::ItemId; use rustc_query_system::ich::{NodeIdHashingMode, StableHashingContext}; use rustc_session::config::OptLevel; use rustc_span::source_map::Span; @@ -338,7 +338,7 @@ impl<'tcx> CodegenUnit<'tcx> { } pub fn work_product_id(&self) -> WorkProductId { - WorkProductId::from_cgu_name(&self.name().as_str()) + WorkProductId::from_cgu_name(self.name().as_str()) } pub fn work_product(&self, tcx: TyCtxt<'_>) -> WorkProduct { @@ -355,7 +355,7 @@ impl<'tcx> CodegenUnit<'tcx> { // The codegen tests rely on items being process in the same order as // they appear in the file, so for local items, we sort by node_id first #[derive(PartialEq, Eq, PartialOrd, Ord)] - pub struct ItemSortKey<'tcx>(Option, SymbolName<'tcx>); + pub struct ItemSortKey<'tcx>(Option, SymbolName<'tcx>); fn item_sort_key<'tcx>(tcx: TyCtxt<'tcx>, item: MonoItem<'tcx>) -> ItemSortKey<'tcx> { ItemSortKey( @@ -366,10 +366,7 @@ impl<'tcx> CodegenUnit<'tcx> { // instances into account. The others don't matter for // the codegen tests and can even make item order // unstable. - InstanceDef::Item(def) => def - .did - .as_local() - .map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)), + InstanceDef::Item(def) => Some(def.did.index.as_usize()), InstanceDef::VtableShim(..) | InstanceDef::ReifyShim(..) | InstanceDef::Intrinsic(..) @@ -380,10 +377,10 @@ impl<'tcx> CodegenUnit<'tcx> { | InstanceDef::CloneShim(..) => None, } } - MonoItem::Static(def_id) => { - def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)) + MonoItem::Static(def_id) => Some(def_id.index.as_usize()), + MonoItem::GlobalAsm(item_id) => { + Some(item_id.def_id.to_def_id().index.as_usize()) } - MonoItem::GlobalAsm(item_id) => Some(item_id.hir_id()), }, item.symbol_name(tcx), ) @@ -431,7 +428,7 @@ pub struct CodegenUnitNameBuilder<'tcx> { cache: FxHashMap, } -impl CodegenUnitNameBuilder<'tcx> { +impl<'tcx> CodegenUnitNameBuilder<'tcx> { pub fn new(tcx: TyCtxt<'tcx>) -> Self { CodegenUnitNameBuilder { tcx, cache: Default::default() } } @@ -470,7 +467,7 @@ impl CodegenUnitNameBuilder<'tcx> { if self.tcx.sess.opts.debugging_opts.human_readable_cgu_names { cgu_name } else { - Symbol::intern(&CodegenUnit::mangle_name(&cgu_name.as_str())) + Symbol::intern(&CodegenUnit::mangle_name(cgu_name.as_str())) } } @@ -530,6 +527,6 @@ impl CodegenUnitNameBuilder<'tcx> { write!(cgu_name, ".{}", special_suffix).unwrap(); } - Symbol::intern(&cgu_name[..]) + Symbol::intern(&cgu_name) } } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 8e1b887f87..8cc705384b 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -167,8 +167,8 @@ fn dump_matched_mir_node<'tcx, F>( /// Returns the file basename portion (without extension) of a filename path /// where we should dump a MIR representation output files. -fn dump_file_basename( - tcx: TyCtxt<'_>, +fn dump_file_basename<'tcx>( + tcx: TyCtxt<'tcx>, pass_num: Option<&dyn Display>, pass_name: &str, disambiguator: &dyn Display, @@ -251,8 +251,8 @@ fn create_dump_file_with_basename( /// bit of MIR-related data. Used by `mir-dump`, but also by other /// bits of code (e.g., NLL inference) that dump graphviz data or /// other things, and hence takes the extension as an argument. -pub fn create_dump_file( - tcx: TyCtxt<'_>, +pub fn create_dump_file<'tcx>( + tcx: TyCtxt<'tcx>, extension: &str, pass_num: Option<&dyn Display>, pass_name: &str, @@ -419,7 +419,7 @@ struct ExtraComments<'tcx> { comments: Vec, } -impl ExtraComments<'tcx> { +impl<'tcx> ExtraComments<'tcx> { fn push(&mut self, lines: &str) { for line in lines.split('\n') { self.comments.push(line.to_string()); @@ -427,7 +427,7 @@ impl ExtraComments<'tcx> { } } -fn use_verbose(ty: &&TyS<'tcx>, fn_def: bool) -> bool { +fn use_verbose<'tcx>(ty: &&TyS<'tcx>, fn_def: bool) -> bool { match ty.kind() { ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char | ty::Float(_) => false, // Unit type @@ -439,7 +439,7 @@ fn use_verbose(ty: &&TyS<'tcx>, fn_def: bool) -> bool { } } -impl Visitor<'tcx> for ExtraComments<'tcx> { +impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) { self.super_constant(constant, location); let Constant { span, user_ty, literal } = constant; @@ -762,7 +762,7 @@ pub fn write_allocations<'tcx>( /// After the hex dump, an ascii dump follows, replacing all unprintable characters (control /// characters or characters whose value is larger than 127) with a `.` /// This also prints relocations adequately. -pub fn display_allocation( +pub fn display_allocation<'a, 'tcx, Tag, Extra>( tcx: TyCtxt<'tcx>, alloc: &'a Allocation, ) -> RenderAllocation<'a, 'tcx, Tag, Extra> { @@ -775,7 +775,9 @@ pub struct RenderAllocation<'a, 'tcx, Tag, Extra> { alloc: &'a Allocation, } -impl std::fmt::Display for RenderAllocation<'a, 'tcx, Tag, Extra> { +impl<'a, 'tcx, Tag: Provenance, Extra> std::fmt::Display + for RenderAllocation<'a, 'tcx, Tag, Extra> +{ fn fmt(&self, w: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let RenderAllocation { tcx, alloc } = *self; write!(w, "size: {}, align: {})", alloc.size().bytes(), alloc.align.bytes())?; @@ -818,7 +820,7 @@ fn write_allocation_newline( /// The `prefix` argument allows callers to add an arbitrary prefix before each line (even if there /// is only one line). Note that your prefix should contain a trailing space as the lines are /// printed directly after it. -fn write_allocation_bytes( +fn write_allocation_bytes<'tcx, Tag: Provenance, Extra>( tcx: TyCtxt<'tcx>, alloc: &Allocation, w: &mut dyn std::fmt::Write, diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs index 1260c691e7..507f997198 100644 --- a/compiler/rustc_middle/src/mir/spanview.rs +++ b/compiler/rustc_middle/src/mir/spanview.rs @@ -681,13 +681,13 @@ fn hir_body<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<&'tcx rustc_hir::B } fn escape_html(s: &str) -> String { - s.replace("&", "&").replace("<", "<").replace(">", ">") + s.replace('&', "&").replace('<', "<").replace('>', ">") } fn escape_attr(s: &str) -> String { - s.replace("&", "&") - .replace("\"", """) - .replace("'", "'") - .replace("<", "<") - .replace(">", ">") + s.replace('&', "&") + .replace('\"', """) + .replace('\'', "'") + .replace('<', "<") + .replace('>', ">") } diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index c3c5ebe705..dc53dc8de9 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -195,12 +195,11 @@ impl<'tcx> Rvalue<'tcx> { } Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, ref operand) => operand.ty(local_decls, tcx), Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx), - Rvalue::NullaryOp(NullOp::Box, t) => tcx.mk_box(t), Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => tcx.types.usize, Rvalue::Aggregate(ref ak, ref ops) => match **ak { AggregateKind::Array(ty) => tcx.mk_array(ty, ops.len() as u64), AggregateKind::Tuple => tcx.mk_tup(ops.iter().map(|op| op.ty(local_decls, tcx))), - AggregateKind::Adt(def, _, substs, _, _) => tcx.type_of(def.did).subst(tcx, substs), + AggregateKind::Adt(did, _, substs, _, _) => tcx.type_of(did).subst(tcx, substs), AggregateKind::Closure(did, substs) => tcx.mk_closure(did, substs), AggregateKind::Generator(did, substs, movability) => { tcx.mk_generator(did, substs, movability) @@ -215,9 +214,7 @@ impl<'tcx> Rvalue<'tcx> { /// whether its only shallowly initialized (`Rvalue::Box`). pub fn initialization_state(&self) -> RvalueInitializationState { match *self { - Rvalue::NullaryOp(NullOp::Box, _) | Rvalue::ShallowInitBox(_, _) => { - RvalueInitializationState::Shallow - } + Rvalue::ShallowInitBox(_, _) => RvalueInitializationState::Shallow, _ => RvalueInitializationState::Deep, } } diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index e78b6fd092..51e4afaf22 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -78,6 +78,13 @@ impl SwitchTargets { pub fn all_targets_mut(&mut self) -> &mut [BasicBlock] { &mut self.targets } + + /// Finds the `BasicBlock` to which this `SwitchInt` will branch given the + /// specific value. This cannot fail, as it'll return the `otherwise` + /// branch if there's not a specific match for the value. + pub fn target_for_value(&self, value: u128) -> BasicBlock { + self.iter().find_map(|(v, t)| (v == value).then_some(t)).unwrap_or_else(|| self.otherwise()) + } } pub struct SwitchTargetsIter<'a> { @@ -260,6 +267,10 @@ pub enum TerminatorKind<'tcx> { /// Destination block after the inline assembly returns, unless it is /// diverging (InlineAsmOptions::NORETURN). destination: Option, + + /// Cleanup to be done if the inline assembly unwinds. This is present + /// if and only if InlineAsmOptions::MAY_UNWIND is set. + cleanup: Option, }, } #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] @@ -309,7 +320,7 @@ impl<'tcx> TerminatorKind<'tcx> { | Return | Unreachable | Call { destination: None, cleanup: None, .. } - | InlineAsm { destination: None, .. } => None.into_iter().chain(&[]), + | InlineAsm { destination: None, cleanup: None, .. } => None.into_iter().chain(&[]), Goto { target: ref t } | Call { destination: None, cleanup: Some(ref t), .. } | Call { destination: Some((_, ref t)), cleanup: None, .. } @@ -318,16 +329,20 @@ impl<'tcx> TerminatorKind<'tcx> { | Drop { target: ref t, unwind: None, .. } | Assert { target: ref t, cleanup: None, .. } | FalseUnwind { real_target: ref t, unwind: None } - | InlineAsm { destination: Some(ref t), .. } => Some(t).into_iter().chain(&[]), + | InlineAsm { destination: Some(ref t), cleanup: None, .. } + | InlineAsm { destination: None, cleanup: Some(ref t), .. } => { + Some(t).into_iter().chain(&[]) + } Call { destination: Some((_, ref t)), cleanup: Some(ref u), .. } | Yield { resume: ref t, drop: Some(ref u), .. } | DropAndReplace { target: ref t, unwind: Some(ref u), .. } | Drop { target: ref t, unwind: Some(ref u), .. } | Assert { target: ref t, cleanup: Some(ref u), .. } - | FalseUnwind { real_target: ref t, unwind: Some(ref u) } => { + | FalseUnwind { real_target: ref t, unwind: Some(ref u) } + | InlineAsm { destination: Some(ref t), cleanup: Some(ref u), .. } => { Some(t).into_iter().chain(slice::from_ref(u)) } - SwitchInt { ref targets, .. } => None.into_iter().chain(&targets.targets[..]), + SwitchInt { ref targets, .. } => None.into_iter().chain(&targets.targets), FalseEdge { ref real_target, ref imaginary_target } => { Some(real_target).into_iter().chain(slice::from_ref(imaginary_target)) } @@ -343,7 +358,7 @@ impl<'tcx> TerminatorKind<'tcx> { | Return | Unreachable | Call { destination: None, cleanup: None, .. } - | InlineAsm { destination: None, .. } => None.into_iter().chain(&mut []), + | InlineAsm { destination: None, cleanup: None, .. } => None.into_iter().chain(&mut []), Goto { target: ref mut t } | Call { destination: None, cleanup: Some(ref mut t), .. } | Call { destination: Some((_, ref mut t)), cleanup: None, .. } @@ -352,16 +367,20 @@ impl<'tcx> TerminatorKind<'tcx> { | Drop { target: ref mut t, unwind: None, .. } | Assert { target: ref mut t, cleanup: None, .. } | FalseUnwind { real_target: ref mut t, unwind: None } - | InlineAsm { destination: Some(ref mut t), .. } => Some(t).into_iter().chain(&mut []), + | InlineAsm { destination: Some(ref mut t), cleanup: None, .. } + | InlineAsm { destination: None, cleanup: Some(ref mut t), .. } => { + Some(t).into_iter().chain(&mut []) + } Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut u), .. } | Yield { resume: ref mut t, drop: Some(ref mut u), .. } | DropAndReplace { target: ref mut t, unwind: Some(ref mut u), .. } | Drop { target: ref mut t, unwind: Some(ref mut u), .. } | Assert { target: ref mut t, cleanup: Some(ref mut u), .. } - | FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } => { + | FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } + | InlineAsm { destination: Some(ref mut t), cleanup: Some(ref mut u), .. } => { Some(t).into_iter().chain(slice::from_mut(u)) } - SwitchInt { ref mut targets, .. } => None.into_iter().chain(&mut targets.targets[..]), + SwitchInt { ref mut targets, .. } => None.into_iter().chain(&mut targets.targets), FalseEdge { ref mut real_target, ref mut imaginary_target } => { Some(real_target).into_iter().chain(slice::from_mut(imaginary_target)) } @@ -378,13 +397,13 @@ impl<'tcx> TerminatorKind<'tcx> { | TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } | TerminatorKind::SwitchInt { .. } - | TerminatorKind::FalseEdge { .. } - | TerminatorKind::InlineAsm { .. } => None, + | TerminatorKind::FalseEdge { .. } => None, TerminatorKind::Call { cleanup: ref unwind, .. } | TerminatorKind::Assert { cleanup: ref unwind, .. } | TerminatorKind::DropAndReplace { ref unwind, .. } | TerminatorKind::Drop { ref unwind, .. } - | TerminatorKind::FalseUnwind { ref unwind, .. } => Some(unwind), + | TerminatorKind::FalseUnwind { ref unwind, .. } + | TerminatorKind::InlineAsm { cleanup: ref unwind, .. } => Some(unwind), } } @@ -398,13 +417,13 @@ impl<'tcx> TerminatorKind<'tcx> { | TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } | TerminatorKind::SwitchInt { .. } - | TerminatorKind::FalseEdge { .. } - | TerminatorKind::InlineAsm { .. } => None, + | TerminatorKind::FalseEdge { .. } => None, TerminatorKind::Call { cleanup: ref mut unwind, .. } | TerminatorKind::Assert { cleanup: ref mut unwind, .. } | TerminatorKind::DropAndReplace { ref mut unwind, .. } | TerminatorKind::Drop { ref mut unwind, .. } - | TerminatorKind::FalseUnwind { ref mut unwind, .. } => Some(unwind), + | TerminatorKind::FalseUnwind { ref mut unwind, .. } + | TerminatorKind::InlineAsm { cleanup: ref mut unwind, .. } => Some(unwind), } } @@ -583,8 +602,12 @@ impl<'tcx> TerminatorKind<'tcx> { FalseEdge { .. } => vec!["real".into(), "imaginary".into()], FalseUnwind { unwind: Some(_), .. } => vec!["real".into(), "cleanup".into()], FalseUnwind { unwind: None, .. } => vec!["real".into()], - InlineAsm { destination: Some(_), .. } => vec!["".into()], - InlineAsm { destination: None, .. } => vec![], + InlineAsm { destination: Some(_), cleanup: Some(_), .. } => { + vec!["return".into(), "unwind".into()] + } + InlineAsm { destination: Some(_), cleanup: None, .. } => vec!["return".into()], + InlineAsm { destination: None, cleanup: Some(_), .. } => vec!["unwind".into()], + InlineAsm { destination: None, cleanup: None, .. } => vec![], } } } diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs index 725448584d..8c930fd161 100644 --- a/compiler/rustc_middle/src/mir/traversal.rs +++ b/compiler/rustc_middle/src/mir/traversal.rs @@ -300,7 +300,7 @@ pub fn reachable<'a, 'tcx>( } /// Returns a `BitSet` containing all basic blocks reachable from the `START_BLOCK`. -pub fn reachable_as_bitset(body: &Body<'tcx>) -> BitSet { +pub fn reachable_as_bitset<'tcx>(body: &Body<'tcx>) -> BitSet { let mut iter = preorder(body); (&mut iter).for_each(drop); iter.visited diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs index b7201f7acf..901f3bf4f7 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -16,37 +16,42 @@ TrivialTypeFoldableAndLiftImpls! { } impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { use crate::mir::TerminatorKind::*; let kind = match self.kind { Goto { target } => Goto { target }, SwitchInt { discr, switch_ty, targets } => SwitchInt { - discr: discr.fold_with(folder), - switch_ty: switch_ty.fold_with(folder), + discr: discr.try_fold_with(folder)?, + switch_ty: switch_ty.try_fold_with(folder)?, targets, }, Drop { place, target, unwind } => { - Drop { place: place.fold_with(folder), target, unwind } + Drop { place: place.try_fold_with(folder)?, target, unwind } } DropAndReplace { place, value, target, unwind } => DropAndReplace { - place: place.fold_with(folder), - value: value.fold_with(folder), + place: place.try_fold_with(folder)?, + value: value.try_fold_with(folder)?, target, unwind, }, Yield { value, resume, resume_arg, drop } => Yield { - value: value.fold_with(folder), + value: value.try_fold_with(folder)?, resume, - resume_arg: resume_arg.fold_with(folder), + resume_arg: resume_arg.try_fold_with(folder)?, drop, }, Call { func, args, destination, cleanup, from_hir_call, fn_span } => { - let dest = destination.map(|(loc, dest)| (loc.fold_with(folder), dest)); + let dest = destination + .map(|(loc, dest)| (loc.try_fold_with(folder).map(|loc| (loc, dest)))) + .transpose()?; Call { - func: func.fold_with(folder), - args: args.fold_with(folder), + func: func.try_fold_with(folder)?, + args: args.try_fold_with(folder)?, destination: dest, cleanup, from_hir_call, @@ -56,16 +61,19 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { Assert { cond, expected, msg, target, cleanup } => { use AssertKind::*; let msg = match msg { - BoundsCheck { len, index } => { - BoundsCheck { len: len.fold_with(folder), index: index.fold_with(folder) } + BoundsCheck { len, index } => BoundsCheck { + len: len.try_fold_with(folder)?, + index: index.try_fold_with(folder)?, + }, + Overflow(op, l, r) => { + Overflow(op, l.try_fold_with(folder)?, r.try_fold_with(folder)?) } - Overflow(op, l, r) => Overflow(op, l.fold_with(folder), r.fold_with(folder)), - OverflowNeg(op) => OverflowNeg(op.fold_with(folder)), - DivisionByZero(op) => DivisionByZero(op.fold_with(folder)), - RemainderByZero(op) => RemainderByZero(op.fold_with(folder)), + OverflowNeg(op) => OverflowNeg(op.try_fold_with(folder)?), + DivisionByZero(op) => DivisionByZero(op.try_fold_with(folder)?), + RemainderByZero(op) => RemainderByZero(op.try_fold_with(folder)?), ResumedAfterReturn(_) | ResumedAfterPanic(_) => msg, }; - Assert { cond: cond.fold_with(folder), expected, msg, target, cleanup } + Assert { cond: cond.try_fold_with(folder)?, expected, msg, target, cleanup } } GeneratorDrop => GeneratorDrop, Resume => Resume, @@ -76,15 +84,18 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { FalseEdge { real_target, imaginary_target } } FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind }, - InlineAsm { template, operands, options, line_spans, destination } => InlineAsm { - template, - operands: operands.fold_with(folder), - options, - line_spans, - destination, - }, + InlineAsm { template, operands, options, line_spans, destination, cleanup } => { + InlineAsm { + template, + operands: operands.try_fold_with(folder)?, + options, + line_spans, + destination, + cleanup, + } + } }; - Terminator { source_info: self.source_info, kind } + Ok(Terminator { source_info: self.source_info, kind }) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -140,8 +151,8 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for GeneratorKind { - fn super_fold_with>(self, _: &mut F) -> Self { - self + fn try_super_fold_with>(self, _: &mut F) -> Result { + Ok(self) } fn super_visit_with>(&self, _: &mut V) -> ControlFlow { @@ -150,8 +161,14 @@ impl<'tcx> TypeFoldable<'tcx> for GeneratorKind { } impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { - Place { local: self.local.fold_with(folder), projection: self.projection.fold_with(folder) } + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + Ok(Place { + local: self.local.try_fold_with(folder)?, + projection: self.projection.try_fold_with(folder)?, + }) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -161,7 +178,10 @@ impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_place_elems(v)) } @@ -171,47 +191,57 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { } impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { use crate::mir::Rvalue::*; - match self { - Use(op) => Use(op.fold_with(folder)), - Repeat(op, len) => Repeat(op.fold_with(folder), len.fold_with(folder)), - ThreadLocalRef(did) => ThreadLocalRef(did.fold_with(folder)), - Ref(region, bk, place) => Ref(region.fold_with(folder), bk, place.fold_with(folder)), - AddressOf(mutability, place) => AddressOf(mutability, place.fold_with(folder)), - Len(place) => Len(place.fold_with(folder)), - Cast(kind, op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)), + Ok(match self { + Use(op) => Use(op.try_fold_with(folder)?), + Repeat(op, len) => Repeat(op.try_fold_with(folder)?, len.try_fold_with(folder)?), + ThreadLocalRef(did) => ThreadLocalRef(did.try_fold_with(folder)?), + Ref(region, bk, place) => { + Ref(region.try_fold_with(folder)?, bk, place.try_fold_with(folder)?) + } + AddressOf(mutability, place) => AddressOf(mutability, place.try_fold_with(folder)?), + Len(place) => Len(place.try_fold_with(folder)?), + Cast(kind, op, ty) => Cast(kind, op.try_fold_with(folder)?, ty.try_fold_with(folder)?), BinaryOp(op, box (rhs, lhs)) => { - BinaryOp(op, Box::new((rhs.fold_with(folder), lhs.fold_with(folder)))) + BinaryOp(op, Box::new((rhs.try_fold_with(folder)?, lhs.try_fold_with(folder)?))) } - CheckedBinaryOp(op, box (rhs, lhs)) => { - CheckedBinaryOp(op, Box::new((rhs.fold_with(folder), lhs.fold_with(folder)))) - } - UnaryOp(op, val) => UnaryOp(op, val.fold_with(folder)), - Discriminant(place) => Discriminant(place.fold_with(folder)), - NullaryOp(op, ty) => NullaryOp(op, ty.fold_with(folder)), + CheckedBinaryOp(op, box (rhs, lhs)) => CheckedBinaryOp( + op, + Box::new((rhs.try_fold_with(folder)?, lhs.try_fold_with(folder)?)), + ), + UnaryOp(op, val) => UnaryOp(op, val.try_fold_with(folder)?), + Discriminant(place) => Discriminant(place.try_fold_with(folder)?), + NullaryOp(op, ty) => NullaryOp(op, ty.try_fold_with(folder)?), Aggregate(kind, fields) => { - let kind = kind.map_id(|kind| match kind { - AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)), - AggregateKind::Tuple => AggregateKind::Tuple, - AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt( - def, - v, - substs.fold_with(folder), - user_ty.fold_with(folder), - n, - ), - AggregateKind::Closure(id, substs) => { - AggregateKind::Closure(id, substs.fold_with(folder)) - } - AggregateKind::Generator(id, substs, movablity) => { - AggregateKind::Generator(id, substs.fold_with(folder), movablity) - } - }); - Aggregate(kind, fields.fold_with(folder)) + let kind = kind.try_map_id(|kind| { + Ok(match kind { + AggregateKind::Array(ty) => AggregateKind::Array(ty.try_fold_with(folder)?), + AggregateKind::Tuple => AggregateKind::Tuple, + AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt( + def, + v, + substs.try_fold_with(folder)?, + user_ty.try_fold_with(folder)?, + n, + ), + AggregateKind::Closure(id, substs) => { + AggregateKind::Closure(id, substs.try_fold_with(folder)?) + } + AggregateKind::Generator(id, substs, movablity) => { + AggregateKind::Generator(id, substs.try_fold_with(folder)?, movablity) + } + }) + })?; + Aggregate(kind, fields.try_fold_with(folder)?) } - ShallowInitBox(op, ty) => ShallowInitBox(op.fold_with(folder), ty.fold_with(folder)), - } + ShallowInitBox(op, ty) => { + ShallowInitBox(op.try_fold_with(folder)?, ty.try_fold_with(folder)?) + } + }) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -265,12 +295,15 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { - match self { - Operand::Copy(place) => Operand::Copy(place.fold_with(folder)), - Operand::Move(place) => Operand::Move(place.fold_with(folder)), - Operand::Constant(c) => Operand::Constant(c.fold_with(folder)), - } + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + Ok(match self { + Operand::Copy(place) => Operand::Copy(place.try_fold_with(folder)?), + Operand::Move(place) => Operand::Move(place.try_fold_with(folder)?), + Operand::Constant(c) => Operand::Constant(c.try_fold_with(folder)?), + }) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -282,19 +315,22 @@ impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { use crate::mir::ProjectionElem::*; - match self { + Ok(match self { Deref => Deref, - Field(f, ty) => Field(f, ty.fold_with(folder)), - Index(v) => Index(v.fold_with(folder)), + Field(f, ty) => Field(f, ty.try_fold_with(folder)?), + Index(v) => Index(v.try_fold_with(folder)?), Downcast(symbol, variantidx) => Downcast(symbol, variantidx), ConstantIndex { offset, min_length, from_end } => { ConstantIndex { offset, min_length, from_end } } Subslice { from, to, from_end } => Subslice { from, to, from_end }, - } + }) } fn super_visit_with>( @@ -312,8 +348,8 @@ impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for Field { - fn super_fold_with>(self, _: &mut F) -> Self { - self + fn try_super_fold_with>(self, _: &mut F) -> Result { + Ok(self) } fn super_visit_with>(&self, _: &mut V) -> ControlFlow { ControlFlow::CONTINUE @@ -321,8 +357,8 @@ impl<'tcx> TypeFoldable<'tcx> for Field { } impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal { - fn super_fold_with>(self, _: &mut F) -> Self { - self + fn try_super_fold_with>(self, _: &mut F) -> Result { + Ok(self) } fn super_visit_with>(&self, _: &mut V) -> ControlFlow { ControlFlow::CONTINUE @@ -330,8 +366,8 @@ impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal { } impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix { - fn super_fold_with>(self, _: &mut F) -> Self { - self + fn try_super_fold_with>(self, _: &mut F) -> Result { + Ok(self) } fn super_visit_with>(&self, _: &mut V) -> ControlFlow { ControlFlow::CONTINUE @@ -339,12 +375,15 @@ impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix { } impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { - Constant { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + Ok(Constant { span: self.span, - user_ty: self.user_ty.fold_with(folder), - literal: self.literal.fold_with(folder), - } + user_ty: self.user_ty.try_fold_with(folder)?, + literal: self.literal.try_fold_with(folder)?, + }) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { self.literal.visit_with(visitor)?; @@ -354,14 +393,17 @@ impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> { #[inline(always)] - fn fold_with>(self, folder: &mut F) -> Self { - folder.fold_mir_const(self) + fn try_fold_with>(self, folder: &mut F) -> Result { + folder.try_fold_mir_const(self) } - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { match self { - ConstantKind::Ty(c) => ConstantKind::Ty(c.fold_with(folder)), - ConstantKind::Val(v, t) => ConstantKind::Val(v, t.fold_with(folder)), + ConstantKind::Ty(c) => Ok(ConstantKind::Ty(c.try_fold_with(folder)?)), + ConstantKind::Val(v, t) => Ok(ConstantKind::Val(v, t.try_fold_with(folder)?)), } } diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index fda7ebe1a4..f301c68a7c 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -412,7 +412,7 @@ macro_rules! make_mir_visitor { for output in & $($mutability)? asm.outputs[..] { self.visit_place( output, - PlaceContext::MutatingUse(MutatingUseContext::AsmOutput), + PlaceContext::MutatingUse(MutatingUseContext::LlvmAsmOutput), location ); } @@ -581,6 +581,7 @@ macro_rules! make_mir_visitor { options: _, line_spans: _, destination: _, + cleanup: _, } => { for op in operands { match op { @@ -590,7 +591,7 @@ macro_rules! make_mir_visitor { InlineAsmOperand::Out { place: Some(place), .. } => { self.visit_place( place, - PlaceContext::MutatingUse(MutatingUseContext::Store), + PlaceContext::MutatingUse(MutatingUseContext::AsmOutput), location, ); } @@ -599,7 +600,7 @@ macro_rules! make_mir_visitor { if let Some(out_place) = out_place { self.visit_place( out_place, - PlaceContext::MutatingUse(MutatingUseContext::Store), + PlaceContext::MutatingUse(MutatingUseContext::AsmOutput), location, ); } @@ -964,7 +965,7 @@ macro_rules! visit_place_fns { } } - fn process_projection( + fn process_projection<'a>( &mut self, projection: &'a [PlaceElem<'tcx>], location: Location, @@ -1004,8 +1005,12 @@ macro_rules! visit_place_fns { if new_local == local { None } else { Some(PlaceElem::Index(new_local)) } } + PlaceElem::Field(field, ty) => { + let mut new_ty = ty; + self.visit_ty(&mut new_ty, TyContext::Location(location)); + if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None } + } PlaceElem::Deref - | PlaceElem::Field(..) | PlaceElem::ConstantIndex { .. } | PlaceElem::Subslice { .. } | PlaceElem::Downcast(..) => None, @@ -1174,8 +1179,10 @@ pub enum MutatingUseContext { /// Appears as LHS of an assignment. Store, /// Can often be treated as a `Store`, but needs to be separate because - /// ASM is allowed to read outputs as well, so a `Store`-`AsmOutput` sequence + /// ASM is allowed to read outputs as well, so a `Store`-`LlvmAsmOutput` sequence /// cannot be simplified the way a `Store`-`Store` can be. + LlvmAsmOutput, + /// Output operand of an inline assembly block. AsmOutput, /// Destination of a call. Call, @@ -1264,6 +1271,7 @@ impl PlaceContext { PlaceContext::MutatingUse( MutatingUseContext::Store | MutatingUseContext::Call + | MutatingUseContext::LlvmAsmOutput | MutatingUseContext::AsmOutput, ) ) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index ca93efbf19..b3db2e6340 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -522,6 +522,7 @@ rustc_queries! { } query adt_def(key: DefId) -> &'tcx ty::AdtDef { desc { |tcx| "computing ADT definition for `{}`", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } separate_provide_extern } query adt_destructor(key: DefId) -> Option { @@ -771,11 +772,24 @@ rustc_queries! { desc { |tcx| "type-checking `{}`", tcx.def_path_str(key.to_def_id()) } cache_on_disk_if { true } load_cached(tcx, id) { - let typeck_results: Option> = tcx - .on_disk_cache().as_ref() - .and_then(|c| c.try_load_query_result(*tcx, id)); + #[cfg(bootstrap)] + { + match match tcx.on_disk_cache().as_ref() { + Some(c) => c.try_load_query_result(*tcx, id), + None => None, + } { + Some(x) => Some(&*tcx.arena.alloc(x)), + None => None, + } + } + #[cfg(not(bootstrap))] + { + let typeck_results: Option> = tcx + .on_disk_cache().as_ref() + .and_then(|c| c.try_load_query_result(*tcx, id)); - typeck_results.map(|x| &*tcx.arena.alloc(x)) + typeck_results.map(|x| &*tcx.arena.alloc(x)) + } } } @@ -880,6 +894,7 @@ rustc_queries! { key: ty::ParamEnvAnd<'tcx, ConstAlloc<'tcx>> ) -> Option> { desc { "destructure constant" } + remap_env_constness } /// Destructure a constant ADT or array into its variant index and its @@ -888,6 +903,7 @@ rustc_queries! { key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>> ) -> mir::DestructuredConst<'tcx> { desc { "destructure constant" } + remap_env_constness } /// Dereference a constant reference or raw pointer and turn the result into a constant @@ -896,6 +912,7 @@ rustc_queries! { key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>> ) -> &'tcx ty::Const<'tcx> { desc { "deref constant" } + remap_env_constness } query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> { @@ -1100,26 +1117,32 @@ rustc_queries! { /// `ty.is_copy()`, etc, since that will prune the environment where possible. query is_copy_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is `Copy`", env.value } + remap_env_constness } /// Query backing `TyS::is_sized`. query is_sized_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is `Sized`", env.value } + remap_env_constness } /// Query backing `TyS::is_freeze`. query is_freeze_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is freeze", env.value } + remap_env_constness } /// Query backing `TyS::is_unpin`. query is_unpin_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is `Unpin`", env.value } + remap_env_constness } /// Query backing `TyS::needs_drop`. query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` needs drop", env.value } + remap_env_constness } /// Query backing `TyS::has_significant_drop_raw`. query has_significant_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` has a significant drop", env.value } + remap_env_constness } /// Query backing `TyS::is_structural_eq_shallow`. @@ -1158,6 +1181,7 @@ rustc_queries! { key: ty::ParamEnvAnd<'tcx, Ty<'tcx>> ) -> Result, ty::layout::LayoutError<'tcx>> { desc { "computing layout of `{}`", key.value } + remap_env_constness } /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers. @@ -1168,6 +1192,7 @@ rustc_queries! { key: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List>)> ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> { desc { "computing call ABI of `{}` function pointers", key.value.0 } + remap_env_constness } /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for @@ -1179,6 +1204,7 @@ rustc_queries! { key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List>)> ) -> Result<&'tcx abi::call::FnAbi<'tcx, Ty<'tcx>>, ty::layout::FnAbiError<'tcx>> { desc { "computing call ABI of `{}`", key.value.0 } + remap_env_constness } query dylib_dependency_formats(_: CrateNum) @@ -1385,16 +1411,14 @@ rustc_queries! { /// Given a crate and a trait, look up all impls of that trait in the crate. /// Return `(impl_id, self_ty)`. - query implementations_of_trait(_: (CrateNum, DefId)) - -> &'tcx [(DefId, Option)] { + query implementations_of_trait(_: (CrateNum, DefId)) -> &'tcx [(DefId, Option)] { desc { "looking up implementations of a trait in a crate" } separate_provide_extern } /// Given a crate, look up all trait impls in that crate. /// Return `(impl_id, self_ty)`. - query all_trait_implementations(_: CrateNum) - -> &'tcx [(DefId, Option)] { + query all_trait_implementations(_: CrateNum) -> &'tcx [(DefId, Option)] { desc { "looking up all (?) trait implementations" } separate_provide_extern } @@ -1463,6 +1487,7 @@ rustc_queries! { key: ty::ParamEnvAnd<'tcx, Ty<'tcx>> ) -> ty::inhabitedness::DefIdForest { desc { "computing the inhabitedness of `{:?}`", key } + remap_env_constness } query dep_kind(_: CrateNum) -> CrateDepKind { @@ -1485,9 +1510,8 @@ rustc_queries! { desc { |tcx| "computing crate imported by `{}`", tcx.def_path_str(def_id.to_def_id()) } } - query get_lib_features(_: ()) -> LibFeatures { + query lib_features(_: ()) -> LibFeatures { storage(ArenaCacheSelector<'tcx>) - eval_always desc { "calculating the lib features map" } } query defined_lib_features(_: CrateNum) @@ -1583,11 +1607,11 @@ rustc_queries! { desc { "fetching all foreign CrateNum instances" } } - /// A vector of every trait accessible in the whole crate - /// (i.e., including those from subcrates). This is used only for - /// error reporting. - query all_traits(_: ()) -> &'tcx [DefId] { - desc { "fetching all foreign and local traits" } + /// A list of all traits in a crate, used by rustdoc and error reporting. + /// NOTE: Not named just `traits` due to a naming conflict. + query traits_in_crate(_: CrateNum) -> &'tcx [DefId] { + desc { "fetching all traits in a crate" } + separate_provide_extern } /// The list of symbols exported from the given crate. @@ -1643,20 +1667,23 @@ rustc_queries! { NoSolution, > { desc { "normalizing `{:?}`", goal } + remap_env_constness } - /// Do not call this query directly: invoke `normalize_erasing_regions` instead. - query normalize_generic_arg_after_erasing_regions( + /// Do not call this query directly: invoke `try_normalize_erasing_regions` instead. + query try_normalize_generic_arg_after_erasing_regions( goal: ParamEnvAnd<'tcx, GenericArg<'tcx>> - ) -> GenericArg<'tcx> { + ) -> Result, NoSolution> { desc { "normalizing `{}`", goal.value } + remap_env_constness } - /// Do not call this query directly: invoke `normalize_erasing_regions` instead. - query normalize_mir_const_after_erasing_regions( + /// Do not call this query directly: invoke `try_normalize_erasing_regions` instead. + query try_normalize_mir_const_after_erasing_regions( goal: ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>> - ) -> mir::ConstantKind<'tcx> { + ) -> Result, NoSolution> { desc { "normalizing `{}`", goal.value } + remap_env_constness } query implied_outlives_bounds( @@ -1666,6 +1693,7 @@ rustc_queries! { NoSolution, > { desc { "computing implied outlives bounds for `{:?}`", goal } + remap_env_constness } /// Do not call this query directly: invoke `infcx.at().dropck_outlives()` instead. @@ -1676,6 +1704,7 @@ rustc_queries! { NoSolution, > { desc { "computing dropck types for `{:?}`", goal } + remap_env_constness } /// Do not call this query directly: invoke `infcx.predicate_may_hold()` or @@ -1703,6 +1732,7 @@ rustc_queries! { NoSolution, > { desc { "evaluating `type_op_ascribe_user_type` `{:?}`", goal } + remap_env_constness } /// Do not call this query directly: part of the `Eq` type-op @@ -1713,6 +1743,7 @@ rustc_queries! { NoSolution, > { desc { "evaluating `type_op_eq` `{:?}`", goal } + remap_env_constness } /// Do not call this query directly: part of the `Subtype` type-op @@ -1723,6 +1754,7 @@ rustc_queries! { NoSolution, > { desc { "evaluating `type_op_subtype` `{:?}`", goal } + remap_env_constness } /// Do not call this query directly: part of the `ProvePredicate` type-op @@ -1743,6 +1775,7 @@ rustc_queries! { NoSolution, > { desc { "normalizing `{:?}`", goal } + remap_env_constness } /// Do not call this query directly: part of the `Normalize` type-op @@ -1753,6 +1786,7 @@ rustc_queries! { NoSolution, > { desc { "normalizing `{:?}`", goal } + remap_env_constness } /// Do not call this query directly: part of the `Normalize` type-op @@ -1763,6 +1797,7 @@ rustc_queries! { NoSolution, > { desc { "normalizing `{:?}`", goal } + remap_env_constness } /// Do not call this query directly: part of the `Normalize` type-op @@ -1773,6 +1808,7 @@ rustc_queries! { NoSolution, > { desc { "normalizing `{:?}`", goal } + remap_env_constness } query subst_and_check_impossible_predicates(key: (DefId, SubstsRef<'tcx>)) -> bool { @@ -1786,6 +1822,7 @@ rustc_queries! { goal: CanonicalTyGoal<'tcx> ) -> MethodAutoderefStepsResult<'tcx> { desc { "computing autoderef types for `{:?}`", goal } + remap_env_constness } query supported_target_features(_: CrateNum) -> FxHashMap> { @@ -1818,6 +1855,7 @@ rustc_queries! { key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)> ) -> Result>, ErrorReported> { desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) } + remap_env_constness } query resolve_instance_of_const_arg( @@ -1827,6 +1865,7 @@ rustc_queries! { "resolving instance of the const argument `{}`", ty::Instance::new(key.value.0.to_def_id(), key.value.2), } + remap_env_constness } query normalize_opaque_types(key: &'tcx ty::List>) -> &'tcx ty::List> { @@ -1841,6 +1880,7 @@ rustc_queries! { /// size, to account for partial initialisation. See #49298 for details.) query conservative_is_privately_uninhabited(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { desc { "conservatively checking if {:?} is privately uninhabited", key } + remap_env_constness } query limits(key: ()) -> Limits { diff --git a/compiler/rustc_middle/src/traits/chalk.rs b/compiler/rustc_middle/src/traits/chalk.rs index 74873778f7..09a28249cc 100644 --- a/compiler/rustc_middle/src/traits/chalk.rs +++ b/compiler/rustc_middle/src/traits/chalk.rs @@ -206,35 +206,36 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> { Some(write!(fmt, "{:?}", opaque_ty.opaque_ty_id)) } - fn intern_ty(&self, ty: chalk_ir::TyData) -> Self::InternedType { - Box::new(ty) + fn intern_ty(self, ty: chalk_ir::TyKind) -> Self::InternedType { + let flags = ty.compute_flags(self); + Box::new(chalk_ir::TyData { kind: ty, flags: flags }) } - fn ty_data<'a>(&self, ty: &'a Self::InternedType) -> &'a chalk_ir::TyData { + fn ty_data<'a>(self, ty: &'a Self::InternedType) -> &'a chalk_ir::TyData { ty } - fn intern_lifetime(&self, lifetime: chalk_ir::LifetimeData) -> Self::InternedLifetime { + fn intern_lifetime(self, lifetime: chalk_ir::LifetimeData) -> Self::InternedLifetime { Box::new(lifetime) } fn lifetime_data<'a>( - &self, + self, lifetime: &'a Self::InternedLifetime, ) -> &'a chalk_ir::LifetimeData { &lifetime } - fn intern_const(&self, constant: chalk_ir::ConstData) -> Self::InternedConst { + fn intern_const(self, constant: chalk_ir::ConstData) -> Self::InternedConst { Box::new(constant) } - fn const_data<'a>(&self, constant: &'a Self::InternedConst) -> &'a chalk_ir::ConstData { + fn const_data<'a>(self, constant: &'a Self::InternedConst) -> &'a chalk_ir::ConstData { &constant } fn const_eq( - &self, + self, _ty: &Self::InternedType, c1: &Self::InternedConcreteConst, c2: &Self::InternedConcreteConst, @@ -242,143 +243,143 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> { c1 == c2 } - fn intern_generic_arg(&self, data: chalk_ir::GenericArgData) -> Self::InternedGenericArg { + fn intern_generic_arg(self, data: chalk_ir::GenericArgData) -> Self::InternedGenericArg { Box::new(data) } fn generic_arg_data<'a>( - &self, + self, data: &'a Self::InternedGenericArg, ) -> &'a chalk_ir::GenericArgData { &data } - fn intern_goal(&self, goal: chalk_ir::GoalData) -> Self::InternedGoal { + fn intern_goal(self, goal: chalk_ir::GoalData) -> Self::InternedGoal { Box::new(goal) } - fn goal_data<'a>(&self, goal: &'a Self::InternedGoal) -> &'a chalk_ir::GoalData { + fn goal_data<'a>(self, goal: &'a Self::InternedGoal) -> &'a chalk_ir::GoalData { &goal } fn intern_goals( - &self, + self, data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect::, _>>() } - fn goals_data<'a>(&self, goals: &'a Self::InternedGoals) -> &'a [chalk_ir::Goal] { + fn goals_data<'a>(self, goals: &'a Self::InternedGoals) -> &'a [chalk_ir::Goal] { goals } fn intern_substitution( - &self, + self, data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect::, _>>() } fn substitution_data<'a>( - &self, + self, substitution: &'a Self::InternedSubstitution, ) -> &'a [chalk_ir::GenericArg] { substitution } fn intern_program_clause( - &self, + self, data: chalk_ir::ProgramClauseData, ) -> Self::InternedProgramClause { Box::new(data) } fn program_clause_data<'a>( - &self, + self, clause: &'a Self::InternedProgramClause, ) -> &'a chalk_ir::ProgramClauseData { &clause } fn intern_program_clauses( - &self, + self, data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect::, _>>() } fn program_clauses_data<'a>( - &self, + self, clauses: &'a Self::InternedProgramClauses, ) -> &'a [chalk_ir::ProgramClause] { clauses } fn intern_quantified_where_clauses( - &self, + self, data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect::, _>>() } fn quantified_where_clauses_data<'a>( - &self, + self, clauses: &'a Self::InternedQuantifiedWhereClauses, ) -> &'a [chalk_ir::QuantifiedWhereClause] { clauses } fn intern_generic_arg_kinds( - &self, + self, data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect::, _>>() } fn variable_kinds_data<'a>( - &self, + self, parameter_kinds: &'a Self::InternedVariableKinds, ) -> &'a [chalk_ir::VariableKind] { parameter_kinds } fn intern_canonical_var_kinds( - &self, + self, data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect::, _>>() } fn canonical_var_kinds_data<'a>( - &self, + self, canonical_var_kinds: &'a Self::InternedCanonicalVarKinds, ) -> &'a [chalk_ir::CanonicalVarKind] { canonical_var_kinds } fn intern_constraints( - &self, + self, data: impl IntoIterator>, E>>, ) -> Result { data.into_iter().collect::, _>>() } fn constraints_data<'a>( - &self, + self, constraints: &'a Self::InternedConstraints, ) -> &'a [chalk_ir::InEnvironment>] { constraints } fn intern_variances( - &self, + self, data: impl IntoIterator>, ) -> Result { data.into_iter().collect::, _>>() } fn variances_data<'a>( - &self, + self, variances: &'a Self::InternedVariances, ) -> &'a [chalk_ir::Variance] { variances diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 49a64cb246..de5beffb5c 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -23,9 +23,7 @@ use rustc_span::{Span, DUMMY_SP}; use smallvec::SmallVec; use std::borrow::Cow; -use std::fmt; use std::hash::{Hash, Hasher}; -use std::ops::Deref; pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache}; @@ -80,38 +78,14 @@ pub enum Reveal { /// The reason why we incurred this obligation; used for error reporting. /// -/// As the happy path does not care about this struct, storing this on the heap -/// ends up increasing performance. +/// Non-misc `ObligationCauseCode`s are stored on the heap. This gives the +/// best trade-off between keeping the type small (which makes copies cheaper) +/// while not doing too many heap allocations. /// /// We do not want to intern this as there are a lot of obligation causes which /// only live for a short period of time. -#[derive(Clone, PartialEq, Eq, Hash, Lift)] -pub struct ObligationCause<'tcx> { - /// `None` for `ObligationCause::dummy`, `Some` otherwise. - data: Option>>, -} - -const DUMMY_OBLIGATION_CAUSE_DATA: ObligationCauseData<'static> = - ObligationCauseData { span: DUMMY_SP, body_id: hir::CRATE_HIR_ID, code: MiscObligation }; - -// Correctly format `ObligationCause::dummy`. -impl<'tcx> fmt::Debug for ObligationCause<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - ObligationCauseData::fmt(self, f) - } -} - -impl Deref for ObligationCause<'tcx> { - type Target = ObligationCauseData<'tcx>; - - #[inline(always)] - fn deref(&self) -> &Self::Target { - self.data.as_deref().unwrap_or(&DUMMY_OBLIGATION_CAUSE_DATA) - } -} - #[derive(Clone, Debug, PartialEq, Eq, Lift)] -pub struct ObligationCauseData<'tcx> { +pub struct ObligationCause<'tcx> { pub span: Span, /// The ID of the fn body that triggered this obligation. This is @@ -122,17 +96,25 @@ pub struct ObligationCauseData<'tcx> { /// information. pub body_id: hir::HirId, - pub code: ObligationCauseCode<'tcx>, + /// `None` for `MISC_OBLIGATION_CAUSE_CODE` (a common case, occurs ~60% of + /// the time). `Some` otherwise. + code: Option>>, } -impl Hash for ObligationCauseData<'_> { +// This custom hash function speeds up hashing for `Obligation` deduplication +// greatly by skipping the `code` field, which can be large and complex. That +// shouldn't affect hash quality much since there are several other fields in +// `Obligation` which should be unique enough, especially the predicate itself +// which is hashed as an interned pointer. See #90996. +impl Hash for ObligationCause<'_> { fn hash(&self, state: &mut H) { self.body_id.hash(state); self.span.hash(state); - std::mem::discriminant(&self.code).hash(state); } } +const MISC_OBLIGATION_CAUSE_CODE: ObligationCauseCode<'static> = MiscObligation; + impl<'tcx> ObligationCause<'tcx> { #[inline] pub fn new( @@ -140,28 +122,32 @@ impl<'tcx> ObligationCause<'tcx> { body_id: hir::HirId, code: ObligationCauseCode<'tcx>, ) -> ObligationCause<'tcx> { - ObligationCause { data: Some(Lrc::new(ObligationCauseData { span, body_id, code })) } + ObligationCause { + span, + body_id, + code: if code == MISC_OBLIGATION_CAUSE_CODE { None } else { Some(Lrc::new(code)) }, + } } pub fn misc(span: Span, body_id: hir::HirId) -> ObligationCause<'tcx> { ObligationCause::new(span, body_id, MiscObligation) } - pub fn dummy_with_span(span: Span) -> ObligationCause<'tcx> { - ObligationCause::new(span, hir::CRATE_HIR_ID, MiscObligation) - } - #[inline(always)] pub fn dummy() -> ObligationCause<'tcx> { - ObligationCause { data: None } + ObligationCause { span: DUMMY_SP, body_id: hir::CRATE_HIR_ID, code: None } } - pub fn make_mut(&mut self) -> &mut ObligationCauseData<'tcx> { - Lrc::make_mut(self.data.get_or_insert_with(|| Lrc::new(DUMMY_OBLIGATION_CAUSE_DATA))) + pub fn dummy_with_span(span: Span) -> ObligationCause<'tcx> { + ObligationCause { span, body_id: hir::CRATE_HIR_ID, code: None } + } + + pub fn make_mut_code(&mut self) -> &mut ObligationCauseCode<'tcx> { + Lrc::make_mut(self.code.get_or_insert_with(|| Lrc::new(MISC_OBLIGATION_CAUSE_CODE))) } pub fn span(&self, tcx: TyCtxt<'tcx>) -> Span { - match self.code { + match *self.code() { ObligationCauseCode::CompareImplMethodObligation { .. } | ObligationCauseCode::MainFunctionType | ObligationCauseCode::StartFunctionType => { @@ -174,6 +160,18 @@ impl<'tcx> ObligationCause<'tcx> { _ => self.span, } } + + #[inline] + pub fn code(&self) -> &ObligationCauseCode<'tcx> { + self.code.as_deref().unwrap_or(&MISC_OBLIGATION_CAUSE_CODE) + } + + pub fn clone_code(&self) -> Lrc> { + match &self.code { + Some(code) => code.clone(), + None => Lrc::new(MISC_OBLIGATION_CAUSE_CODE), + } + } } #[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)] @@ -348,6 +346,12 @@ pub enum ObligationCauseCode<'tcx> { /// If `X` is the concrete type of an opaque type `impl Y`, then `X` must implement `Y` OpaqueType, + AwaitableExpr(Option), + + ForLoopIterator, + + QuestionMark, + /// Well-formed checking. If a `WellFormedLoc` is provided, /// then it will be used to eprform HIR-based wf checking /// after an error occurs, in order to generate a more precise error span. @@ -587,18 +591,18 @@ impl<'tcx, N> ImplSource<'tcx, N> { pub fn borrow_nested_obligations(&self) -> &[N] { match &self { ImplSource::UserDefined(i) => &i.nested[..], - ImplSource::Param(n, _) => &n[..], - ImplSource::Builtin(i) => &i.nested[..], - ImplSource::AutoImpl(d) => &d.nested[..], - ImplSource::Closure(c) => &c.nested[..], - ImplSource::Generator(c) => &c.nested[..], - ImplSource::Object(d) => &d.nested[..], - ImplSource::FnPointer(d) => &d.nested[..], + ImplSource::Param(n, _) => &n, + ImplSource::Builtin(i) => &i.nested, + ImplSource::AutoImpl(d) => &d.nested, + ImplSource::Closure(c) => &c.nested, + ImplSource::Generator(c) => &c.nested, + ImplSource::Object(d) => &d.nested, + ImplSource::FnPointer(d) => &d.nested, ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData) | ImplSource::Pointee(ImplSourcePointeeData) | ImplSource::ConstDrop(ImplSourceConstDropData) => &[], - ImplSource::TraitAlias(d) => &d.nested[..], - ImplSource::TraitUpcasting(d) => &d.nested[..], + ImplSource::TraitAlias(d) => &d.nested, + ImplSource::TraitUpcasting(d) => &d.nested, } } diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index 560660517f..71ee00c602 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -12,14 +12,12 @@ use rustc_hir::def_id::DefId; use rustc_query_system::cache::Cache; pub type SelectionCache<'tcx> = Cache< - (ty::ConstnessAnd>>, ty::ImplPolarity), + ty::ParamEnvAnd<'tcx, ty::TraitPredicate<'tcx>>, SelectionResult<'tcx, SelectionCandidate<'tcx>>, >; -pub type EvaluationCache<'tcx> = Cache< - (ty::ParamEnvAnd<'tcx, ty::ConstnessAnd>>, ty::ImplPolarity), - EvaluationResult, ->; +pub type EvaluationCache<'tcx> = + Cache>, EvaluationResult>; /// The selection process begins by considering all impls, where /// clauses, and so forth that might resolve an obligation. Sometimes @@ -103,7 +101,7 @@ pub enum SelectionCandidate<'tcx> { /// `false` if there are no *further* obligations. has_nested: bool, }, - ParamCandidate((ty::ConstnessAnd>, ty::ImplPolarity)), + ParamCandidate(ty::PolyTraitPredicate<'tcx>), ImplCandidate(DefId), AutoImplCandidate(DefId), diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs index ab47c2a763..3e9cd6b46b 100644 --- a/compiler/rustc_middle/src/traits/specialization_graph.rs +++ b/compiler/rustc_middle/src/traits/specialization_graph.rs @@ -216,7 +216,7 @@ impl<'tcx> Ancestors<'tcx> { /// /// Returns `Err` if an error was reported while building the specialization /// graph. -pub fn ancestors( +pub fn ancestors<'tcx>( tcx: TyCtxt<'tcx>, trait_def_id: DefId, start_from_impl: DefId, diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs index 6032004e60..aa2f37bd81 100644 --- a/compiler/rustc_middle/src/traits/structural_impls.rs +++ b/compiler/rustc_middle/src/traits/structural_impls.rs @@ -74,7 +74,7 @@ impl fmt::Debug for traits::ImplSourceBuiltinData { } } -impl fmt::Debug for traits::ImplSourceTraitUpcastingData<'tcx, N> { +impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceTraitUpcastingData<'tcx, N> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, diff --git a/compiler/rustc_middle/src/traits/util.rs b/compiler/rustc_middle/src/traits/util.rs index 3490c68817..815f4824bc 100644 --- a/compiler/rustc_middle/src/traits/util.rs +++ b/compiler/rustc_middle/src/traits/util.rs @@ -26,9 +26,9 @@ impl<'tcx> Elaborator<'tcx> { .predicates .into_iter() .flat_map(|(pred, _)| { - pred.subst_supertrait(self.tcx, &trait_ref).to_opt_poly_trait_ref() + pred.subst_supertrait(self.tcx, &trait_ref).to_opt_poly_trait_pred() }) - .map(|t| t.value) + .map(|t| t.map_bound(|pred| pred.trait_ref)) .filter(|supertrait_ref| self.visited.insert(*supertrait_ref)); self.stack.extend(supertrait_refs); diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs index 02ff1b9f4d..e0e3febe6b 100644 --- a/compiler/rustc_middle/src/ty/_match.rs +++ b/compiler/rustc_middle/src/ty/_match.rs @@ -23,13 +23,13 @@ pub struct Match<'tcx> { param_env: ty::ParamEnv<'tcx>, } -impl Match<'tcx> { +impl<'tcx> Match<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Match<'tcx> { Match { tcx, param_env } } } -impl TypeRelation<'tcx> for Match<'tcx> { +impl<'tcx> TypeRelation<'tcx> for Match<'tcx> { fn tag(&self) -> &'static str { "Match" } diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs index 8f648b2113..2676b7ab52 100644 --- a/compiler/rustc_middle/src/ty/adjustment.rs +++ b/compiler/rustc_middle/src/ty/adjustment.rs @@ -83,7 +83,7 @@ pub struct Adjustment<'tcx> { pub target: Ty<'tcx>, } -impl Adjustment<'tcx> { +impl<'tcx> Adjustment<'tcx> { pub fn is_region_borrow(&self) -> bool { matches!(self.kind, Adjust::Borrow(AutoBorrow::Ref(..))) } diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 44f741c5df..5cde54c932 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -7,11 +7,10 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::ErrorReported; use rustc_hir as hir; -use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_index::vec::{Idx, IndexVec}; use rustc_query_system::ich::StableHashingContext; -use rustc_serialize::{self, Encodable, Encoder}; use rustc_session::DataTypeKind; use rustc_span::symbol::sym; use rustc_target::abi::VariantIdx; @@ -20,7 +19,7 @@ use std::cell::RefCell; use std::cmp::Ordering; use std::hash::{Hash, Hasher}; use std::ops::Range; -use std::{ptr, str}; +use std::str; use super::{ Destructor, FieldDef, GenericPredicates, ReprOptions, Ty, TyCtxt, VariantDef, VariantDiscr, @@ -30,7 +29,7 @@ use super::{ pub struct AdtSizedConstraint<'tcx>(pub &'tcx [Ty<'tcx>]); bitflags! { - #[derive(HashStable)] + #[derive(HashStable, TyEncodable, TyDecodable)] pub struct AdtFlags: u32 { const NO_ADT_FLAGS = 0; /// Indicates whether the ADT is an enum. @@ -64,6 +63,31 @@ bitflags! { /// Moreover, Rust only allows recursive data types through indirection. /// /// [adt]: https://en.wikipedia.org/wiki/Algebraic_data_type +/// +/// # Recursive types +/// +/// It may seem impossible to represent recursive types using [`Ty`], +/// since [`TyKind::Adt`] includes [`AdtDef`], which includes its fields, +/// creating a cycle. However, `AdtDef` does not actually include the *types* +/// of its fields; it includes just their [`DefId`]s. +/// +/// [`TyKind::Adt`]: ty::TyKind::Adt +/// +/// For example, the following type: +/// +/// ``` +/// struct S { x: Box } +/// ``` +/// +/// is essentially represented with [`Ty`] as the following pseudocode: +/// +/// ``` +/// struct S { x } +/// ``` +/// +/// where `x` here represents the `DefId` of `S.x`. Then, the `DefId` +/// can be used with [`TyCtxt::type_of()`] to get the type of the field. +#[derive(TyEncodable, TyDecodable)] pub struct AdtDef { /// The `DefId` of the struct, enum or union item. pub did: DefId, @@ -89,26 +113,23 @@ impl Ord for AdtDef { } } +/// There should be only one AdtDef for each `did`, therefore +/// it is fine to implement `PartialEq` only based on `did`. impl PartialEq for AdtDef { - // `AdtDef`s are always interned, and this is part of `TyS` equality. #[inline] fn eq(&self, other: &Self) -> bool { - ptr::eq(self, other) + self.did == other.did } } impl Eq for AdtDef {} +/// There should be only one AdtDef for each `did`, therefore +/// it is fine to implement `Hash` only based on `did`. impl Hash for AdtDef { #[inline] fn hash(&self, s: &mut H) { - (self as *const AdtDef).hash(s) - } -} - -impl Encodable for AdtDef { - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - self.did.encode(s) + self.did.hash(s) } } @@ -137,7 +158,7 @@ impl<'a> HashStable> for AdtDef { } } -#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, TyEncodable, TyDecodable)] pub enum AdtKind { Struct, Union, @@ -314,6 +335,22 @@ impl<'tcx> AdtDef { /// Whether the ADT lacks fields. Note that this includes uninhabited enums, /// e.g., `enum Void {}` is considered payload free as well. pub fn is_payloadfree(&self) -> bool { + // Treat the ADT as not payload-free if arbitrary_enum_discriminant is used (#88621). + // This would disallow the following kind of enum from being casted into integer. + // ``` + // enum Enum { + // Foo() = 1, + // Bar{} = 2, + // Baz = 3, + // } + // ``` + if self + .variants + .iter() + .any(|v| matches!(v.discr, VariantDiscr::Explicit(_)) && v.ctor_kind != CtorKind::Const) + { + return false; + } self.variants.iter().all(|v| v.fields.is_empty()) } diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index 5cb2b90fe1..bf5a3e6825 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -139,7 +139,7 @@ impl<'tcx> AssocItems<'tcx> { /// Multiple items may have the same name if they are in different `Namespace`s. For example, /// an associated type can have the same name as a method. Use one of the `find_by_name_and_*` /// methods below if you know which item you are looking for. - pub fn filter_by_name( + pub fn filter_by_name<'a>( &'a self, tcx: TyCtxt<'a>, ident: Ident, diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index 4eacb3c417..771acc2964 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -156,7 +156,7 @@ pub struct CapturedPlace<'tcx> { pub mutability: hir::Mutability, } -impl CapturedPlace<'tcx> { +impl<'tcx> CapturedPlace<'tcx> { pub fn to_string(&self, tcx: TyCtxt<'tcx>) -> String { place_to_string_for_capture(tcx, &self.place) } @@ -328,7 +328,7 @@ pub struct CaptureInfo<'tcx> { pub capture_kind: UpvarCapture<'tcx>, } -pub fn place_to_string_for_capture(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) -> String { +pub fn place_to_string_for_capture<'tcx>(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) -> String { let mut curr_string: String = match place.base { HirPlaceBase::Upvar(upvar_id) => tcx.hir().name(upvar_id.var_path.hir_id).to_string(), _ => bug!("Capture_information should only contain upvars"), diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 3f2b987b1e..db37d98614 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -16,7 +16,6 @@ use crate::thir; use crate::ty::subst::SubstsRef; use crate::ty::{self, List, Ty, TyCtxt}; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::def_id::DefId; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_span::Span; use std::hash::Hash; @@ -76,7 +75,11 @@ pub trait RefDecodable<'tcx, D: TyDecoder<'tcx>> { } /// Encode the given value or a previously cached shorthand. -pub fn encode_with_shorthand(encoder: &mut E, value: &T, cache: M) -> Result<(), E::Error> +pub fn encode_with_shorthand<'tcx, E, T, M>( + encoder: &mut E, + value: &T, + cache: M, +) -> Result<(), E::Error> where E: TyEncoder<'tcx>, M: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap, @@ -156,7 +159,8 @@ encodable_via_deref! { &'tcx mir::Body<'tcx>, &'tcx mir::UnsafetyCheckResult, &'tcx mir::BorrowCheckResult<'tcx>, - &'tcx mir::coverage::CodeRegion + &'tcx mir::coverage::CodeRegion, + &'tcx ty::AdtDef } pub trait TyDecoder<'tcx>: Decoder { @@ -308,13 +312,6 @@ macro_rules! impl_decodable_via_ref { } } -impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::AdtDef { - fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { - let def_id = >::decode(decoder)?; - Ok(decoder.tcx().adt_def(def_id)) - } -} - impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List> { fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> { let len = decoder.read_usize()?; @@ -399,7 +396,8 @@ impl_decodable_via_ref! { &'tcx mir::UnsafetyCheckResult, &'tcx mir::BorrowCheckResult<'tcx>, &'tcx mir::coverage::CodeRegion, - &'tcx ty::List + &'tcx ty::List, + &'tcx ty::AdtDef } #[macro_export] diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index 8262bc2619..1f4ebd0367 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -234,7 +234,7 @@ impl ScalarInt { } #[inline] - pub fn try_to_machine_usize(&self, tcx: TyCtxt<'tcx>) -> Result { + pub fn try_to_machine_usize<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Result { Ok(self.to_bits(tcx.data_layout.pointer_size)? as u64) } } diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs index f1b78c8763..fae22c2862 100644 --- a/compiler/rustc_middle/src/ty/consts/valtree.rs +++ b/compiler/rustc_middle/src/ty/consts/valtree.rs @@ -27,7 +27,7 @@ pub enum ValTree<'tcx> { Branch(&'tcx [ValTree<'tcx>]), } -impl ValTree<'tcx> { +impl<'tcx> ValTree<'tcx> { pub fn zst() -> Self { Self::Branch(&[]) } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 8240273aca..dd571e29bf 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -5,7 +5,6 @@ use crate::dep_graph::{DepGraph, DepKind, DepKindStruct}; use crate::hir::place::Place as HirPlace; use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos}; use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource}; -use crate::middle; use crate::middle::resolve_lifetime::{self, LifetimeScopeForPath, ObjectLifetimeDefault}; use crate::middle::stability; use crate::mir::interpret::{self, Allocation, ConstValue, Scalar}; @@ -113,6 +112,7 @@ pub struct CtxtInterners<'tcx> { const_allocation: InternedSet<'tcx, Allocation>, bound_variable_kinds: InternedSet<'tcx, List>, layout: InternedSet<'tcx, Layout>, + adt_def: InternedSet<'tcx, AdtDef>, } impl<'tcx> CtxtInterners<'tcx> { @@ -133,6 +133,7 @@ impl<'tcx> CtxtInterners<'tcx> { const_allocation: Default::default(), bound_variable_kinds: Default::default(), layout: Default::default(), + adt_def: Default::default(), } } @@ -825,7 +826,7 @@ pub struct CanonicalUserTypeAnnotation<'tcx> { /// Canonicalized user type annotation. pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>; -impl CanonicalUserType<'tcx> { +impl<'tcx> CanonicalUserType<'tcx> { /// Returns `true` if this represents a substitution of the form `[?0, ?1, ?2]`, /// i.e., each thing is mapped to a canonical variable with the same index. pub fn is_identity(&self) -> bool { @@ -1079,7 +1080,7 @@ impl<'tcx> TyCtxt<'tcx> { variants: IndexVec, repr: ReprOptions, ) -> &'tcx ty::AdtDef { - self.arena.alloc(ty::AdtDef::new(self, did, kind, variants, repr)) + self.intern_adt_def(ty::AdtDef::new(self, did, kind, variants, repr)) } /// Allocates a read-only byte or string literal for `mir::interpret`. @@ -1112,7 +1113,11 @@ impl<'tcx> TyCtxt<'tcx> { }; debug!("layout_scalar_valid_range: attr={:?}", attr); if let Some( - &[ast::NestedMetaItem::Literal(ast::Lit { kind: ast::LitKind::Int(a, _), .. })], + &[ + ast::NestedMetaItem::Literal(ast::Lit { + kind: ast::LitKind::Int(a, _), .. + }), + ], ) = attr.meta_item_list().as_deref() { Bound::Included(a) @@ -1213,12 +1218,8 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn consider_optimizing String>(self, msg: T) -> bool { - let cname = self.crate_name(LOCAL_CRATE).as_str(); - self.sess.consider_optimizing(&cname, msg) - } - - pub fn lib_features(self) -> &'tcx middle::lib_features::LibFeatures { - self.get_lib_features(()) + let cname = self.crate_name(LOCAL_CRATE); + self.sess.consider_optimizing(cname.as_str(), msg) } /// Obtain all lang items of this crate and all dependencies (recursively) @@ -1482,40 +1483,8 @@ impl<'tcx> TyCtxt<'tcx> { scope_def_id: LocalDefId, ) -> Vec<&'tcx hir::Ty<'tcx>> { let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id); - let hir_output = match self.hir().get(hir_id) { - Node::Item(hir::Item { - kind: - ItemKind::Fn( - hir::FnSig { - decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. }, - .. - }, - .., - ), - .. - }) - | Node::ImplItem(hir::ImplItem { - kind: - hir::ImplItemKind::Fn( - hir::FnSig { - decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. }, - .. - }, - _, - ), - .. - }) - | Node::TraitItem(hir::TraitItem { - kind: - hir::TraitItemKind::Fn( - hir::FnSig { - decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. }, - .. - }, - _, - ), - .. - }) => ty, + let hir_output = match self.hir().fn_decl_by_hir_id(hir_id) { + Some(hir::FnDecl { output: hir::FnRetTy::Return(ty), .. }) => ty, _ => return vec![], }; @@ -1608,6 +1577,12 @@ impl<'tcx> TyCtxt<'tcx> { pub fn const_eval_limit(self) -> Limit { self.limits(()).const_eval_limit } + + pub fn all_traits(self) -> impl Iterator + 'tcx { + iter::once(LOCAL_CRATE) + .chain(self.crates(()).iter().copied()) + .flat_map(move |cnum| self.traits_in_crate(cnum).iter().copied()) + } } /// A trait implemented for all `X<'a>` types that can be safely and @@ -1926,7 +1901,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn debug_stats(self) -> impl std::fmt::Debug + 'tcx { struct DebugStats<'tcx>(TyCtxt<'tcx>); - impl std::fmt::Debug for DebugStats<'tcx> { + impl<'tcx> std::fmt::Debug for DebugStats<'tcx> { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { sty_debug_print!( fmt, @@ -2090,6 +2065,7 @@ direct_interners! { const_: mk_const(Const<'tcx>), const_allocation: intern_const_alloc(Allocation), layout: intern_layout(Layout), + adt_def: intern_adt_def(AdtDef), } macro_rules! slice_interners { @@ -2744,7 +2720,7 @@ impl<'tcx> TyCtxt<'tcx> { } } -impl TyCtxtAt<'tcx> { +impl<'tcx> TyCtxtAt<'tcx> { /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used. #[track_caller] pub fn ty_error(self) -> Ty<'tcx> { diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 1b32c8a669..ee00f6c62f 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -1,11 +1,17 @@ //! Diagnostics related methods for `TyS`. +use crate::ty::subst::{GenericArg, GenericArgKind}; use crate::ty::TyKind::*; -use crate::ty::{InferTy, TyCtxt, TyS}; +use crate::ty::{ + ConstKind, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, InferTy, + ProjectionTy, TyCtxt, TyS, TypeAndMut, +}; + use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::{QPath, TyKind, WhereBoundPredicate, WherePredicate}; +use rustc_span::Span; impl<'tcx> TyS<'tcx> { /// Similar to `TyS::is_primitive`, but also considers inferred numeric values to be primitive. @@ -62,16 +68,55 @@ impl<'tcx> TyS<'tcx> { /// Whether the type can be safely suggested during error recovery. pub fn is_suggestable(&self) -> bool { - !matches!( - self.kind(), + fn generic_arg_is_suggestible(arg: GenericArg<'_>) -> bool { + match arg.unpack() { + GenericArgKind::Type(ty) => ty.is_suggestable(), + GenericArgKind::Const(c) => const_is_suggestable(c.val), + _ => true, + } + } + + fn const_is_suggestable(kind: ConstKind<'_>) -> bool { + match kind { + ConstKind::Infer(..) + | ConstKind::Bound(..) + | ConstKind::Placeholder(..) + | ConstKind::Error(..) => false, + _ => true, + } + } + + // FIXME(compiler-errors): Some types are still not good to suggest, + // specifically references with lifetimes within the function. Not + //sure we have enough information to resolve whether a region is + // temporary, so I'll leave this as a fixme. + + match self.kind() { Opaque(..) - | FnDef(..) - | FnPtr(..) - | Dynamic(..) - | Closure(..) - | Infer(..) - | Projection(..) - ) + | FnDef(..) + | Closure(..) + | Infer(..) + | Generator(..) + | GeneratorWitness(..) + | Bound(_, _) + | Placeholder(_) + | Error(_) => false, + Dynamic(dty, _) => dty.iter().all(|pred| match pred.skip_binder() { + ExistentialPredicate::Trait(ExistentialTraitRef { substs, .. }) => { + substs.iter().all(generic_arg_is_suggestible) + } + ExistentialPredicate::Projection(ExistentialProjection { substs, ty, .. }) => { + ty.is_suggestable() && substs.iter().all(generic_arg_is_suggestible) + } + _ => true, + }), + Projection(ProjectionTy { substs: args, .. }) | Adt(_, args) | Tuple(args) => { + args.iter().all(generic_arg_is_suggestible) + } + Slice(ty) | RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => ty.is_suggestable(), + Array(ty, c) => ty.is_suggestable() && const_is_suggestable(c.val), + _ => true, + } } } @@ -270,7 +315,7 @@ pub fn suggest_constraining_type_param( // `where` clause instead of `trait Base: Super`. && !matches!(param.kind, hir::GenericParamKind::Type { default: Some(_), .. }) { - if let Some(bounds_span) = param.bounds_span() { + if let Some(span) = param.bounds_span_for_suggestions() { // If user has provided some bounds, suggest restricting them: // // fn foo(t: T) { ... } @@ -284,7 +329,7 @@ pub fn suggest_constraining_type_param( // -- // | // replace with: `T: Bar +` - suggest_restrict(bounds_span.shrink_to_hi()); + suggest_restrict(span); } else { // If user hasn't provided any bounds, suggest adding a new one: // @@ -432,3 +477,22 @@ impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> { hir::intravisit::walk_ty(self, ty); } } + +/// Collect al types that have an implicit `'static` obligation that we could suggest `'_` for. +pub struct StaticLifetimeVisitor<'tcx>(pub Vec, pub crate::hir::map::Map<'tcx>); + +impl<'v> hir::intravisit::Visitor<'v> for StaticLifetimeVisitor<'v> { + type Map = rustc_hir::intravisit::ErasedMap<'v>; + + fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap { + hir::intravisit::NestedVisitorMap::None + } + + fn visit_lifetime(&mut self, lt: &'v hir::Lifetime) { + if let hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static = + lt.name + { + self.0.push(lt.span); + } + } +} diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index 63eb55ed1a..0d290752e8 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -37,7 +37,7 @@ struct RegionEraserVisitor<'tcx> { tcx: TyCtxt<'tcx>, } -impl TypeFolder<'tcx> for RegionEraserVisitor<'tcx> { +impl<'tcx> TypeFolder<'tcx> for RegionEraserVisitor<'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { self.tcx } diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index b14a698926..df6e739dc2 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -118,8 +118,7 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { ArgumentMutability(_) | Mutability => write!(f, "types differ in mutability"), TupleSize(values) => write!( f, - "expected a tuple with {} element{}, \ - found one with {} element{}", + "expected a tuple with {} element{}, found one with {} element{}", values.expected, pluralize!(values.expected), values.found, @@ -127,8 +126,7 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { ), FixedArraySize(values) => write!( f, - "expected an array with a fixed size of {} element{}, \ - found one with {} element{}", + "expected an array with a fixed size of {} element{}, found one with {} element{}", values.expected, pluralize!(values.expected), values.found, @@ -521,7 +519,7 @@ impl Trait for X { proj_ty, values, body_owner_def_id, - &cause.code, + cause.code(), ); } (_, ty::Projection(proj_ty)) => { @@ -777,9 +775,7 @@ fn foo(&self) -> Self::T { String::new() } if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() { let opaque_local_def_id = def_id.as_local(); let opaque_hir_ty = if let Some(opaque_local_def_id) = opaque_local_def_id { - let hir = self.hir(); - let opaque_hir_id = hir.local_def_id_to_hir_id(opaque_local_def_id); - match &hir.expect_item(opaque_hir_id).kind { + match &self.hir().expect_item(opaque_local_def_id).kind { hir::ItemKind::OpaqueTy(opaque_hir_ty) => opaque_hir_ty, _ => bug!("The HirId comes from a `ty::Opaque`"), } diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 11ee942b83..daf9156a15 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -1,3 +1,4 @@ +use crate::mir::Mutability; use crate::ty::{self, Ty, TyCtxt}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def_id::DefId; @@ -19,7 +20,7 @@ pub type SimplifiedType = SimplifiedTypeGen; #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, TyEncodable, TyDecodable)] pub enum SimplifiedTypeGen where - D: Copy + Debug + Ord + Eq, + D: Copy + Debug + Eq, { BoolSimplifiedType, CharSimplifiedType, @@ -27,9 +28,12 @@ where UintSimplifiedType(ty::UintTy), FloatSimplifiedType(ty::FloatTy), AdtSimplifiedType(D), + ForeignSimplifiedType(D), StrSimplifiedType, ArraySimplifiedType, - PtrSimplifiedType, + SliceSimplifiedType, + RefSimplifiedType(Mutability), + PtrSimplifiedType(Mutability), NeverSimplifiedType, TupleSimplifiedType(usize), /// A trait object, all of whose components are markers @@ -42,22 +46,48 @@ where OpaqueSimplifiedType(D), FunctionSimplifiedType(usize), ParameterSimplifiedType, - ForeignSimplifiedType(DefId), } -/// Tries to simplify a type by dropping type parameters, deref'ing away any reference types, etc. -/// The idea is to get something simple that we can use to quickly decide if two types could unify -/// during method lookup. +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +pub enum SimplifyParams { + Yes, + No, +} + +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +pub enum StripReferences { + Yes, + No, +} + +/// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists. /// -/// If `can_simplify_params` is false, then we will fail to simplify type parameters entirely. This -/// is useful when those type parameters would be instantiated with fresh type variables, since -/// then we can't say much about whether two types would unify. Put another way, -/// `can_simplify_params` should be true if type parameters appear free in `ty` and `false` if they -/// are to be considered bound. +/// The idea is to get something simple that we can use to quickly decide if two types could unify, +/// for example during method lookup. +/// +/// A special case here are parameters and projections. Projections can be normalized to +/// a different type, meaning that `::Assoc` and `u8` can be unified, even though +/// their outermost layer is different while parameters like `T` of impls are later replaced +/// with an inference variable, which then also allows unification with other types. +/// +/// When using `SimplifyParams::Yes`, we still return a simplified type for params and projections², +/// the reasoning for this can be seen at the places doing this. +/// +/// For diagnostics we strip references with `StripReferences::Yes`. This is currently the best +/// way to skip some unhelpful suggestions. +/// +/// ¹ meaning that if two outermost layers are different, then the whole types are also different. +/// ² FIXME(@lcnr): this seems like it can actually end up being unsound with the way it's used during +/// candidate selection. We do not consider non blanket impls for `<_ as Trait>::Assoc` even +/// though `_` can be inferred to a concrete type later at which point a concrete impl +/// could actually apply. After experimenting for about an hour I wasn't able to cause any issues +/// this way so I am not going to change this until we actually find an issue as I am really +/// interesting in getting an actual test for this. pub fn simplify_type( tcx: TyCtxt<'_>, ty: Ty<'_>, - can_simplify_params: bool, + can_simplify_params: SimplifyParams, + strip_references: StripReferences, ) -> Option { match *ty.kind() { ty::Bool => Some(BoolSimplifiedType), @@ -67,19 +97,24 @@ pub fn simplify_type( ty::Float(float_type) => Some(FloatSimplifiedType(float_type)), ty::Adt(def, _) => Some(AdtSimplifiedType(def.did)), ty::Str => Some(StrSimplifiedType), - ty::Array(..) | ty::Slice(_) => Some(ArraySimplifiedType), - ty::RawPtr(_) => Some(PtrSimplifiedType), + ty::Array(..) => Some(ArraySimplifiedType), + ty::Slice(..) => Some(SliceSimplifiedType), + ty::RawPtr(ptr) => Some(PtrSimplifiedType(ptr.mutbl)), ty::Dynamic(ref trait_info, ..) => match trait_info.principal_def_id() { Some(principal_def_id) if !tcx.trait_is_auto(principal_def_id) => { Some(TraitSimplifiedType(principal_def_id)) } _ => Some(MarkerTraitObjectSimplifiedType), }, - ty::Ref(_, ty, _) => { - // since we introduce auto-refs during method lookup, we - // just treat &T and T as equivalent from the point of - // view of possibly unifying - simplify_type(tcx, ty, can_simplify_params) + ty::Ref(_, ty, mutbl) => { + if strip_references == StripReferences::Yes { + // For diagnostics, when recommending similar impls we want to + // recommend impls even when there is a reference mismatch, + // so we treat &T and T equivalently in that case. + simplify_type(tcx, ty, can_simplify_params, strip_references) + } else { + Some(RefSimplifiedType(mutbl)) + } } ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(ClosureSimplifiedType(def_id)), ty::Generator(def_id, _, _) => Some(GeneratorSimplifiedType(def_id)), @@ -90,7 +125,7 @@ pub fn simplify_type( ty::Tuple(ref tys) => Some(TupleSimplifiedType(tys.len())), ty::FnPtr(ref f) => Some(FunctionSimplifiedType(f.skip_binder().inputs().len())), ty::Projection(_) | ty::Param(_) => { - if can_simplify_params { + if can_simplify_params == SimplifyParams::Yes { // In normalized types, projections don't unify with // anything. when lazy normalization happens, this // will change. It would still be nice to have a way @@ -108,6 +143,18 @@ pub fn simplify_type( } impl SimplifiedTypeGen { + pub fn def(self) -> Option { + match self { + AdtSimplifiedType(d) + | ForeignSimplifiedType(d) + | TraitSimplifiedType(d) + | ClosureSimplifiedType(d) + | GeneratorSimplifiedType(d) + | OpaqueSimplifiedType(d) => Some(d), + _ => None, + } + } + pub fn map_def(self, map: F) -> SimplifiedTypeGen where F: Fn(D) -> U, @@ -120,9 +167,12 @@ impl SimplifiedTypeGen { UintSimplifiedType(t) => UintSimplifiedType(t), FloatSimplifiedType(t) => FloatSimplifiedType(t), AdtSimplifiedType(d) => AdtSimplifiedType(map(d)), + ForeignSimplifiedType(d) => ForeignSimplifiedType(map(d)), StrSimplifiedType => StrSimplifiedType, ArraySimplifiedType => ArraySimplifiedType, - PtrSimplifiedType => PtrSimplifiedType, + SliceSimplifiedType => SliceSimplifiedType, + RefSimplifiedType(m) => RefSimplifiedType(m), + PtrSimplifiedType(m) => PtrSimplifiedType(m), NeverSimplifiedType => NeverSimplifiedType, MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType, TupleSimplifiedType(n) => TupleSimplifiedType(n), @@ -133,7 +183,6 @@ impl SimplifiedTypeGen { OpaqueSimplifiedType(d) => OpaqueSimplifiedType(map(d)), FunctionSimplifiedType(n) => FunctionSimplifiedType(n), ParameterSimplifiedType => ParameterSimplifiedType, - ForeignSimplifiedType(d) => ForeignSimplifiedType(d), } } } @@ -149,12 +198,13 @@ where | CharSimplifiedType | StrSimplifiedType | ArraySimplifiedType - | PtrSimplifiedType + | SliceSimplifiedType | NeverSimplifiedType | ParameterSimplifiedType | MarkerTraitObjectSimplifiedType => { // nothing to do } + RefSimplifiedType(m) | PtrSimplifiedType(m) => m.hash_stable(hcx, hasher), IntSimplifiedType(t) => t.hash_stable(hcx, hasher), UintSimplifiedType(t) => t.hash_stable(hcx, hasher), FloatSimplifiedType(t) => t.hash_stable(hcx, hasher), diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index a078b6fb74..617c522ac8 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -22,7 +22,7 @@ impl FlagComputation { result } - pub fn for_predicate(binder: ty::Binder<'tcx, ty::PredicateKind<'_>>) -> FlagComputation { + pub fn for_predicate<'tcx>(binder: ty::Binder<'tcx, ty::PredicateKind<'_>>) -> FlagComputation { let mut result = FlagComputation::new(); result.add_predicate(binder); result @@ -216,7 +216,7 @@ impl FlagComputation { } } - fn add_predicate(&mut self, binder: ty::Binder<'tcx, ty::PredicateKind<'_>>) { + fn add_predicate(&mut self, binder: ty::Binder<'_, ty::PredicateKind<'_>>) { self.bound_computation(binder, |computation, atom| computation.add_predicate_atom(atom)); } @@ -310,7 +310,7 @@ impl FlagComputation { } } - fn add_unevaluated_const

(&mut self, ct: ty::Unevaluated<'tcx, P>) { + fn add_unevaluated_const

(&mut self, ct: ty::Unevaluated<'_, P>) { // The generic arguments of unevaluated consts are a bit special, // see the `rustc-dev-guide` for more information. // diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index e16491dcc9..f5be8b21e8 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -46,9 +46,30 @@ use std::ops::ControlFlow; /// /// To implement this conveniently, use the derive macro located in `rustc_macros`. pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { - fn super_fold_with>(self, folder: &mut F) -> Self; - fn fold_with>(self, folder: &mut F) -> Self { - self.super_fold_with(folder) + /// Consumers may find this more convenient to use with infallible folders than + /// [`try_super_fold_with`][`TypeFoldable::try_super_fold_with`], to which the + /// provided default definition delegates. Implementors **should not** override + /// this provided default definition, to ensure that the two methods are coherent + /// (provide a definition of `try_super_fold_with` instead). + fn super_fold_with>(self, folder: &mut F) -> Self { + self.try_super_fold_with(folder).into_ok() + } + /// Consumers may find this more convenient to use with infallible folders than + /// [`try_fold_with`][`TypeFoldable::try_fold_with`], to which the provided + /// default definition delegates. Implementors **should not** override this + /// provided default definition, to ensure that the two methods are coherent + /// (provide a definition of `try_fold_with` instead). + fn fold_with>(self, folder: &mut F) -> Self { + self.try_fold_with(folder).into_ok() + } + + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result; + + fn try_fold_with>(self, folder: &mut F) -> Result { + self.try_super_fold_with(folder) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow; @@ -178,9 +199,9 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { } } -impl TypeFoldable<'tcx> for hir::Constness { - fn super_fold_with>(self, _: &mut F) -> Self { - self +impl<'tcx> TypeFoldable<'tcx> for hir::Constness { + fn try_super_fold_with>(self, _: &mut F) -> Result { + Ok(self) } fn super_visit_with>(&self, _: &mut V) -> ControlFlow { ControlFlow::CONTINUE @@ -192,37 +213,152 @@ impl TypeFoldable<'tcx> for hir::Constness { /// default implementation that does an "identity" fold. Within each /// identity fold, it should invoke `foo.fold_with(self)` to fold each /// sub-item. +/// +/// If this folder is fallible (and therefore its [`Error`][`TypeFolder::Error`] +/// associated type is something other than the default, never), +/// [`FallibleTypeFolder`] should be implemented manually; otherwise, +/// a blanket implementation of [`FallibleTypeFolder`] will defer to +/// the infallible methods of this trait to ensure that the two APIs +/// are coherent. pub trait TypeFolder<'tcx>: Sized { + type Error = !; + fn tcx<'a>(&'a self) -> TyCtxt<'tcx>; fn fold_binder(&mut self, t: Binder<'tcx, T>) -> Binder<'tcx, T> where T: TypeFoldable<'tcx>, + Self: TypeFolder<'tcx, Error = !>, { t.super_fold_with(self) } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> + where + Self: TypeFolder<'tcx, Error = !>, + { t.super_fold_with(self) } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> + where + Self: TypeFolder<'tcx, Error = !>, + { r.super_fold_with(self) } - fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { + fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> + where + Self: TypeFolder<'tcx, Error = !>, + { c.super_fold_with(self) } - fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { + fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> + where + Self: TypeFolder<'tcx, Error = !>, + { p.super_fold_with(self) } - fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { + fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> + where + Self: TypeFolder<'tcx, Error = !>, + { bug!("most type folders should not be folding MIR datastructures: {:?}", c) } } +/// The `FallibleTypeFolder` trait defines the actual *folding*. There is a +/// method defined for every foldable type. Each of these has a +/// default implementation that does an "identity" fold. Within each +/// identity fold, it should invoke `foo.try_fold_with(self)` to fold each +/// sub-item. +/// +/// A blanket implementation of this trait (that defers to the relevant +/// method of [`TypeFolder`]) is provided for all infallible folders in +/// order to ensure the two APIs are coherent. +pub trait FallibleTypeFolder<'tcx>: TypeFolder<'tcx> { + fn try_fold_binder(&mut self, t: Binder<'tcx, T>) -> Result, Self::Error> + where + T: TypeFoldable<'tcx>, + { + t.try_super_fold_with(self) + } + + fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result, Self::Error> { + t.try_super_fold_with(self) + } + + fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result, Self::Error> { + r.try_super_fold_with(self) + } + + fn try_fold_const( + &mut self, + c: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { + c.try_super_fold_with(self) + } + + fn try_fold_predicate( + &mut self, + p: ty::Predicate<'tcx>, + ) -> Result, Self::Error> { + p.try_super_fold_with(self) + } + + fn try_fold_mir_const( + &mut self, + c: mir::ConstantKind<'tcx>, + ) -> Result, Self::Error> { + bug!("most type folders should not be folding MIR datastructures: {:?}", c) + } +} + +// Blanket implementation of fallible trait for infallible folders +// delegates to infallible methods to prevent incoherence +impl<'tcx, F> FallibleTypeFolder<'tcx> for F +where + F: TypeFolder<'tcx, Error = !>, +{ + fn try_fold_binder(&mut self, t: Binder<'tcx, T>) -> Result, Self::Error> + where + T: TypeFoldable<'tcx>, + { + Ok(self.fold_binder(t)) + } + + fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result, Self::Error> { + Ok(self.fold_ty(t)) + } + + fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result, Self::Error> { + Ok(self.fold_region(r)) + } + + fn try_fold_const( + &mut self, + c: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { + Ok(self.fold_const(c)) + } + + fn try_fold_predicate( + &mut self, + p: ty::Predicate<'tcx>, + ) -> Result, Self::Error> { + Ok(self.fold_predicate(p)) + } + + fn try_fold_mir_const( + &mut self, + c: mir::ConstantKind<'tcx>, + ) -> Result, Self::Error> { + Ok(self.fold_mir_const(c)) + } +} + pub trait TypeVisitor<'tcx>: Sized { type BreakTy = !; /// Supplies the `tcx` for an unevaluated anonymous constant in case its default substs @@ -924,13 +1060,13 @@ struct Shifter<'tcx> { amount: u32, } -impl Shifter<'tcx> { +impl<'tcx> Shifter<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, amount: u32) -> Self { Shifter { tcx, current_index: ty::INNERMOST, amount } } } -impl TypeFolder<'tcx> for Shifter<'tcx> { +impl<'tcx> TypeFolder<'tcx> for Shifter<'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { self.tcx } @@ -1121,7 +1257,7 @@ struct HasTypeFlagsVisitor<'tcx> { flags: ty::TypeFlags, } -impl std::fmt::Debug for HasTypeFlagsVisitor<'tcx> { +impl<'tcx> std::fmt::Debug for HasTypeFlagsVisitor<'tcx> { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.flags.fmt(fmt) } @@ -1318,7 +1454,7 @@ struct LateBoundRegionsCollector<'tcx> { just_constrained: bool, } -impl LateBoundRegionsCollector<'tcx> { +impl<'tcx> LateBoundRegionsCollector<'tcx> { fn new(tcx: TyCtxt<'tcx>, just_constrained: bool) -> Self { LateBoundRegionsCollector { tcx, diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index f53f187150..1c3a01e2cf 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -24,13 +24,11 @@ impl GenericParamDefKind { GenericParamDefKind::Const { .. } => "constant", } } - pub fn to_ord(&self, tcx: TyCtxt<'_>) -> ast::ParamKindOrd { + pub fn to_ord(&self) -> ast::ParamKindOrd { match self { GenericParamDefKind::Lifetime => ast::ParamKindOrd::Lifetime, GenericParamDefKind::Type { .. } => ast::ParamKindOrd::Type, - GenericParamDefKind::Const { .. } => { - ast::ParamKindOrd::Const { unordered: tcx.features().unordered_const_ty_params() } - } + GenericParamDefKind::Const { .. } => ast::ParamKindOrd::Const, } } } diff --git a/compiler/rustc_middle/src/ty/inhabitedness/def_id_forest.rs b/compiler/rustc_middle/src/ty/inhabitedness/def_id_forest.rs index 275384e227..f31c7dd743 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/def_id_forest.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/def_id_forest.rs @@ -30,7 +30,7 @@ pub enum DefIdForest { /// Tests whether a slice of roots contains a given DefId. #[inline] -fn slice_contains(tcx: TyCtxt<'tcx>, slice: &[DefId], id: DefId) -> bool { +fn slice_contains<'tcx>(tcx: TyCtxt<'tcx>, slice: &[DefId], id: DefId) -> bool { slice.iter().any(|root_id| tcx.is_descendant_of(id, *root_id)) } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 4b38105e44..eaa7ee84b7 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -7,6 +7,7 @@ use rustc_hir::def::Namespace; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::lang_items::LangItem; use rustc_macros::HashStable; +use rustc_middle::ty::normalize_erasing_regions::NormalizationError; use std::fmt; @@ -575,6 +576,23 @@ impl<'tcx> Instance<'tcx> { } } + #[inline(always)] + pub fn try_subst_mir_and_normalize_erasing_regions( + &self, + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + v: T, + ) -> Result> + where + T: TypeFoldable<'tcx> + Clone, + { + if let Some(substs) = self.substs_for_mir_body() { + tcx.try_subst_and_normalize_erasing_regions(substs, param_env, v) + } else { + tcx.try_normalize_erasing_regions(param_env, v) + } + } + /// Returns a new `Instance` where generic parameters in `instance.substs` are replaced by /// identity parameters if they are determined to be unused in `instance.def`. pub fn polymorphize(self, tcx: TyCtxt<'tcx>) -> Self { @@ -617,7 +635,7 @@ fn polymorphize<'tcx>( tcx: TyCtxt<'tcx>, } - impl ty::TypeFolder<'tcx> for PolymorphizationFolder<'tcx> { + impl<'tcx> ty::TypeFolder<'tcx> for PolymorphizationFolder<'tcx> { fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { self.tcx } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index b87e23af72..196fe7ce1b 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1,5 +1,6 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::mir::{GeneratorLayout, GeneratorSavedLocal}; +use crate::ty::normalize_erasing_regions::NormalizationError; use crate::ty::subst::Subst; use crate::ty::{self, subst::SubstsRef, ReprOptions, Ty, TyCtxt, TypeFoldable}; use rustc_ast as ast; @@ -167,7 +168,7 @@ impl PrimitiveExt for Primitive { /// Return an *integer* type matching this primitive. /// Useful in particular when dealing with enum discriminants. #[inline] - fn to_int_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + fn to_int_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { match *self { Int(i, signed) => i.to_ty(tcx, signed), Pointer => tcx.types.usize, @@ -199,6 +200,7 @@ pub const MAX_SIMD_LANES: u64 = 1 << 0xF; pub enum LayoutError<'tcx> { Unknown(Ty<'tcx>), SizeOverflow(Ty<'tcx>), + NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>), } impl<'tcx> fmt::Display for LayoutError<'tcx> { @@ -208,16 +210,24 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> { LayoutError::SizeOverflow(ty) => { write!(f, "values of the type `{}` are too big for the current architecture", ty) } + LayoutError::NormalizationFailure(t, e) => write!( + f, + "unable to determine layout for `{}` because `{}` cannot be normalized", + t, + e.get_type_for_failure() + ), } } } +#[instrument(skip(tcx, query), level = "debug")] fn layout_of<'tcx>( tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, ) -> Result, LayoutError<'tcx>> { ty::tls::with_related_context(tcx, move |icx| { let (param_env, ty) = query.into_parts(); + debug!(?ty); if !tcx.recursion_limit().value_within_limit(icx.layout_depth) { tcx.sess.fatal(&format!("overflow representing the type `{}`", ty)); @@ -229,7 +239,18 @@ fn layout_of<'tcx>( ty::tls::enter_context(&icx, |_| { let param_env = param_env.with_reveal_all_normalized(tcx); let unnormalized_ty = ty; - let ty = tcx.normalize_erasing_regions(param_env, ty); + + // FIXME: We might want to have two different versions of `layout_of`: + // One that can be called after typecheck has completed and can use + // `normalize_erasing_regions` here and another one that can be called + // before typecheck has completed and uses `try_normalize_erasing_regions`. + let ty = match tcx.try_normalize_erasing_regions(param_env, ty) { + Ok(t) => t, + Err(normalization_error) => { + return Err(LayoutError::NormalizationFailure(ty, normalization_error)); + } + }; + if ty != unnormalized_ty { // Ensure this layout is also cached for the normalized type. return tcx.layout_of(param_env.and(ty)); @@ -326,10 +347,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let mut inverse_memory_index: Vec = (0..fields.len() as u32).collect(); - // `ReprOptions.layout_seed` is a deterministic seed that we can use to - // randomize field ordering with - let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed); - let optimize = !repr.inhibit_struct_field_reordering_opt(); if optimize { let end = @@ -343,6 +360,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // the field ordering to try and catch some code making assumptions about layouts // we don't guarantee if repr.can_randomize_type_layout() { + // `ReprOptions.layout_seed` is a deterministic seed that we can use to + // randomize field ordering with + let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed); + // Shuffle the ordering of the fields optimizing.shuffle(&mut rng); @@ -512,7 +533,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } } - if sized && fields.iter().any(|f| f.abi.is_uninhabited()) { + if fields.iter().any(|f| f.abi.is_uninhabited()) { abi = Abi::Uninhabited; } @@ -2174,9 +2195,9 @@ pub trait LayoutOf<'tcx>: LayoutOfHelpers<'tcx> { } } -impl> LayoutOf<'tcx> for C {} +impl<'tcx, C: LayoutOfHelpers<'tcx>> LayoutOf<'tcx> for C {} -impl LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxt<'tcx>> { +impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxt<'tcx>> { type LayoutOfResult = Result, LayoutError<'tcx>>; #[inline] @@ -2185,7 +2206,7 @@ impl LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxt<'tcx>> { } } -impl LayoutOfHelpers<'tcx> for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> { +impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> { type LayoutOfResult = Result, LayoutError<'tcx>>; #[inline] @@ -2261,7 +2282,7 @@ where TyAndLayout(TyAndLayout<'tcx>), } - fn field_ty_or_layout( + fn field_ty_or_layout<'tcx>( this: TyAndLayout<'tcx>, cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>), i: usize, @@ -2560,9 +2581,12 @@ impl<'tcx> ty::Instance<'tcx> { // for `Instance` (e.g. typeck would use `Ty::fn_sig` instead), // or should go through `FnAbi` instead, to avoid losing any // adjustments `fn_abi_of_instance` might be performing. - fn fn_sig_for_fn_abi(&self, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { - // FIXME(davidtwco,eddyb): A `ParamEnv` should be passed through to this function. - let ty = self.ty(tcx, ty::ParamEnv::reveal_all()); + fn fn_sig_for_fn_abi( + &self, + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> ty::PolyFnSig<'tcx> { + let ty = self.ty(tcx, param_env); match *ty.kind() { ty::FnDef(..) => { // HACK(davidtwco,eddyb): This is a workaround for polymorphization considering @@ -2703,7 +2727,7 @@ impl<'tcx> ty::Instance<'tcx> { /// with `-Cpanic=abort` will look like they can't unwind when in fact they /// might (from a foreign exception or similar). #[inline] -pub fn fn_can_unwind( +pub fn fn_can_unwind<'tcx>( tcx: TyCtxt<'tcx>, codegen_fn_attr_flags: CodegenFnAttrFlags, abi: SpecAbi, @@ -2821,7 +2845,7 @@ pub enum FnAbiError<'tcx> { AdjustForForeignAbi(call::AdjustForForeignAbiError), } -impl From> for FnAbiError<'tcx> { +impl<'tcx> From> for FnAbiError<'tcx> { fn from(err: LayoutError<'tcx>) -> Self { Self::Layout(err) } @@ -2921,7 +2945,7 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> { } } -impl> FnAbiOf<'tcx> for C {} +impl<'tcx, C: FnAbiOfHelpers<'tcx>> FnAbiOf<'tcx> for C {} fn fn_abi_of_fn_ptr<'tcx>( tcx: TyCtxt<'tcx>, @@ -2944,7 +2968,7 @@ fn fn_abi_of_instance<'tcx>( ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> { let (param_env, (instance, extra_args)) = query.into_parts(); - let sig = instance.fn_sig_for_fn_abi(tcx); + let sig = instance.fn_sig_for_fn_abi(tcx, param_env); let caller_location = if instance.def.requires_caller_location(tcx) { Some(tcx.caller_location_ty()) diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs index 1dceda6c7a..adba7d1315 100644 --- a/compiler/rustc_middle/src/ty/list.rs +++ b/compiler/rustc_middle/src/ty/list.rs @@ -1,7 +1,5 @@ use crate::arena::Arena; - use rustc_serialize::{Encodable, Encoder}; - use std::alloc::Layout; use std::cmp::Ordering; use std::fmt; @@ -12,49 +10,69 @@ use std::ops::Deref; use std::ptr; use std::slice; -extern "C" { - /// A dummy type used to force `List` to be unsized while not requiring references to it be wide - /// pointers. - type OpaqueListContents; -} - -/// A wrapper for slices with the additional invariant -/// that the slice is interned and no other slice with -/// the same contents can exist in the same context. -/// This means we can use pointer for both -/// equality comparisons and hashing. -/// -/// Unlike slices, the types contained in `List` are expected to be `Copy` -/// and iterating over a `List` returns `T` instead of a reference. -/// -/// Note: `Slice` was already taken by the `Ty`. +/// `List` is a bit like `&[T]`, but with some critical differences. +/// - IMPORTANT: Every `List` is *required* to have unique contents. The +/// type's correctness relies on this, *but it does not enforce it*. +/// Therefore, any code that creates a `List` must ensure uniqueness +/// itself. In practice this is achieved by interning. +/// - The length is stored within the `List`, so `&List` is a thin +/// pointer. +/// - Because of this, you cannot get a `List` that is a sub-list of another +/// `List`. You can get a sub-slice `&[T]`, however. +/// - `List` can be used with `CopyTaggedPtr`, which is useful within +/// structs whose size must be minimized. +/// - Because of the uniqueness assumption, we can use the address of a +/// `List` for faster equality comparisons and hashing. +/// - `T` must be `Copy`. This lets `List` be stored in a dropless arena and +/// iterators return a `T` rather than a `&T`. +/// - `T` must not be zero-sized. #[repr(C)] pub struct List { len: usize, + + /// Although this claims to be a zero-length array, in practice `len` + /// elements are actually present. data: [T; 0], + opaque: OpaqueListContents, } -unsafe impl<'a, T: 'a> rustc_data_structures::tagged_ptr::Pointer for &'a List { - const BITS: usize = std::mem::align_of::().trailing_zeros() as usize; - #[inline] - fn into_usize(self) -> usize { - self as *const List as usize - } - #[inline] - unsafe fn from_usize(ptr: usize) -> Self { - &*(ptr as *const List) - } - unsafe fn with_ref R>(ptr: usize, f: F) -> R { - // Self: Copy so this is fine - let ptr = Self::from_usize(ptr); - f(&ptr) +extern "C" { + /// A dummy type used to force `List` to be unsized while not requiring + /// references to it be wide pointers. + type OpaqueListContents; +} + +impl List { + /// Returns a reference to the (unique, static) empty list. + #[inline(always)] + pub fn empty<'a>() -> &'a List { + #[repr(align(64))] + struct MaxAlign; + + assert!(mem::align_of::() <= mem::align_of::()); + + #[repr(C)] + struct InOrder(T, U); + + // The empty slice is static and contains a single `0` usize (for the + // length) that is 64-byte aligned, thus featuring the necessary + // trailing padding for elements with up to 64-byte alignment. + static EMPTY_SLICE: InOrder = InOrder(0, MaxAlign); + unsafe { &*(&EMPTY_SLICE as *const _ as *const List) } } } -unsafe impl Sync for List {} - impl List { + /// Allocates a list from `arena` and copies the contents of `slice` into it. + /// + /// WARNING: the contents *must be unique*, such that no list with these + /// contents has been previously created. If not, operations such as `eq` + /// and `hash` might give incorrect results. + /// + /// Panics if `T` is `Drop`, or `T` is zero-sized, or the slice is empty + /// (because the empty list exists statically, and is available via + /// `empty()`). #[inline] pub(super) fn from_arena<'tcx>(arena: &'tcx Arena<'tcx>, slice: &[T]) -> &'tcx List { assert!(!mem::needs_drop::()); @@ -73,7 +91,7 @@ impl List { .cast::() .copy_from_nonoverlapping(slice.as_ptr(), slice.len()); - &mut *mem + &*mem } } @@ -107,11 +125,24 @@ impl> Encodable for &List { } } +impl PartialEq for List { + #[inline] + fn eq(&self, other: &List) -> bool { + // Pointer equality implies list equality (due to the unique contents + // assumption). + ptr::eq(self, other) + } +} + +impl Eq for List {} + impl Ord for List where T: Ord, { fn cmp(&self, other: &List) -> Ordering { + // Pointer equality implies list equality (due to the unique contents + // assumption), but the contents must be compared otherwise. if self == other { Ordering::Equal } else { <[T] as Ord>::cmp(&**self, &**other) } } } @@ -121,6 +152,8 @@ where T: PartialOrd, { fn partial_cmp(&self, other: &List) -> Option { + // Pointer equality implies list equality (due to the unique contents + // assumption), but the contents must be compared otherwise. if self == other { Some(Ordering::Equal) } else { @@ -129,17 +162,11 @@ where } } -impl PartialEq for List { - #[inline] - fn eq(&self, other: &List) -> bool { - ptr::eq(self, other) - } -} -impl Eq for List {} - impl Hash for List { #[inline] fn hash(&self, s: &mut H) { + // Pointer hashing is sufficient (due to the unique contents + // assumption). (self as *const List).hash(s) } } @@ -168,13 +195,24 @@ impl<'a, T: Copy> IntoIterator for &'a List { } } -impl List { - #[inline(always)] - pub fn empty<'a>() -> &'a List { - #[repr(align(64), C)] - struct EmptySlice([u8; 64]); - static EMPTY_SLICE: EmptySlice = EmptySlice([0; 64]); - assert!(mem::align_of::() <= 64); - unsafe { &*(&EMPTY_SLICE as *const _ as *const List) } +unsafe impl Sync for List {} + +unsafe impl<'a, T: 'a> rustc_data_structures::tagged_ptr::Pointer for &'a List { + const BITS: usize = std::mem::align_of::().trailing_zeros() as usize; + + #[inline] + fn into_usize(self) -> usize { + self as *const List as usize + } + + #[inline] + unsafe fn from_usize(ptr: usize) -> &'a List { + &*(ptr as *const List) + } + + unsafe fn with_ref R>(ptr: usize, f: F) -> R { + // `Self` is `&'a List` which impls `Copy`, so this is fine. + let ptr = Self::from_usize(ptr); + f(&ptr) } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 673733faa7..78ccfbd5e8 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -9,7 +9,7 @@ //! //! ["The `ty` module: representing types"]: https://rustc-dev-guide.rust-lang.org/ty.html -pub use self::fold::{TypeFoldable, TypeFolder, TypeVisitor}; +pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeVisitor}; pub use self::AssocItemContainer::*; pub use self::BorrowKind::*; pub use self::IntVarValue::*; @@ -77,7 +77,7 @@ pub use self::sty::{ GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts, InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, ProjectionTy, Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, - UpvarSubsts, VarianceDiagInfo, VarianceDiagMutKind, + UpvarSubsts, VarianceDiagInfo, }; pub use self::trait_def::TraitDef; @@ -230,6 +230,19 @@ pub enum BoundConstness { ConstIfConst, } +impl BoundConstness { + /// Reduce `self` and `constness` to two possible combined states instead of four. + pub fn and(&mut self, constness: hir::Constness) -> hir::Constness { + match (constness, self) { + (hir::Constness::Const, BoundConstness::ConstIfConst) => hir::Constness::Const, + (_, this) => { + *this = BoundConstness::NotConst; + hir::Constness::NotConst + } + } + } +} + impl fmt::Display for BoundConstness { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { @@ -721,6 +734,15 @@ pub struct TraitPredicate<'tcx> { pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>; impl<'tcx> TraitPredicate<'tcx> { + pub fn remap_constness(&mut self, tcx: TyCtxt<'tcx>, param_env: &mut ParamEnv<'tcx>) { + if unlikely!(Some(self.trait_ref.def_id) == tcx.lang_items().drop_trait()) { + // remap without changing constness of this predicate. + // this is because `T: ~const Drop` has a different meaning to `T: Drop` + param_env.remap_constness_with(self.constness) + } else { + *param_env = param_env.with_constness(self.constness.and(param_env.constness())) + } + } pub fn def_id(self) -> DefId { self.trait_ref.def_id } @@ -839,27 +861,13 @@ pub trait ToPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx>; } -impl ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> { +impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> { #[inline(always)] fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { tcx.mk_predicate(self) } } -impl<'tcx> ToPredicate<'tcx> for ConstnessAnd> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { - self.value - .map_bound(|trait_ref| { - PredicateKind::Trait(ty::TraitPredicate { - trait_ref, - constness: self.constness, - polarity: ty::ImplPolarity::Positive, - }) - }) - .to_predicate(tcx) - } -} - impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { self.map_bound(PredicateKind::Trait).to_predicate(tcx) @@ -885,12 +893,10 @@ impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> { } impl<'tcx> Predicate<'tcx> { - pub fn to_opt_poly_trait_ref(self) -> Option>> { + pub fn to_opt_poly_trait_pred(self) -> Option> { let predicate = self.kind(); match predicate.skip_binder() { - PredicateKind::Trait(t) => { - Some(ConstnessAnd { constness: t.constness, value: predicate.rebind(t.trait_ref) }) - } + PredicateKind::Trait(t) => Some(predicate.rebind(t)), PredicateKind::Projection(..) | PredicateKind::Subtype(..) | PredicateKind::Coerce(..) @@ -1221,23 +1227,33 @@ pub struct ParamEnv<'tcx> { /// want `Reveal::All`. /// /// Note: This is packed, use the reveal() method to access it. - packed: CopyTaggedPtr<&'tcx List>, traits::Reveal, true>, + packed: CopyTaggedPtr<&'tcx List>, ParamTag, true>, } -unsafe impl rustc_data_structures::tagged_ptr::Tag for traits::Reveal { - const BITS: usize = 1; +#[derive(Copy, Clone)] +struct ParamTag { + reveal: traits::Reveal, + constness: hir::Constness, +} + +unsafe impl rustc_data_structures::tagged_ptr::Tag for ParamTag { + const BITS: usize = 2; #[inline] fn into_usize(self) -> usize { match self { - traits::Reveal::UserFacing => 0, - traits::Reveal::All => 1, + Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst } => 0, + Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst } => 1, + Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const } => 2, + Self { reveal: traits::Reveal::All, constness: hir::Constness::Const } => 3, } } #[inline] unsafe fn from_usize(ptr: usize) -> Self { match ptr { - 0 => traits::Reveal::UserFacing, - 1 => traits::Reveal::All, + 0 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst }, + 1 => Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst }, + 2 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const }, + 3 => Self { reveal: traits::Reveal::All, constness: hir::Constness::Const }, _ => std::hint::unreachable_unchecked(), } } @@ -1248,6 +1264,7 @@ impl<'tcx> fmt::Debug for ParamEnv<'tcx> { f.debug_struct("ParamEnv") .field("caller_bounds", &self.caller_bounds()) .field("reveal", &self.reveal()) + .field("constness", &self.constness()) .finish() } } @@ -1256,17 +1273,26 @@ impl<'a, 'tcx> HashStable> for ParamEnv<'tcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { self.caller_bounds().hash_stable(hcx, hasher); self.reveal().hash_stable(hcx, hasher); + self.constness().hash_stable(hcx, hasher); } } impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { - ParamEnv::new(self.caller_bounds().fold_with(folder), self.reveal().fold_with(folder)) + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + Ok(ParamEnv::new( + self.caller_bounds().try_fold_with(folder)?, + self.reveal().try_fold_with(folder)?, + self.constness().try_fold_with(folder)?, + )) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { self.caller_bounds().visit_with(visitor)?; - self.reveal().visit_with(visitor) + self.reveal().visit_with(visitor)?; + self.constness().visit_with(visitor) } } @@ -1277,7 +1303,7 @@ impl<'tcx> ParamEnv<'tcx> { /// type-checking. #[inline] pub fn empty() -> Self { - Self::new(List::empty(), Reveal::UserFacing) + Self::new(List::empty(), Reveal::UserFacing, hir::Constness::NotConst) } #[inline] @@ -1287,7 +1313,12 @@ impl<'tcx> ParamEnv<'tcx> { #[inline] pub fn reveal(self) -> traits::Reveal { - self.packed.tag() + self.packed.tag().reveal + } + + #[inline] + pub fn constness(self) -> hir::Constness { + self.packed.tag().constness } /// Construct a trait environment with no where-clauses in scope @@ -1299,20 +1330,47 @@ impl<'tcx> ParamEnv<'tcx> { /// or invoke `param_env.with_reveal_all()`. #[inline] pub fn reveal_all() -> Self { - Self::new(List::empty(), Reveal::All) + Self::new(List::empty(), Reveal::All, hir::Constness::NotConst) } /// Construct a trait environment with the given set of predicates. #[inline] - pub fn new(caller_bounds: &'tcx List>, reveal: Reveal) -> Self { - ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, reveal) } + pub fn new( + caller_bounds: &'tcx List>, + reveal: Reveal, + constness: hir::Constness, + ) -> Self { + ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, ParamTag { reveal, constness }) } } pub fn with_user_facing(mut self) -> Self { - self.packed.set_tag(Reveal::UserFacing); + self.packed.set_tag(ParamTag { reveal: Reveal::UserFacing, ..self.packed.tag() }); self } + #[inline] + pub fn with_constness(mut self, constness: hir::Constness) -> Self { + self.packed.set_tag(ParamTag { constness, ..self.packed.tag() }); + self + } + + #[inline] + pub fn with_const(mut self) -> Self { + self.packed.set_tag(ParamTag { constness: hir::Constness::Const, ..self.packed.tag() }); + self + } + + #[inline] + pub fn without_const(mut self) -> Self { + self.packed.set_tag(ParamTag { constness: hir::Constness::NotConst, ..self.packed.tag() }); + self + } + + #[inline] + pub fn remap_constness_with(&mut self, mut constness: ty::BoundConstness) { + *self = self.with_constness(constness.and(self.constness())) + } + /// Returns a new parameter environment with the same clauses, but /// which "reveals" the true results of projections in all cases /// (even for associated types that are specializable). This is @@ -1323,17 +1381,21 @@ impl<'tcx> ParamEnv<'tcx> { /// will be normalized to their underlying types. /// See PR #65989 and issue #65918 for more details pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> Self { - if self.packed.tag() == traits::Reveal::All { + if self.packed.tag().reveal == traits::Reveal::All { return self; } - ParamEnv::new(tcx.normalize_opaque_types(self.caller_bounds()), Reveal::All) + ParamEnv::new( + tcx.normalize_opaque_types(self.caller_bounds()), + Reveal::All, + self.constness(), + ) } /// Returns this same environment but with no caller bounds. #[inline] pub fn without_caller_bounds(self) -> Self { - Self::new(List::empty(), self.reveal()) + Self::new(List::empty(), self.reveal(), self.constness()) } /// Creates a suitable environment in which to perform trait @@ -1363,33 +1425,23 @@ impl<'tcx> ParamEnv<'tcx> { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)] -pub struct ConstnessAnd { - pub constness: BoundConstness, - pub value: T, -} - // FIXME(ecstaticmorse): Audit all occurrences of `without_const().to_predicate(tcx)` to ensure that // the constness of trait bounds is being propagated correctly. -pub trait WithConstness: Sized { +impl<'tcx> PolyTraitRef<'tcx> { #[inline] - fn with_constness(self, constness: BoundConstness) -> ConstnessAnd { - ConstnessAnd { constness, value: self } + pub fn with_constness(self, constness: BoundConstness) -> PolyTraitPredicate<'tcx> { + self.map_bound(|trait_ref| ty::TraitPredicate { + trait_ref, + constness, + polarity: ty::ImplPolarity::Positive, + }) } - #[inline] - fn with_const_if_const(self) -> ConstnessAnd { - self.with_constness(BoundConstness::ConstIfConst) - } - - #[inline] - fn without_const(self) -> ConstnessAnd { + pub fn without_const(self) -> PolyTraitPredicate<'tcx> { self.with_constness(BoundConstness::NotConst) } } -impl WithConstness for T {} - #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)] pub struct ParamEnvAnd<'tcx, T> { pub param_env: ParamEnv<'tcx>, @@ -1400,6 +1452,12 @@ impl<'tcx, T> ParamEnvAnd<'tcx, T> { pub fn into_parts(self) -> (ParamEnv<'tcx>, T) { (self.param_env, self.value) } + + #[inline] + pub fn without_const(mut self) -> Self { + self.param_env = self.param_env.without_const(); + self + } } impl<'a, 'tcx, T> HashStable> for ParamEnvAnd<'tcx, T> @@ -1423,7 +1481,7 @@ pub struct Destructor { } bitflags! { - #[derive(HashStable)] + #[derive(HashStable, TyEncodable, TyDecodable)] pub struct VariantFlags: u32 { const NO_VARIANT_FLAGS = 0; /// Indicates whether the field list of this variant is `#[non_exhaustive]`. @@ -1435,7 +1493,7 @@ bitflags! { } /// Definition of a variant -- a struct's fields or an enum variant. -#[derive(Debug, HashStable)] +#[derive(Debug, HashStable, TyEncodable, TyDecodable)] pub struct VariantDef { /// `DefId` that identifies the variant itself. /// If this variant belongs to a struct or union, then this is a copy of its `DefId`. @@ -1537,7 +1595,7 @@ pub enum VariantDiscr { Relative(u32), } -#[derive(Debug, HashStable)] +#[derive(Debug, HashStable, TyEncodable, TyDecodable)] pub struct FieldDef { pub did: DefId, #[stable_hasher(project(name))] @@ -1559,9 +1617,9 @@ bitflags! { // the seed stored in `ReprOptions.layout_seed` const RANDOMIZE_LAYOUT = 1 << 5; // Any of these flags being set prevent field reordering optimisation. - const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits | - ReprFlags::IS_SIMD.bits | - ReprFlags::IS_LINEAR.bits; + const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits + | ReprFlags::IS_SIMD.bits + | ReprFlags::IS_LINEAR.bits; } } @@ -1591,7 +1649,14 @@ impl ReprOptions { // Generate a deterministically-derived seed from the item's path hash // to allow for cross-crate compilation to actually work - let field_shuffle_seed = tcx.def_path_hash(did).0.to_smaller_hash(); + let mut field_shuffle_seed = tcx.def_path_hash(did).0.to_smaller_hash(); + + // If the user defined a custom seed for layout randomization, xor the item's + // path hash with the user defined seed, this will allowing determinism while + // still allowing users to further randomize layout generation for e.g. fuzzing + if let Some(user_seed) = tcx.sess.opts.debugging_opts.layout_seed { + field_shuffle_seed ^= user_seed; + } for attr in tcx.get_attrs(did).iter() { for r in attr::find_repr_attrs(&tcx.sess, attr) { @@ -1705,7 +1770,7 @@ impl ReprOptions { impl<'tcx> FieldDef { /// Returns the type of this field. The resulting type is not normalized. The `subst` is - /// typically obtained via the second field of `TyKind::AdtDef`. + /// typically obtained via the second field of [`TyKind::Adt`]. pub fn ty(&self, tcx: TyCtxt<'tcx>, subst: SubstsRef<'tcx>) -> Ty<'tcx> { tcx.type_of(self.did).subst(tcx, subst) } @@ -2049,13 +2114,17 @@ impl<'tcx> TyCtxt<'tcx> { } } -/// Yields the parent function's `DefId` if `def_id` is an `impl Trait` definition. -pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option { - if let Some(def_id) = def_id.as_local() { - if let Node::Item(item) = tcx.hir().get(tcx.hir().local_def_id_to_hir_id(def_id)) { - if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind { - return opaque_ty.impl_trait_fn; - } +/// Yields the parent function's `LocalDefId` if `def_id` is an `impl Trait` definition. +pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option { + let def_id = def_id.as_local()?; + if let Node::Item(item) = tcx.hir().get(tcx.hir().local_def_id_to_hir_id(def_id)) { + if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind { + return match opaque_ty.origin { + hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent) => { + Some(parent) + } + hir::OpaqueTyOrigin::TyAlias => None, + }; } } None diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index 11399506b9..84ab42a760 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -8,10 +8,28 @@ //! or constant found within. (This underlying query is what is cached.) use crate::mir; -use crate::ty::fold::{TypeFoldable, TypeFolder}; +use crate::traits::query::NoSolution; +use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder}; use crate::ty::subst::{Subst, SubstsRef}; use crate::ty::{self, Ty, TyCtxt}; +#[derive(Debug, Copy, Clone, HashStable, TyEncodable, TyDecodable)] +pub enum NormalizationError<'tcx> { + Type(Ty<'tcx>), + Const(ty::Const<'tcx>), + ConstantKind(mir::ConstantKind<'tcx>), +} + +impl<'tcx> NormalizationError<'tcx> { + pub fn get_type_for_failure(&self) -> String { + match self { + NormalizationError::Type(t) => format!("{}", t), + NormalizationError::Const(c) => format!("{}", c), + NormalizationError::ConstantKind(ck) => format!("{}", ck), + } + } +} + impl<'tcx> TyCtxt<'tcx> { /// Erase the regions in `value` and then fully normalize all the /// types found within. The result will also have regions erased. @@ -32,6 +50,8 @@ impl<'tcx> TyCtxt<'tcx> { // Erase first before we do the real query -- this keeps the // cache from being too polluted. let value = self.erase_regions(value); + debug!(?value); + if !value.has_projections() { value } else { @@ -39,6 +59,39 @@ impl<'tcx> TyCtxt<'tcx> { } } + /// Tries to erase the regions in `value` and then fully normalize all the + /// types found within. The result will also have regions erased. + /// + /// Contrary to `normalize_erasing_regions` this function does not assume that normalization + /// succeeds. + pub fn try_normalize_erasing_regions( + self, + param_env: ty::ParamEnv<'tcx>, + value: T, + ) -> Result> + where + T: TypeFoldable<'tcx>, + { + debug!( + "try_normalize_erasing_regions::<{}>(value={:?}, param_env={:?})", + std::any::type_name::(), + value, + param_env, + ); + + // Erase first before we do the real query -- this keeps the + // cache from being too polluted. + let value = self.erase_regions(value); + debug!(?value); + + if !value.has_projections() { + Ok(value) + } else { + let mut folder = TryNormalizeAfterErasingRegionsFolder::new(self, param_env); + value.try_fold_with(&mut folder) + } + } + /// If you have a `Binder<'tcx, T>`, you can do this to strip out the /// late-bound regions and then normalize the result, yielding up /// a `T` (with regions erased). This is appropriate when the @@ -62,6 +115,8 @@ impl<'tcx> TyCtxt<'tcx> { /// Monomorphizes a type from the AST by first applying the /// in-scope substitutions and then normalizing any associated /// types. + /// Panics if normalization fails. In case normalization might fail + /// use `try_subst_and_normalize_erasing_regions` instead. pub fn subst_and_normalize_erasing_regions( self, param_substs: SubstsRef<'tcx>, @@ -81,6 +136,30 @@ impl<'tcx> TyCtxt<'tcx> { let substituted = value.subst(self, param_substs); self.normalize_erasing_regions(param_env, substituted) } + + /// Monomorphizes a type from the AST by first applying the + /// in-scope substitutions and then trying to normalize any associated + /// types. Contrary to `subst_and_normalize_erasing_regions` this does + /// not assume that normalization succeeds. + pub fn try_subst_and_normalize_erasing_regions( + self, + param_substs: SubstsRef<'tcx>, + param_env: ty::ParamEnv<'tcx>, + value: T, + ) -> Result> + where + T: TypeFoldable<'tcx>, + { + debug!( + "subst_and_normalize_erasing_regions(\ + param_substs={:?}, \ + value={:?}, \ + param_env={:?})", + param_substs, value, param_env, + ); + let substituted = value.subst(self, param_substs); + self.try_normalize_erasing_regions(param_env, substituted) + } } struct NormalizeAfterErasingRegionsFolder<'tcx> { @@ -89,16 +168,22 @@ struct NormalizeAfterErasingRegionsFolder<'tcx> { } impl<'tcx> NormalizeAfterErasingRegionsFolder<'tcx> { + #[instrument(skip(self), level = "debug")] fn normalize_generic_arg_after_erasing_regions( &self, arg: ty::GenericArg<'tcx>, ) -> ty::GenericArg<'tcx> { let arg = self.param_env.and(arg); - self.tcx.normalize_generic_arg_after_erasing_regions(arg) + debug!(?arg); + + self.tcx.try_normalize_generic_arg_after_erasing_regions(arg).unwrap_or_else(|_| bug!( + "Failed to normalize {:?}, maybe try to call `try_normalize_erasing_regions` instead", + arg.value + )) } } -impl TypeFolder<'tcx> for NormalizeAfterErasingRegionsFolder<'tcx> { +impl<'tcx> TypeFolder<'tcx> for NormalizeAfterErasingRegionsFolder<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -115,6 +200,69 @@ impl TypeFolder<'tcx> for NormalizeAfterErasingRegionsFolder<'tcx> { fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { // FIXME: This *probably* needs canonicalization too! let arg = self.param_env.and(c); - self.tcx.normalize_mir_const_after_erasing_regions(arg) + self.tcx + .try_normalize_mir_const_after_erasing_regions(arg) + .unwrap_or_else(|_| bug!("failed to normalize {:?}", c)) + } +} + +struct TryNormalizeAfterErasingRegionsFolder<'tcx> { + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, +} + +impl<'tcx> TryNormalizeAfterErasingRegionsFolder<'tcx> { + fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self { + TryNormalizeAfterErasingRegionsFolder { tcx, param_env } + } + + #[instrument(skip(self), level = "debug")] + fn try_normalize_generic_arg_after_erasing_regions( + &self, + arg: ty::GenericArg<'tcx>, + ) -> Result, NoSolution> { + let arg = self.param_env.and(arg); + debug!(?arg); + + self.tcx.try_normalize_generic_arg_after_erasing_regions(arg) + } +} + +impl<'tcx> TypeFolder<'tcx> for TryNormalizeAfterErasingRegionsFolder<'tcx> { + type Error = NormalizationError<'tcx>; + + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } +} + +impl<'tcx> FallibleTypeFolder<'tcx> for TryNormalizeAfterErasingRegionsFolder<'tcx> { + fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result, Self::Error> { + match self.try_normalize_generic_arg_after_erasing_regions(ty.into()) { + Ok(t) => Ok(t.expect_ty()), + Err(_) => Err(NormalizationError::Type(ty)), + } + } + + fn try_fold_const( + &mut self, + c: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { + match self.try_normalize_generic_arg_after_erasing_regions(c.into()) { + Ok(t) => Ok(t.expect_const()), + Err(_) => Err(NormalizationError::Const(*c)), + } + } + + fn try_fold_mir_const( + &mut self, + c: mir::ConstantKind<'tcx>, + ) -> Result, Self::Error> { + // FIXME: This *probably* needs canonicalization too! + let arg = self.param_env.and(c); + match self.tcx.try_normalize_mir_const_after_erasing_regions(arg) { + Ok(c) => Ok(c), + Err(_) => Err(NormalizationError::ConstantKind(c)), + } } } diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 308b4d2fef..94127a144d 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -37,7 +37,7 @@ pub trait Printer<'tcx>: Sized { type DynExistential; type Const; - fn tcx(&'a self) -> TyCtxt<'tcx>; + fn tcx<'a>(&'a self) -> TyCtxt<'tcx>; fn print_def_path( self, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 175295b319..47a9234419 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -303,7 +303,7 @@ pub trait PrettyPrinter<'tcx>: match self.tcx().trimmed_def_paths(()).get(&def_id) { None => Ok((self, false)), Some(symbol) => { - self.write_str(&symbol.as_str())?; + self.write_str(symbol.as_str())?; Ok((self, true)) } } @@ -319,6 +319,9 @@ pub trait PrettyPrinter<'tcx>: /// /// `callers` is a chain of visible_parent's leading to `def_id`, /// to support cycle detection during recursion. + /// + /// This method returns false if we can't print the visible path, so + /// `print_def_path` can fall back on the item's real definition path. fn try_print_visible_def_path_recur( mut self, def_id: DefId, @@ -405,19 +408,7 @@ pub trait PrettyPrinter<'tcx>: Some(parent) => parent, None => return Ok((self, false)), }; - if callers.contains(&visible_parent) { - return Ok((self, false)); - } - callers.push(visible_parent); - // HACK(eddyb) this bypasses `path_append`'s prefix printing to avoid - // knowing ahead of time whether the entire path will succeed or not. - // To support printers that do not implement `PrettyPrinter`, a `Vec` or - // linked list on the stack would need to be built, before any printing. - match self.try_print_visible_def_path_recur(visible_parent, callers)? { - (cx, false) => return Ok((cx, false)), - (cx, true) => self = cx, - } - callers.pop(); + let actual_parent = self.tcx().parent(def_id); debug!( "try_print_visible_def_path: visible_parent={:?} actual_parent={:?}", @@ -463,14 +454,21 @@ pub trait PrettyPrinter<'tcx>: // `visible_parent_map`), looking for the specific child we currently have and then // have access to the re-exported name. DefPathData::TypeNs(ref mut name) if Some(visible_parent) != actual_parent => { + // Item might be re-exported several times, but filter for the one + // that's public and whose identifier isn't `_`. let reexport = self .tcx() .item_children(visible_parent) .iter() - .find(|child| child.res.opt_def_id() == Some(def_id)) + .filter(|child| child.res.opt_def_id() == Some(def_id)) + .find(|child| child.vis.is_public() && child.ident.name != kw::Underscore) .map(|child| child.ident.name); - if let Some(reexport) = reexport { - *name = reexport; + + if let Some(new_name) = reexport { + *name = new_name; + } else { + // There is no name that is public and isn't `_`, so bail. + return Ok((self, false)); } } // Re-exported `extern crate` (#43189). @@ -481,6 +479,20 @@ pub trait PrettyPrinter<'tcx>: } debug!("try_print_visible_def_path: data={:?}", data); + if callers.contains(&visible_parent) { + return Ok((self, false)); + } + callers.push(visible_parent); + // HACK(eddyb) this bypasses `path_append`'s prefix printing to avoid + // knowing ahead of time whether the entire path will succeed or not. + // To support printers that do not implement `PrettyPrinter`, a `Vec` or + // linked list on the stack would need to be built, before any printing. + match self.try_print_visible_def_path_recur(visible_parent, callers)? { + (cx, false) => return Ok((cx, false)), + (cx, true) => self = cx, + } + callers.pop(); + Ok((self.path_append(Ok, &DisambiguatedDefPathData { data, disambiguator: 0 })?, true)) } @@ -1513,7 +1525,7 @@ pub struct FmtPrinterData<'a, 'tcx, F> { pub name_resolver: Option Option>>, } -impl Deref for FmtPrinter<'a, 'tcx, F> { +impl<'a, 'tcx, F> Deref for FmtPrinter<'a, 'tcx, F> { type Target = FmtPrinterData<'a, 'tcx, F>; fn deref(&self) -> &Self::Target { &self.0 @@ -1526,7 +1538,7 @@ impl DerefMut for FmtPrinter<'_, '_, F> { } } -impl FmtPrinter<'a, 'tcx, F> { +impl<'a, 'tcx, F> FmtPrinter<'a, 'tcx, F> { pub fn new(tcx: TyCtxt<'tcx>, fmt: F, ns: Namespace) -> Self { FmtPrinter(Box::new(FmtPrinterData { tcx, @@ -1563,7 +1575,7 @@ fn guess_def_namespace(tcx: TyCtxt<'_>, def_id: DefId) -> Namespace { } } -impl TyCtxt<'t> { +impl<'t> TyCtxt<'t> { /// Returns a string identifying this `DefId`. This string is /// suitable for user output. pub fn def_path_str(self, def_id: DefId) -> String { @@ -1585,7 +1597,7 @@ impl fmt::Write for FmtPrinter<'_, '_, F> { } } -impl Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { +impl<'tcx, F: fmt::Write> Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { type Error = fmt::Error; type Path = Self; @@ -1594,7 +1606,7 @@ impl Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { type DynExistential = Self; type Const = Self; - fn tcx(&'a self) -> TyCtxt<'tcx> { + fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { self.tcx } @@ -1740,31 +1752,27 @@ impl Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { ) -> Result { self = print_prefix(self)?; - // Skip `::{{constructor}}` on tuple/unit structs. - if let DefPathData::Ctor = disambiguated_data.data { + // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs. + if let DefPathData::ForeignMod | DefPathData::Ctor = disambiguated_data.data { return Ok(self); } - // FIXME(eddyb) `name` should never be empty, but it - // currently is for `extern { ... }` "foreign modules". let name = disambiguated_data.data.name(); - if name != DefPathDataName::Named(kw::Empty) { - if !self.empty_path { - write!(self, "::")?; - } - - if let DefPathDataName::Named(name) = name { - if Ident::with_dummy_span(name).is_raw_guess() { - write!(self, "r#")?; - } - } - - let verbose = self.tcx.sess.verbose(); - disambiguated_data.fmt_maybe_verbose(&mut self, verbose)?; - - self.empty_path = false; + if !self.empty_path { + write!(self, "::")?; } + if let DefPathDataName::Named(name) = name { + if Ident::with_dummy_span(name).is_raw_guess() { + write!(self, "r#")?; + } + } + + let verbose = self.tcx.sess.verbose(); + disambiguated_data.fmt_maybe_verbose(&mut self, verbose)?; + + self.empty_path = false; + Ok(self) } @@ -1796,7 +1804,7 @@ impl Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { } } -impl PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { +impl<'tcx, F: fmt::Write> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { fn infer_ty_name(&self, id: ty::TyVid) -> Option { self.0.name_resolver.as_ref().and_then(|func| func(id)) } @@ -2062,7 +2070,7 @@ impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> { // HACK(eddyb) limited to `FmtPrinter` because of `binder_depth`, // `region_index` and `used_region_names`. -impl FmtPrinter<'_, 'tcx, F> { +impl<'tcx, F: fmt::Write> FmtPrinter<'_, 'tcx, F> { pub fn name_all_regions( mut self, value: &ty::Binder<'tcx, T>, @@ -2316,7 +2324,8 @@ where macro_rules! forward_display_to_print { ($($ty:ty),+) => { - $(impl fmt::Display for $ty { + // Some of the $ty arguments may not actually use 'tcx + $(#[allow(unused_lifetimes)] impl<'tcx> fmt::Display for $ty { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ty::tls::with(|tcx| { tcx.lift(*self) @@ -2364,7 +2373,7 @@ impl fmt::Display for ty::RegionKind { #[derive(Copy, Clone, TypeFoldable, Lift)] pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>); -impl fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> { +impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(self, f) } @@ -2376,13 +2385,13 @@ impl fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> { #[derive(Copy, Clone, TypeFoldable, Lift)] pub struct TraitRefPrintOnlyTraitName<'tcx>(ty::TraitRef<'tcx>); -impl fmt::Debug for TraitRefPrintOnlyTraitName<'tcx> { +impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitName<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(self, f) } } -impl ty::TraitRef<'tcx> { +impl<'tcx> ty::TraitRef<'tcx> { pub fn print_only_trait_path(self) -> TraitRefPrintOnlyTraitPath<'tcx> { TraitRefPrintOnlyTraitPath(self) } @@ -2392,7 +2401,7 @@ impl ty::TraitRef<'tcx> { } } -impl ty::Binder<'tcx, ty::TraitRef<'tcx>> { +impl<'tcx> ty::Binder<'tcx, ty::TraitRef<'tcx>> { pub fn print_only_trait_path(self) -> ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>> { self.map_bound(|tr| tr.print_only_trait_path()) } diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index 34f8062719..3af1b3a044 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -28,6 +28,7 @@ use crate::traits::query::{ }; use crate::traits::specialization_graph; use crate::traits::{self, ImplSource}; +use crate::ty::fast_reject::SimplifiedType; use crate::ty::subst::{GenericArg, SubstsRef}; use crate::ty::util::AlwaysRequiresDrop; use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt}; @@ -69,7 +70,7 @@ pub struct TyCtxtAt<'tcx> { pub span: Span, } -impl Deref for TyCtxtAt<'tcx> { +impl<'tcx> Deref for TyCtxtAt<'tcx> { type Target = TyCtxt<'tcx>; #[inline(always)] fn deref(&self) -> &Self::Target { @@ -82,7 +83,7 @@ pub struct TyCtxtEnsure<'tcx> { pub tcx: TyCtxt<'tcx>, } -impl TyCtxt<'tcx> { +impl<'tcx> TyCtxt<'tcx> { /// Returns a transparent wrapper for `TyCtxt`, which ensures queries /// are executed instead of just returning their results. #[inline(always)] @@ -156,6 +157,16 @@ macro_rules! separate_provide_extern_default { }; } +macro_rules! opt_remap_env_constness { + ([][$name:ident]) => {}; + ([(remap_env_constness) $($rest:tt)*][$name:ident]) => { + let $name = $name.without_const(); + }; + ([$other:tt $($modifiers:tt)*][$name:ident]) => { + opt_remap_env_constness!([$($modifiers)*][$name]) + }; +} + macro_rules! define_callbacks { (<$tcx:tt> $($(#[$attr:meta])* @@ -197,11 +208,13 @@ macro_rules! define_callbacks { $($(#[$attr])* pub $name: QueryCacheStore>,)* } - impl TyCtxtEnsure<$tcx> { + impl<$tcx> TyCtxtEnsure<$tcx> { $($(#[$attr])* #[inline(always)] pub fn $name(self, key: query_helper_param_ty!($($K)*)) { let key = key.into_query_param(); + opt_remap_env_constness!([$($modifiers)*][key]); + let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, noop); let lookup = match cached { @@ -213,7 +226,7 @@ macro_rules! define_callbacks { })* } - impl TyCtxt<$tcx> { + impl<$tcx> TyCtxt<$tcx> { $($(#[$attr])* #[inline(always)] #[must_use] @@ -223,12 +236,14 @@ macro_rules! define_callbacks { })* } - impl TyCtxtAt<$tcx> { + impl<$tcx> TyCtxtAt<$tcx> { $($(#[$attr])* #[inline(always)] pub fn $name(self, key: query_helper_param_ty!($($K)*)) -> query_stored::$name<$tcx> { let key = key.into_query_param(); + opt_remap_env_constness!([$($modifiers)*][key]); + let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, Clone::clone); let lookup = match cached { @@ -343,7 +358,7 @@ mod sealed { use sealed::IntoQueryParam; -impl TyCtxt<'tcx> { +impl<'tcx> TyCtxt<'tcx> { pub fn def_kind(self, def_id: impl IntoQueryParam) -> DefKind { let def_id = def_id.into_query_param(); self.opt_def_kind(def_id) @@ -351,7 +366,7 @@ impl TyCtxt<'tcx> { } } -impl TyCtxtAt<'tcx> { +impl<'tcx> TyCtxtAt<'tcx> { pub fn def_kind(self, def_id: impl IntoQueryParam) -> DefKind { let def_id = def_id.into_query_param(); self.opt_def_kind(def_id) diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index c7d8bec506..63ed318cad 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -6,7 +6,7 @@ use crate::mir::interpret::{get_slice_bytes, ConstValue, GlobalAlloc, Scalar}; use crate::ty::error::{ExpectedFound, TypeError}; -use crate::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; +use crate::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef}; use crate::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_hir as ast; use rustc_hir::def_id::DefId; @@ -59,8 +59,9 @@ pub trait TypeRelation<'tcx>: Sized { item_def_id, a_subst, b_subst ); - let opt_variances = self.tcx().variances_of(item_def_id); - relate_substs(self, Some(opt_variances), a_subst, b_subst) + let tcx = self.tcx(); + let opt_variances = tcx.variances_of(item_def_id); + relate_substs(self, Some((item_def_id, opt_variances)), a_subst, b_subst) } /// Switch variance for the purpose of relating `a` and `b`. @@ -116,7 +117,7 @@ pub fn relate_type_and_mut<'tcx, R: TypeRelation<'tcx>>( relation: &mut R, a: ty::TypeAndMut<'tcx>, b: ty::TypeAndMut<'tcx>, - kind: ty::VarianceDiagMutKind, + base_ty: Ty<'tcx>, ) -> RelateResult<'tcx, ty::TypeAndMut<'tcx>> { debug!("{}.mts({:?}, {:?})", relation.tag(), a, b); if a.mutbl != b.mutbl { @@ -125,24 +126,40 @@ pub fn relate_type_and_mut<'tcx, R: TypeRelation<'tcx>>( let mutbl = a.mutbl; let (variance, info) = match mutbl { ast::Mutability::Not => (ty::Covariant, ty::VarianceDiagInfo::None), - ast::Mutability::Mut => (ty::Invariant, ty::VarianceDiagInfo::Mut { kind, ty: a.ty }), + ast::Mutability::Mut => { + (ty::Invariant, ty::VarianceDiagInfo::Invariant { ty: base_ty, param_index: 0 }) + } }; let ty = relation.relate_with_variance(variance, info, a.ty, b.ty)?; Ok(ty::TypeAndMut { ty, mutbl }) } } -pub fn relate_substs>( +pub fn relate_substs<'tcx, R: TypeRelation<'tcx>>( relation: &mut R, - variances: Option<&[ty::Variance]>, + variances: Option<(DefId, &[ty::Variance])>, a_subst: SubstsRef<'tcx>, b_subst: SubstsRef<'tcx>, ) -> RelateResult<'tcx, SubstsRef<'tcx>> { let tcx = relation.tcx(); + let mut cached_ty = None; let params = iter::zip(a_subst, b_subst).enumerate().map(|(i, (a, b))| { - let variance = variances.map_or(ty::Invariant, |v| v[i]); - relation.relate_with_variance(variance, ty::VarianceDiagInfo::default(), a, b) + let (variance, variance_info) = match variances { + Some((ty_def_id, variances)) => { + let variance = variances[i]; + let variance_info = if variance == ty::Invariant { + let ty = + cached_ty.get_or_insert_with(|| tcx.type_of(ty_def_id).subst(tcx, a_subst)); + ty::VarianceDiagInfo::Invariant { ty, param_index: i.try_into().unwrap() } + } else { + ty::VarianceDiagInfo::default() + }; + (variance, variance_info) + } + None => (ty::Invariant, ty::VarianceDiagInfo::default()), + }; + relation.relate_with_variance(variance, variance_info, a, b) }); tcx.mk_substs(params) @@ -218,19 +235,6 @@ impl<'tcx> Relate<'tcx> for ty::BoundConstness { } } -impl<'tcx, T: Relate<'tcx>> Relate<'tcx> for ty::ConstnessAnd { - fn relate>( - relation: &mut R, - a: ty::ConstnessAnd, - b: ty::ConstnessAnd, - ) -> RelateResult<'tcx, ty::ConstnessAnd> { - Ok(ty::ConstnessAnd { - constness: relation.relate(a.constness, b.constness)?, - value: relation.relate(a.value, b.value)?, - }) - } -} - impl<'tcx> Relate<'tcx> for ast::Unsafety { fn relate>( relation: &mut R, @@ -366,7 +370,7 @@ impl<'tcx> Relate<'tcx> for Ty<'tcx> { /// The main "type relation" routine. Note that this does not handle /// inference artifacts, so you should filter those out before calling /// it. -pub fn super_relate_tys>( +pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( relation: &mut R, a: Ty<'tcx>, b: Ty<'tcx>, @@ -449,7 +453,7 @@ pub fn super_relate_tys>( } (&ty::RawPtr(a_mt), &ty::RawPtr(b_mt)) => { - let mt = relate_type_and_mut(relation, a_mt, b_mt, ty::VarianceDiagMutKind::RawPtr)?; + let mt = relate_type_and_mut(relation, a_mt, b_mt, a)?; Ok(tcx.mk_ptr(mt)) } @@ -462,7 +466,7 @@ pub fn super_relate_tys>( )?; let a_mt = ty::TypeAndMut { ty: a_ty, mutbl: a_mutbl }; let b_mt = ty::TypeAndMut { ty: b_ty, mutbl: b_mutbl }; - let mt = relate_type_and_mut(relation, a_mt, b_mt, ty::VarianceDiagMutKind::Ref)?; + let mt = relate_type_and_mut(relation, a_mt, b_mt, a)?; Ok(tcx.mk_ref(r, mt)) } @@ -539,7 +543,7 @@ pub fn super_relate_tys>( /// The main "const relation" routine. Note that this does not handle /// inference artifacts, so you should filter those out before calling /// it. -pub fn super_relate_consts>( +pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( relation: &mut R, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>, @@ -612,7 +616,7 @@ pub fn super_relate_consts>( if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(expected_found(relation, a, b))) } } -fn check_const_value_eq>( +fn check_const_value_eq<'tcx, R: TypeRelation<'tcx>>( relation: &mut R, a_val: ConstValue<'tcx>, b_val: ConstValue<'tcx>, @@ -845,17 +849,9 @@ impl<'tcx> Relate<'tcx> for ty::ProjectionPredicate<'tcx> { /////////////////////////////////////////////////////////////////////////// // Error handling -pub fn expected_found(relation: &mut R, a: T, b: T) -> ExpectedFound +pub fn expected_found<'tcx, R, T>(relation: &mut R, a: T, b: T) -> ExpectedFound where R: TypeRelation<'tcx>, { - expected_found_bool(relation.a_is_expected(), a, b) -} - -pub fn expected_found_bool(a_is_expected: bool, a: T, b: T) -> ExpectedFound { - if a_is_expected { - ExpectedFound { expected: a, found: b } - } else { - ExpectedFound { expected: b, found: a } - } + ExpectedFound::new(relation.a_is_expected(), a, b) } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 0f8e80806e..98b1a8b4d7 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -4,7 +4,7 @@ use crate::mir::interpret; use crate::mir::ProjectionKind; -use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; +use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeVisitor}; use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer}; use crate::ty::{self, InferConst, Lift, Ty, TyCtxt}; use rustc_data_structures::functor::IdFunctor; @@ -13,6 +13,7 @@ use rustc_hir::def_id::CRATE_DEF_INDEX; use rustc_index::vec::{Idx, IndexVec}; use std::fmt; +use std::mem::ManuallyDrop; use std::ops::ControlFlow; use std::rc::Rc; use std::sync::Arc; @@ -46,19 +47,19 @@ impl fmt::Debug for ty::UpvarId { } } -impl fmt::Debug for ty::UpvarBorrow<'tcx> { +impl<'tcx> fmt::Debug for ty::UpvarBorrow<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "UpvarBorrow({:?}, {:?})", self.kind, self.region) } } -impl fmt::Debug for ty::ExistentialTraitRef<'tcx> { +impl<'tcx> fmt::Debug for ty::ExistentialTraitRef<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { with_no_trimmed_paths(|| fmt::Display::fmt(self, f)) } } -impl fmt::Debug for ty::adjustment::Adjustment<'tcx> { +impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?} -> {}", self.kind, self.target) } @@ -110,7 +111,7 @@ impl fmt::Debug for ty::FreeRegion { } } -impl fmt::Debug for ty::FnSig<'tcx> { +impl<'tcx> fmt::Debug for ty::FnSig<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "({:?}; c_variadic: {})->{:?}", self.inputs(), self.c_variadic, self.output()) } @@ -128,13 +129,13 @@ impl fmt::Debug for ty::RegionVid { } } -impl fmt::Debug for ty::TraitRef<'tcx> { +impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { with_no_trimmed_paths(|| fmt::Display::fmt(self, f)) } } -impl fmt::Debug for Ty<'tcx> { +impl<'tcx> fmt::Debug for Ty<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { with_no_trimmed_paths(|| fmt::Display::fmt(self, f)) } @@ -152,7 +153,7 @@ impl fmt::Debug for ty::ParamConst { } } -impl fmt::Debug for ty::TraitPredicate<'tcx> { +impl<'tcx> fmt::Debug for ty::TraitPredicate<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let ty::BoundConstness::ConstIfConst = self.constness { write!(f, "~const ")?; @@ -161,19 +162,19 @@ impl fmt::Debug for ty::TraitPredicate<'tcx> { } } -impl fmt::Debug for ty::ProjectionPredicate<'tcx> { +impl<'tcx> fmt::Debug for ty::ProjectionPredicate<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_ty, self.ty) } } -impl fmt::Debug for ty::Predicate<'tcx> { +impl<'tcx> fmt::Debug for ty::Predicate<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", self.kind()) } } -impl fmt::Debug for ty::PredicateKind<'tcx> { +impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { ty::PredicateKind::Trait(ref a) => a.fmt(f), @@ -480,7 +481,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ParamEnv<'a> { type Lifted = ty::ParamEnv<'tcx>; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { tcx.lift(self.caller_bounds()) - .map(|caller_bounds| ty::ParamEnv::new(caller_bounds, self.reveal())) + .map(|caller_bounds| ty::ParamEnv::new(caller_bounds, self.reveal(), self.constness())) } } @@ -669,8 +670,11 @@ impl<'a, 'tcx> Lift<'tcx> for ty::InstanceDef<'a> { /// AdtDefs are basically the same as a DefId. impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::AdtDef { - fn super_fold_with>(self, _folder: &mut F) -> Self { - self + fn try_super_fold_with>( + self, + _folder: &mut F, + ) -> Result { + Ok(self) } fn super_visit_with>(&self, _visitor: &mut V) -> ControlFlow { @@ -679,8 +683,11 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::AdtDef { } impl<'tcx, T: TypeFoldable<'tcx>, U: TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) { - fn super_fold_with>(self, folder: &mut F) -> (T, U) { - (self.0.fold_with(folder), self.1.fold_with(folder)) + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result<(T, U), F::Error> { + Ok((self.0.try_fold_with(folder)?, self.1.try_fold_with(folder)?)) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -692,8 +699,15 @@ impl<'tcx, T: TypeFoldable<'tcx>, U: TypeFoldable<'tcx>> TypeFoldable<'tcx> for impl<'tcx, A: TypeFoldable<'tcx>, B: TypeFoldable<'tcx>, C: TypeFoldable<'tcx>> TypeFoldable<'tcx> for (A, B, C) { - fn super_fold_with>(self, folder: &mut F) -> (A, B, C) { - (self.0.fold_with(folder), self.1.fold_with(folder), self.2.fold_with(folder)) + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result<(A, B, C), F::Error> { + Ok(( + self.0.try_fold_with(folder)?, + self.1.try_fold_with(folder)?, + self.2.try_fold_with(folder)?, + )) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -718,9 +732,42 @@ EnumTypeFoldableImpl! { } impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc { - fn super_fold_with>(self, folder: &mut F) -> Self { - // FIXME: Reuse the `Rc` here. - Rc::new((*self).clone().fold_with(folder)) + fn try_super_fold_with>( + mut self, + folder: &mut F, + ) -> Result { + // We merely want to replace the contained `T`, if at all possible, + // so that we don't needlessly allocate a new `Rc` or indeed clone + // the contained type. + unsafe { + // First step is to ensure that we have a unique reference to + // the contained type, which `Rc::make_mut` will accomplish (by + // allocating a new `Rc` and cloning the `T` only if required). + // This is done *before* casting to `Rc>` so that + // panicking during `make_mut` does not leak the `T`. + Rc::make_mut(&mut self); + + // Casting to `Rc>` is safe because `ManuallyDrop` + // is `repr(transparent)`. + let ptr = Rc::into_raw(self).cast::>(); + let mut unique = Rc::from_raw(ptr); + + // Call to `Rc::make_mut` above guarantees that `unique` is the + // sole reference to the contained value, so we can avoid doing + // a checked `get_mut` here. + let slot = Rc::get_mut_unchecked(&mut unique); + + // Semantically move the contained type out from `unique`, fold + // it, then move the folded value back into `unique`. Should + // folding fail, `ManuallyDrop` ensures that the "moved-out" + // value is not re-dropped. + let owned = ManuallyDrop::take(slot); + let folded = owned.try_fold_with(folder)?; + *slot = ManuallyDrop::new(folded); + + // Cast back to `Rc`. + Ok(Rc::from_raw(Rc::into_raw(unique).cast())) + } } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -729,9 +776,42 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc { } impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Arc { - fn super_fold_with>(self, folder: &mut F) -> Self { - // FIXME: Reuse the `Arc` here. - Arc::new((*self).clone().fold_with(folder)) + fn try_super_fold_with>( + mut self, + folder: &mut F, + ) -> Result { + // We merely want to replace the contained `T`, if at all possible, + // so that we don't needlessly allocate a new `Arc` or indeed clone + // the contained type. + unsafe { + // First step is to ensure that we have a unique reference to + // the contained type, which `Arc::make_mut` will accomplish (by + // allocating a new `Arc` and cloning the `T` only if required). + // This is done *before* casting to `Arc>` so that + // panicking during `make_mut` does not leak the `T`. + Arc::make_mut(&mut self); + + // Casting to `Arc>` is safe because `ManuallyDrop` + // is `repr(transparent)`. + let ptr = Arc::into_raw(self).cast::>(); + let mut unique = Arc::from_raw(ptr); + + // Call to `Arc::make_mut` above guarantees that `unique` is the + // sole reference to the contained value, so we can avoid doing + // a checked `get_mut` here. + let slot = Arc::get_mut_unchecked(&mut unique); + + // Semantically move the contained type out from `unique`, fold + // it, then move the folded value back into `unique`. Should + // folding fail, `ManuallyDrop` ensures that the "moved-out" + // value is not re-dropped. + let owned = ManuallyDrop::take(slot); + let folded = owned.try_fold_with(folder)?; + *slot = ManuallyDrop::new(folded); + + // Cast back to `Arc`. + Ok(Arc::from_raw(Arc::into_raw(unique).cast())) + } } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -740,8 +820,11 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Arc { } impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box { - fn super_fold_with>(self, folder: &mut F) -> Self { - self.map_id(|value| value.fold_with(folder)) + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + self.try_map_id(|value| value.try_fold_with(folder)) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -750,8 +833,11 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box { } impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec { - fn super_fold_with>(self, folder: &mut F) -> Self { - self.map_id(|t| t.fold_with(folder)) + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + self.try_map_id(|t| t.try_fold_with(folder)) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -760,8 +846,11 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec { } impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<[T]> { - fn super_fold_with>(self, folder: &mut F) -> Self { - self.map_id(|t| t.fold_with(folder)) + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + self.try_map_id(|t| t.try_fold_with(folder)) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -770,12 +859,15 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<[T]> { } impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<'tcx, T> { - fn super_fold_with>(self, folder: &mut F) -> Self { - self.map_bound(|ty| ty.fold_with(folder)) + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + self.try_map_bound(|ty| ty.try_fold_with(folder)) } - fn fold_with>(self, folder: &mut F) -> Self { - folder.fold_binder(self) + fn try_fold_with>(self, folder: &mut F) -> Result { + folder.try_fold_binder(self) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -788,7 +880,10 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<'tcx, T> { } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List>> { - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_poly_existential_predicates(v)) } @@ -798,7 +893,10 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List TypeFoldable<'tcx> for &'tcx ty::List> { - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_type_list(v)) } @@ -808,7 +906,10 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List { - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_projs(v)) } @@ -818,24 +919,33 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List { } impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { use crate::ty::InstanceDef::*; - Self { - substs: self.substs.fold_with(folder), + Ok(Self { + substs: self.substs.try_fold_with(folder)?, def: match self.def { - Item(def) => Item(def.fold_with(folder)), - VtableShim(did) => VtableShim(did.fold_with(folder)), - ReifyShim(did) => ReifyShim(did.fold_with(folder)), - Intrinsic(did) => Intrinsic(did.fold_with(folder)), - FnPtrShim(did, ty) => FnPtrShim(did.fold_with(folder), ty.fold_with(folder)), - Virtual(did, i) => Virtual(did.fold_with(folder), i), - ClosureOnceShim { call_once, track_caller } => { - ClosureOnceShim { call_once: call_once.fold_with(folder), track_caller } + Item(def) => Item(def.try_fold_with(folder)?), + VtableShim(did) => VtableShim(did.try_fold_with(folder)?), + ReifyShim(did) => ReifyShim(did.try_fold_with(folder)?), + Intrinsic(did) => Intrinsic(did.try_fold_with(folder)?), + FnPtrShim(did, ty) => { + FnPtrShim(did.try_fold_with(folder)?, ty.try_fold_with(folder)?) + } + Virtual(did, i) => Virtual(did.try_fold_with(folder)?, i), + ClosureOnceShim { call_once, track_caller } => { + ClosureOnceShim { call_once: call_once.try_fold_with(folder)?, track_caller } + } + DropGlue(did, ty) => { + DropGlue(did.try_fold_with(folder)?, ty.try_fold_with(folder)?) + } + CloneShim(did, ty) => { + CloneShim(did.try_fold_with(folder)?, ty.try_fold_with(folder)?) } - DropGlue(did, ty) => DropGlue(did.fold_with(folder), ty.fold_with(folder)), - CloneShim(did, ty) => CloneShim(did.fold_with(folder), ty.fold_with(folder)), }, - } + }) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -860,8 +970,11 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for interpret::GlobalId<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { - Self { instance: self.instance.fold_with(folder), promoted: self.promoted } + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + Ok(Self { instance: self.instance.try_fold_with(folder)?, promoted: self.promoted }) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -870,26 +983,31 @@ impl<'tcx> TypeFoldable<'tcx> for interpret::GlobalId<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { let kind = match *self.kind() { - ty::RawPtr(tm) => ty::RawPtr(tm.fold_with(folder)), - ty::Array(typ, sz) => ty::Array(typ.fold_with(folder), sz.fold_with(folder)), - ty::Slice(typ) => ty::Slice(typ.fold_with(folder)), - ty::Adt(tid, substs) => ty::Adt(tid, substs.fold_with(folder)), + ty::RawPtr(tm) => ty::RawPtr(tm.try_fold_with(folder)?), + ty::Array(typ, sz) => ty::Array(typ.try_fold_with(folder)?, sz.try_fold_with(folder)?), + ty::Slice(typ) => ty::Slice(typ.try_fold_with(folder)?), + ty::Adt(tid, substs) => ty::Adt(tid, substs.try_fold_with(folder)?), ty::Dynamic(trait_ty, region) => { - ty::Dynamic(trait_ty.fold_with(folder), region.fold_with(folder)) + ty::Dynamic(trait_ty.try_fold_with(folder)?, region.try_fold_with(folder)?) + } + ty::Tuple(ts) => ty::Tuple(ts.try_fold_with(folder)?), + ty::FnDef(def_id, substs) => ty::FnDef(def_id, substs.try_fold_with(folder)?), + ty::FnPtr(f) => ty::FnPtr(f.try_fold_with(folder)?), + ty::Ref(r, ty, mutbl) => { + ty::Ref(r.try_fold_with(folder)?, ty.try_fold_with(folder)?, mutbl) } - ty::Tuple(ts) => ty::Tuple(ts.fold_with(folder)), - ty::FnDef(def_id, substs) => ty::FnDef(def_id, substs.fold_with(folder)), - ty::FnPtr(f) => ty::FnPtr(f.fold_with(folder)), - ty::Ref(r, ty, mutbl) => ty::Ref(r.fold_with(folder), ty.fold_with(folder), mutbl), ty::Generator(did, substs, movability) => { - ty::Generator(did, substs.fold_with(folder), movability) + ty::Generator(did, substs.try_fold_with(folder)?, movability) } - ty::GeneratorWitness(types) => ty::GeneratorWitness(types.fold_with(folder)), - ty::Closure(did, substs) => ty::Closure(did, substs.fold_with(folder)), - ty::Projection(data) => ty::Projection(data.fold_with(folder)), - ty::Opaque(did, substs) => ty::Opaque(did, substs.fold_with(folder)), + ty::GeneratorWitness(types) => ty::GeneratorWitness(types.try_fold_with(folder)?), + ty::Closure(did, substs) => ty::Closure(did, substs.try_fold_with(folder)?), + ty::Projection(data) => ty::Projection(data.try_fold_with(folder)?), + ty::Opaque(did, substs) => ty::Opaque(did, substs.try_fold_with(folder)?), ty::Bool | ty::Char @@ -903,14 +1021,14 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { | ty::Bound(..) | ty::Placeholder(..) | ty::Never - | ty::Foreign(..) => return self, + | ty::Foreign(..) => return Ok(self), }; - if *self.kind() == kind { self } else { folder.tcx().mk_ty(kind) } + Ok(if *self.kind() == kind { self } else { folder.tcx().mk_ty(kind) }) } - fn fold_with>(self, folder: &mut F) -> Self { - folder.fold_ty(self) + fn try_fold_with>(self, folder: &mut F) -> Result { + folder.try_fold_ty(self) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -961,12 +1079,15 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> { - fn super_fold_with>(self, _folder: &mut F) -> Self { - self + fn try_super_fold_with>( + self, + _folder: &mut F, + ) -> Result { + Ok(self) } - fn fold_with>(self, folder: &mut F) -> Self { - folder.fold_region(self) + fn try_fold_with>(self, folder: &mut F) -> Result { + folder.try_fold_region(self) } fn super_visit_with>(&self, _visitor: &mut V) -> ControlFlow { @@ -979,13 +1100,16 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> { - fn fold_with>(self, folder: &mut F) -> Self { - folder.fold_predicate(self) + fn try_fold_with>(self, folder: &mut F) -> Result { + folder.try_fold_predicate(self) } - fn super_fold_with>(self, folder: &mut F) -> Self { - let new = self.inner.kind.fold_with(folder); - folder.tcx().reuse_or_mk_predicate(self, new) + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + let new = self.inner.kind.try_fold_with(folder)?; + Ok(folder.tcx().reuse_or_mk_predicate(self, new)) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -1006,7 +1130,10 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_predicates(v)) } @@ -1016,8 +1143,11 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { } impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec { - fn super_fold_with>(self, folder: &mut F) -> Self { - self.map_id(|x| x.fold_with(folder)) + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + self.try_map_id(|x| x.try_fold_with(folder)) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -1026,18 +1156,21 @@ impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec } impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { - let ty = self.ty.fold_with(folder); - let val = self.val.fold_with(folder); + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + let ty = self.ty.try_fold_with(folder)?; + let val = self.val.try_fold_with(folder)?; if ty != self.ty || val != self.val { - folder.tcx().mk_const(ty::Const { ty, val }) + Ok(folder.tcx().mk_const(ty::Const { ty, val })) } else { - self + Ok(self) } } - fn fold_with>(self, folder: &mut F) -> Self { - folder.fold_const(self) + fn try_fold_with>(self, folder: &mut F) -> Result { + folder.try_fold_const(self) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -1051,16 +1184,19 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { - match self { - ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.fold_with(folder)), - ty::ConstKind::Param(p) => ty::ConstKind::Param(p.fold_with(folder)), - ty::ConstKind::Unevaluated(uv) => ty::ConstKind::Unevaluated(uv.fold_with(folder)), + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + Ok(match self { + ty::ConstKind::Infer(ic) => ty::ConstKind::Infer(ic.try_fold_with(folder)?), + ty::ConstKind::Param(p) => ty::ConstKind::Param(p.try_fold_with(folder)?), + ty::ConstKind::Unevaluated(uv) => ty::ConstKind::Unevaluated(uv.try_fold_with(folder)?), ty::ConstKind::Value(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(..) | ty::ConstKind::Error(_) => self, - } + }) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -1077,8 +1213,11 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> { - fn super_fold_with>(self, _folder: &mut F) -> Self { - self + fn try_super_fold_with>( + self, + _folder: &mut F, + ) -> Result { + Ok(self) } fn super_visit_with>(&self, _visitor: &mut V) -> ControlFlow { @@ -1087,12 +1226,15 @@ impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { - ty::Unevaluated { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + Ok(ty::Unevaluated { def: self.def, - substs_: Some(self.substs(folder.tcx()).fold_with(folder)), + substs_: Some(self.substs(folder.tcx()).try_fold_with(folder)?), promoted: self.promoted, - } + }) } fn visit_with>(&self, visitor: &mut V) -> ControlFlow { @@ -1112,12 +1254,15 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx, ()> { - fn super_fold_with>(self, folder: &mut F) -> Self { - ty::Unevaluated { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + Ok(ty::Unevaluated { def: self.def, - substs_: Some(self.substs(folder.tcx()).fold_with(folder)), + substs_: Some(self.substs(folder.tcx()).try_fold_with(folder)?), promoted: self.promoted, - } + }) } fn visit_with>(&self, visitor: &mut V) -> ControlFlow { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index c2b32cd06e..c24a1d8eb5 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -8,9 +8,7 @@ use crate::infer::canonical::Canonical; use crate::ty::fold::ValidateBoundVars; use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; use crate::ty::InferTy::{self, *}; -use crate::ty::{ - self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable, WithConstness, -}; +use crate::ty::{self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable}; use crate::ty::{DelaySpanBugEmitted, List, ParamEnv, TyS}; use polonius_engine::Atom; use rustc_data_structures::captures::Captures; @@ -200,7 +198,7 @@ pub enum TyKind<'tcx> { Error(DelaySpanBugEmitted), } -impl TyKind<'tcx> { +impl<'tcx> TyKind<'tcx> { #[inline] pub fn is_primitive(&self) -> bool { matches!(self, Bool | Char | Int(_) | Uint(_) | Float(_)) @@ -356,14 +354,17 @@ impl<'tcx> ClosureSubsts<'tcx> { /// The ordering assumed here must match that used by `ClosureSubsts::new` above. fn split(self) -> ClosureSubstsParts<'tcx, GenericArg<'tcx>> { match self.substs[..] { - [ref parent_substs @ .., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => { - ClosureSubstsParts { - parent_substs, - closure_kind_ty, - closure_sig_as_fn_ptr_ty, - tupled_upvars_ty, - } - } + [ + ref parent_substs @ .., + closure_kind_ty, + closure_sig_as_fn_ptr_ty, + tupled_upvars_ty, + ] => ClosureSubstsParts { + parent_substs, + closure_kind_ty, + closure_sig_as_fn_ptr_ty, + tupled_upvars_ty, + }, _ => bug!("closure substs missing synthetics"), } } @@ -786,7 +787,7 @@ impl<'tcx> ExistentialPredicate<'tcx> { tcx.def_path_hash(a.item_def_id).cmp(&tcx.def_path_hash(b.item_def_id)) } (AutoTrait(ref a), AutoTrait(ref b)) => { - tcx.trait_def(*a).def_path_hash.cmp(&tcx.trait_def(*b).def_path_hash) + tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b)) } (Trait(_), _) => Ordering::Less, (Projection(_), Trait(_)) => Ordering::Greater, @@ -1101,6 +1102,18 @@ impl<'tcx, T> Binder<'tcx, T> { Binder(value, self.1) } + pub fn try_map_bound, E>(self, f: F) -> Result, E> + where + F: FnOnce(T) -> Result, + { + let value = f(self.0)?; + if cfg!(debug_assertions) { + let mut validator = ValidateBoundVars::new(self.1); + value.visit_with(&mut validator); + } + Ok(Binder(value, self.1)) + } + /// Wraps a `value` in a binder, using the same bound variables as the /// current `Binder`. This should not be used if the new value *changes* /// the bound variables. Note: the (old or new) value itself does not @@ -2269,36 +2282,26 @@ pub enum VarianceDiagInfo<'tcx> { /// We will not add any additional information to error messages. #[default] None, - /// We switched our variance because a type occurs inside - /// the generic argument of a mutable reference or pointer - /// (`*mut T` or `&mut T`). In either case, our variance - /// will always be `Invariant`. - Mut { - /// Tracks whether we had a mutable pointer or reference, - /// for better error messages - kind: VarianceDiagMutKind, - /// The type parameter of the mutable pointer/reference - /// (the `T` in `&mut T` or `*mut T`). + /// We switched our variance because a generic argument occurs inside + /// the invariant generic argument of another type. + Invariant { + /// The generic type containing the generic parameter + /// that changes the variance (e.g. `*mut T`, `MyStruct`) ty: Ty<'tcx>, + /// The index of the generic parameter being used + /// (e.g. `0` for `*mut T`, `1` for `MyStruct<'CovariantParam, 'InvariantParam>`) + param_index: u32, }, } -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub enum VarianceDiagMutKind { - /// A mutable raw pointer (`*mut T`) - RawPtr, - /// A mutable reference (`&mut T`) - Ref, -} - impl<'tcx> VarianceDiagInfo<'tcx> { /// Mirrors `Variance::xform` - used to 'combine' the existing /// and new `VarianceDiagInfo`s when our variance changes. pub fn xform(self, other: VarianceDiagInfo<'tcx>) -> VarianceDiagInfo<'tcx> { - // For now, just use the first `VarianceDiagInfo::Mut` that we see + // For now, just use the first `VarianceDiagInfo::Invariant` that we see match self { VarianceDiagInfo::None => other, - VarianceDiagInfo::Mut { .. } => self, + VarianceDiagInfo::Invariant { .. } => self, } } } diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 73a8e18949..a711811491 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -2,7 +2,7 @@ use crate::mir; use crate::ty::codec::{TyDecoder, TyEncoder}; -use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; +use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeVisitor}; use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts}; use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; @@ -67,7 +67,7 @@ impl<'tcx> GenericArgKind<'tcx> { } } -impl fmt::Debug for GenericArg<'tcx> { +impl<'tcx> fmt::Debug for GenericArg<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.unpack() { GenericArgKind::Lifetime(lt) => lt.fmt(f), @@ -153,11 +153,14 @@ impl<'a, 'tcx> Lift<'tcx> for GenericArg<'a> { } impl<'tcx> TypeFoldable<'tcx> for GenericArg<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { match self.unpack() { - GenericArgKind::Lifetime(lt) => lt.fold_with(folder).into(), - GenericArgKind::Type(ty) => ty.fold_with(folder).into(), - GenericArgKind::Const(ct) => ct.fold_with(folder).into(), + GenericArgKind::Lifetime(lt) => lt.try_fold_with(folder).map(Into::into), + GenericArgKind::Type(ty) => ty.try_fold_with(folder).map(Into::into), + GenericArgKind::Const(ct) => ct.try_fold_with(folder).map(Into::into), } } @@ -372,7 +375,10 @@ impl<'a, 'tcx> InternalSubsts<'tcx> { } impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> { - fn super_fold_with>(self, folder: &mut F) -> Self { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { // This code is hot enough that it's worth specializing for the most // common length lists, to avoid the overhead of `SmallVec` creation. // The match arms are in order of frequency. The 1, 2, and 0 cases are @@ -381,22 +387,27 @@ impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> { // calling `intern_substs`. match self.len() { 1 => { - let param0 = self[0].fold_with(folder); - if param0 == self[0] { self } else { folder.tcx().intern_substs(&[param0]) } + let param0 = self[0].try_fold_with(folder)?; + if param0 == self[0] { Ok(self) } else { Ok(folder.tcx().intern_substs(&[param0])) } } 2 => { - let param0 = self[0].fold_with(folder); - let param1 = self[1].fold_with(folder); + let param0 = self[0].try_fold_with(folder)?; + let param1 = self[1].try_fold_with(folder)?; if param0 == self[0] && param1 == self[1] { - self + Ok(self) } else { - folder.tcx().intern_substs(&[param0, param1]) + Ok(folder.tcx().intern_substs(&[param0, param1])) } } - 0 => self, + 0 => Ok(self), _ => { - let params: SmallVec<[_; 8]> = self.iter().map(|k| k.fold_with(folder)).collect(); - if params[..] == self[..] { self } else { folder.tcx().intern_substs(¶ms) } + let params: SmallVec<[_; 8]> = + self.iter().map(|k| k.try_fold_with(folder)).collect::>()?; + if params[..] == self[..] { + Ok(self) + } else { + Ok(folder.tcx().intern_substs(¶ms)) + } } } } diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 25a310b12d..34d059f4ec 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -1,5 +1,5 @@ use crate::traits::specialization_graph; -use crate::ty::fast_reject; +use crate::ty::fast_reject::{self, SimplifiedType, SimplifyParams, StripReferences}; use crate::ty::fold::TypeFoldable; use crate::ty::{Ty, TyCtxt}; use rustc_hir as hir; @@ -68,7 +68,7 @@ pub enum TraitSpecializationKind { pub struct TraitImpls { blanket_impls: Vec, /// Impls indexed by their simplified self type, for fast lookup. - non_blanket_impls: FxIndexMap>, + non_blanket_impls: FxIndexMap>, } impl TraitImpls { @@ -146,6 +146,11 @@ impl<'tcx> TyCtxt<'tcx> { self_ty: Ty<'tcx>, mut f: F, ) -> Option { + // FIXME: This depends on the set of all impls for the trait. That is + // unfortunate wrt. incremental compilation. + // + // If we want to be faster, we could have separate queries for + // blanket and non-blanket impls, and compare them separately. let impls = self.trait_impls_of(def_id); for &impl_def_id in impls.blanket_impls.iter() { @@ -154,32 +159,16 @@ impl<'tcx> TyCtxt<'tcx> { } } - // simplify_type(.., false) basically replaces type parameters and - // projections with infer-variables. This is, of course, done on - // the impl trait-ref when it is instantiated, but not on the - // predicate trait-ref which is passed here. + // Note that we're using `SimplifyParams::Yes` to query `non_blanket_impls` while using + // `SimplifyParams::No` while actually adding them. // - // for example, if we match `S: Copy` against an impl like - // `impl Copy for Option`, we replace the type variable - // in `Option` with an infer variable, to `Option<_>` (this - // doesn't actually change fast_reject output), but we don't - // replace `S` with anything - this impl of course can't be - // selected, and as there are hundreds of similar impls, - // considering them would significantly harm performance. - - // This depends on the set of all impls for the trait. That is - // unfortunate. When we get red-green recompilation, we would like - // to have a way of knowing whether the set of relevant impls - // changed. The most naive - // way would be to compute the Vec of relevant impls and see whether - // it differs between compilations. That shouldn't be too slow by - // itself - we do quite a bit of work for each relevant impl anyway. - // - // If we want to be faster, we could have separate queries for - // blanket and non-blanket impls, and compare them separately. - // - // I think we'll cross that bridge when we get to it. - if let Some(simp) = fast_reject::simplify_type(self, self_ty, true) { + // This way, when searching for some impl for `T: Trait`, we do not look at any impls + // whose outer level is not a parameter or projection. Especially for things like + // `T: Clone` this is incredibly useful as we would otherwise look at all the impls + // of `Clone` for `Option`, `Vec`, `ConcreteType` and so on. + if let Some(simp) = + fast_reject::simplify_type(self, self_ty, SimplifyParams::Yes, StripReferences::No) + { if let Some(impls) = impls.non_blanket_impls.get(&simp) { for &impl_def_id in impls { if let result @ Some(_) = f(impl_def_id) { @@ -238,7 +227,9 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait continue; } - if let Some(simplified_self_ty) = fast_reject::simplify_type(tcx, impl_self_ty, false) { + if let Some(simplified_self_ty) = + fast_reject::simplify_type(tcx, impl_self_ty, SimplifyParams::No, StripReferences::No) + { impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id); } else { impls.blanket_impls.push(impl_def_id); diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 6e7acb244d..669065598f 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1,7 +1,7 @@ //! Miscellaneous type-system utilities that are too small to deserve their own modules. use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use crate::ty::fold::TypeFolder; +use crate::ty::fold::{FallibleTypeFolder, TypeFolder}; use crate::ty::layout::IntegerExt; use crate::ty::query::TyCtxtAt; use crate::ty::subst::{GenericArgKind, Subst, SubstsRef}; @@ -788,10 +788,14 @@ impl<'tcx> ty::TyS<'tcx> { [component_ty] => component_ty, _ => self, }; + // This doesn't depend on regions, so try to minimize distinct // query keys used. - let erased = tcx.normalize_erasing_regions(param_env, query_ty); - tcx.needs_drop_raw(param_env.and(erased)) + // If normalization fails, we just use `query_ty`. + let query_ty = + tcx.try_normalize_erasing_regions(param_env, query_ty).unwrap_or(query_ty); + + tcx.needs_drop_raw(param_env.and(query_ty)) } } } @@ -977,7 +981,7 @@ impl<'tcx> ExplicitSelf<'tcx> { /// Returns a list of types such that the given type needs drop if and only if /// *any* of the returned types need drop. Returns `Err(AlwaysRequiresDrop)` if /// this type always needs drop. -pub fn needs_drop_components( +pub fn needs_drop_components<'tcx>( ty: Ty<'tcx>, target_layout: &TargetDataLayout, ) -> Result; 2]>, AlwaysRequiresDrop> { @@ -1046,25 +1050,31 @@ pub fn fold_list<'tcx, F, T>( list: &'tcx ty::List, folder: &mut F, intern: impl FnOnce(TyCtxt<'tcx>, &[T]) -> &'tcx ty::List, -) -> &'tcx ty::List +) -> Result<&'tcx ty::List, F::Error> where - F: TypeFolder<'tcx>, + F: FallibleTypeFolder<'tcx>, T: TypeFoldable<'tcx> + PartialEq + Copy, { let mut iter = list.iter(); // Look for the first element that changed - if let Some((i, new_t)) = iter.by_ref().enumerate().find_map(|(i, t)| { - let new_t = t.fold_with(folder); - if new_t == t { None } else { Some((i, new_t)) } + match iter.by_ref().enumerate().find_map(|(i, t)| match t.try_fold_with(folder) { + Ok(new_t) if new_t == t => None, + new_t => Some((i, new_t)), }) { - // An element changed, prepare to intern the resulting list - let mut new_list = SmallVec::<[_; 8]>::with_capacity(list.len()); - new_list.extend_from_slice(&list[..i]); - new_list.push(new_t); - new_list.extend(iter.map(|t| t.fold_with(folder))); - intern(folder.tcx(), &new_list) - } else { - list + Some((i, Ok(new_t))) => { + // An element changed, prepare to intern the resulting list + let mut new_list = SmallVec::<[_; 8]>::with_capacity(list.len()); + new_list.extend_from_slice(&list[..i]); + new_list.push(new_t); + for t in iter { + new_list.push(t.try_fold_with(folder)?) + } + Ok(intern(folder.tcx(), &new_list)) + } + Some((_, Err(err))) => { + return Err(err); + } + None => Ok(list), } } @@ -1073,7 +1083,7 @@ pub struct AlwaysRequiresDrop; /// Normalizes all opaque types in the given value, replacing them /// with their underlying types. -pub fn normalize_opaque_types( +pub fn normalize_opaque_types<'tcx>( tcx: TyCtxt<'tcx>, val: &'tcx List>, ) -> &'tcx List> { diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 73985cf31e..ba5775fd77 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -69,7 +69,7 @@ impl<'tcx> Iterator for TypeWalker<'tcx> { } } -impl GenericArg<'tcx> { +impl<'tcx> GenericArg<'tcx> { /// Iterator that walks `self` and any types reachable from /// `self`, in depth-first order. Note that just walks the types /// that appear in `self`, it does not descend into the fields of diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 53868f2855..d9896ff5ac 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -377,7 +377,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }) }); let adt = Box::new(AggregateKind::Adt( - adt_def, + adt_def.did, variant_index, substs, user_ty, @@ -467,8 +467,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } else { Some(destination_block) }, + cleanup: None, }, ); + if options.contains(InlineAsmOptions::MAY_UNWIND) { + this.diverge_from(block); + } destination_block.unit() } diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 8dadbf5f02..fc46c54c2f 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -1034,6 +1034,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | TerminatorKind::Call { .. } | TerminatorKind::DropAndReplace { .. } | TerminatorKind::FalseUnwind { .. } + | TerminatorKind::InlineAsm { .. } ), "diverge_from called on block with terminator that cannot unwind." ); @@ -1373,7 +1374,8 @@ impl<'tcx> DropTreeBuilder<'tcx> for Unwind { | TerminatorKind::DropAndReplace { unwind, .. } | TerminatorKind::FalseUnwind { unwind, .. } | TerminatorKind::Call { cleanup: unwind, .. } - | TerminatorKind::Assert { cleanup: unwind, .. } => { + | TerminatorKind::Assert { cleanup: unwind, .. } + | TerminatorKind::InlineAsm { cleanup: unwind, .. } => { *unwind = Some(to); } TerminatorKind::Goto { .. } @@ -1384,8 +1386,7 @@ impl<'tcx> DropTreeBuilder<'tcx> for Unwind { | TerminatorKind::Unreachable | TerminatorKind::Yield { .. } | TerminatorKind::GeneratorDrop - | TerminatorKind::FalseEdge { .. } - | TerminatorKind::InlineAsm { .. } => { + | TerminatorKind::FalseEdge { .. } => { span_bug!(term.source_info.span, "cannot unwind from {:?}", term.kind) } } diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index b0f1e08562..38bb00f985 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -5,7 +5,6 @@ #![feature(control_flow_enum)] #![feature(crate_visibility_modifier)] #![feature(bool_to_option)] -#![feature(iter_zip)] #![feature(let_else)] #![feature(once_cell)] #![feature(min_specialization)] diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index f9e7b39f70..9b54db0d7d 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -46,7 +46,9 @@ crate fn lit_to_const<'tcx>( (ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => { trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })? } - (ast::LitKind::Float(n, _), ty::Float(fty)) => parse_float(*n, *fty, neg), + (ast::LitKind::Float(n, _), ty::Float(fty)) => { + parse_float(*n, *fty, neg).ok_or(LitToConstError::Reported)? + } (ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)), (ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)), (ast::LitKind::Err(_), _) => return Err(LitToConstError::Reported), @@ -55,14 +57,15 @@ crate fn lit_to_const<'tcx>( Ok(ty::Const::from_value(tcx, lit, ty)) } -fn parse_float<'tcx>(num: Symbol, fty: ty::FloatTy, neg: bool) -> ConstValue<'tcx> { +fn parse_float<'tcx>(num: Symbol, fty: ty::FloatTy, neg: bool) -> Option> { let num = num.as_str(); use rustc_apfloat::ieee::{Double, Single}; let scalar = match fty { ty::FloatTy::F32 => { - let rust_f = num - .parse::() - .unwrap_or_else(|e| panic!("f32 failed to parse `{}`: {:?}", num, e)); + let rust_f = match num.parse::() { + Ok(f) => f, + Err(_) => return None, + }; let mut f = num.parse::().unwrap_or_else(|e| { panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e) }); @@ -82,9 +85,10 @@ fn parse_float<'tcx>(num: Symbol, fty: ty::FloatTy, neg: bool) -> ConstValue<'tc Scalar::from_f32(f) } ty::FloatTy::F64 => { - let rust_f = num - .parse::() - .unwrap_or_else(|e| panic!("f64 failed to parse `{}`: {:?}", num, e)); + let rust_f = match num.parse::() { + Ok(f) => f, + Err(_) => return None, + }; let mut f = num.parse::().unwrap_or_else(|e| { panic!("apfloat::ieee::Double failed to parse `{}`: {:?}", num, e) }); @@ -105,5 +109,5 @@ fn parse_float<'tcx>(num: Symbol, fty: ty::FloatTy, neg: bool) -> ConstValue<'tc } }; - ConstValue::Scalar(scalar) + Some(ConstValue::Scalar(scalar)) } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index b4005ccd1c..bdde6b4a35 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -583,9 +583,12 @@ impl<'tcx> Cx<'tcx> { ExprKind::ConstBlock { value } } // Now comes the rote stuff: - hir::ExprKind::Repeat(ref v, ref count) => { - let count_def_id = self.tcx.hir().local_def_id(count.hir_id); - let count = ty::Const::from_anon_const(self.tcx, count_def_id); + hir::ExprKind::Repeat(ref v, _) => { + let ty = self.typeck_results().expr_ty(expr); + let count = match ty.kind() { + ty::Array(_, ct) => ct, + _ => span_bug!(expr.span, "unexpected repeat expr ty: {:?}", ty), + }; ExprKind::Repeat { value: self.mirror_expr(v), count } } @@ -605,9 +608,10 @@ impl<'tcx> Cx<'tcx> { }, Err(err) => bug!("invalid loop id for continue: {}", err), }, - hir::ExprKind::Let(ref pat, ref expr, _) => { - ExprKind::Let { expr: self.mirror_expr(expr), pat: self.pattern_from_hir(pat) } - } + hir::ExprKind::Let(let_expr) => ExprKind::Let { + expr: self.mirror_expr(let_expr.init), + pat: self.pattern_from_hir(let_expr.pat), + }, hir::ExprKind::If(cond, then, else_opt) => ExprKind::If { if_then_scope: region::Scope { id: then.hir_id.local_id, diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index d74c53fae5..7a4fd6ffc4 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -64,7 +64,9 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, '_, 'tcx> { intravisit::walk_expr(self, ex); match &ex.kind { hir::ExprKind::Match(scrut, arms, source) => self.check_match(scrut, arms, *source), - hir::ExprKind::Let(pat, scrut, span) => self.check_let(pat, scrut, *span), + hir::ExprKind::Let(hir::Let { pat, init, span, .. }) => { + self.check_let(pat, init, *span) + } _ => {} } } @@ -148,9 +150,9 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { } } - fn check_let(&mut self, pat: &'tcx hir::Pat<'tcx>, expr: &hir::Expr<'_>, span: Span) { + fn check_let(&mut self, pat: &'tcx hir::Pat<'tcx>, scrutinee: &hir::Expr<'_>, span: Span) { self.check_patterns(pat, Refutable); - let mut cx = self.new_cx(expr.hir_id); + let mut cx = self.new_cx(scrutinee.hir_id); let tpat = self.lower_pattern(&mut cx, pat, &mut false); check_let_reachability(&mut cx, pat.hir_id, tpat, span); } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index ce80214c87..55cf807172 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -533,43 +533,64 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } } + /// Converts inline const patterns. + fn lower_inline_const( + &mut self, + anon_const: &'tcx hir::AnonConst, + id: hir::HirId, + span: Span, + ) -> PatKind<'tcx> { + let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id); + let value = ty::Const::from_inline_const(self.tcx, anon_const_def_id); + + // Evaluate early like we do in `lower_path`. + let value = value.eval(self.tcx, self.param_env); + + match value.val { + ConstKind::Param(_) => { + self.errors.push(PatternError::ConstParamInPattern(span)); + return PatKind::Wild; + } + ConstKind::Unevaluated(_) => { + // If we land here it means the const can't be evaluated because it's `TooGeneric`. + self.tcx.sess.span_err(span, "constant pattern depends on a generic parameter"); + return PatKind::Wild; + } + _ => (), + } + + *self.const_to_pat(value, id, span, false).kind + } + /// Converts literals, paths and negation of literals to patterns. /// The special case for negation exists to allow things like `-128_i8` /// which would overflow if we tried to evaluate `128_i8` and then negate /// afterwards. fn lower_lit(&mut self, expr: &'tcx hir::Expr<'tcx>) -> PatKind<'tcx> { - if let hir::ExprKind::Path(ref qpath) = expr.kind { - *self.lower_path(qpath, expr.hir_id, expr.span).kind - } else { - let (lit, neg) = match expr.kind { - hir::ExprKind::ConstBlock(ref anon_const) => { - let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id); - let value = ty::Const::from_inline_const(self.tcx, anon_const_def_id); - if matches!(value.val, ConstKind::Param(_)) { - let span = self.tcx.hir().span(anon_const.hir_id); - self.errors.push(PatternError::ConstParamInPattern(span)); - return PatKind::Wild; - } - return *self.const_to_pat(value, expr.hir_id, expr.span, false).kind; - } - hir::ExprKind::Lit(ref lit) => (lit, false), - hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => { - let lit = match expr.kind { - hir::ExprKind::Lit(ref lit) => lit, - _ => span_bug!(expr.span, "not a literal: {:?}", expr), - }; - (lit, true) - } - _ => span_bug!(expr.span, "not a literal: {:?}", expr), - }; - - let lit_input = - LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg }; - match self.tcx.at(expr.span).lit_to_const(lit_input) { - Ok(val) => *self.const_to_pat(val, expr.hir_id, lit.span, false).kind, - Err(LitToConstError::Reported) => PatKind::Wild, - Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"), + let (lit, neg) = match expr.kind { + hir::ExprKind::Path(ref qpath) => { + return *self.lower_path(qpath, expr.hir_id, expr.span).kind; } + hir::ExprKind::ConstBlock(ref anon_const) => { + return self.lower_inline_const(anon_const, expr.hir_id, expr.span); + } + hir::ExprKind::Lit(ref lit) => (lit, false), + hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => { + let lit = match expr.kind { + hir::ExprKind::Lit(ref lit) => lit, + _ => span_bug!(expr.span, "not a literal: {:?}", expr), + }; + (lit, true) + } + _ => span_bug!(expr.span, "not a literal: {:?}", expr), + }; + + let lit_input = + LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg }; + match self.tcx.at(expr.span).lit_to_const(lit_input) { + Ok(val) => *self.const_to_pat(val, expr.hir_id, lit.span, false).kind, + Err(LitToConstError::Reported) => PatKind::Wild, + Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"), } } } diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 8a9ced91eb..102e743977 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -4,7 +4,9 @@ use rustc_middle::ty::TyCtxt; use std::ops::RangeInclusive; use super::visitor::{ResultsVisitable, ResultsVisitor}; -use super::{Analysis, Effect, EffectIndex, GenKillAnalysis, GenKillSet, SwitchIntTarget}; +use super::{ + Analysis, CallReturnPlaces, Effect, EffectIndex, GenKillAnalysis, GenKillSet, SwitchIntTarget, +}; pub trait Direction { fn is_forward() -> bool; @@ -16,7 +18,7 @@ pub trait Direction { /// Applies all effects between the given `EffectIndex`s. /// /// `effects.start()` must precede or equal `effects.end()` in this direction. - fn apply_effects_in_range( + fn apply_effects_in_range<'tcx, A>( analysis: &A, state: &mut A::Domain, block: BasicBlock, @@ -25,7 +27,7 @@ pub trait Direction { ) where A: Analysis<'tcx>; - fn apply_effects_in_block( + fn apply_effects_in_block<'tcx, A>( analysis: &A, state: &mut A::Domain, block: BasicBlock, @@ -33,7 +35,7 @@ pub trait Direction { ) where A: Analysis<'tcx>; - fn gen_kill_effects_in_block( + fn gen_kill_effects_in_block<'tcx, A>( analysis: &A, trans: &mut GenKillSet, block: BasicBlock, @@ -41,7 +43,7 @@ pub trait Direction { ) where A: GenKillAnalysis<'tcx>; - fn visit_results_in_block( + fn visit_results_in_block<'mir, 'tcx, F, R>( state: &mut F, block: BasicBlock, block_data: &'mir mir::BasicBlockData<'tcx>, @@ -50,7 +52,7 @@ pub trait Direction { ) where R: ResultsVisitable<'tcx, FlowState = F>; - fn join_state_into_successors_of( + fn join_state_into_successors_of<'tcx, A>( analysis: &A, tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>, @@ -70,7 +72,7 @@ impl Direction for Backward { false } - fn apply_effects_in_block( + fn apply_effects_in_block<'tcx, A>( analysis: &A, state: &mut A::Domain, block: BasicBlock, @@ -90,7 +92,7 @@ impl Direction for Backward { } } - fn gen_kill_effects_in_block( + fn gen_kill_effects_in_block<'tcx, A>( analysis: &A, trans: &mut GenKillSet, block: BasicBlock, @@ -110,7 +112,7 @@ impl Direction for Backward { } } - fn apply_effects_in_range( + fn apply_effects_in_range<'tcx, A>( analysis: &A, state: &mut A::Domain, block: BasicBlock, @@ -187,7 +189,7 @@ impl Direction for Backward { analysis.apply_statement_effect(state, statement, location); } - fn visit_results_in_block( + fn visit_results_in_block<'mir, 'tcx, F, R>( state: &mut F, block: BasicBlock, block_data: &'mir mir::BasicBlockData<'tcx>, @@ -219,7 +221,7 @@ impl Direction for Backward { vis.visit_block_start(state, block_data, block); } - fn join_state_into_successors_of( + fn join_state_into_successors_of<'tcx, A>( analysis: &A, _tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>, @@ -235,14 +237,26 @@ impl Direction for Backward { // Apply terminator-specific edge effects. // // FIXME(ecstaticmorse): Avoid cloning the exit state unconditionally. - mir::TerminatorKind::Call { - destination: Some((return_place, dest)), - ref func, - ref args, - .. + mir::TerminatorKind::Call { destination: Some((return_place, dest)), .. } + if dest == bb => + { + let mut tmp = exit_state.clone(); + analysis.apply_call_return_effect( + &mut tmp, + pred, + CallReturnPlaces::Call(return_place), + ); + propagate(pred, &tmp); + } + mir::TerminatorKind::InlineAsm { + destination: Some(dest), ref operands, .. } if dest == bb => { let mut tmp = exit_state.clone(); - analysis.apply_call_return_effect(&mut tmp, pred, func, args, return_place); + analysis.apply_call_return_effect( + &mut tmp, + pred, + CallReturnPlaces::InlineAsm(operands), + ); propagate(pred, &tmp); } @@ -258,6 +272,7 @@ impl Direction for Backward { | mir::TerminatorKind::Drop { unwind: Some(unwind), .. } | mir::TerminatorKind::DropAndReplace { unwind: Some(unwind), .. } | mir::TerminatorKind::FalseUnwind { unwind: Some(unwind), .. } + | mir::TerminatorKind::InlineAsm { cleanup: Some(unwind), .. } if unwind == bb => { if dead_unwinds.map_or(true, |dead| !dead.contains(bb)) { @@ -279,7 +294,7 @@ impl Direction for Forward { true } - fn apply_effects_in_block( + fn apply_effects_in_block<'tcx, A>( analysis: &A, state: &mut A::Domain, block: BasicBlock, @@ -299,7 +314,7 @@ impl Direction for Forward { analysis.apply_terminator_effect(state, terminator, location); } - fn gen_kill_effects_in_block( + fn gen_kill_effects_in_block<'tcx, A>( analysis: &A, trans: &mut GenKillSet, block: BasicBlock, @@ -319,7 +334,7 @@ impl Direction for Forward { analysis.terminator_effect(trans, terminator, location); } - fn apply_effects_in_range( + fn apply_effects_in_range<'tcx, A>( analysis: &A, state: &mut A::Domain, block: BasicBlock, @@ -392,7 +407,7 @@ impl Direction for Forward { } } - fn visit_results_in_block( + fn visit_results_in_block<'mir, 'tcx, F, R>( state: &mut F, block: BasicBlock, block_data: &'mir mir::BasicBlockData<'tcx>, @@ -423,7 +438,7 @@ impl Direction for Forward { vis.visit_block_end(state, block_data, block); } - fn join_state_into_successors_of( + fn join_state_into_successors_of<'tcx, A>( analysis: &A, _tcx: TyCtxt<'tcx>, _body: &mir::Body<'tcx>, @@ -467,7 +482,7 @@ impl Direction for Forward { propagate(target, exit_state); } - Call { cleanup, destination, ref func, ref args, from_hir_call: _, fn_span: _ } => { + Call { cleanup, destination, func: _, args: _, from_hir_call: _, fn_span: _ } => { if let Some(unwind) = cleanup { if dead_unwinds.map_or(true, |dead| !dead.contains(bb)) { propagate(unwind, exit_state); @@ -477,13 +492,37 @@ impl Direction for Forward { if let Some((dest_place, target)) = destination { // N.B.: This must be done *last*, otherwise the unwind path will see the call // return effect. - analysis.apply_call_return_effect(exit_state, bb, func, args, dest_place); + analysis.apply_call_return_effect( + exit_state, + bb, + CallReturnPlaces::Call(dest_place), + ); propagate(target, exit_state); } } - InlineAsm { template: _, operands: _, options: _, line_spans: _, destination } => { + InlineAsm { + template: _, + ref operands, + options: _, + line_spans: _, + destination, + cleanup, + } => { + if let Some(unwind) = cleanup { + if dead_unwinds.map_or(true, |dead| !dead.contains(bb)) { + propagate(unwind, exit_state); + } + } + if let Some(target) = destination { + // N.B.: This must be done *last*, otherwise the unwind path will see the call + // return effect. + analysis.apply_call_return_effect( + exit_state, + bb, + CallReturnPlaces::InlineAsm(operands), + ); propagate(target, exit_state); } } @@ -552,7 +591,7 @@ where // // FIXME: Figure out how to express this using `Option::clone_from`, or maybe lift it into the // standard library? -fn opt_clone_from_or_clone(opt: &'a mut Option, val: &T) -> &'a mut T { +fn opt_clone_from_or_clone<'a, T: Clone>(opt: &'a mut Option, val: &T) -> &'a mut T { if opt.is_some() { let ret = opt.as_mut().unwrap(); ret.clone_from(val); diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs index 804abc3b42..e8a6d8dad4 100644 --- a/compiler/rustc_mir_dataflow/src/framework/engine.rs +++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs @@ -31,12 +31,15 @@ where pub(super) entry_sets: IndexVec, } -impl Results<'tcx, A> +impl<'tcx, A> Results<'tcx, A> where A: Analysis<'tcx>, { /// Creates a `ResultsCursor` that can inspect these `Results`. - pub fn into_results_cursor(self, body: &'mir mir::Body<'tcx>) -> ResultsCursor<'mir, 'tcx, A> { + pub fn into_results_cursor<'mir>( + self, + body: &'mir mir::Body<'tcx>, + ) -> ResultsCursor<'mir, 'tcx, A> { ResultsCursor::new(body, self) } @@ -45,7 +48,7 @@ where &self.entry_sets[block] } - pub fn visit_with( + pub fn visit_with<'mir>( &self, body: &'mir mir::Body<'tcx>, blocks: impl IntoIterator, @@ -54,7 +57,7 @@ where visit_results(body, blocks, self, vis) } - pub fn visit_reachable_with( + pub fn visit_reachable_with<'mir>( &self, body: &'mir mir::Body<'tcx>, vis: &mut impl ResultsVisitor<'mir, 'tcx, FlowState = A::Domain>, @@ -85,7 +88,7 @@ where apply_trans_for_block: Option>, } -impl Engine<'a, 'tcx, A> +impl<'a, 'tcx, A, D, T> Engine<'a, 'tcx, A> where A: GenKillAnalysis<'tcx, Idx = T, Domain = D>, D: Clone + JoinSemiLattice + GenKill + BorrowMut>, @@ -119,7 +122,7 @@ where } } -impl Engine<'a, 'tcx, A> +impl<'a, 'tcx, A, D> Engine<'a, 'tcx, A> where A: Analysis<'tcx, Domain = D>, D: Clone + JoinSemiLattice, @@ -257,7 +260,7 @@ where /// Writes a DOT file containing the results of a dataflow analysis if the user requested it via /// `rustc_mir` attributes. -fn write_graphviz_results( +fn write_graphviz_results<'tcx, A>( tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>, results: &Results<'tcx, A>, @@ -330,7 +333,7 @@ struct RustcMirAttrs { } impl RustcMirAttrs { - fn parse(tcx: TyCtxt<'tcx>, def_id: DefId) -> Result { + fn parse(tcx: TyCtxt<'_>, def_id: DefId) -> Result { let attrs = tcx.get_attrs(def_id); let mut result = Ok(()); @@ -373,7 +376,7 @@ impl RustcMirAttrs { fn set_field( field: &mut Option, - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, attr: &ast::NestedMetaItem, mapper: impl FnOnce(Symbol) -> Result, ) -> Result<(), ()> { diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index a370f8e40f..34bc157a74 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -10,7 +10,7 @@ use rustc_middle::mir::graphviz_safe_def_name; use rustc_middle::mir::{self, BasicBlock, Body, Location}; use super::fmt::{DebugDiffWithAdapter, DebugWithAdapter, DebugWithContext}; -use super::{Analysis, Direction, Results, ResultsRefCursor, ResultsVisitor}; +use super::{Analysis, CallReturnPlaces, Direction, Results, ResultsRefCursor, ResultsVisitor}; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum OutputStyle { @@ -36,7 +36,7 @@ where style: OutputStyle, } -impl Formatter<'a, 'tcx, A> +impl<'a, 'tcx, A> Formatter<'a, 'tcx, A> where A: Analysis<'tcx>, { @@ -52,7 +52,7 @@ pub struct CfgEdge { index: usize, } -fn dataflow_successors(body: &Body<'tcx>, bb: BasicBlock) -> Vec { +fn dataflow_successors(body: &Body<'_>, bb: BasicBlock) -> Vec { body[bb] .terminator() .successors() @@ -61,7 +61,7 @@ fn dataflow_successors(body: &Body<'tcx>, bb: BasicBlock) -> Vec { .collect() } -impl dot::Labeller<'_> for Formatter<'a, 'tcx, A> +impl<'tcx, A> dot::Labeller<'_> for Formatter<'_, 'tcx, A> where A: Analysis<'tcx>, A::Domain: DebugWithContext, @@ -100,7 +100,7 @@ where } } -impl dot::GraphWalk<'a> for Formatter<'a, 'tcx, A> +impl<'a, 'tcx, A> dot::GraphWalk<'a> for Formatter<'a, 'tcx, A> where A: Analysis<'tcx>, { @@ -138,7 +138,7 @@ where style: OutputStyle, } -impl BlockFormatter<'a, 'tcx, A> +impl<'a, 'tcx, A> BlockFormatter<'a, 'tcx, A> where A: Analysis<'tcx>, A::Domain: DebugWithContext, @@ -231,16 +231,15 @@ where // for the basic block itself. That way, we could display terminator-specific effects for // backward dataflow analyses as well as effects for `SwitchInt` terminators. match terminator.kind { - mir::TerminatorKind::Call { - destination: Some((return_place, _)), - ref func, - ref args, - .. - } => { + mir::TerminatorKind::Call { destination: Some((return_place, _)), .. } => { self.write_row(w, "", "(on successful return)", |this, w, fmt| { let state_on_unwind = this.results.get().clone(); this.results.apply_custom_effect(|analysis, state| { - analysis.apply_call_return_effect(state, block, func, args, return_place); + analysis.apply_call_return_effect( + state, + block, + CallReturnPlaces::Call(return_place), + ); }); write!( @@ -278,6 +277,31 @@ where })?; } + mir::TerminatorKind::InlineAsm { destination: Some(_), ref operands, .. } => { + self.write_row(w, "", "(on successful return)", |this, w, fmt| { + let state_on_unwind = this.results.get().clone(); + this.results.apply_custom_effect(|analysis, state| { + analysis.apply_call_return_effect( + state, + block, + CallReturnPlaces::InlineAsm(operands), + ); + }); + + write!( + w, + r#"{diff}"#, + colspan = this.style.num_state_columns(), + fmt = fmt, + diff = diff_pretty( + this.results.get(), + &state_on_unwind, + this.results.analysis() + ), + ) + })?; + } + _ => {} }; @@ -467,7 +491,7 @@ where after: Vec, } -impl StateDiffCollector<'a, 'tcx, A> +impl<'a, 'tcx, A> StateDiffCollector<'a, 'tcx, A> where A: Analysis<'tcx>, A::Domain: DebugWithContext, @@ -490,7 +514,7 @@ where } } -impl ResultsVisitor<'a, 'tcx> for StateDiffCollector<'a, 'tcx, A> +impl<'a, 'tcx, A> ResultsVisitor<'a, 'tcx> for StateDiffCollector<'a, 'tcx, A> where A: Analysis<'tcx>, A::Domain: DebugWithContext, @@ -500,7 +524,7 @@ where fn visit_block_start( &mut self, state: &Self::FlowState, - _block_data: &'mir mir::BasicBlockData<'tcx>, + _block_data: &mir::BasicBlockData<'tcx>, _block: BasicBlock, ) { if A::Direction::is_forward() { @@ -511,7 +535,7 @@ where fn visit_block_end( &mut self, state: &Self::FlowState, - _block_data: &'mir mir::BasicBlockData<'tcx>, + _block_data: &mir::BasicBlockData<'tcx>, _block: BasicBlock, ) { if A::Direction::is_backward() { @@ -522,7 +546,7 @@ where fn visit_statement_before_primary_effect( &mut self, state: &Self::FlowState, - _statement: &'mir mir::Statement<'tcx>, + _statement: &mir::Statement<'tcx>, _location: Location, ) { if let Some(before) = self.before.as_mut() { @@ -534,7 +558,7 @@ where fn visit_statement_after_primary_effect( &mut self, state: &Self::FlowState, - _statement: &'mir mir::Statement<'tcx>, + _statement: &mir::Statement<'tcx>, _location: Location, ) { self.after.push(diff_pretty(state, &self.prev_state, self.analysis)); @@ -544,7 +568,7 @@ where fn visit_terminator_before_primary_effect( &mut self, state: &Self::FlowState, - _terminator: &'mir mir::Terminator<'tcx>, + _terminator: &mir::Terminator<'tcx>, _location: Location, ) { if let Some(before) = self.before.as_mut() { @@ -556,7 +580,7 @@ where fn visit_terminator_after_primary_effect( &mut self, state: &Self::FlowState, - _terminator: &'mir mir::Terminator<'tcx>, + _terminator: &mir::Terminator<'tcx>, _location: Location, ) { self.after.push(diff_pretty(state, &self.prev_state, self.analysis)); diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs index f0c9ac4c50..dac6720a6e 100644 --- a/compiler/rustc_mir_dataflow/src/framework/mod.rs +++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs @@ -160,9 +160,7 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> { &self, state: &mut Self::Domain, block: BasicBlock, - func: &mir::Operand<'tcx>, - args: &[mir::Operand<'tcx>], - return_place: mir::Place<'tcx>, + return_places: CallReturnPlaces<'_, 'tcx>, ); /// Updates the current dataflow state with the effect of resuming from a `Yield` terminator. @@ -216,7 +214,11 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> { /// .iterate_to_fixpoint() /// .into_results_cursor(body); /// ``` - fn into_engine(self, tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>) -> Engine<'mir, 'tcx, Self> + fn into_engine<'mir>( + self, + tcx: TyCtxt<'tcx>, + body: &'mir mir::Body<'tcx>, + ) -> Engine<'mir, 'tcx, Self> where Self: Sized, { @@ -276,9 +278,7 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> { &self, trans: &mut impl GenKill, block: BasicBlock, - func: &mir::Operand<'tcx>, - args: &[mir::Operand<'tcx>], - return_place: mir::Place<'tcx>, + return_places: CallReturnPlaces<'_, 'tcx>, ); /// See `Analysis::apply_yield_resume_effect`. @@ -300,7 +300,7 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> { } } -impl Analysis<'tcx> for A +impl<'tcx, A> Analysis<'tcx> for A where A: GenKillAnalysis<'tcx>, A::Domain: GenKill + BorrowMut>, @@ -347,11 +347,9 @@ where &self, state: &mut A::Domain, block: BasicBlock, - func: &mir::Operand<'tcx>, - args: &[mir::Operand<'tcx>], - return_place: mir::Place<'tcx>, + return_places: CallReturnPlaces<'_, 'tcx>, ) { - self.call_return_effect(state, block, func, args, return_place); + self.call_return_effect(state, block, return_places); } fn apply_yield_resume_effect( @@ -374,7 +372,11 @@ where /* Extension methods */ - fn into_engine(self, tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>) -> Engine<'mir, 'tcx, Self> + fn into_engine<'mir>( + self, + tcx: TyCtxt<'tcx>, + body: &'mir mir::Body<'tcx>, + ) -> Engine<'mir, 'tcx, Self> where Self: Sized, { @@ -542,5 +544,29 @@ pub trait SwitchIntEdgeEffects { fn apply(&mut self, apply_edge_effect: impl FnMut(&mut D, SwitchIntTarget)); } +/// List of places that are written to after a successful (non-unwind) return +/// from a `Call` or `InlineAsm`. +pub enum CallReturnPlaces<'a, 'tcx> { + Call(mir::Place<'tcx>), + InlineAsm(&'a [mir::InlineAsmOperand<'tcx>]), +} + +impl<'tcx> CallReturnPlaces<'_, 'tcx> { + pub fn for_each(&self, mut f: impl FnMut(mir::Place<'tcx>)) { + match *self { + Self::Call(place) => f(place), + Self::InlineAsm(operands) => { + for op in operands { + match *op { + mir::InlineAsmOperand::Out { place: Some(place), .. } + | mir::InlineAsmOperand::InOut { out_place: Some(place), .. } => f(place), + _ => {} + } + } + } + } + } +} + #[cfg(test)] mod tests; diff --git a/compiler/rustc_mir_dataflow/src/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs index 6efa8daec4..3cc8d30259 100644 --- a/compiler/rustc_mir_dataflow/src/framework/tests.rs +++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs @@ -85,7 +85,7 @@ struct MockAnalysis<'tcx, D> { dir: PhantomData, } -impl MockAnalysis<'tcx, D> { +impl MockAnalysis<'_, D> { const BASIC_BLOCK_OFFSET: usize = 100; /// The entry set for each `BasicBlock` is the ID of that block offset by a fixed amount to @@ -160,7 +160,7 @@ impl MockAnalysis<'tcx, D> { } } -impl AnalysisDomain<'tcx> for MockAnalysis<'tcx, D> { +impl<'tcx, D: Direction> AnalysisDomain<'tcx> for MockAnalysis<'tcx, D> { type Domain = BitSet; type Direction = D; @@ -175,7 +175,7 @@ impl AnalysisDomain<'tcx> for MockAnalysis<'tcx, D> { } } -impl Analysis<'tcx> for MockAnalysis<'tcx, D> { +impl<'tcx, D: Direction> Analysis<'tcx> for MockAnalysis<'tcx, D> { fn apply_statement_effect( &self, state: &mut Self::Domain, @@ -220,9 +220,7 @@ impl Analysis<'tcx> for MockAnalysis<'tcx, D> { &self, _state: &mut Self::Domain, _block: BasicBlock, - _func: &mir::Operand<'tcx>, - _args: &[mir::Operand<'tcx>], - _return_place: mir::Place<'tcx>, + _return_places: CallReturnPlaces<'_, 'tcx>, ) { } } @@ -262,7 +260,7 @@ impl SeekTarget { } } -fn test_cursor(analysis: MockAnalysis<'tcx, D>) { +fn test_cursor(analysis: MockAnalysis<'_, D>) { let body = analysis.body; let mut cursor = diff --git a/compiler/rustc_mir_dataflow/src/framework/visitor.rs b/compiler/rustc_mir_dataflow/src/framework/visitor.rs index 84136c4d78..75b4e150a8 100644 --- a/compiler/rustc_mir_dataflow/src/framework/visitor.rs +++ b/compiler/rustc_mir_dataflow/src/framework/visitor.rs @@ -4,7 +4,7 @@ use super::{Analysis, Direction, Results}; /// Calls the corresponding method in `ResultsVisitor` for every location in a `mir::Body` with the /// dataflow state at that location. -pub fn visit_results( +pub fn visit_results<'mir, 'tcx, F, V>( body: &'mir mir::Body<'tcx>, blocks: impl IntoIterator, results: &V, diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index d38b567a95..bb9755e4f4 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -1,6 +1,6 @@ use super::*; -use crate::{AnalysisDomain, GenKill, GenKillAnalysis}; +use crate::{AnalysisDomain, CallReturnPlaces, GenKill, GenKillAnalysis}; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; @@ -45,7 +45,7 @@ impl MaybeBorrowedLocals { } } -impl AnalysisDomain<'tcx> for MaybeBorrowedLocals { +impl<'tcx> AnalysisDomain<'tcx> for MaybeBorrowedLocals { type Domain = BitSet; const NAME: &'static str = "maybe_borrowed_locals"; @@ -59,7 +59,7 @@ impl AnalysisDomain<'tcx> for MaybeBorrowedLocals { } } -impl GenKillAnalysis<'tcx> for MaybeBorrowedLocals { +impl<'tcx> GenKillAnalysis<'tcx> for MaybeBorrowedLocals { type Idx = Local; fn statement_effect( @@ -84,9 +84,7 @@ impl GenKillAnalysis<'tcx> for MaybeBorrowedLocals { &self, _trans: &mut impl GenKill, _block: mir::BasicBlock, - _func: &mir::Operand<'tcx>, - _args: &[mir::Operand<'tcx>], - _dest_place: mir::Place<'tcx>, + _return_places: CallReturnPlaces<'_, 'tcx>, ) { } } @@ -97,7 +95,7 @@ struct TransferFunction<'a, T> { ignore_borrow_on_drop: bool, } -impl Visitor<'tcx> for TransferFunction<'a, T> +impl<'tcx, T> Visitor<'tcx> for TransferFunction<'_, T> where T: GenKill, { diff --git a/compiler/rustc_mir_dataflow/src/impls/init_locals.rs b/compiler/rustc_mir_dataflow/src/impls/init_locals.rs index 07570e764f..b355871d64 100644 --- a/compiler/rustc_mir_dataflow/src/impls/init_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/init_locals.rs @@ -2,7 +2,7 @@ //! //! A local will be maybe initialized if *any* projections of that local might be initialized. -use crate::GenKill; +use crate::{CallReturnPlaces, GenKill}; use rustc_index::bit_set::BitSet; use rustc_middle::mir::visit::{PlaceContext, Visitor}; @@ -10,7 +10,7 @@ use rustc_middle::mir::{self, BasicBlock, Local, Location}; pub struct MaybeInitializedLocals; -impl crate::AnalysisDomain<'tcx> for MaybeInitializedLocals { +impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeInitializedLocals { type Domain = BitSet; const NAME: &'static str = "maybe_init_locals"; @@ -28,7 +28,7 @@ impl crate::AnalysisDomain<'tcx> for MaybeInitializedLocals { } } -impl crate::GenKillAnalysis<'tcx> for MaybeInitializedLocals { +impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeInitializedLocals { type Idx = Local; fn statement_effect( @@ -53,11 +53,9 @@ impl crate::GenKillAnalysis<'tcx> for MaybeInitializedLocals { &self, trans: &mut impl GenKill, _block: BasicBlock, - _func: &mir::Operand<'tcx>, - _args: &[mir::Operand<'tcx>], - return_place: mir::Place<'tcx>, + return_places: CallReturnPlaces<'_, 'tcx>, ) { - trans.gen(return_place.local) + return_places.for_each(|place| trans.gen(place.local)); } /// See `Analysis::apply_yield_resume_effect`. @@ -75,7 +73,7 @@ struct TransferFunction<'a, T> { trans: &'a mut T, } -impl Visitor<'tcx> for TransferFunction<'a, T> +impl Visitor<'_> for TransferFunction<'_, T> where T: GenKill, { @@ -83,7 +81,11 @@ where use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, NonUseContext}; match context { // These are handled specially in `call_return_effect` and `yield_resume_effect`. - PlaceContext::MutatingUse(MutatingUseContext::Call | MutatingUseContext::Yield) => {} + PlaceContext::MutatingUse( + MutatingUseContext::Call + | MutatingUseContext::AsmOutput + | MutatingUseContext::Yield, + ) => {} // Otherwise, when a place is mutated, we must consider it possibly initialized. PlaceContext::MutatingUse(_) => self.trans.gen(local), diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs index 3e2548845e..65c388f812 100644 --- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs @@ -2,7 +2,7 @@ use rustc_index::bit_set::BitSet; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::{self, Local, Location}; -use crate::{AnalysisDomain, Backward, GenKill, GenKillAnalysis}; +use crate::{AnalysisDomain, Backward, CallReturnPlaces, GenKill, GenKillAnalysis}; /// A [live-variable dataflow analysis][liveness]. /// @@ -48,12 +48,12 @@ use crate::{AnalysisDomain, Backward, GenKill, GenKillAnalysis}; pub struct MaybeLiveLocals; impl MaybeLiveLocals { - fn transfer_function(&self, trans: &'a mut T) -> TransferFunction<'a, T> { + fn transfer_function<'a, T>(&self, trans: &'a mut T) -> TransferFunction<'a, T> { TransferFunction(trans) } } -impl AnalysisDomain<'tcx> for MaybeLiveLocals { +impl<'tcx> AnalysisDomain<'tcx> for MaybeLiveLocals { type Domain = BitSet; type Direction = Backward; @@ -69,7 +69,7 @@ impl AnalysisDomain<'tcx> for MaybeLiveLocals { } } -impl GenKillAnalysis<'tcx> for MaybeLiveLocals { +impl<'tcx> GenKillAnalysis<'tcx> for MaybeLiveLocals { type Idx = Local; fn statement_effect( @@ -94,13 +94,13 @@ impl GenKillAnalysis<'tcx> for MaybeLiveLocals { &self, trans: &mut impl GenKill, _block: mir::BasicBlock, - _func: &mir::Operand<'tcx>, - _args: &[mir::Operand<'tcx>], - dest_place: mir::Place<'tcx>, + return_places: CallReturnPlaces<'_, 'tcx>, ) { - if let Some(local) = dest_place.as_local() { - trans.kill(local); - } + return_places.for_each(|place| { + if let Some(local) = place.as_local() { + trans.kill(local); + } + }); } fn yield_resume_effect( @@ -167,12 +167,16 @@ impl DefUse { // destination place for a `Call` return or `Yield` resume respectively. Since this is // only a `Def` when the function returns successfully, we handle this case separately // in `call_return_effect` above. - PlaceContext::MutatingUse(MutatingUseContext::Call | MutatingUseContext::Yield) => None, + PlaceContext::MutatingUse( + MutatingUseContext::Call + | MutatingUseContext::AsmOutput + | MutatingUseContext::Yield, + ) => None, // All other contexts are uses... PlaceContext::MutatingUse( MutatingUseContext::AddressOf - | MutatingUseContext::AsmOutput + | MutatingUseContext::LlvmAsmOutput | MutatingUseContext::Borrow | MutatingUseContext::Drop | MutatingUseContext::Retag, diff --git a/compiler/rustc_mir_dataflow/src/impls/mod.rs b/compiler/rustc_mir_dataflow/src/impls/mod.rs index 2585701f60..5dc8a003b4 100644 --- a/compiler/rustc_mir_dataflow/src/impls/mod.rs +++ b/compiler/rustc_mir_dataflow/src/impls/mod.rs @@ -11,7 +11,7 @@ use rustc_middle::ty::{self, TyCtxt}; use crate::drop_flag_effects_for_function_entry; use crate::drop_flag_effects_for_location; use crate::elaborate_drops::DropFlagState; -use crate::framework::SwitchIntEdgeEffects; +use crate::framework::{CallReturnPlaces, SwitchIntEdgeEffects}; use crate::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData, MovePathIndex}; use crate::on_lookup_result_bits; use crate::MoveDataParamEnv; @@ -354,21 +354,21 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { &self, trans: &mut impl GenKill, _block: mir::BasicBlock, - _func: &mir::Operand<'tcx>, - _args: &[mir::Operand<'tcx>], - dest_place: mir::Place<'tcx>, + return_places: CallReturnPlaces<'_, 'tcx>, ) { - // when a call returns successfully, that means we need to set - // the bits for that dest_place to 1 (initialized). - on_lookup_result_bits( - self.tcx, - self.body, - self.move_data(), - self.move_data().rev_lookup.find(dest_place.as_ref()), - |mpi| { - trans.gen(mpi); - }, - ); + return_places.for_each(|place| { + // when a call returns successfully, that means we need to set + // the bits for that dest_place to 1 (initialized). + on_lookup_result_bits( + self.tcx, + self.body, + self.move_data(), + self.move_data().rev_lookup.find(place.as_ref()), + |mpi| { + trans.gen(mpi); + }, + ); + }); } fn switch_int_edge_effects>( @@ -472,21 +472,21 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { &self, trans: &mut impl GenKill, _block: mir::BasicBlock, - _func: &mir::Operand<'tcx>, - _args: &[mir::Operand<'tcx>], - dest_place: mir::Place<'tcx>, + return_places: CallReturnPlaces<'_, 'tcx>, ) { - // when a call returns successfully, that means we need to set - // the bits for that dest_place to 0 (initialized). - on_lookup_result_bits( - self.tcx, - self.body, - self.move_data(), - self.move_data().rev_lookup.find(dest_place.as_ref()), - |mpi| { - trans.kill(mpi); - }, - ); + return_places.for_each(|place| { + // when a call returns successfully, that means we need to set + // the bits for that dest_place to 0 (initialized). + on_lookup_result_bits( + self.tcx, + self.body, + self.move_data(), + self.move_data().rev_lookup.find(place.as_ref()), + |mpi| { + trans.kill(mpi); + }, + ); + }); } fn switch_int_edge_effects>( @@ -591,21 +591,21 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> { &self, trans: &mut impl GenKill, _block: mir::BasicBlock, - _func: &mir::Operand<'tcx>, - _args: &[mir::Operand<'tcx>], - dest_place: mir::Place<'tcx>, + return_places: CallReturnPlaces<'_, 'tcx>, ) { - // when a call returns successfully, that means we need to set - // the bits for that dest_place to 1 (initialized). - on_lookup_result_bits( - self.tcx, - self.body, - self.move_data(), - self.move_data().rev_lookup.find(dest_place.as_ref()), - |mpi| { - trans.gen(mpi); - }, - ); + return_places.for_each(|place| { + // when a call returns successfully, that means we need to set + // the bits for that dest_place to 1 (initialized). + on_lookup_result_bits( + self.tcx, + self.body, + self.move_data(), + self.move_data().rev_lookup.find(place.as_ref()), + |mpi| { + trans.gen(mpi); + }, + ); + }); } } @@ -679,9 +679,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { &self, trans: &mut impl GenKill, block: mir::BasicBlock, - _func: &mir::Operand<'tcx>, - _args: &[mir::Operand<'tcx>], - _dest_place: mir::Place<'tcx>, + _return_places: CallReturnPlaces<'_, 'tcx>, ) { let move_data = self.move_data(); let init_loc_map = &move_data.init_loc_map; @@ -706,7 +704,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, 'tcx> { /// /// If the basic block matches this pattern, this function returns the place corresponding to the /// enum (`_1` in the example above) as well as the `AdtDef` of that enum. -fn switch_on_enum_discriminant( +fn switch_on_enum_discriminant<'mir, 'tcx>( tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>, block: &'mir mir::BasicBlockData<'tcx>, diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index b468e50b39..896377f2bc 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -1,7 +1,7 @@ pub use super::*; use crate::storage::AlwaysLiveLocals; -use crate::{GenKill, Results, ResultsRefCursor}; +use crate::{CallReturnPlaces, GenKill, Results, ResultsRefCursor}; use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use std::cell::RefCell; @@ -17,7 +17,7 @@ impl MaybeStorageLive { } } -impl crate::AnalysisDomain<'tcx> for MaybeStorageLive { +impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeStorageLive { type Domain = BitSet; const NAME: &'static str = "maybe_storage_live"; @@ -39,7 +39,7 @@ impl crate::AnalysisDomain<'tcx> for MaybeStorageLive { } } -impl crate::GenKillAnalysis<'tcx> for MaybeStorageLive { +impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageLive { type Idx = Local; fn statement_effect( @@ -68,9 +68,7 @@ impl crate::GenKillAnalysis<'tcx> for MaybeStorageLive { &self, _trans: &mut impl GenKill, _block: BasicBlock, - _func: &mir::Operand<'tcx>, - _args: &[mir::Operand<'tcx>], - _return_place: mir::Place<'tcx>, + _return_places: CallReturnPlaces<'_, 'tcx>, ) { // Nothing to do when a call returns successfully } @@ -226,7 +224,7 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc terminator: &mir::Terminator<'tcx>, loc: Location, ) { - match &terminator.kind { + match terminator.kind { // For call terminators the destination requires storage for the call // and after the call returns successfully, but not after a panic. // Since `propagate_call_unwind` doesn't exist, we have to kill the @@ -235,6 +233,11 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc trans.kill(place.local); } + // The same applies to InlineAsm outputs. + TerminatorKind::InlineAsm { ref operands, .. } => { + CallReturnPlaces::InlineAsm(operands).for_each(|place| trans.kill(place.local)); + } + // Nothing to do for these. Match exhaustively so this fails to compile when new // variants are added. TerminatorKind::Call { destination: None, .. } @@ -247,7 +250,6 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc | TerminatorKind::FalseUnwind { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::Goto { .. } - | TerminatorKind::InlineAsm { .. } | TerminatorKind::Resume | TerminatorKind::Return | TerminatorKind::SwitchInt { .. } @@ -261,11 +263,9 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc &self, trans: &mut impl GenKill, _block: BasicBlock, - _func: &mir::Operand<'tcx>, - _args: &[mir::Operand<'tcx>], - return_place: mir::Place<'tcx>, + return_places: CallReturnPlaces<'_, 'tcx>, ) { - trans.gen(return_place.local); + return_places.for_each(|place| trans.gen(place.local)); } fn yield_resume_effect( diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 77a72ce63c..6c2d1b8564 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -3,8 +3,6 @@ #![feature(box_patterns)] #![feature(box_syntax)] #![feature(exact_size_is_empty)] -#![feature(in_band_lifetimes)] -#![feature(iter_zip)] #![feature(let_else)] #![feature(min_specialization)] #![feature(once_cell)] @@ -28,9 +26,9 @@ pub use self::drop_flag_effects::{ on_lookup_result_bits, }; pub use self::framework::{ - fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, Backward, Direction, Engine, - Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results, ResultsCursor, ResultsRefCursor, - ResultsVisitable, ResultsVisitor, + fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, Backward, CallReturnPlaces, + Direction, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results, ResultsCursor, + ResultsRefCursor, ResultsVisitable, ResultsVisitor, }; use self::move_paths::MoveData; diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index e404b49ecb..2e00b4f9a5 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -343,19 +343,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { | Rvalue::AddressOf(..) | Rvalue::Discriminant(..) | Rvalue::Len(..) - | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) - | Rvalue::NullaryOp(NullOp::Box, _) => { - // This returns an rvalue with uninitialized contents. We can't - // move out of it here because it is an rvalue - assignments always - // completely initialize their place. - // - // However, this does not matter - MIR building is careful to - // only emit a shallow free for the partially-initialized - // temporary. - // - // In any case, if we want to fix this, we have to register a - // special move and change the `statement_effect` functions. - } + | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {} } } @@ -419,6 +407,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { options: _, line_spans: _, destination: _, + cleanup: _, } => { for op in operands { match *op { diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index 28e5d76783..1746d5ee38 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -20,6 +20,7 @@ use crate::{Analysis, JoinSemiLattice, Results, ResultsCursor}; pub struct SanityCheck; +// FIXME: This should be a `MirLint`, but it needs to be moved back to `rustc_mir_transform` first. impl<'tcx> MirPass<'tcx> for SanityCheck { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { use crate::has_rustc_mir_with; diff --git a/compiler/rustc_mir_dataflow/src/storage.rs b/compiler/rustc_mir_dataflow/src/storage.rs index 18b8ef557d..218d455721 100644 --- a/compiler/rustc_mir_dataflow/src/storage.rs +++ b/compiler/rustc_mir_dataflow/src/storage.rs @@ -11,7 +11,7 @@ use rustc_middle::mir::{self, Local}; pub struct AlwaysLiveLocals(BitSet); impl AlwaysLiveLocals { - pub fn new(body: &mir::Body<'tcx>) -> Self { + pub fn new(body: &mir::Body<'_>) -> Self { let mut always_live_locals = AlwaysLiveLocals(BitSet::new_filled(body.local_decls.len())); for block in body.basic_blocks() { diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs index 7a8dee09c2..28a5a22dd9 100644 --- a/compiler/rustc_mir_transform/src/add_retag.rs +++ b/compiler/rustc_mir_transform/src/add_retag.rs @@ -34,7 +34,7 @@ fn is_stable(place: PlaceRef<'_>) -> bool { } /// Determine whether this type may be a reference (or box), and thus needs retagging. -fn may_be_reference(ty: Ty<'tcx>) -> bool { +fn may_be_reference(ty: Ty<'_>) -> bool { match ty.kind() { // Primitive types that are not references ty::Bool @@ -58,11 +58,11 @@ fn may_be_reference(ty: Ty<'tcx>) -> bool { } impl<'tcx> MirPass<'tcx> for AddRetag { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if !tcx.sess.opts.debugging_opts.mir_emit_retag { - return; - } + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.opts.debugging_opts.mir_emit_retag + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // We need an `AllCallEdges` pass before we can do any work. super::add_call_guards::AllCallEdges.run_pass(tcx, body); diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs index 27fe80a456..a19a3c8b1d 100644 --- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs +++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs @@ -6,12 +6,12 @@ use rustc_middle::ty::TyCtxt; use rustc_session::lint::builtin::CONST_ITEM_MUTATION; use rustc_span::def_id::DefId; -use crate::MirPass; +use crate::MirLint; pub struct CheckConstItemMutation; -impl<'tcx> MirPass<'tcx> for CheckConstItemMutation { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirLint<'tcx> for CheckConstItemMutation { + fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let mut checker = ConstMutationChecker { body, tcx, target_local: None }; checker.visit_body(&body); } @@ -23,7 +23,7 @@ struct ConstMutationChecker<'a, 'tcx> { target_local: Option, } -impl<'a, 'tcx> ConstMutationChecker<'a, 'tcx> { +impl<'tcx> ConstMutationChecker<'_, 'tcx> { fn is_const_item(&self, local: Local) -> Option { if let Some(box LocalInfo::ConstRef { def_id }) = self.body.local_decls[local].local_info { Some(def_id) @@ -95,7 +95,7 @@ impl<'a, 'tcx> ConstMutationChecker<'a, 'tcx> { } } -impl<'a, 'tcx> Visitor<'tcx> for ConstMutationChecker<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> { fn visit_statement(&mut self, stmt: &Statement<'tcx>, loc: Location) { if let StatementKind::Assign(box (lhs, _)) = &stmt.kind { // Check for assignment to fields of a constant diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs index 49be34c7a2..23d59c8007 100644 --- a/compiler/rustc_mir_transform/src/check_packed_ref.rs +++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs @@ -7,7 +7,7 @@ use rustc_session::lint::builtin::UNALIGNED_REFERENCES; use rustc_span::symbol::sym; use crate::util; -use crate::MirPass; +use crate::MirLint; pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { unsafe_derive_on_repr_packed, ..*providers }; @@ -15,8 +15,8 @@ pub(crate) fn provide(providers: &mut Providers) { pub struct CheckPackedRef; -impl<'tcx> MirPass<'tcx> for CheckPackedRef { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirLint<'tcx> for CheckPackedRef { + fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let param_env = tcx.param_env(body.source.def_id()); let source_info = SourceInfo::outermost(body.span); let mut checker = PackedRefChecker { body, tcx, param_env, source_info }; @@ -66,7 +66,7 @@ fn builtin_derive_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option { } } -impl<'a, 'tcx> Visitor<'tcx> for PackedRefChecker<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { // Make sure we know where in the MIR we are. self.source_info = terminator.source_info; @@ -105,6 +105,11 @@ impl<'a, 'tcx> Visitor<'tcx> for PackedRefChecker<'a, 'tcx> { a misaligned reference is undefined behavior (even if that \ reference is never dereferenced)", ) + .help( + "copy the field contents to a local variable, or replace the \ + reference with a raw pointer and use `read_unaligned`/`write_unaligned` \ + (loads and stores via `*p` must be properly aligned even when using raw pointers)" + ) .emit() }, ); diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index 1ff9bd1572..a40c4d1c36 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -46,7 +46,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { } } -impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { self.source_info = terminator.source_info; match terminator.kind { @@ -117,8 +117,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { match rvalue { Rvalue::Aggregate(box ref aggregate, _) => match aggregate { &AggregateKind::Array(..) | &AggregateKind::Tuple => {} - &AggregateKind::Adt(ref def, ..) => { - match self.tcx.layout_scalar_valid_range(def.did) { + &AggregateKind::Adt(adt_did, ..) => { + match self.tcx.layout_scalar_valid_range(adt_did) { (Bound::Unbounded, Bound::Unbounded) => {} _ => self.require_unsafe( UnsafetyViolationKind::General, @@ -208,6 +208,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { MutatingUseContext::Store | MutatingUseContext::Drop | MutatingUseContext::AsmOutput + | MutatingUseContext::LlvmAsmOutput ) ); // If this is just an assignment, determine if the assigned type needs dropping. @@ -243,7 +244,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { } } -impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { +impl<'tcx> UnsafetyChecker<'_, 'tcx> { fn require_unsafe(&mut self, kind: UnsafetyViolationKind, details: UnsafetyViolationDetails) { // Violations can turn out to be `UnsafeFn` during analysis, but they should not start out as such. assert_ne!(kind, UnsafetyViolationKind::UnsafeFn); @@ -396,7 +397,7 @@ struct UnusedUnsafeVisitor<'a> { unsafe_blocks: &'a mut Vec<(hir::HirId, bool)>, } -impl<'a, 'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'a> { +impl<'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'_> { type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { diff --git a/compiler/rustc_mir_transform/src/const_debuginfo.rs b/compiler/rustc_mir_transform/src/const_debuginfo.rs index b613634560..839d94167f 100644 --- a/compiler/rustc_mir_transform/src/const_debuginfo.rs +++ b/compiler/rustc_mir_transform/src/const_debuginfo.rs @@ -15,11 +15,11 @@ use rustc_index::{bit_set::BitSet, vec::IndexVec}; pub struct ConstDebugInfo; impl<'tcx> MirPass<'tcx> for ConstDebugInfo { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if !tcx.sess.opts.debugging_opts.unsound_mir_opts { - return; - } + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.opts.debugging_opts.unsound_mir_opts && sess.mir_opt_level() > 0 + } + fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) { trace!("running ConstDebugInfo on {:?}", body.source); for (local, constant) in find_optimization_oportunities(body) { @@ -89,7 +89,7 @@ fn find_optimization_oportunities<'tcx>(body: &Body<'tcx>) -> Vec<(Local, Consta eligable_locals } -impl<'tcx> Visitor<'tcx> for LocalUseVisitor { +impl Visitor<'_> for LocalUseVisitor { fn visit_local(&mut self, local: &Local, context: PlaceContext, location: Location) { if context.is_mutating_use() { self.local_mutating_uses[*local] = self.local_mutating_uses[*local].saturating_add(1); diff --git a/compiler/rustc_mir_transform/src/const_goto.rs b/compiler/rustc_mir_transform/src/const_goto.rs index d319fdcaa6..905173b045 100644 --- a/compiler/rustc_mir_transform/src/const_goto.rs +++ b/compiler/rustc_mir_transform/src/const_goto.rs @@ -27,10 +27,11 @@ use super::simplify::{simplify_cfg, simplify_locals}; pub struct ConstGoto; impl<'tcx> MirPass<'tcx> for ConstGoto { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() >= 4 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.mir_opt_level() < 4 { - return; - } trace!("Running ConstGoto on {:?}", body.source); let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); let mut opt_finder = @@ -53,7 +54,7 @@ impl<'tcx> MirPass<'tcx> for ConstGoto { } } -impl<'a, 'tcx> Visitor<'tcx> for ConstGotoOptimizationFinder<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for ConstGotoOptimizationFinder<'_, 'tcx> { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { let _: Option<_> = try { let target = terminator.kind.as_goto()?; @@ -82,20 +83,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ConstGotoOptimizationFinder<'a, 'tcx> { // Now find which value in the Switch matches the const value. let const_value = _const.literal.try_eval_bits(self.tcx, self.param_env, switch_ty)?; - let found_value_idx_option = targets - .iter() - .enumerate() - .find(|(_, (value, _))| const_value == *value) - .map(|(idx, _)| idx); - - let target_to_use_in_goto = - if let Some(found_value_idx) = found_value_idx_option { - targets.iter().nth(found_value_idx).unwrap().1 - } else { - // If we did not find the const value in values, it must be the otherwise case - targets.otherwise() - }; - + let target_to_use_in_goto = targets.target_for_value(const_value); self.optimizations.push(OptimizationToApply { bb_with_goto: location.block, target_to_use_in_goto, diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 63c637af5c..e3ff6ad454 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -62,6 +62,13 @@ macro_rules! throw_machine_stop_str { pub struct ConstProp; impl<'tcx> MirPass<'tcx> for ConstProp { + fn is_enabled(&self, _sess: &rustc_session::Session) -> bool { + // FIXME(#70073): Unlike the other passes in "optimizations", this one emits errors, so it + // runs even when MIR optimizations are disabled. We should separate the lint out from the + // transform and move the lint as early in the pipeline as possible. + true + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // will be evaluated by miri and produce its errors there if body.source.promoted.is_some() { @@ -164,7 +171,7 @@ struct ConstPropMachine<'mir, 'tcx> { can_const_prop: IndexVec, } -impl<'mir, 'tcx> ConstPropMachine<'mir, 'tcx> { +impl ConstPropMachine<'_, '_> { fn new( only_propagate_inside_block_locals: BitSet, can_const_prop: IndexVec, @@ -200,7 +207,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> _args: &[OpTy<'tcx>], _ret: Option<(&PlaceTy<'tcx>, BasicBlock)>, _unwind: StackPopUnwind, - ) -> InterpResult<'tcx, Option<&'mir Body<'tcx>>> { + ) -> InterpResult<'tcx, Option<(&'mir Body<'tcx>, ty::Instance<'tcx>)>> { Ok(None) } @@ -232,13 +239,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> throw_machine_stop_str!("pointer arithmetic or comparisons aren't supported in ConstProp") } - fn box_alloc( - _ecx: &mut InterpCx<'mir, 'tcx, Self>, - _dest: &PlaceTy<'tcx>, - ) -> InterpResult<'tcx> { - throw_machine_stop_str!("can't const prop heap allocations") - } - fn access_local( _ecx: &InterpCx<'mir, 'tcx, Self>, frame: &Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>, @@ -301,14 +301,14 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> } #[inline(always)] - fn stack( + fn stack<'a>( ecx: &'a InterpCx<'mir, 'tcx, Self>, ) -> &'a [Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>] { &ecx.machine.stack } #[inline(always)] - fn stack_mut( + fn stack_mut<'a>( ecx: &'a mut InterpCx<'mir, 'tcx, Self>, ) -> &'a mut Vec> { &mut ecx.machine.stack @@ -329,7 +329,7 @@ struct ConstPropagator<'mir, 'tcx> { source_info: Option, } -impl<'mir, 'tcx> LayoutOfHelpers<'tcx> for ConstPropagator<'mir, 'tcx> { +impl<'tcx> LayoutOfHelpers<'tcx> for ConstPropagator<'_, 'tcx> { type LayoutOfResult = Result, LayoutError<'tcx>>; #[inline] @@ -338,21 +338,21 @@ impl<'mir, 'tcx> LayoutOfHelpers<'tcx> for ConstPropagator<'mir, 'tcx> { } } -impl<'mir, 'tcx> HasDataLayout for ConstPropagator<'mir, 'tcx> { +impl HasDataLayout for ConstPropagator<'_, '_> { #[inline] fn data_layout(&self) -> &TargetDataLayout { &self.tcx.data_layout } } -impl<'mir, 'tcx> ty::layout::HasTyCtxt<'tcx> for ConstPropagator<'mir, 'tcx> { +impl<'tcx> ty::layout::HasTyCtxt<'tcx> for ConstPropagator<'_, 'tcx> { #[inline] fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } } -impl<'mir, 'tcx> ty::layout::HasParamEnv<'tcx> for ConstPropagator<'mir, 'tcx> { +impl<'tcx> ty::layout::HasParamEnv<'tcx> for ConstPropagator<'_, 'tcx> { #[inline] fn param_env(&self) -> ty::ParamEnv<'tcx> { self.param_env @@ -406,7 +406,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { Instance::new(def_id, substs), dummy_body, ret.as_ref(), - StackPopCleanup::None { cleanup: false }, + StackPopCleanup::Root { cleanup: false }, ) .expect("failed to push initial stack frame"); @@ -745,62 +745,44 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { rvalue: &Rvalue<'tcx>, place: Place<'tcx>, ) -> Option<()> { - self.use_ecx(|this| { - match rvalue { - Rvalue::BinaryOp(op, box (left, right)) - | Rvalue::CheckedBinaryOp(op, box (left, right)) => { - let l = this.ecx.eval_operand(left, None); - let r = this.ecx.eval_operand(right, None); + self.use_ecx(|this| match rvalue { + Rvalue::BinaryOp(op, box (left, right)) + | Rvalue::CheckedBinaryOp(op, box (left, right)) => { + let l = this.ecx.eval_operand(left, None); + let r = this.ecx.eval_operand(right, None); - let const_arg = match (l, r) { - (Ok(ref x), Err(_)) | (Err(_), Ok(ref x)) => this.ecx.read_immediate(x)?, - (Err(e), Err(_)) => return Err(e), - (Ok(_), Ok(_)) => { - this.ecx.eval_rvalue_into_place(rvalue, place)?; - return Ok(()); - } - }; + let const_arg = match (l, r) { + (Ok(ref x), Err(_)) | (Err(_), Ok(ref x)) => this.ecx.read_immediate(x)?, + (Err(e), Err(_)) => return Err(e), + (Ok(_), Ok(_)) => return this.ecx.eval_rvalue_into_place(rvalue, place), + }; - let arg_value = const_arg.to_scalar()?.to_bits(const_arg.layout.size)?; - let dest = this.ecx.eval_place(place)?; + let arg_value = const_arg.to_scalar()?.to_bits(const_arg.layout.size)?; + let dest = this.ecx.eval_place(place)?; - match op { - BinOp::BitAnd => { - if arg_value == 0 { - this.ecx.write_immediate(*const_arg, &dest)?; - } - } - BinOp::BitOr => { - if arg_value == const_arg.layout.size.truncate(u128::MAX) - || (const_arg.layout.ty.is_bool() && arg_value == 1) - { - this.ecx.write_immediate(*const_arg, &dest)?; - } - } - BinOp::Mul => { - if const_arg.layout.ty.is_integral() && arg_value == 0 { - if let Rvalue::CheckedBinaryOp(_, _) = rvalue { - let val = Immediate::ScalarPair( - const_arg.to_scalar()?.into(), - Scalar::from_bool(false).into(), - ); - this.ecx.write_immediate(val, &dest)?; - } else { - this.ecx.write_immediate(*const_arg, &dest)?; - } - } - } - _ => { - this.ecx.eval_rvalue_into_place(rvalue, place)?; + match op { + BinOp::BitAnd if arg_value == 0 => this.ecx.write_immediate(*const_arg, &dest), + BinOp::BitOr + if arg_value == const_arg.layout.size.truncate(u128::MAX) + || (const_arg.layout.ty.is_bool() && arg_value == 1) => + { + this.ecx.write_immediate(*const_arg, &dest) + } + BinOp::Mul if const_arg.layout.ty.is_integral() && arg_value == 0 => { + if let Rvalue::CheckedBinaryOp(_, _) = rvalue { + let val = Immediate::ScalarPair( + const_arg.to_scalar()?.into(), + Scalar::from_bool(false).into(), + ); + this.ecx.write_immediate(val, &dest) + } else { + this.ecx.write_immediate(*const_arg, &dest) } } - } - _ => { - this.ecx.eval_rvalue_into_place(rvalue, place)?; + _ => this.ecx.eval_rvalue_into_place(rvalue, place), } } - - Ok(()) + _ => this.ecx.eval_rvalue_into_place(rvalue, place), }) } @@ -964,7 +946,7 @@ struct CanConstProp { impl CanConstProp { /// Returns true if `local` can be propagated - fn check( + fn check<'tcx>( tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, body: &Body<'tcx>, @@ -1012,7 +994,7 @@ impl CanConstProp { } } -impl<'tcx> Visitor<'tcx> for CanConstProp { +impl Visitor<'_> for CanConstProp { fn visit_local(&mut self, &local: &Local, context: PlaceContext, _: Location) { use rustc_middle::mir::visit::PlaceContext::*; match context { @@ -1022,6 +1004,7 @@ impl<'tcx> Visitor<'tcx> for CanConstProp { // These are just stores, where the storing is not propagatable, but there may be later // mutations of the same local via `Store` | MutatingUse(MutatingUseContext::Call) + | MutatingUse(MutatingUseContext::AsmOutput) // Actual store that can possibly even propagate a value | MutatingUse(MutatingUseContext::Store) => { if !self.found_assignment.insert(local) { @@ -1052,7 +1035,7 @@ impl<'tcx> Visitor<'tcx> for CanConstProp { // These could be propagated with a smarter analysis or just some careful thinking about // whether they'd be fine right now. - MutatingUse(MutatingUseContext::AsmOutput) + MutatingUse(MutatingUseContext::LlvmAsmOutput) | MutatingUse(MutatingUseContext::Yield) | MutatingUse(MutatingUseContext::Drop) | MutatingUse(MutatingUseContext::Retag) @@ -1071,7 +1054,7 @@ impl<'tcx> Visitor<'tcx> for CanConstProp { } } -impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { +impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } diff --git a/compiler/rustc_mir_transform/src/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs index 513a85b591..c61ee6f7e6 100644 --- a/compiler/rustc_mir_transform/src/coverage/debug.rs +++ b/compiler/rustc_mir_transform/src/coverage/debug.rs @@ -148,7 +148,7 @@ impl DebugOptions { let mut counter_format = ExpressionFormat::default(); if let Ok(env_debug_options) = std::env::var(RUSTC_COVERAGE_DEBUG_OPTIONS) { - for setting_str in env_debug_options.replace(" ", "").replace("-", "_").split(',') { + for setting_str in env_debug_options.replace(' ', "").replace('-', "_").split(',') { let (option, value) = match setting_str.split_once('=') { None => (setting_str, None), Some((k, v)) => (k, Some(v)), @@ -629,7 +629,7 @@ impl UsedExpressions { } /// Generates the MIR pass `CoverageSpan`-specific spanview dump file. -pub(super) fn dump_coverage_spanview( +pub(super) fn dump_coverage_spanview<'tcx>( tcx: TyCtxt<'tcx>, mir_body: &mir::Body<'tcx>, basic_coverage_blocks: &CoverageGraph, @@ -651,7 +651,7 @@ pub(super) fn dump_coverage_spanview( } /// Converts the computed `BasicCoverageBlockData`s into `SpanViewable`s. -fn span_viewables( +fn span_viewables<'tcx>( tcx: TyCtxt<'tcx>, mir_body: &mir::Body<'tcx>, basic_coverage_blocks: &CoverageGraph, @@ -670,7 +670,7 @@ fn span_viewables( } /// Generates the MIR pass coverage-specific graphviz dump file. -pub(super) fn dump_coverage_graphviz( +pub(super) fn dump_coverage_graphviz<'tcx>( tcx: TyCtxt<'tcx>, mir_body: &mir::Body<'tcx>, pass_name: &str, @@ -750,7 +750,7 @@ pub(super) fn dump_coverage_graphviz( .expect("Unexpected error writing BasicCoverageBlock graphviz DOT file"); } -fn bcb_to_string_sections( +fn bcb_to_string_sections<'tcx>( tcx: TyCtxt<'tcx>, mir_body: &mir::Body<'tcx>, debug_counters: &DebugCounters, @@ -817,7 +817,7 @@ fn bcb_to_string_sections( /// Returns a simple string representation of a `TerminatorKind` variant, independent of any /// values it might hold. -pub(super) fn term_type(kind: &TerminatorKind<'tcx>) -> &'static str { +pub(super) fn term_type(kind: &TerminatorKind<'_>) -> &'static str { match kind { TerminatorKind::Goto { .. } => "Goto", TerminatorKind::SwitchInt { .. } => "SwitchInt", diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index d78ad6ce97..a25402a1ff 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -27,7 +27,7 @@ pub(super) struct CoverageGraph { } impl CoverageGraph { - pub fn from_mir(mir_body: &mir::Body<'tcx>) -> Self { + pub fn from_mir(mir_body: &mir::Body<'_>) -> Self { let (bcbs, bb_to_bcb) = Self::compute_basic_coverage_blocks(mir_body); // Pre-transform MIR `BasicBlock` successors and predecessors into the BasicCoverageBlock @@ -74,7 +74,7 @@ impl CoverageGraph { } fn compute_basic_coverage_blocks( - mir_body: &mir::Body<'tcx>, + mir_body: &mir::Body<'_>, ) -> ( IndexVec, IndexVec>, @@ -267,7 +267,7 @@ impl graph::WithSuccessors for CoverageGraph { } } -impl graph::GraphPredecessors<'graph> for CoverageGraph { +impl<'graph> graph::GraphPredecessors<'graph> for CoverageGraph { type Item = BasicCoverageBlock; type Iter = std::iter::Copied>; } diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 6807d02519..b009e2fd0e 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -49,6 +49,10 @@ impl Error { pub struct InstrumentCoverage; impl<'tcx> MirPass<'tcx> for InstrumentCoverage { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.instrument_coverage() + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, mir_body: &mut mir::Body<'tcx>) { let mir_source = mir_body.source; @@ -439,7 +443,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { } fn inject_edge_counter_basic_block( - mir_body: &mut mir::Body<'tcx>, + mir_body: &mut mir::Body<'_>, from_bb: BasicBlock, to_bb: BasicBlock, ) -> BasicBlock { @@ -462,7 +466,7 @@ fn inject_edge_counter_basic_block( } fn inject_statement( - mir_body: &mut mir::Body<'tcx>, + mir_body: &mut mir::Body<'_>, counter_kind: CoverageKind, bb: BasicBlock, some_code_region: Option, @@ -484,7 +488,7 @@ fn inject_statement( } // Non-code expressions are injected into the coverage map, without generating executable code. -fn inject_intermediate_expression(mir_body: &mut mir::Body<'tcx>, expression: CoverageKind) { +fn inject_intermediate_expression(mir_body: &mut mir::Body<'_>, expression: CoverageKind) { debug_assert!(matches!(expression, CoverageKind::Expression { .. })); debug!(" injecting non-code expression {:?}", expression); let inject_in_bb = mir::START_BLOCK; diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index 760f16eae6..1721fb5cde 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -137,7 +137,7 @@ fn coverageinfo<'tcx>(tcx: TyCtxt<'tcx>, instance_def: ty::InstanceDef<'tcx>) -> coverage_visitor.info } -fn covered_file_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option { +fn covered_file_name(tcx: TyCtxt<'_>, def_id: DefId) -> Option { if tcx.is_mir_available(def_id) { let body = mir_body(tcx, def_id); for bb_data in body.basic_blocks().iter() { diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index d13fa0729c..b5356a817f 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -21,7 +21,7 @@ pub(super) enum CoverageStatement { } impl CoverageStatement { - pub fn format(&self, tcx: TyCtxt<'tcx>, mir_body: &'a mir::Body<'tcx>) -> String { + pub fn format<'tcx>(&self, tcx: TyCtxt<'tcx>, mir_body: &mir::Body<'tcx>) -> String { match *self { Self::Statement(bb, span, stmt_index) => { let stmt = &mir_body[bb].statements[stmt_index]; @@ -86,7 +86,7 @@ impl CoverageSpan { } pub fn for_statement( - statement: &Statement<'tcx>, + statement: &Statement<'_>, span: Span, expn_span: Span, bcb: BasicCoverageBlock, @@ -151,18 +151,18 @@ impl CoverageSpan { self.bcb == other.bcb } - pub fn format(&self, tcx: TyCtxt<'tcx>, mir_body: &'a mir::Body<'tcx>) -> String { + pub fn format<'tcx>(&self, tcx: TyCtxt<'tcx>, mir_body: &mir::Body<'tcx>) -> String { format!( "{}\n {}", source_range_no_file(tcx, &self.span), - self.format_coverage_statements(tcx, mir_body).replace("\n", "\n "), + self.format_coverage_statements(tcx, mir_body).replace('\n', "\n "), ) } - pub fn format_coverage_statements( + pub fn format_coverage_statements<'tcx>( &self, tcx: TyCtxt<'tcx>, - mir_body: &'a mir::Body<'tcx>, + mir_body: &mir::Body<'tcx>, ) -> String { let mut sorted_coverage_statements = self.coverage_statements.clone(); sorted_coverage_statements.sort_unstable_by_key(|covstmt| match *covstmt { @@ -329,9 +329,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> { fn mir_to_initial_sorted_coverage_spans(&self) -> Vec { let mut initial_spans = Vec::::with_capacity(self.mir_body.num_nodes() * 2); for (bcb, bcb_data) in self.basic_coverage_blocks.iter_enumerated() { - for coverage_span in self.bcb_to_initial_coverage_spans(bcb, bcb_data) { - initial_spans.push(coverage_span); - } + initial_spans.extend(self.bcb_to_initial_coverage_spans(bcb, bcb_data)); } if initial_spans.is_empty() { @@ -803,7 +801,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> { /// If the MIR `Statement` has a span contributive to computing coverage spans, /// return it; otherwise return `None`. -pub(super) fn filtered_statement_span(statement: &'a Statement<'tcx>) -> Option { +pub(super) fn filtered_statement_span(statement: &Statement<'_>) -> Option { match statement.kind { // These statements have spans that are often outside the scope of the executed source code // for their parent `BasicBlock`. @@ -847,7 +845,7 @@ pub(super) fn filtered_statement_span(statement: &'a Statement<'tcx>) -> Option< /// If the MIR `Terminator` has a span contributive to computing coverage spans, /// return it; otherwise return `None`. -pub(super) fn filtered_terminator_span(terminator: &'a Terminator<'tcx>) -> Option { +pub(super) fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option { match terminator.kind { // These terminators have spans that don't positively contribute to computing a reasonable // span of actually executed source code. (For example, SwitchInt terminators extracted from diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs index 14dd0a8b92..b9c79d4cf2 100644 --- a/compiler/rustc_mir_transform/src/coverage/tests.rs +++ b/compiler/rustc_mir_transform/src/coverage/tests.rs @@ -180,7 +180,7 @@ impl<'tcx> MockBlocks<'tcx> { } } -fn debug_basic_blocks(mir_body: &Body<'tcx>) -> String { +fn debug_basic_blocks<'tcx>(mir_body: &Body<'tcx>) -> String { format!( "{:?}", mir_body @@ -273,7 +273,7 @@ fn print_coverage_graphviz( } /// Create a mock `Body` with a simple flow. -fn goto_switchint() -> Body<'a> { +fn goto_switchint<'a>() -> Body<'a> { let mut blocks = MockBlocks::new(); let start = blocks.call(None); let goto = blocks.goto(Some(start)); @@ -363,7 +363,7 @@ fn test_covgraph_goto_switchint() { } /// Create a mock `Body` with a loop. -fn switchint_then_loop_else_return() -> Body<'a> { +fn switchint_then_loop_else_return<'a>() -> Body<'a> { let mut blocks = MockBlocks::new(); let start = blocks.call(None); let switchint = blocks.switchint(Some(start)); @@ -449,7 +449,7 @@ fn test_covgraph_switchint_then_loop_else_return() { } /// Create a mock `Body` with nested loops. -fn switchint_loop_then_inner_loop_else_break() -> Body<'a> { +fn switchint_loop_then_inner_loop_else_break<'a>() -> Body<'a> { let mut blocks = MockBlocks::new(); let start = blocks.call(None); let switchint = blocks.switchint(Some(start)); diff --git a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs index 8d2413433a..d1977ed49f 100644 --- a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs +++ b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs @@ -15,10 +15,11 @@ use super::simplify::simplify_cfg; pub struct DeduplicateBlocks; impl<'tcx> MirPass<'tcx> for DeduplicateBlocks { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() >= 4 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.mir_opt_level() < 4 { - return; - } debug!("Running DeduplicateBlocks on `{:?}`", body.source); let duplicates = find_duplicates(body); let has_opts_to_apply = !duplicates.is_empty(); @@ -53,7 +54,7 @@ impl<'tcx> MutVisitor<'tcx> for OptApplier<'tcx> { } } -fn find_duplicates<'a, 'tcx>(body: &'a Body<'tcx>) -> FxHashMap { +fn find_duplicates(body: &Body<'_>) -> FxHashMap { let mut duplicates = FxHashMap::default(); let bbs_to_go_through = @@ -101,7 +102,7 @@ struct BasicBlockHashable<'tcx, 'a> { basic_block_data: &'a BasicBlockData<'tcx>, } -impl<'tcx, 'a> Hash for BasicBlockHashable<'tcx, 'a> { +impl Hash for BasicBlockHashable<'_, '_> { fn hash(&self, state: &mut H) { hash_statements(state, self.basic_block_data.statements.iter()); // Note that since we only hash the kind, we lose span information if we deduplicate the blocks @@ -109,9 +110,9 @@ impl<'tcx, 'a> Hash for BasicBlockHashable<'tcx, 'a> { } } -impl<'tcx, 'a> Eq for BasicBlockHashable<'tcx, 'a> {} +impl Eq for BasicBlockHashable<'_, '_> {} -impl<'tcx, 'a> PartialEq for BasicBlockHashable<'tcx, 'a> { +impl PartialEq for BasicBlockHashable<'_, '_> { fn eq(&self, other: &Self) -> bool { self.basic_block_data.statements.len() == other.basic_block_data.statements.len() && &self.basic_block_data.terminator().kind == &other.basic_block_data.terminator().kind @@ -131,7 +132,7 @@ fn hash_statements<'a, 'tcx, H: Hasher>( } } -fn statement_hash<'tcx, H: Hasher>(hasher: &mut H, stmt: &StatementKind<'tcx>) { +fn statement_hash(hasher: &mut H, stmt: &StatementKind<'_>) { match stmt { StatementKind::Assign(box (place, rvalue)) => { place.hash(hasher); @@ -141,14 +142,14 @@ fn statement_hash<'tcx, H: Hasher>(hasher: &mut H, stmt: &StatementKind<'tcx>) { }; } -fn rvalue_hash(hasher: &mut H, rvalue: &Rvalue<'tcx>) { +fn rvalue_hash(hasher: &mut H, rvalue: &Rvalue<'_>) { match rvalue { Rvalue::Use(op) => operand_hash(hasher, op), x => x.hash(hasher), }; } -fn operand_hash(hasher: &mut H, operand: &Operand<'tcx>) { +fn operand_hash(hasher: &mut H, operand: &Operand<'_>) { match operand { Operand::Constant(box Constant { user_ty: _, literal, span: _ }) => literal.hash(hasher), x => x.hash(hasher), @@ -167,7 +168,7 @@ fn statement_eq<'tcx>(lhs: &StatementKind<'tcx>, rhs: &StatementKind<'tcx>) -> b res } -fn rvalue_eq(lhs: &Rvalue<'tcx>, rhs: &Rvalue<'tcx>) -> bool { +fn rvalue_eq<'tcx>(lhs: &Rvalue<'tcx>, rhs: &Rvalue<'tcx>) -> bool { let res = match (lhs, rhs) { (Rvalue::Use(op1), Rvalue::Use(op2)) => operand_eq(op1, op2), (x, y) => x == y, @@ -176,7 +177,7 @@ fn rvalue_eq(lhs: &Rvalue<'tcx>, rhs: &Rvalue<'tcx>) -> bool { res } -fn operand_eq(lhs: &Operand<'tcx>, rhs: &Operand<'tcx>) -> bool { +fn operand_eq<'tcx>(lhs: &Operand<'tcx>, rhs: &Operand<'tcx>) -> bool { let res = match (lhs, rhs) { ( Operand::Constant(box Constant { user_ty: _, literal, span: _ }), diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 790d9243fb..2b382468be 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -124,18 +124,15 @@ const MAX_BLOCKS: usize = 250; pub struct DestinationPropagation; impl<'tcx> MirPass<'tcx> for DestinationPropagation { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - // FIXME(#79191, #82678) - if !tcx.sess.opts.debugging_opts.unsound_mir_opts { - return; - } - + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + // FIXME(#79191, #82678): This is unsound. + // // Only run at mir-opt-level=3 or higher for now (we don't fix up debuginfo and remove // storage statements at the moment). - if tcx.sess.mir_opt_level() < 3 { - return; - } + sess.opts.debugging_opts.unsound_mir_opts && sess.mir_opt_level() >= 3 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let def_id = body.source.def_id(); let candidates = find_candidates(tcx, body); @@ -244,7 +241,7 @@ struct Replacements<'tcx> { kill: BitSet, } -impl Replacements<'tcx> { +impl<'tcx> Replacements<'tcx> { fn new(locals: usize) -> Self { Self { map: IndexVec::from_elem_n(None, locals), kill: BitSet::new_empty(locals) } } @@ -301,7 +298,7 @@ struct Replacer<'tcx> { } impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> { - fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -316,28 +313,6 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> { } } - fn process_projection_elem( - &mut self, - elem: PlaceElem<'tcx>, - _: Location, - ) -> Option> { - match elem { - PlaceElem::Index(local) => { - if let Some(replacement) = self.replacements.for_src(local) { - bug!( - "cannot replace {:?} with {:?} in index projection {:?}", - local, - replacement, - elem, - ); - } else { - None - } - } - _ => None, - } - } - fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) { if let Some(replacement) = self.replacements.for_src(place.local) { // Rebase `place`s projections onto `replacement`'s. @@ -397,7 +372,7 @@ struct Conflicts<'a> { unified_locals: InPlaceUnificationTable, } -impl Conflicts<'a> { +impl<'a> Conflicts<'a> { fn build<'tcx>( tcx: TyCtxt<'tcx>, body: &'_ Body<'tcx>, @@ -646,6 +621,7 @@ impl Conflicts<'a> { options: _, line_spans: _, destination: _, + cleanup: _, } => { // The intended semantics here aren't documented, we just assume that nothing that // could be written to by the assembly may overlap with any other operands. @@ -844,10 +820,7 @@ struct CandidateAssignment<'tcx> { /// comment) and also throw out assignments that involve a local that has its address taken or is /// otherwise ineligible (eg. locals used as array indices are ignored because we cannot propagate /// arbitrary places into array indices). -fn find_candidates<'a, 'tcx>( - tcx: TyCtxt<'tcx>, - body: &'a Body<'tcx>, -) -> Vec> { +fn find_candidates<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> Vec> { let mut visitor = FindAssignments { tcx, body, @@ -867,7 +840,7 @@ struct FindAssignments<'a, 'tcx> { locals_used_as_array_index: BitSet, } -impl<'a, 'tcx> Visitor<'tcx> for FindAssignments<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for FindAssignments<'_, 'tcx> { fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { if let StatementKind::Assign(box ( dest, diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index f191911a6c..ac88060f0d 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -25,16 +25,14 @@ use super::simplify::simplify_cfg; pub struct EarlyOtherwiseBranch; impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { // FIXME(#78496) - if !tcx.sess.opts.debugging_opts.unsound_mir_opts { - return; - } + sess.opts.debugging_opts.unsound_mir_opts && sess.mir_opt_level() >= 3 + } - if tcx.sess.mir_opt_level() < 3 { - return; - } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { trace!("running EarlyOtherwiseBranch on {:?}", body.source); + // we are only interested in this bb if the terminator is a switchInt let bbs_with_switch = body.basic_blocks().iter_enumerated().filter(|(_, bb)| is_switch(bb.terminator())); @@ -169,7 +167,7 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch { } } -fn is_switch<'tcx>(terminator: &Terminator<'tcx>) -> bool { +fn is_switch(terminator: &Terminator<'_>) -> bool { matches!(terminator.kind, TerminatorKind::SwitchInt { .. }) } @@ -210,7 +208,7 @@ struct OptimizationInfo<'tcx> { second_switch_info: SwitchDiscriminantInfo<'tcx>, } -impl<'a, 'tcx> Helper<'a, 'tcx> { +impl<'tcx> Helper<'_, 'tcx> { pub fn go( &self, bb: &BasicBlockData<'tcx>, diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index b9a48197a3..7320b2738a 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -19,6 +19,10 @@ use std::fmt; pub struct ElaborateDrops; impl<'tcx> MirPass<'tcx> for ElaborateDrops { + fn phase_change(&self) -> Option { + Some(MirPhase::DropLowering) + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!("elaborate_drops({:?} @ {:?})", body.source, body.span); @@ -145,13 +149,13 @@ struct Elaborator<'a, 'b, 'tcx> { ctxt: &'a mut ElaborateDropsCtxt<'b, 'tcx>, } -impl<'a, 'b, 'tcx> fmt::Debug for Elaborator<'a, 'b, 'tcx> { +impl fmt::Debug for Elaborator<'_, '_, '_> { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { Ok(()) } } -impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> { +impl<'a, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, '_, 'tcx> { type Path = MovePathIndex; fn patch(&mut self) -> &mut MirPatch<'tcx> { @@ -312,12 +316,12 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { LookupResult::Parent(Some(parent)) => { let (_maybe_live, maybe_dead) = self.init_data.maybe_live_dead(parent); if maybe_dead { - span_bug!( + self.tcx.sess.delay_span_bug( terminator.source_info.span, - "drop of untracked, uninitialized value {:?}, place {:?} ({:?})", - bb, - place, - path + &format!( + "drop of untracked, uninitialized value {:?}, place {:?} ({:?})", + bb, place, path, + ), ); } continue; @@ -364,10 +368,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { bb, ), LookupResult::Parent(..) => { - span_bug!( + self.tcx.sess.delay_span_bug( terminator.source_info.span, - "drop of untracked value {:?}", - bb + &format!("drop of untracked value {:?}", bb), ); } } diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs index 996c158c06..05834b443d 100644 --- a/compiler/rustc_mir_transform/src/function_item_references.rs +++ b/compiler/rustc_mir_transform/src/function_item_references.rs @@ -11,12 +11,12 @@ use rustc_session::lint::builtin::FUNCTION_ITEM_REFERENCES; use rustc_span::{symbol::sym, Span}; use rustc_target::spec::abi::Abi; -use crate::MirPass; +use crate::MirLint; pub struct FunctionItemReferences; -impl<'tcx> MirPass<'tcx> for FunctionItemReferences { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirLint<'tcx> for FunctionItemReferences { + fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let mut checker = FunctionItemRefChecker { tcx, body }; checker.visit_body(&body); } @@ -27,7 +27,7 @@ struct FunctionItemRefChecker<'a, 'tcx> { body: &'a Body<'tcx>, } -impl<'a, 'tcx> Visitor<'tcx> for FunctionItemRefChecker<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for FunctionItemRefChecker<'_, 'tcx> { /// Emits a lint for function reference arguments bound by `fmt::Pointer` or passed to /// `transmute`. This only handles arguments in calls outside macro expansions to avoid double /// counting function references formatted as pointers by macros. @@ -92,7 +92,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FunctionItemRefChecker<'a, 'tcx> { } } -impl<'a, 'tcx> FunctionItemRefChecker<'a, 'tcx> { +impl<'tcx> FunctionItemRefChecker<'_, 'tcx> { /// Emits a lint for function reference arguments bound by `fmt::Pointer` in calls to the /// function defined by `def_id` with the substitutions `substs_ref`. fn check_bound_args( diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index bc72e9d94a..bc9a104e84 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -233,7 +233,7 @@ struct TransformVisitor<'tcx> { new_ret_local: Local, } -impl TransformVisitor<'tcx> { +impl<'tcx> TransformVisitor<'tcx> { // Make a GeneratorState variant assignment. `core::ops::GeneratorState` only has single // element tuple variants, so we can just write to the downcasted first field and then set the // discriminant to the appropriate variant. @@ -243,7 +243,7 @@ impl TransformVisitor<'tcx> { val: Operand<'tcx>, source_info: SourceInfo, ) -> impl Iterator> { - let kind = AggregateKind::Adt(self.state_adt_ref, idx, self.state_substs, None, None); + let kind = AggregateKind::Adt(self.state_adt_ref.did, idx, self.state_substs, None, None); assert_eq!(self.state_adt_ref.variants[idx].fields.len(), 1); let ty = self .tcx @@ -295,7 +295,7 @@ impl TransformVisitor<'tcx> { } } -impl MutVisitor<'tcx> for TransformVisitor<'tcx> { +impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -446,7 +446,7 @@ struct LivenessInfo { storage_liveness: IndexVec>>, } -fn locals_live_across_suspend_points( +fn locals_live_across_suspend_points<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, always_live_locals: &storage::AlwaysLiveLocals, @@ -613,7 +613,7 @@ impl ops::Deref for GeneratorSavedLocals { /// time. Generates a bitset for every local of all the other locals that may be /// StorageLive simultaneously with that local. This is used in the layout /// computation; see `GeneratorLayout` for more. -fn compute_storage_conflicts( +fn compute_storage_conflicts<'mir, 'tcx>( body: &'mir Body<'tcx>, saved_locals: &GeneratorSavedLocals, always_live_locals: storage::AlwaysLiveLocals, @@ -672,7 +672,9 @@ struct StorageConflictVisitor<'mir, 'tcx, 's> { local_conflicts: BitMatrix, } -impl rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx> for StorageConflictVisitor<'mir, 'tcx, '_> { +impl<'mir, 'tcx> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx> + for StorageConflictVisitor<'mir, 'tcx, '_> +{ type FlowState = BitSet; fn visit_statement_before_primary_effect( @@ -694,7 +696,7 @@ impl rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx> for StorageConflictVisitor<' } } -impl<'body, 'tcx, 's> StorageConflictVisitor<'body, 'tcx, 's> { +impl StorageConflictVisitor<'_, '_, '_> { fn apply_state(&mut self, flow_state: &BitSet, loc: Location) { // Ignore unreachable blocks. if self.body.basic_blocks()[loc.block].terminator().kind == TerminatorKind::Unreachable { @@ -1232,6 +1234,10 @@ fn create_cases<'tcx>( } impl<'tcx> MirPass<'tcx> for StateTransform { + fn phase_change(&self) -> Option { + Some(MirPhase::GeneratorLowering) + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let yield_ty = if let Some(yield_ty) = body.yield_ty() { yield_ty @@ -1394,7 +1400,7 @@ impl EnsureGeneratorFieldAssignmentsNeverAlias<'_> { self.saved_locals.get(place.local) } - fn check_assigned_place(&mut self, place: Place<'tcx>, f: impl FnOnce(&mut Self)) { + fn check_assigned_place(&mut self, place: Place<'_>, f: impl FnOnce(&mut Self)) { if let Some(assigned_local) = self.saved_local_for_direct_place(place) { assert!(self.assigned_local.is_none(), "`check_assigned_place` must not recurse"); @@ -1405,7 +1411,7 @@ impl EnsureGeneratorFieldAssignmentsNeverAlias<'_> { } } -impl Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> { +impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> { fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) { let lhs = match self.assigned_local { Some(l) => l, diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 84a1e3fb60..e1f30fef44 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -37,21 +37,16 @@ struct CallSite<'tcx> { source_info: SourceInfo, } -/// Returns true if MIR inlining is enabled in the current compilation session. -crate fn is_enabled(tcx: TyCtxt<'_>) -> bool { - if let Some(enabled) = tcx.sess.opts.debugging_opts.inline_mir { - return enabled; - } - - tcx.sess.mir_opt_level() >= 3 -} - impl<'tcx> MirPass<'tcx> for Inline { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if !is_enabled(tcx) { - return; + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + if let Some(enabled) = sess.opts.debugging_opts.inline_mir { + return enabled; } + sess.opts.mir_opt_level() >= 3 + } + + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let span = trace_span!("inline", body = %tcx.def_path_str(body.source.def_id())); let _guard = span.enter(); if inline(tcx, body) { @@ -62,7 +57,7 @@ impl<'tcx> MirPass<'tcx> for Inline { } } -fn inline(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { +fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { let def_id = body.source.def_id(); let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); @@ -73,6 +68,12 @@ fn inline(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { if body.source.promoted.is_some() { return false; } + // Avoid inlining into generators, since their `optimized_mir` is used for layout computation, + // which can create a cycle, even when no attempt is made to inline the function in the other + // direction. + if body.generator.is_some() { + return false; + } let mut this = Inliner { tcx, @@ -100,7 +101,7 @@ struct Inliner<'tcx> { changed: bool, } -impl Inliner<'tcx> { +impl<'tcx> Inliner<'tcx> { fn process_blocks(&mut self, caller_body: &mut Body<'tcx>, blocks: Range) { for bb in blocks { let bb_data = &caller_body[bb]; @@ -207,19 +208,12 @@ impl Inliner<'tcx> { if let Some(callee_def_id) = callee.def_id().as_local() { let callee_hir_id = self.tcx.hir().local_def_id_to_hir_id(callee_def_id); - // Avoid inlining into generators, - // since their `optimized_mir` is used for layout computation, which can - // create a cycle, even when no attempt is made to inline the function - // in the other direction. - if caller_body.generator.is_some() { - return Err("local generator (query cycle avoidance)"); - } - // Avoid a cycle here by only using `instance_mir` only if we have // a lower `HirId` than the callee. This ensures that the callee will // not inline us. This trick only works without incremental compilation. // So don't do it if that is enabled. - if !self.tcx.dep_graph.is_fully_enabled() && self.hir_id < callee_hir_id { + if !self.tcx.dep_graph.is_fully_enabled() && self.hir_id.index() < callee_hir_id.index() + { return Ok(()); } @@ -441,6 +435,13 @@ impl Inliner<'tcx> { } } TerminatorKind::Resume => cost += RESUME_PENALTY, + TerminatorKind::InlineAsm { cleanup, .. } => { + cost += INSTR_COST; + + if cleanup.is_some() { + cost += LANDINGPAD_PENALTY; + } + } _ => cost += INSTR_COST, } @@ -784,7 +785,7 @@ struct Integrator<'a, 'tcx> { always_live_locals: BitSet, } -impl<'a, 'tcx> Integrator<'a, 'tcx> { +impl Integrator<'_, '_> { fn map_local(&self, local: Local) -> Local { let new = if local == RETURN_PLACE { self.destination.local @@ -813,7 +814,7 @@ impl<'a, 'tcx> Integrator<'a, 'tcx> { } } -impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { +impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -954,9 +955,13 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { { bug!("False unwinds should have been removed before inlining") } - TerminatorKind::InlineAsm { ref mut destination, .. } => { + TerminatorKind::InlineAsm { ref mut destination, ref mut cleanup, .. } => { if let Some(ref mut tgt) = *destination { *tgt = self.map_block(*tgt); + } else if !self.in_cleanup_block { + // Unless this inline asm is in a cleanup block, add an unwind edge to + // the original call's cleanup block + *cleanup = self.cleanup_block; } } } diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index 385394ba67..747e760a18 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -10,7 +10,7 @@ use rustc_session::Limit; // FIXME: check whether it is cheaper to precompute the entire call graph instead of invoking // this query riddiculously often. #[instrument(level = "debug", skip(tcx, root, target))] -crate fn mir_callgraph_reachable( +crate fn mir_callgraph_reachable<'tcx>( tcx: TyCtxt<'tcx>, (root, target): (ty::Instance<'tcx>, LocalDefId), ) -> bool { @@ -33,7 +33,7 @@ crate fn mir_callgraph_reachable( level = "debug", skip(tcx, param_env, target, stack, seen, recursion_limiter, caller, recursion_limit) )] - fn process( + fn process<'tcx>( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, caller: ty::Instance<'tcx>, diff --git a/compiler/rustc_mir_transform/src/instcombine.rs b/compiler/rustc_mir_transform/src/instcombine.rs index e15a69c95a..792ac68671 100644 --- a/compiler/rustc_mir_transform/src/instcombine.rs +++ b/compiler/rustc_mir_transform/src/instcombine.rs @@ -11,6 +11,10 @@ use rustc_middle::ty::{self, TyCtxt}; pub struct InstCombine; impl<'tcx> MirPass<'tcx> for InstCombine { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() > 0 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); let ctx = InstCombineContext { tcx, local_decls }; @@ -34,7 +38,7 @@ struct InstCombineContext<'tcx, 'a> { local_decls: &'a LocalDecls<'tcx>, } -impl<'tcx, 'a> InstCombineContext<'tcx, 'a> { +impl<'tcx> InstCombineContext<'tcx, '_> { fn should_combine(&self, source_info: &SourceInfo, rvalue: &Rvalue<'tcx>) -> bool { self.tcx.consider_optimizing(|| { format!("InstCombine - Rvalue: {:?} SourceInfo: {:?}", rvalue, source_info) diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index f9ef314627..638baa0b8d 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -1,8 +1,6 @@ #![feature(box_patterns)] #![feature(box_syntax)] #![feature(crate_visibility_modifier)] -#![feature(in_band_lifetimes)] -#![feature(iter_zip)] #![feature(let_else)] #![feature(map_try_insert)] #![feature(min_specialization)] @@ -27,11 +25,16 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_index::vec::IndexVec; use rustc_middle::mir::visit::Visitor as _; -use rustc_middle::mir::{dump_mir, traversal, Body, ConstQualifs, MirPhase, Promoted}; +use rustc_middle::mir::{traversal, Body, ConstQualifs, MirPass, MirPhase, Promoted}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; use rustc_span::{Span, Symbol}; +#[macro_use] +mod pass_manager; + +use pass_manager::{self as pm, Lint, MirLint, WithMinOptLevel}; + mod abort_unwinding_calls; mod add_call_guards; mod add_moves_for_packed_drops; @@ -56,12 +59,15 @@ mod inline; mod instcombine; mod lower_intrinsics; mod lower_slice_len; +mod marker; mod match_branches; mod multiple_return_terminators; mod normalize_array_len; mod nrvo; +mod remove_false_edges; mod remove_noop_landing_pads; mod remove_storage_markers; +mod remove_uninit_drops; mod remove_unneeded_drops; mod remove_zsts; mod required_consts; @@ -75,10 +81,9 @@ mod simplify_try; mod uninhabited_enum_branching; mod unreachable_prop; -use rustc_const_eval::transform::check_consts; +use rustc_const_eval::transform::check_consts::{self, ConstCx}; use rustc_const_eval::transform::promote_consts; use rustc_const_eval::transform::validate; -pub use rustc_const_eval::transform::MirPass; use rustc_mir_dataflow::rustc_peek; pub fn provide(providers: &mut Providers) { @@ -143,7 +148,7 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxHashSet { tcx: TyCtxt<'tcx>, set: &'a mut FxHashSet, } - impl<'a, 'tcx> Visitor<'tcx> for GatherCtors<'a, 'tcx> { + impl<'tcx> Visitor<'tcx> for GatherCtors<'_, 'tcx> { fn visit_variant_data( &mut self, v: &'tcx hir::VariantData<'tcx>, @@ -167,66 +172,6 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxHashSet { set } -fn run_passes( - tcx: TyCtxt<'tcx>, - body: &mut Body<'tcx>, - mir_phase: MirPhase, - passes: &[&[&dyn MirPass<'tcx>]], -) { - let phase_index = mir_phase.phase_index(); - let validate = tcx.sess.opts.debugging_opts.validate_mir; - - if body.phase >= mir_phase { - return; - } - - if validate { - validate::Validator { when: format!("input to phase {:?}", mir_phase), mir_phase } - .run_pass(tcx, body); - } - - let mut index = 0; - let mut run_pass = |pass: &dyn MirPass<'tcx>| { - let run_hooks = |body: &_, index, is_after| { - let disambiguator = if is_after { "after" } else { "before" }; - dump_mir( - tcx, - Some(&format_args!("{:03}-{:03}", phase_index, index)), - &pass.name(), - &disambiguator, - body, - |_, _| Ok(()), - ); - }; - run_hooks(body, index, false); - pass.run_pass(tcx, body); - run_hooks(body, index, true); - - if validate { - validate::Validator { - when: format!("after {} in phase {:?}", pass.name(), mir_phase), - mir_phase, - } - .run_pass(tcx, body); - } - - index += 1; - }; - - for pass_group in passes { - for pass in *pass_group { - run_pass(*pass); - } - } - - body.phase = mir_phase; - - if mir_phase == MirPhase::Optimization { - validate::Validator { when: format!("end of phase {:?}", mir_phase), mir_phase } - .run_pass(tcx, body); - } -} - fn mir_const_qualif(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> ConstQualifs { let const_kind = tcx.hir().body_const_context(def.did); @@ -278,25 +223,25 @@ fn mir_const<'tcx>( rustc_middle::mir::dump_mir(tcx, None, "mir_map", &0, &body, |_, _| Ok(())); - run_passes( + pm::run_passes( tcx, &mut body, - MirPhase::Const, - &[&[ + &[ // MIR-level lints. - &check_packed_ref::CheckPackedRef, - &check_const_item_mutation::CheckConstItemMutation, - &function_item_references::FunctionItemReferences, + &Lint(check_packed_ref::CheckPackedRef), + &Lint(check_const_item_mutation::CheckConstItemMutation), + &Lint(function_item_references::FunctionItemReferences), // What we need to do constant evaluation. &simplify::SimplifyCfg::new("initial"), - &rustc_peek::SanityCheck, - ]], + &rustc_peek::SanityCheck, // Just a lint + &marker::PhaseChange(MirPhase::Const), + ], ); tcx.alloc_steal_mir(body) } /// Compute the main MIR body and the list of MIR bodies of the promoteds. -fn mir_promoted( +fn mir_promoted<'tcx>( tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam, ) -> (&'tcx Steal>, &'tcx Steal>>) { @@ -317,17 +262,17 @@ fn mir_promoted( } body.required_consts = required_consts; + // What we need to run borrowck etc. let promote_pass = promote_consts::PromoteTemps::default(); - let promote: &[&dyn MirPass<'tcx>] = &[ - // What we need to run borrowck etc. - &promote_pass, - &simplify::SimplifyCfg::new("promote-consts"), - ]; - - let opt_coverage: &[&dyn MirPass<'tcx>] = - if tcx.sess.instrument_coverage() { &[&coverage::InstrumentCoverage] } else { &[] }; - - run_passes(tcx, &mut body, MirPhase::ConstPromotion, &[promote, opt_coverage]); + pm::run_passes( + tcx, + &mut body, + &[ + &promote_pass, + &simplify::SimplifyCfg::new("promote-consts"), + &coverage::InstrumentCoverage, + ], + ); let promoted = promote_pass.promoted_fragments.into_inner(); (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted)) @@ -389,19 +334,10 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) - // Technically we want to not run on regular const items, but oli-obk doesn't know how to // conveniently detect that at this point without looking at the HIR. hir::ConstContext::Const => { - #[rustfmt::skip] - let optimizations: &[&dyn MirPass<'_>] = &[ - &const_prop::ConstProp, - ]; - - #[rustfmt::skip] - run_passes( + pm::run_passes( tcx, &mut body, - MirPhase::Optimization, - &[ - optimizations, - ], + &[&const_prop::ConstProp, &marker::PhaseChange(MirPhase::Optimization)], ); } } @@ -437,7 +373,7 @@ fn mir_drops_elaborated_and_const_checked<'tcx>( let def = ty::WithOptConstParam::unknown(did); // Do not compute the mir call graph without said call graph actually being used. - if inline::is_enabled(tcx) { + if inline::Inline.is_enabled(&tcx.sess) { let _ = tcx.mir_inliner_callees(ty::InstanceDef::Item(def)); } } @@ -445,8 +381,24 @@ fn mir_drops_elaborated_and_const_checked<'tcx>( let (body, _) = tcx.mir_promoted(def); let mut body = body.steal(); + // IMPORTANT + pm::run_passes(tcx, &mut body, &[&remove_false_edges::RemoveFalseEdges]); + + // Do a little drop elaboration before const-checking if `const_precise_live_drops` is enabled. + if check_consts::post_drop_elaboration::checking_enabled(&ConstCx::new(tcx, &body)) { + pm::run_passes( + tcx, + &mut body, + &[ + &simplify::SimplifyCfg::new("remove-false-edges"), + &remove_uninit_drops::RemoveUninitDrops, + ], + ); + check_consts::post_drop_elaboration::check_live_drops(tcx, &body); // FIXME: make this a MIR lint + } + run_post_borrowck_cleanup_passes(tcx, &mut body); - check_consts::post_drop_elaboration::check_live_drops(tcx, &body); + assert!(body.phase == MirPhase::DropLowering); tcx.alloc_steal_mir(body) } @@ -456,7 +408,7 @@ fn run_post_borrowck_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tc let post_borrowck_cleanup: &[&dyn MirPass<'tcx>] = &[ // Remove all things only needed by analysis - &simplify_branches::SimplifyBranches::new("initial"), + &simplify_branches::SimplifyConstCondition::new("initial"), &remove_noop_landing_pads::RemoveNoopLandingPads, &cleanup_post_borrowck::CleanupNonCodegenStatements, &simplify::SimplifyCfg::new("early-opt"), @@ -480,95 +432,72 @@ fn run_post_borrowck_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tc &deaggregator::Deaggregator, ]; - run_passes(tcx, body, MirPhase::DropLowering, &[post_borrowck_cleanup]); + pm::run_passes(tcx, body, post_borrowck_cleanup); } fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let mir_opt_level = tcx.sess.mir_opt_level(); + fn o1(x: T) -> WithMinOptLevel { + WithMinOptLevel(1, x) + } // Lowering generator control-flow and variables has to happen before we do anything else // to them. We run some optimizations before that, because they may be harder to do on the state // machine than on MIR with async primitives. - let optimizations_with_generators: &[&dyn MirPass<'tcx>] = &[ - &reveal_all::RevealAll, // has to be done before inlining, since inlined code is in RevealAll mode. - &lower_slice_len::LowerSliceLenCalls, // has to be done before inlining, otherwise actual call will be almost always inlined. Also simple, so can just do first - &normalize_array_len::NormalizeArrayLen, // has to run after `slice::len` lowering - &unreachable_prop::UnreachablePropagation, - &uninhabited_enum_branching::UninhabitedEnumBranching, - &simplify::SimplifyCfg::new("after-uninhabited-enum-branching"), - &inline::Inline, - &generator::StateTransform, - ]; - - // Even if we don't do optimizations, we still have to lower generators for codegen. - let no_optimizations_with_generators: &[&dyn MirPass<'tcx>] = &[&generator::StateTransform]; - - // The main optimizations that we do on MIR. - let optimizations: &[&dyn MirPass<'tcx>] = &[ - &remove_storage_markers::RemoveStorageMarkers, - &remove_zsts::RemoveZsts, - &const_goto::ConstGoto, - &remove_unneeded_drops::RemoveUnneededDrops, - &match_branches::MatchBranchSimplification, - // inst combine is after MatchBranchSimplification to clean up Ne(_1, false) - &multiple_return_terminators::MultipleReturnTerminators, - &instcombine::InstCombine, - &separate_const_switch::SeparateConstSwitch, - &const_prop::ConstProp, - &simplify_branches::SimplifyBranches::new("after-const-prop"), - &early_otherwise_branch::EarlyOtherwiseBranch, - &simplify_comparison_integral::SimplifyComparisonIntegral, - &simplify_try::SimplifyArmIdentity, - &simplify_try::SimplifyBranchSame, - &dest_prop::DestinationPropagation, - &simplify_branches::SimplifyBranches::new("final"), - &remove_noop_landing_pads::RemoveNoopLandingPads, - &simplify::SimplifyCfg::new("final"), - &nrvo::RenameReturnPlace, - &const_debuginfo::ConstDebugInfo, - &simplify::SimplifyLocals, - &multiple_return_terminators::MultipleReturnTerminators, - &deduplicate_blocks::DeduplicateBlocks, - ]; - - // Optimizations to run even if mir optimizations have been disabled. - let no_optimizations: &[&dyn MirPass<'tcx>] = &[ - // FIXME(#70073): This pass is responsible for both optimization as well as some lints. - &const_prop::ConstProp, - ]; - - // Some cleanup necessary at least for LLVM and potentially other codegen backends. - let pre_codegen_cleanup: &[&dyn MirPass<'tcx>] = &[ - &add_call_guards::CriticalCallEdges, - // Dump the end result for testing and debugging purposes. - &dump_mir::Marker("PreCodegen"), - ]; - - // End of pass declarations, now actually run the passes. - // Generator Lowering - #[rustfmt::skip] - run_passes( + pm::run_passes( tcx, body, - MirPhase::GeneratorLowering, &[ - if mir_opt_level > 0 { - optimizations_with_generators - } else { - no_optimizations_with_generators - } + &reveal_all::RevealAll, // has to be done before inlining, since inlined code is in RevealAll mode. + &lower_slice_len::LowerSliceLenCalls, // has to be done before inlining, otherwise actual call will be almost always inlined. Also simple, so can just do first + &normalize_array_len::NormalizeArrayLen, // has to run after `slice::len` lowering + &unreachable_prop::UnreachablePropagation, + &uninhabited_enum_branching::UninhabitedEnumBranching, + &o1(simplify::SimplifyCfg::new("after-uninhabited-enum-branching")), + &inline::Inline, + &generator::StateTransform, ], ); - // Main optimization passes - #[rustfmt::skip] - run_passes( + assert!(body.phase == MirPhase::GeneratorLowering); + + // The main optimizations that we do on MIR. + pm::run_passes( tcx, body, - MirPhase::Optimization, &[ - if mir_opt_level > 0 { optimizations } else { no_optimizations }, - pre_codegen_cleanup, + &remove_storage_markers::RemoveStorageMarkers, + &remove_zsts::RemoveZsts, + &const_goto::ConstGoto, + &remove_unneeded_drops::RemoveUnneededDrops, + &match_branches::MatchBranchSimplification, + // inst combine is after MatchBranchSimplification to clean up Ne(_1, false) + &multiple_return_terminators::MultipleReturnTerminators, + &instcombine::InstCombine, + &separate_const_switch::SeparateConstSwitch, + // + // FIXME(#70073): This pass is responsible for both optimization as well as some lints. + &const_prop::ConstProp, + // + // Const-prop runs unconditionally, but doesn't mutate the MIR at mir-opt-level=0. + &o1(simplify_branches::SimplifyConstCondition::new("after-const-prop")), + &early_otherwise_branch::EarlyOtherwiseBranch, + &simplify_comparison_integral::SimplifyComparisonIntegral, + &simplify_try::SimplifyArmIdentity, + &simplify_try::SimplifyBranchSame, + &dest_prop::DestinationPropagation, + &o1(simplify_branches::SimplifyConstCondition::new("final")), + &o1(remove_noop_landing_pads::RemoveNoopLandingPads), + &o1(simplify::SimplifyCfg::new("final")), + &nrvo::RenameReturnPlace, + &const_debuginfo::ConstDebugInfo, + &simplify::SimplifyLocals, + &multiple_return_terminators::MultipleReturnTerminators, + &deduplicate_blocks::DeduplicateBlocks, + // Some cleanup necessary at least for LLVM and potentially other codegen backends. + &add_call_guards::CriticalCallEdges, + &marker::PhaseChange(MirPhase::Optimization), + // Dump the end result for testing and debugging purposes. + &dump_mir::Marker("PreCodegen"), ], ); } diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index 5848163af7..4c4497ad62 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -135,7 +135,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { } } -fn resolve_rust_intrinsic( +fn resolve_rust_intrinsic<'tcx>( tcx: TyCtxt<'tcx>, func_ty: Ty<'tcx>, ) -> Option<(Symbol, SubstsRef<'tcx>)> { @@ -148,7 +148,7 @@ fn resolve_rust_intrinsic( None } -fn validate_simd_shuffle(tcx: TyCtxt<'tcx>, args: &[Operand<'tcx>], span: Span) { +fn validate_simd_shuffle<'tcx>(tcx: TyCtxt<'tcx>, args: &[Operand<'tcx>], span: Span) { match &args[2] { Operand::Constant(_) => {} // all good _ => { diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs index 822a372d8c..c829774487 100644 --- a/compiler/rustc_mir_transform/src/lower_slice_len.rs +++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs @@ -10,6 +10,10 @@ use rustc_middle::ty::{self, TyCtxt}; pub struct LowerSliceLenCalls; impl<'tcx> MirPass<'tcx> for LowerSliceLenCalls { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.opts.mir_opt_level() > 0 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { lower_slice_len_calls(tcx, body) } diff --git a/compiler/rustc_mir_transform/src/marker.rs b/compiler/rustc_mir_transform/src/marker.rs new file mode 100644 index 0000000000..06819fc1d3 --- /dev/null +++ b/compiler/rustc_mir_transform/src/marker.rs @@ -0,0 +1,20 @@ +use std::borrow::Cow; + +use crate::MirPass; +use rustc_middle::mir::{Body, MirPhase}; +use rustc_middle::ty::TyCtxt; + +/// Changes the MIR phase without changing the MIR itself. +pub struct PhaseChange(pub MirPhase); + +impl<'tcx> MirPass<'tcx> for PhaseChange { + fn phase_change(&self) -> Option { + Some(self.0) + } + + fn name(&self) -> Cow<'_, str> { + Cow::from(format!("PhaseChange-{:?}", self.0)) + } + + fn run_pass(&self, _: TyCtxt<'tcx>, _body: &mut Body<'tcx>) {} +} diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index c618abe9d0..3c14a324c3 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -40,11 +40,11 @@ pub struct MatchBranchSimplification; /// ``` impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.mir_opt_level() < 3 { - return; - } + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() >= 3 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let def_id = body.source.def_id(); let param_env = tcx.param_env(def_id); diff --git a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs index b614917a88..22b6dead99 100644 --- a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs +++ b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs @@ -9,11 +9,11 @@ use rustc_middle::ty::TyCtxt; pub struct MultipleReturnTerminators; impl<'tcx> MirPass<'tcx> for MultipleReturnTerminators { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.mir_opt_level() < 4 { - return; - } + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() >= 4 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // find basic blocks with no statement and a return terminator let mut bbs_simple_returns = BitSet::new_empty(body.basic_blocks().len()); let def_id = body.source.def_id(); diff --git a/compiler/rustc_mir_transform/src/normalize_array_len.rs b/compiler/rustc_mir_transform/src/normalize_array_len.rs index a04a0b5153..e4ac57ac92 100644 --- a/compiler/rustc_mir_transform/src/normalize_array_len.rs +++ b/compiler/rustc_mir_transform/src/normalize_array_len.rs @@ -14,11 +14,11 @@ const MAX_NUM_LOCALS: usize = 3000; pub struct NormalizeArrayLen; impl<'tcx> MirPass<'tcx> for NormalizeArrayLen { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.mir_opt_level() < 4 { - return; - } + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() >= 4 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // early returns for edge cases of highly unrolled functions if body.basic_blocks().len() > MAX_NUM_BLOCKS { return; @@ -85,7 +85,7 @@ struct Patcher<'a, 'tcx> { statement_idx: usize, } -impl<'a, 'tcx> Patcher<'a, 'tcx> { +impl<'tcx> Patcher<'_, 'tcx> { fn patch_expand_statement( &mut self, statement: &mut Statement<'tcx>, diff --git a/compiler/rustc_mir_transform/src/nrvo.rs b/compiler/rustc_mir_transform/src/nrvo.rs index 3ac4e77cf9..797f7ee268 100644 --- a/compiler/rustc_mir_transform/src/nrvo.rs +++ b/compiler/rustc_mir_transform/src/nrvo.rs @@ -33,11 +33,11 @@ use crate::MirPass; pub struct RenameReturnPlace; impl<'tcx> MirPass<'tcx> for RenameReturnPlace { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) { - if tcx.sess.mir_opt_level() == 0 { - return; - } + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() > 0 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) { let def_id = body.source.def_id(); let returned_local = match local_eligible_for_nrvo(body) { Some(l) => l, @@ -165,7 +165,7 @@ struct RenameToReturnPlace<'tcx> { } /// Replaces all uses of `self.to_rename` with `_0`. -impl MutVisitor<'tcx> for RenameToReturnPlace<'tcx> { +impl<'tcx> MutVisitor<'tcx> for RenameToReturnPlace<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -221,7 +221,7 @@ impl IsReturnPlaceRead { } } -impl Visitor<'tcx> for IsReturnPlaceRead { +impl<'tcx> Visitor<'tcx> for IsReturnPlaceRead { fn visit_local(&mut self, &l: &Local, ctxt: PlaceContext, _: Location) { if l == mir::RETURN_PLACE && ctxt.is_use() && !ctxt.is_place_assignment() { self.0 = true; diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs new file mode 100644 index 0000000000..8725eae870 --- /dev/null +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -0,0 +1,144 @@ +use std::borrow::Cow; + +use rustc_middle::mir::{self, Body, MirPhase}; +use rustc_middle::ty::TyCtxt; +use rustc_session::Session; + +use crate::{validate, MirPass}; + +/// Just like `MirPass`, except it cannot mutate `Body`. +pub trait MirLint<'tcx> { + fn name(&self) -> Cow<'_, str> { + let name = std::any::type_name::(); + if let Some(tail) = name.rfind(':') { + Cow::from(&name[tail + 1..]) + } else { + Cow::from(name) + } + } + + fn is_enabled(&self, _sess: &Session) -> bool { + true + } + + fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>); +} + +/// An adapter for `MirLint`s that implements `MirPass`. +#[derive(Debug, Clone)] +pub struct Lint(pub T); + +impl<'tcx, T> MirPass<'tcx> for Lint +where + T: MirLint<'tcx>, +{ + fn name(&self) -> Cow<'_, str> { + self.0.name() + } + + fn is_enabled(&self, sess: &Session) -> bool { + self.0.is_enabled(sess) + } + + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + self.0.run_lint(tcx, body) + } + + fn is_mir_dump_enabled(&self) -> bool { + false + } +} + +pub struct WithMinOptLevel(pub u32, pub T); + +impl<'tcx, T> MirPass<'tcx> for WithMinOptLevel +where + T: MirPass<'tcx>, +{ + fn name(&self) -> Cow<'_, str> { + self.1.name() + } + + fn is_enabled(&self, sess: &Session) -> bool { + sess.mir_opt_level() >= self.0 as usize + } + + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + self.1.run_pass(tcx, body) + } + + fn phase_change(&self) -> Option { + self.1.phase_change() + } +} + +pub fn run_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, passes: &[&dyn MirPass<'tcx>]) { + let start_phase = body.phase; + let mut cnt = 0; + + let validate = tcx.sess.opts.debugging_opts.validate_mir; + + if validate { + validate_body(tcx, body, format!("start of phase transition from {:?}", start_phase)); + } + + for pass in passes { + if !pass.is_enabled(&tcx.sess) { + continue; + } + + let name = pass.name(); + let dump_enabled = pass.is_mir_dump_enabled(); + + if dump_enabled { + dump_mir(tcx, body, start_phase, &name, cnt, false); + } + + pass.run_pass(tcx, body); + + if dump_enabled { + dump_mir(tcx, body, start_phase, &name, cnt, true); + cnt += 1; + } + + if let Some(new_phase) = pass.phase_change() { + if body.phase >= new_phase { + panic!("Invalid MIR phase transition from {:?} to {:?}", body.phase, new_phase); + } + + body.phase = new_phase; + } + + if validate { + validate_body(tcx, body, format!("after pass {}", pass.name())); + } + } + + if validate || body.phase == MirPhase::Optimization { + validate_body(tcx, body, format!("end of phase transition to {:?}", body.phase)); + } +} + +pub fn validate_body<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when: String) { + validate::Validator { when, mir_phase: body.phase }.run_pass(tcx, body); +} + +pub fn dump_mir<'tcx>( + tcx: TyCtxt<'tcx>, + body: &Body<'tcx>, + phase: MirPhase, + pass_name: &str, + cnt: usize, + is_after: bool, +) { + let phase_index = phase as u32; + + mir::dump_mir( + tcx, + Some(&format_args!("{:03}-{:03}", phase_index, cnt)), + pass_name, + if is_after { &"after" } else { &"before" }, + body, + |_, _| Ok(()), + ); +} diff --git a/compiler/rustc_mir_transform/src/remove_false_edges.rs b/compiler/rustc_mir_transform/src/remove_false_edges.rs new file mode 100644 index 0000000000..71f5ccf7e2 --- /dev/null +++ b/compiler/rustc_mir_transform/src/remove_false_edges.rs @@ -0,0 +1,29 @@ +use rustc_middle::mir::{Body, TerminatorKind}; +use rustc_middle::ty::TyCtxt; + +use crate::MirPass; + +/// Removes `FalseEdge` and `FalseUnwind` terminators from the MIR. +/// +/// These are only needed for borrow checking, and can be removed afterwards. +/// +/// FIXME: This should probably have its own MIR phase. +pub struct RemoveFalseEdges; + +impl<'tcx> MirPass<'tcx> for RemoveFalseEdges { + fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + for block in body.basic_blocks_mut() { + let terminator = block.terminator_mut(); + terminator.kind = match terminator.kind { + TerminatorKind::FalseEdge { real_target, .. } => { + TerminatorKind::Goto { target: real_target } + } + TerminatorKind::FalseUnwind { real_target, .. } => { + TerminatorKind::Goto { target: real_target } + } + + _ => continue, + } + } + } +} diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index 298bcd9dc2..2a73e341f1 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -10,18 +10,14 @@ use rustc_target::spec::PanicStrategy; /// code for these. pub struct RemoveNoopLandingPads; -pub fn remove_noop_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.panic_strategy() == PanicStrategy::Abort { - return; - } - debug!("remove_noop_landing_pads({:?})", body); - - RemoveNoopLandingPads.remove_nop_landing_pads(body) -} - impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - remove_noop_landing_pads(tcx, body); + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.panic_strategy() != PanicStrategy::Abort + } + + fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + debug!("remove_noop_landing_pads({:?})", body); + self.remove_nop_landing_pads(body) } } diff --git a/compiler/rustc_mir_transform/src/remove_storage_markers.rs b/compiler/rustc_mir_transform/src/remove_storage_markers.rs index 0c7323cbac..c9b6e1459d 100644 --- a/compiler/rustc_mir_transform/src/remove_storage_markers.rs +++ b/compiler/rustc_mir_transform/src/remove_storage_markers.rs @@ -7,6 +7,10 @@ use rustc_middle::ty::TyCtxt; pub struct RemoveStorageMarkers; impl<'tcx> MirPass<'tcx> for RemoveStorageMarkers { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() > 0 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { if tcx.sess.emit_lifetime_markers() { return; diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs new file mode 100644 index 0000000000..fc5ac97e3e --- /dev/null +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -0,0 +1,171 @@ +use rustc_index::bit_set::BitSet; +use rustc_middle::mir::{Body, Field, Rvalue, Statement, StatementKind, TerminatorKind}; +use rustc_middle::ty::subst::SubstsRef; +use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, VariantDef}; +use rustc_mir_dataflow::impls::MaybeInitializedPlaces; +use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex}; +use rustc_mir_dataflow::{self, move_path_children_matching, Analysis, MoveDataParamEnv}; + +use crate::MirPass; + +/// Removes `Drop` and `DropAndReplace` terminators whose target is known to be uninitialized at +/// that point. +/// +/// This is redundant with drop elaboration, but we need to do it prior to const-checking, and +/// running const-checking after drop elaboration makes it opimization dependent, causing issues +/// like [#90770]. +/// +/// [#90770]: https://github.com/rust-lang/rust/issues/90770 +pub struct RemoveUninitDrops; + +impl<'tcx> MirPass<'tcx> for RemoveUninitDrops { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + let param_env = tcx.param_env(body.source.def_id()); + let Ok(move_data) = MoveData::gather_moves(body, tcx, param_env) else { + // We could continue if there are move errors, but there's not much point since our + // init data isn't complete. + return; + }; + + let mdpe = MoveDataParamEnv { move_data, param_env }; + let mut maybe_inits = MaybeInitializedPlaces::new(tcx, body, &mdpe) + .into_engine(tcx, body) + .pass_name("remove_uninit_drops") + .iterate_to_fixpoint() + .into_results_cursor(body); + + let mut to_remove = vec![]; + for (bb, block) in body.basic_blocks().iter_enumerated() { + let terminator = block.terminator(); + let (TerminatorKind::Drop { place, .. } | TerminatorKind::DropAndReplace { place, .. }) + = &terminator.kind + else { continue }; + + maybe_inits.seek_before_primary_effect(body.terminator_loc(bb)); + + // If there's no move path for the dropped place, it's probably a `Deref`. Let it alone. + let LookupResult::Exact(mpi) = mdpe.move_data.rev_lookup.find(place.as_ref()) else { + continue; + }; + + let should_keep = is_needs_drop_and_init( + tcx, + param_env, + maybe_inits.get(), + &mdpe.move_data, + place.ty(body, tcx).ty, + mpi, + ); + if !should_keep { + to_remove.push(bb) + } + } + + for bb in to_remove { + let block = &mut body.basic_blocks_mut()[bb]; + + let (TerminatorKind::Drop { target, .. } | TerminatorKind::DropAndReplace { target, .. }) + = &block.terminator().kind + else { unreachable!() }; + + // Replace block terminator with `Goto`. + let target = *target; + let old_terminator_kind = std::mem::replace( + &mut block.terminator_mut().kind, + TerminatorKind::Goto { target }, + ); + + // If this is a `DropAndReplace`, we need to emulate the assignment to the return place. + if let TerminatorKind::DropAndReplace { place, value, .. } = old_terminator_kind { + block.statements.push(Statement { + source_info: block.terminator().source_info, + kind: StatementKind::Assign(Box::new((place, Rvalue::Use(value)))), + }); + } + } + } +} + +fn is_needs_drop_and_init<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + maybe_inits: &BitSet, + move_data: &MoveData<'tcx>, + ty: Ty<'tcx>, + mpi: MovePathIndex, +) -> bool { + // No need to look deeper if the root is definitely uninit or if it has no `Drop` impl. + if !maybe_inits.contains(mpi) || !ty.needs_drop(tcx, param_env) { + return false; + } + + let field_needs_drop_and_init = |(f, f_ty, mpi)| { + let child = move_path_children_matching(move_data, mpi, |x| x.is_field_to(f)); + let Some(mpi) = child else { + return f_ty.needs_drop(tcx, param_env); + }; + + is_needs_drop_and_init(tcx, param_env, maybe_inits, move_data, f_ty, mpi) + }; + + // This pass is only needed for const-checking, so it doesn't handle as many cases as + // `DropCtxt::open_drop`, since they aren't relevant in a const-context. + match ty.kind() { + ty::Adt(adt, substs) => { + let dont_elaborate = adt.is_union() || adt.is_manually_drop() || adt.has_dtor(tcx); + if dont_elaborate { + return true; + } + + // Look at all our fields, or if we are an enum all our variants and their fields. + // + // If a field's projection *is not* present in `MoveData`, it has the same + // initializedness as its parent (maybe init). + // + // If its projection *is* present in `MoveData`, then the field may have been moved + // from separate from its parent. Recurse. + adt.variants.iter_enumerated().any(|(vid, variant)| { + // Enums have multiple variants, which are discriminated with a `Downcast` projection. + // Structs have a single variant, and don't use a `Downcast` projection. + let mpi = if adt.is_enum() { + let downcast = + move_path_children_matching(move_data, mpi, |x| x.is_downcast_to(vid)); + let Some(dc_mpi) = downcast else { + return variant_needs_drop(tcx, param_env, substs, variant); + }; + + dc_mpi + } else { + mpi + }; + + variant + .fields + .iter() + .enumerate() + .map(|(f, field)| (Field::from_usize(f), field.ty(tcx, substs), mpi)) + .any(field_needs_drop_and_init) + }) + } + + ty::Tuple(_) => ty + .tuple_fields() + .enumerate() + .map(|(f, f_ty)| (Field::from_usize(f), f_ty, mpi)) + .any(field_needs_drop_and_init), + + _ => true, + } +} + +fn variant_needs_drop<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + substs: SubstsRef<'tcx>, + variant: &VariantDef, +) -> bool { + variant.fields.iter().any(|field| { + let f_ty = field.ty(tcx, substs); + f_ty.needs_drop(tcx, param_env) + }) +} diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs index c71bc512c3..39f78e9555 100644 --- a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs @@ -1,4 +1,8 @@ -//! This pass replaces a drop of a type that does not need dropping, with a goto +//! This pass replaces a drop of a type that does not need dropping, with a goto. +//! +//! When the MIR is built, we check `needs_drop` before emitting a `Drop` for a place. This pass is +//! useful because (unlike MIR building) it runs after type checking, so it can make use of +//! `Reveal::All` to provide more precies type information. use crate::MirPass; use rustc_middle::mir::*; diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index d93ffa38c6..1d912e6140 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -8,6 +8,10 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; pub struct RemoveZsts; impl<'tcx> MirPass<'tcx> for RemoveZsts { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() > 0 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // Avoid query cycles (generators require optimized MIR for layout). if tcx.type_of(body.source.def_id()).is_generator() { diff --git a/compiler/rustc_mir_transform/src/required_consts.rs b/compiler/rustc_mir_transform/src/required_consts.rs index 8b64ad65ab..80c87cafea 100644 --- a/compiler/rustc_mir_transform/src/required_consts.rs +++ b/compiler/rustc_mir_transform/src/required_consts.rs @@ -12,7 +12,7 @@ impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> { } } -impl<'a, 'tcx> Visitor<'tcx> for RequiredConstsVisitor<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> { fn visit_constant(&mut self, constant: &Constant<'tcx>, _: Location) { if let Some(ct) = constant.literal.const_for_ty() { if let ConstKind::Unevaluated(_) = ct.val { diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs index 6c423a2bb5..ee661793a4 100644 --- a/compiler/rustc_mir_transform/src/reveal_all.rs +++ b/compiler/rustc_mir_transform/src/reveal_all.rs @@ -8,15 +8,18 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; pub struct RevealAll; impl<'tcx> MirPass<'tcx> for RevealAll { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.opts.mir_opt_level() >= 3 || super::inline::Inline.is_enabled(sess) + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - // This pass must run before inlining, since we insert callee bodies in RevealAll mode. // Do not apply this transformation to generators. - if (tcx.sess.mir_opt_level() >= 3 || super::inline::is_enabled(tcx)) - && body.generator.is_none() - { - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); - RevealAllVisitor { tcx, param_env }.visit_body(body); + if body.generator.is_some() { + return; } + + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + RevealAllVisitor { tcx, param_env }.visit_body(body); } } @@ -33,26 +36,9 @@ impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> { #[inline] fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) { - *ty = self.tcx.normalize_erasing_regions(self.param_env, ty); - } - - #[inline] - fn process_projection_elem( - &mut self, - elem: PlaceElem<'tcx>, - _: Location, - ) -> Option> { - match elem { - PlaceElem::Field(field, ty) => { - let new_ty = self.tcx.normalize_erasing_regions(self.param_env, ty); - if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None } - } - // None of those contain a Ty. - PlaceElem::Index(..) - | PlaceElem::Deref - | PlaceElem::ConstantIndex { .. } - | PlaceElem::Subslice { .. } - | PlaceElem::Downcast(..) => None, - } + // We have to use `try_normalize_erasing_regions` here, since it's + // possible that we visit impossible-to-satisfy where clauses here, + // see #91745 + *ty = self.tcx.try_normalize_erasing_regions(self.param_env, *ty).unwrap_or(ty); } } diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs index 3002e7041b..612fce71f9 100644 --- a/compiler/rustc_mir_transform/src/separate_const_switch.rs +++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs @@ -45,11 +45,11 @@ use smallvec::SmallVec; pub struct SeparateConstSwitch; impl<'tcx> MirPass<'tcx> for SeparateConstSwitch { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.mir_opt_level() < 4 { - return; - } + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() >= 4 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // If execution did something, applying a simplification layer // helps later passes optimize the copy away. if separate_const_switch(body) > 0 { @@ -59,7 +59,7 @@ impl<'tcx> MirPass<'tcx> for SeparateConstSwitch { } /// Returns the amount of blocks that were duplicated -pub fn separate_const_switch<'tcx>(body: &mut Body<'tcx>) -> usize { +pub fn separate_const_switch(body: &mut Body<'_>) -> usize { let mut new_blocks: SmallVec<[(BasicBlock, BasicBlock); 6]> = SmallVec::new(); let predecessors = body.predecessors(); 'block_iter: for (block_id, block) in body.basic_blocks().iter_enumerated() { diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index f59aaa664f..58996dcd67 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -17,8 +17,8 @@ use std::iter; use crate::util::expand_aggregate; use crate::{ - abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, remove_noop_landing_pads, - run_passes, simplify, + abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, marker, pass_manager as pm, + remove_noop_landing_pads, simplify, }; use rustc_middle::mir::patch::MirPatch; use rustc_mir_dataflow::elaborate_drops::{self, DropElaborator, DropFlagMode, DropStyle}; @@ -64,7 +64,19 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' build_call_shim(tcx, instance, Some(Adjustment::RefMut), CallKind::Direct(call_mut)) } - ty::InstanceDef::DropGlue(def_id, ty) => build_drop_shim(tcx, def_id, ty), + + ty::InstanceDef::DropGlue(def_id, ty) => { + // FIXME(#91576): Drop shims for generators aren't subject to the MIR passes at the end + // of this function. Is this intentional? + if let Some(ty::Generator(gen_def_id, substs, _)) = ty.map(ty::TyS::kind) { + let body = tcx.optimized_mir(*gen_def_id).generator_drop().unwrap(); + let body = body.clone().subst(tcx, substs); + debug!("make_shim({:?}) = {:?}", instance, body); + return body; + } + + build_drop_shim(tcx, def_id, ty) + } ty::InstanceDef::CloneShim(def_id, ty) => build_clone_shim(tcx, def_id, ty), ty::InstanceDef::Virtual(..) => { bug!("InstanceDef::Virtual ({:?}) is for direct calls only", instance) @@ -75,17 +87,17 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' }; debug!("make_shim({:?}) = untransformed {:?}", instance, result); - run_passes( + pm::run_passes( tcx, &mut result, - MirPhase::Const, - &[&[ + &[ &add_moves_for_packed_drops::AddMovesForPackedDrops, &remove_noop_landing_pads::RemoveNoopLandingPads, &simplify::SimplifyCfg::new("make_shim"), &add_call_guards::CriticalCallEdges, &abort_unwinding_calls::AbortUnwindingCalls, - ]], + &marker::PhaseChange(MirPhase::Const), + ], ); debug!("make_shim({:?}) = {:?}", instance, result); @@ -132,11 +144,7 @@ fn local_decls_for_sig<'tcx>( fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) -> Body<'tcx> { debug!("build_drop_shim(def_id={:?}, ty={:?})", def_id, ty); - // Check if this is a generator, if so, return the drop glue for it - if let Some(&ty::Generator(gen_def_id, substs, _)) = ty.map(|ty| ty.kind()) { - let body = tcx.optimized_mir(gen_def_id).generator_drop().unwrap(); - return body.clone().subst(tcx, substs); - } + assert!(!matches!(ty, Some(ty) if ty.is_generator())); let substs = if let Some(ty) = ty { tcx.intern_substs(&[ty.into()]) @@ -239,7 +247,7 @@ pub struct DropShimElaborator<'a, 'tcx> { pub param_env: ty::ParamEnv<'tcx>, } -impl<'a, 'tcx> fmt::Debug for DropShimElaborator<'a, 'tcx> { +impl fmt::Debug for DropShimElaborator<'_, '_> { fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { Ok(()) } @@ -329,7 +337,7 @@ struct CloneShimBuilder<'tcx> { sig: ty::FnSig<'tcx>, } -impl CloneShimBuilder<'tcx> { +impl<'tcx> CloneShimBuilder<'tcx> { fn new(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Self { // we must subst the self_ty because it's // otherwise going to be TySelf and we can't index @@ -769,7 +777,7 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> { adt_def.variants[variant_index].fields.iter().enumerate().map(|(idx, field_def)| { (Operand::Move(Place::from(Local::new(idx + 1))), field_def.ty(tcx, substs)) }), - AggregateKind::Adt(adt_def, variant_index, substs, None, None), + AggregateKind::Adt(adt_def.did, variant_index, substs, None, None), source_info, tcx, ) diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index d6cd505cbb..7992124bac 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -47,7 +47,7 @@ impl SimplifyCfg { } } -pub fn simplify_cfg(tcx: TyCtxt<'tcx>, body: &mut Body<'_>) { +pub fn simplify_cfg<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { CfgSimplifier::new(body).simplify(); remove_dead_blocks(tcx, body); @@ -262,7 +262,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { } } -pub fn remove_dead_blocks(tcx: TyCtxt<'tcx>, body: &mut Body<'_>) { +pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let reachable = traversal::reachable_as_bitset(body); let num_blocks = body.basic_blocks().len(); if num_blocks == reachable.count() { @@ -368,6 +368,10 @@ fn save_unreachable_coverage( pub struct SimplifyLocals; impl<'tcx> MirPass<'tcx> for SimplifyLocals { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() > 0 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { trace!("running SimplifyLocals on {:?}", body.source); simplify_locals(body, tcx); @@ -450,7 +454,7 @@ impl UsedLocals { } /// Updates the use counts to reflect the removal of given statement. - fn statement_removed(&mut self, statement: &Statement<'tcx>) { + fn statement_removed(&mut self, statement: &Statement<'_>) { self.increment = false; // The location of the statement is irrelevant. @@ -459,7 +463,7 @@ impl UsedLocals { } /// Visits a left-hand side of an assignment. - fn visit_lhs(&mut self, place: &Place<'tcx>, location: Location) { + fn visit_lhs(&mut self, place: &Place<'_>, location: Location) { if place.is_indirect() { // A use, not a definition. self.visit_place(place, PlaceContext::MutatingUse(MutatingUseContext::Store), location); @@ -476,7 +480,7 @@ impl UsedLocals { } } -impl Visitor<'_> for UsedLocals { +impl<'tcx> Visitor<'tcx> for UsedLocals { fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { match statement.kind { StatementKind::LlvmInlineAsm(..) @@ -514,7 +518,7 @@ impl Visitor<'_> for UsedLocals { } /// Removes unused definitions. Updates the used locals to reflect the changes made. -fn remove_unused_definitions<'a, 'tcx>(used_locals: &'a mut UsedLocals, body: &mut Body<'tcx>) { +fn remove_unused_definitions(used_locals: &mut UsedLocals, body: &mut Body<'_>) { // The use counts are updated as we remove the statements. A local might become unused // during the retain operation, leading to a temporary inconsistency (storage statements or // definitions referencing the local might remain). For correctness it is crucial that this diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs index df90cfa318..3bbae5b897 100644 --- a/compiler/rustc_mir_transform/src/simplify_branches.rs +++ b/compiler/rustc_mir_transform/src/simplify_branches.rs @@ -1,22 +1,21 @@ -//! A pass that simplifies branches when their condition is known. - use crate::MirPass; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use std::borrow::Cow; -pub struct SimplifyBranches { +/// A pass that replaces a branch with a goto when its condition is known. +pub struct SimplifyConstCondition { label: String, } -impl SimplifyBranches { +impl SimplifyConstCondition { pub fn new(label: &str) -> Self { - SimplifyBranches { label: format!("SimplifyBranches-{}", label) } + SimplifyConstCondition { label: format!("SimplifyConstCondition-{}", label) } } } -impl<'tcx> MirPass<'tcx> for SimplifyBranches { +impl<'tcx> MirPass<'tcx> for SimplifyConstCondition { fn name(&self) -> Cow<'_, str> { Cow::Borrowed(&self.label) } @@ -34,15 +33,8 @@ impl<'tcx> MirPass<'tcx> for SimplifyBranches { } => { let constant = c.literal.try_eval_bits(tcx, param_env, switch_ty); if let Some(constant) = constant { - let otherwise = targets.otherwise(); - let mut ret = TerminatorKind::Goto { target: otherwise }; - for (v, t) in targets.iter() { - if v == constant { - ret = TerminatorKind::Goto { target: t }; - break; - } - } - ret + let target = targets.target_for_value(constant); + TerminatorKind::Goto { target } } else { continue; } @@ -53,12 +45,6 @@ impl<'tcx> MirPass<'tcx> for SimplifyBranches { Some(v) if v == expected => TerminatorKind::Goto { target }, _ => continue, }, - TerminatorKind::FalseEdge { real_target, .. } => { - TerminatorKind::Goto { target: real_target } - } - TerminatorKind::FalseUnwind { real_target, .. } => { - TerminatorKind::Goto { target: real_target } - } _ => continue, }; } diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs index 948fcd9f45..da683a3365 100644 --- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs +++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs @@ -26,6 +26,10 @@ use rustc_middle::{ pub struct SimplifyComparisonIntegral; impl<'tcx> MirPass<'tcx> for SimplifyComparisonIntegral { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() > 0 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { trace!("Running SimplifyComparisonIntegral on {:?}", body.source); @@ -144,7 +148,7 @@ struct OptimizationFinder<'a, 'tcx> { body: &'a Body<'tcx>, } -impl<'a, 'tcx> OptimizationFinder<'a, 'tcx> { +impl<'tcx> OptimizationFinder<'_, 'tcx> { fn find_optimizations(&self) -> Vec> { self.body .basic_blocks() diff --git a/compiler/rustc_mir_transform/src/simplify_try.rs b/compiler/rustc_mir_transform/src/simplify_try.rs index e436d73226..7761d4006d 100644 --- a/compiler/rustc_mir_transform/src/simplify_try.rs +++ b/compiler/rustc_mir_transform/src/simplify_try.rs @@ -102,7 +102,7 @@ fn get_arm_identity_info<'a, 'tcx>( type StmtIter<'a, 'tcx> = Peekable>>>; - fn is_storage_stmt<'tcx>(stmt: &Statement<'tcx>) -> bool { + fn is_storage_stmt(stmt: &Statement<'_>) -> bool { matches!(stmt.kind, StatementKind::StorageLive(_) | StatementKind::StorageDead(_)) } @@ -122,8 +122,8 @@ fn get_arm_identity_info<'a, 'tcx>( /// Eats consecutive `StorageLive` and `StorageDead` Statements. /// The iterator `stmt_iter` is not advanced if none were found. - fn try_eat_storage_stmts<'a, 'tcx>( - stmt_iter: &mut StmtIter<'a, 'tcx>, + fn try_eat_storage_stmts( + stmt_iter: &mut StmtIter<'_, '_>, storage_live_stmts: &mut Vec<(usize, Local)>, storage_dead_stmts: &mut Vec<(usize, Local)>, ) { @@ -136,7 +136,7 @@ fn get_arm_identity_info<'a, 'tcx>( }) } - fn is_tmp_storage_stmt<'tcx>(stmt: &Statement<'tcx>) -> bool { + fn is_tmp_storage_stmt(stmt: &Statement<'_>) -> bool { use rustc_middle::mir::StatementKind::Assign; if let Assign(box (place, Rvalue::Use(Operand::Copy(p) | Operand::Move(p)))) = &stmt.kind { place.as_local().is_some() && p.as_local().is_some() @@ -147,8 +147,8 @@ fn get_arm_identity_info<'a, 'tcx>( /// Eats consecutive `Assign` Statements. // The iterator `stmt_iter` is not advanced if none were found. - fn try_eat_assign_tmp_stmts<'a, 'tcx>( - stmt_iter: &mut StmtIter<'a, 'tcx>, + fn try_eat_assign_tmp_stmts( + stmt_iter: &mut StmtIter<'_, '_>, tmp_assigns: &mut Vec<(Local, Local)>, nop_stmts: &mut Vec, ) { @@ -163,9 +163,9 @@ fn get_arm_identity_info<'a, 'tcx>( }) } - fn find_storage_live_dead_stmts_for_local<'tcx>( + fn find_storage_live_dead_stmts_for_local( local: Local, - stmts: &[Statement<'tcx>], + stmts: &[Statement<'_>], ) -> Option<(usize, usize)> { trace!("looking for {:?}", local); let mut storage_live_stmt = None; @@ -452,14 +452,14 @@ struct LocalUseCounter { } impl LocalUseCounter { - fn get_local_uses<'tcx>(body: &Body<'tcx>) -> IndexVec { + fn get_local_uses(body: &Body<'_>) -> IndexVec { let mut counter = LocalUseCounter { local_uses: IndexVec::from_elem(0, &body.local_decls) }; counter.visit_body(body); counter.local_uses } } -impl<'tcx> Visitor<'tcx> for LocalUseCounter { +impl Visitor<'_> for LocalUseCounter { fn visit_local(&mut self, local: &Local, context: PlaceContext, _location: Location) { if context.is_storage_marker() || context == PlaceContext::NonUse(NonUseContext::VarDebugInfo) @@ -510,7 +510,7 @@ fn match_set_variant_field<'tcx>(stmt: &Statement<'tcx>) -> Option<(Local, Local /// ```rust /// discriminant(_LOCAL_TO_SET) = VAR_IDX; /// ``` -fn match_set_discr<'tcx>(stmt: &Statement<'tcx>) -> Option<(Local, VariantIdx)> { +fn match_set_discr(stmt: &Statement<'_>) -> Option<(Local, VariantIdx)> { match &stmt.kind { StatementKind::SetDiscriminant { place, variant_index } => { Some((place.as_local()?, *variant_index)) @@ -588,7 +588,7 @@ struct SimplifyBranchSameOptimizationFinder<'a, 'tcx> { tcx: TyCtxt<'tcx>, } -impl<'a, 'tcx> SimplifyBranchSameOptimizationFinder<'a, 'tcx> { +impl<'tcx> SimplifyBranchSameOptimizationFinder<'_, 'tcx> { fn find(&self) -> Vec { self.body .basic_blocks() diff --git a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs index 2aa5061129..77bc209539 100644 --- a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs @@ -70,6 +70,10 @@ fn variant_discriminants<'tcx>( } impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() > 0 + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { if body.source.promoted.is_some() { return; diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs index 64cd6f56a9..9e755ab141 100644 --- a/compiler/rustc_mir_transform/src/unreachable_prop.rs +++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs @@ -11,13 +11,13 @@ use rustc_middle::ty::TyCtxt; pub struct UnreachablePropagation; impl MirPass<'_> for UnreachablePropagation { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - if tcx.sess.mir_opt_level() < 4 { - // Enable only under -Zmir-opt-level=4 as in some cases (check the deeply-nested-opt - // perf benchmark) LLVM may spend quite a lot of time optimizing the generated code. - return; - } + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + // Enable only under -Zmir-opt-level=4 as in some cases (check the deeply-nested-opt + // perf benchmark) LLVM may spend quite a lot of time optimizing the generated code. + sess.mir_opt_level() >= 4 + } + fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let mut unreachable_blocks = FxHashSet::default(); let mut replacements = FxHashMap::default(); @@ -64,7 +64,7 @@ impl MirPass<'_> for UnreachablePropagation { } } -fn remove_successors( +fn remove_successors<'tcx, F>( terminator_kind: &TerminatorKind<'tcx>, predicate: F, ) -> Option> diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 59988e69b5..b70c24b76d 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -498,7 +498,7 @@ fn record_accesses<'a, 'tcx: 'a>( /// the user's terminal with thousands of lines of type-name. /// /// If the type name is longer than before+after, it will be written to a file. -fn shrunk_instance_name( +fn shrunk_instance_name<'tcx>( tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>, before: usize, @@ -688,15 +688,6 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { _ => bug!(), } } - mir::Rvalue::NullaryOp(mir::NullOp::Box, _) => { - let tcx = self.tcx; - let exchange_malloc_fn_def_id = - tcx.require_lang_item(LangItem::ExchangeMalloc, None); - let instance = Instance::mono(tcx, exchange_malloc_fn_def_id); - if should_codegen_locally(tcx, &instance) { - self.output.push(create_fn_mono_item(self.tcx, instance, span)); - } - } mir::Rvalue::ThreadLocalRef(def_id) => { assert!(self.tcx.is_thread_local_static(def_id)); let instance = Instance::mono(self.tcx, def_id); @@ -1145,7 +1136,7 @@ struct RootCollector<'a, 'tcx> { entry_fn: Option<(DefId, EntryFnType)>, } -impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> { +impl<'v> ItemLikeVisitor<'v> for RootCollector<'_, 'v> { fn visit_item(&mut self, item: &'v hir::Item<'v>) { match item.kind { hir::ItemKind::ExternCrate(..) @@ -1225,7 +1216,7 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> { fn visit_foreign_item(&mut self, _foreign_item: &'v hir::ForeignItem<'v>) {} } -impl RootCollector<'_, 'v> { +impl<'v> RootCollector<'_, 'v> { fn is_root(&self, def_id: LocalDefId) -> bool { !item_requires_monomorphization(self.tcx, def_id) && match self.mode { diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index f4082153b6..21ac174ba9 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -3,7 +3,6 @@ #![feature(crate_visibility_modifier)] #![feature(control_flow_enum)] #![feature(let_else)] -#![feature(in_band_lifetimes)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_monomorphize/src/partitioning/default.rs b/compiler/rustc_monomorphize/src/partitioning/default.rs index b41906111b..516c9a9259 100644 --- a/compiler/rustc_monomorphize/src/partitioning/default.rs +++ b/compiler/rustc_monomorphize/src/partitioning/default.rs @@ -378,7 +378,7 @@ fn fallback_cgu_name(name_builder: &mut CodegenUnitNameBuilder<'_>) -> Symbol { name_builder.build_cgu_name(LOCAL_CRATE, &["fallback"], Some("cgu")) } -fn mono_item_linkage_and_visibility( +fn mono_item_linkage_and_visibility<'tcx>( tcx: TyCtxt<'tcx>, mono_item: &MonoItem<'tcx>, can_be_internalized: &mut bool, @@ -393,7 +393,7 @@ fn mono_item_linkage_and_visibility( type CguNameCache = FxHashMap<(DefId, bool), Symbol>; -fn mono_item_visibility( +fn mono_item_visibility<'tcx>( tcx: TyCtxt<'tcx>, mono_item: &MonoItem<'tcx>, can_be_internalized: &mut bool, diff --git a/compiler/rustc_monomorphize/src/partitioning/merging.rs b/compiler/rustc_monomorphize/src/partitioning/merging.rs index 229468b47f..09cadc907b 100644 --- a/compiler/rustc_monomorphize/src/partitioning/merging.rs +++ b/compiler/rustc_monomorphize/src/partitioning/merging.rs @@ -3,7 +3,7 @@ use std::cmp; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder}; -use rustc_span::symbol::{Symbol, SymbolStr}; +use rustc_span::symbol::Symbol; use super::PartitioningCx; use crate::partitioning::PreInliningPartitioning; @@ -24,11 +24,11 @@ pub fn merge_codegen_units<'tcx>( // smallest into each other) we're sure to start off with a deterministic // order (sorted by name). This'll mean that if two cgus have the same size // the stable sort below will keep everything nice and deterministic. - codegen_units.sort_by_cached_key(|cgu| cgu.name().as_str()); + codegen_units.sort_by(|a, b| a.name().as_str().partial_cmp(b.name().as_str()).unwrap()); // This map keeps track of what got merged into what. - let mut cgu_contents: FxHashMap> = - codegen_units.iter().map(|cgu| (cgu.name(), vec![cgu.name().as_str()])).collect(); + let mut cgu_contents: FxHashMap> = + codegen_units.iter().map(|cgu| (cgu.name(), vec![cgu.name()])).collect(); // Merge the two smallest codegen units until the target size is reached. while codegen_units.len() > cx.target_cgu_count { @@ -69,7 +69,7 @@ pub fn merge_codegen_units<'tcx>( // were actually modified by merging. .filter(|(_, cgu_contents)| cgu_contents.len() > 1) .map(|(current_cgu_name, cgu_contents)| { - let mut cgu_contents: Vec<&str> = cgu_contents.iter().map(|s| &s[..]).collect(); + let mut cgu_contents: Vec<&str> = cgu_contents.iter().map(|s| s.as_str()).collect(); // Sort the names, so things are deterministic and easy to // predict. diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs index 658c9028ca..dc22ffc674 100644 --- a/compiler/rustc_monomorphize/src/partitioning/mod.rs +++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs @@ -208,7 +208,7 @@ pub fn partition<'tcx>( internalization_candidates: _, } = post_inlining; - result.sort_by_cached_key(|cgu| cgu.name().as_str()); + result.sort_by(|a, b| a.name().as_str().partial_cmp(b.name().as_str()).unwrap()); result } @@ -366,7 +366,7 @@ fn collect_and_partition_mono_items<'tcx>( for cgu in codegen_units { tcx.prof.artifact_size( "codegen_unit_size_estimate", - &cgu.name().as_str()[..], + cgu.name().as_str(), cgu.size_estimate() as u64, ); } @@ -401,7 +401,7 @@ fn collect_and_partition_mono_items<'tcx>( cgus.dedup(); for &(ref cgu_name, (linkage, _)) in cgus.iter() { output.push(' '); - output.push_str(&cgu_name.as_str()); + output.push_str(cgu_name.as_str()); let linkage_abbrev = match linkage { Linkage::External => "External", diff --git a/compiler/rustc_monomorphize/src/util.rs b/compiler/rustc_monomorphize/src/util.rs index 4392c02f87..6084cdda22 100644 --- a/compiler/rustc_monomorphize/src/util.rs +++ b/compiler/rustc_monomorphize/src/util.rs @@ -7,7 +7,7 @@ use std::io::prelude::*; /// /// During the same compile all closures dump the information in the same file /// "closure_profile_XXXXX.csv", which is created in the directory where the compiler is invoked. -crate fn dump_closure_profile(tcx: TyCtxt<'tcx>, closure_instance: Instance<'tcx>) { +crate fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: Instance<'tcx>) { let mut file = if let Ok(file) = OpenOptions::new() .create(true) .append(true) diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index a40f47f895..2b1b2f3fce 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -326,6 +326,12 @@ pub fn fake_token_stream(sess: &ParseSess, nt: &Nonterminal) -> TokenStream { parse_stream_from_source_str(filename, source, sess, Some(nt.span())) } +pub fn fake_token_stream_for_crate(sess: &ParseSess, krate: &ast::Crate) -> TokenStream { + let source = pprust::crate_to_string_for_macros(krate); + let filename = FileName::macro_expansion_source_code(&source); + parse_stream_from_source_str(filename, source, sess, Some(krate.span)) +} + pub fn parse_cfg_attr( attr: &Attribute, parse_sess: &ParseSess, diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index b402b8ba53..ca92d6b7fd 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -1,4 +1,4 @@ -use super::{AttrWrapper, Capturing, ForceCollect, Parser, PathStyle}; +use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle}; use rustc_ast as ast; use rustc_ast::attr; use rustc_ast::token::{self, Nonterminal}; @@ -177,7 +177,7 @@ impl<'a> Parser<'a> { AttrWrapper::empty(), true, false, - |_| true, + FnParseMode { req_name: |_| true, req_body: true }, ForceCollect::No, ) { Ok(Some(item)) => { diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index ce39d07656..9677e7642b 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1,6 +1,9 @@ +use super::pat::Expected; use super::ty::AllowPlus; -use super::TokenType; -use super::{BlockMode, Parser, PathStyle, Restrictions, SemiColonMode, SeqSep, TokenExpectType}; +use super::{ + BlockMode, Parser, PathStyle, RecoverColon, RecoverComma, Restrictions, SemiColonMode, SeqSep, + TokenExpectType, TokenType, +}; use rustc_ast as ast; use rustc_ast::ptr::P; @@ -19,6 +22,8 @@ use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, Ident}; use rustc_span::{MultiSpan, Span, SpanSnippetError, DUMMY_SP}; +use std::mem::take; + use tracing::{debug, trace}; const TURBOFISH_SUGGESTION_STR: &str = @@ -301,7 +306,7 @@ impl<'a> Parser<'a> { } } - let expect = tokens_to_string(&expected[..]); + let expect = tokens_to_string(&expected); let actual = super::token_descr(&self.token); let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 { let short_expect = if expected.len() > 6 { @@ -904,7 +909,7 @@ impl<'a> Parser<'a> { // So far we have parsed `foo Parser<'a> { // Consume the fn call arguments. let modifiers = [(token::OpenDelim(token::Paren), 1), (token::CloseDelim(token::Paren), -1)]; - self.consume_tts(1, &modifiers[..]); + self.consume_tts(1, &modifiers); if self.token.kind == token::Eof { // Not entirely sure that what we consumed were fn arguments, rollback. @@ -1124,7 +1129,8 @@ impl<'a> Parser<'a> { } pub fn maybe_consume_incorrect_semicolon(&mut self, items: &[P]) -> bool { - if self.eat(&token::Semi) { + if self.token.kind == TokenKind::Semi { + self.bump(); let mut err = self.struct_span_err(self.prev_token.span, "expected item, found `;`"); err.span_suggestion_short( self.prev_token.span, @@ -2075,4 +2081,177 @@ impl<'a> Parser<'a> { ); err } + + /// Some special error handling for the "top-level" patterns in a match arm, + /// `for` loop, `let`, &c. (in contrast to subpatterns within such). + crate fn maybe_recover_colon_colon_in_pat_typo( + &mut self, + mut first_pat: P, + ra: RecoverColon, + expected: Expected, + ) -> P { + if RecoverColon::Yes != ra || token::Colon != self.token.kind { + return first_pat; + } + if !matches!(first_pat.kind, PatKind::Ident(_, _, None) | PatKind::Path(..)) + || !self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident()) + { + return first_pat; + } + // The pattern looks like it might be a path with a `::` -> `:` typo: + // `match foo { bar:baz => {} }` + let span = self.token.span; + // We only emit "unexpected `:`" error here if we can successfully parse the + // whole pattern correctly in that case. + let snapshot = self.clone(); + + // Create error for "unexpected `:`". + match self.expected_one_of_not_found(&[], &[]) { + Err(mut err) => { + self.bump(); // Skip the `:`. + match self.parse_pat_no_top_alt(expected) { + Err(mut inner_err) => { + // Carry on as if we had not done anything, callers will emit a + // reasonable error. + inner_err.cancel(); + err.cancel(); + *self = snapshot; + } + Ok(mut pat) => { + // We've parsed the rest of the pattern. + let new_span = first_pat.span.to(pat.span); + let mut show_sugg = false; + // Try to construct a recovered pattern. + match &mut pat.kind { + PatKind::Struct(qself @ None, path, ..) + | PatKind::TupleStruct(qself @ None, path, _) + | PatKind::Path(qself @ None, path) => match &first_pat.kind { + PatKind::Ident(_, ident, _) => { + path.segments.insert(0, PathSegment::from_ident(ident.clone())); + path.span = new_span; + show_sugg = true; + first_pat = pat; + } + PatKind::Path(old_qself, old_path) => { + path.segments = old_path + .segments + .iter() + .cloned() + .chain(take(&mut path.segments)) + .collect(); + path.span = new_span; + *qself = old_qself.clone(); + first_pat = pat; + show_sugg = true; + } + _ => {} + }, + PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None) => { + match &first_pat.kind { + PatKind::Ident(_, old_ident, _) => { + let path = PatKind::Path( + None, + Path { + span: new_span, + segments: vec![ + PathSegment::from_ident(old_ident.clone()), + PathSegment::from_ident(ident.clone()), + ], + tokens: None, + }, + ); + first_pat = self.mk_pat(new_span, path); + show_sugg = true; + } + PatKind::Path(old_qself, old_path) => { + let mut segments = old_path.segments.clone(); + segments.push(PathSegment::from_ident(ident.clone())); + let path = PatKind::Path( + old_qself.clone(), + Path { span: new_span, segments, tokens: None }, + ); + first_pat = self.mk_pat(new_span, path); + show_sugg = true; + } + _ => {} + } + } + _ => {} + } + if show_sugg { + err.span_suggestion( + span, + "maybe write a path separator here", + "::".to_string(), + Applicability::MaybeIncorrect, + ); + } else { + first_pat = self.mk_pat(new_span, PatKind::Wild); + } + err.emit(); + } + } + } + _ => { + // Carry on as if we had not done anything. This should be unreachable. + *self = snapshot; + } + }; + first_pat + } + + /// Some special error handling for the "top-level" patterns in a match arm, + /// `for` loop, `let`, &c. (in contrast to subpatterns within such). + crate fn maybe_recover_unexpected_comma( + &mut self, + lo: Span, + rc: RecoverComma, + ) -> PResult<'a, ()> { + if rc == RecoverComma::No || self.token != token::Comma { + return Ok(()); + } + + // An unexpected comma after a top-level pattern is a clue that the + // user (perhaps more accustomed to some other language) forgot the + // parentheses in what should have been a tuple pattern; return a + // suggestion-enhanced error here rather than choking on the comma later. + let comma_span = self.token.span; + self.bump(); + if let Err(mut err) = self.skip_pat_list() { + // We didn't expect this to work anyway; we just wanted to advance to the + // end of the comma-sequence so we know the span to suggest parenthesizing. + err.cancel(); + } + let seq_span = lo.to(self.prev_token.span); + let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern"); + if let Ok(seq_snippet) = self.span_to_snippet(seq_span) { + const MSG: &str = "try adding parentheses to match on a tuple..."; + + err.span_suggestion( + seq_span, + MSG, + format!("({})", seq_snippet), + Applicability::MachineApplicable, + ); + err.span_suggestion( + seq_span, + "...or a vertical bar to match on multiple alternatives", + seq_snippet.replace(',', " |"), + Applicability::MachineApplicable, + ); + } + Err(err) + } + + /// Parse and throw away a parenthesized comma separated + /// sequence of patterns until `)` is reached. + fn skip_pat_list(&mut self) -> PResult<'a, ()> { + while !self.check(&token::CloseDelim(token::Paren)) { + self.parse_pat_no_top_alt(None)?; + if !self.eat(&token::Comma) { + return Ok(()); + } + } + Ok(()) + } } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index f7ee874c83..f706a98a4f 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -213,11 +213,11 @@ impl<'a> Parser<'a> { } } + // Look for JS' `===` and `!==` and recover if (op.node == AssocOp::Equal || op.node == AssocOp::NotEqual) && self.token.kind == token::Eq && self.prev_token.span.hi() == self.token.span.lo() { - // Look for JS' `===` and `!==` and recover 😇 let sp = op.span.to(self.token.span); let sugg = match op.node { AssocOp::Equal => "==", @@ -235,6 +235,38 @@ impl<'a> Parser<'a> { self.bump(); } + // Look for PHP's `<>` and recover + if op.node == AssocOp::Less + && self.token.kind == token::Gt + && self.prev_token.span.hi() == self.token.span.lo() + { + let sp = op.span.to(self.token.span); + self.struct_span_err(sp, "invalid comparison operator `<>`") + .span_suggestion_short( + sp, + "`<>` is not a valid comparison operator, use `!=`", + "!=".to_string(), + Applicability::MachineApplicable, + ) + .emit(); + self.bump(); + } + + // Look for C++'s `<=>` and recover + if op.node == AssocOp::LessEqual + && self.token.kind == token::Gt + && self.prev_token.span.hi() == self.token.span.lo() + { + let sp = op.span.to(self.token.span); + self.struct_span_err(sp, "invalid comparison operator `<=>`") + .span_label( + sp, + "`<=>` is not a valid comparison operator, use `std::cmp::Ordering`", + ) + .emit(); + self.bump(); + } + let op = op.node; // Special cases: if op == AssocOp::As { @@ -1100,30 +1132,37 @@ impl<'a> Parser<'a> { snapshot.bump(); // `(` match snapshot.parse_struct_fields(path, false, token::Paren) { Ok((fields, ..)) if snapshot.eat(&token::CloseDelim(token::Paren)) => { - // We have are certain we have `Enum::Foo(a: 3, b: 4)`, suggest + // We are certain we have `Enum::Foo(a: 3, b: 4)`, suggest // `Enum::Foo { a: 3, b: 4 }` or `Enum::Foo(3, 4)`. *self = snapshot; let close_paren = self.prev_token.span; let span = lo.to(self.prev_token.span); - err.cancel(); - self.struct_span_err( - span, - "invalid `struct` delimiters or `fn` call arguments", - ) - .multipart_suggestion( - &format!("if `{}` is a struct, use braces as delimiters", name), - vec![(open_paren, " { ".to_string()), (close_paren, " }".to_string())], - Applicability::MaybeIncorrect, - ) - .multipart_suggestion( - &format!("if `{}` is a function, use the arguments directly", name), - fields - .into_iter() - .map(|field| (field.span.until(field.expr.span), String::new())) - .collect(), - Applicability::MaybeIncorrect, - ) - .emit(); + if !fields.is_empty() { + err.cancel(); + let mut err = self.struct_span_err( + span, + "invalid `struct` delimiters or `fn` call arguments", + ); + err.multipart_suggestion( + &format!("if `{}` is a struct, use braces as delimiters", name), + vec![ + (open_paren, " { ".to_string()), + (close_paren, " }".to_string()), + ], + Applicability::MaybeIncorrect, + ); + err.multipart_suggestion( + &format!("if `{}` is a function, use the arguments directly", name), + fields + .into_iter() + .map(|field| (field.span.until(field.expr.span), String::new())) + .collect(), + Applicability::MaybeIncorrect, + ); + err.emit(); + } else { + err.emit(); + } return Some(self.mk_expr_err(span)); } Ok(_) => {} @@ -1258,7 +1297,6 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(kw::Let) { self.parse_let_expr(attrs) } else if self.eat_keyword(kw::Underscore) { - self.sess.gated_spans.gate(sym::destructuring_assignment, self.prev_token.span); Ok(self.mk_expr(self.prev_token.span, ExprKind::Underscore, attrs)) } else if !self.unclosed_delims.is_empty() && self.check(&token::Semi) { // Don't complain about bare semicolons after unclosed braces @@ -1601,7 +1639,7 @@ impl<'a> Parser<'a> { next_token.kind { if self.token.span.hi() == next_token.span.lo() { - let s = String::from("0.") + &symbol.as_str(); + let s = String::from("0.") + symbol.as_str(); let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix); return Some(Token::new(kind, self.token.span.to(next_token.span))); } @@ -1672,7 +1710,8 @@ impl<'a> Parser<'a> { ); } LitError::InvalidIntSuffix => { - let suf = suffix.expect("suffix error with no suffix").as_str(); + let suf = suffix.expect("suffix error with no suffix"); + let suf = suf.as_str(); if looks_like_width_suffix(&['i', 'u'], &suf) { // If it looks like a width, try to be helpful. let msg = format!("invalid width `{}` for integer literal", &suf[1..]); @@ -1688,8 +1727,9 @@ impl<'a> Parser<'a> { } } LitError::InvalidFloatSuffix => { - let suf = suffix.expect("suffix error with no suffix").as_str(); - if looks_like_width_suffix(&['f'], &suf) { + let suf = suffix.expect("suffix error with no suffix"); + let suf = suf.as_str(); + if looks_like_width_suffix(&['f'], suf) { // If it looks like a width, try to be helpful. let msg = format!("invalid width `{}` for float literal", &suf[1..]); self.struct_span_err(span, &msg).help("valid widths are 32 and 64").emit(); @@ -1988,25 +2028,34 @@ impl<'a> Parser<'a> { let lo = self.prev_token.span; let cond = self.parse_cond_expr()?; + let missing_then_block_binop_span = || { + match cond.kind { + ExprKind::Binary(Spanned { span: binop_span, .. }, _, ref right) + if let ExprKind::Block(..) = right.kind => Some(binop_span), + _ => None + } + }; + // Verify that the parsed `if` condition makes sense as a condition. If it is a block, then // verify that the last statement is either an implicit return (no `;`) or an explicit // return. This won't catch blocks with an explicit `return`, but that would be caught by // the dead code lint. - let thn = if self.eat_keyword(kw::Else) || !cond.returns() { - self.error_missing_if_cond(lo, cond.span) + let thn = if self.token.is_keyword(kw::Else) || !cond.returns() { + if let Some(binop_span) = missing_then_block_binop_span() { + self.error_missing_if_then_block(lo, None, Some(binop_span)).emit(); + self.mk_block_err(cond.span) + } else { + self.error_missing_if_cond(lo, cond.span) + } } else { let attrs = self.parse_outer_attributes()?.take_for_recovery(); // For recovery. let not_block = self.token != token::OpenDelim(token::Brace); - let block = self.parse_block().map_err(|mut err| { + let block = self.parse_block().map_err(|err| { if not_block { - err.span_label(lo, "this `if` expression has a condition, but no block"); - if let ExprKind::Binary(_, _, ref right) = cond.kind { - if let ExprKind::Block(_, _) = right.kind { - err.help("maybe you forgot the right operand of the condition?"); - } - } + self.error_missing_if_then_block(lo, Some(err), missing_then_block_binop_span()) + } else { + err } - err })?; self.error_on_if_block_attrs(lo, false, block.span, &attrs); block @@ -2015,6 +2064,28 @@ impl<'a> Parser<'a> { Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els), attrs)) } + fn error_missing_if_then_block( + &self, + if_span: Span, + err: Option>, + binop_span: Option, + ) -> DiagnosticBuilder<'a> { + let msg = "this `if` expression has a condition, but no block"; + + let mut err = if let Some(mut err) = err { + err.span_label(if_span, msg); + err + } else { + self.struct_span_err(if_span, msg) + }; + + if let Some(binop_span) = binop_span { + err.span_help(binop_span, "maybe you forgot the right operand of the condition?"); + } + + err + } + fn error_missing_if_cond(&self, lo: Span, span: Span) -> P { let sp = self.sess.source_map().next_point(lo); self.struct_span_err(sp, "missing condition for `if` expression") @@ -2550,7 +2621,6 @@ impl<'a> Parser<'a> { let exp_span = self.prev_token.span; // We permit `.. }` on the left-hand side of a destructuring assignment. if self.check(&token::CloseDelim(close_delim)) { - self.sess.gated_spans.gate(sym::destructuring_assignment, self.prev_token.span); base = ast::StructRest::Rest(self.prev_token.span.shrink_to_hi()); break; } diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index a9ab2cd3f6..419ea9cced 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -5,7 +5,7 @@ use rustc_ast::{ self as ast, Attribute, GenericBounds, GenericParam, GenericParamKind, WhereClause, }; use rustc_errors::PResult; -use rustc_span::symbol::{kw, sym}; +use rustc_span::symbol::kw; impl<'a> Parser<'a> { /// Parses bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`. @@ -59,19 +59,8 @@ impl<'a> Parser<'a> { self.expect(&token::Colon)?; let ty = self.parse_ty()?; - // Parse optional const generics default value, taking care of feature gating the spans - // with the unstable syntax mechanism. - let default = if self.eat(&token::Eq) { - // The gated span goes from the `=` to the end of the const argument that follows (and - // which could be a block expression). - let start = self.prev_token.span; - let const_arg = self.parse_const_arg()?; - let span = start.to(const_arg.value.span); - self.sess.gated_spans.gate(sym::const_generics_defaults, span); - Some(const_arg) - } else { - None - }; + // Parse optional const generics default value. + let default = if self.eat(&token::Eq) { Some(self.parse_const_arg()?) } else { None }; Ok(GenericParam { ident, @@ -92,6 +81,19 @@ impl<'a> Parser<'a> { let attrs = self.parse_outer_attributes()?; let param = self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { + if this.eat_keyword_noexpect(kw::SelfUpper) { + // `Self` as a generic param is invalid. Here we emit the diagnostic and continue parsing + // as if `Self` never existed. + this.struct_span_err( + this.prev_token.span, + "unexpected keyword `Self` in generic parameters", + ) + .note("you cannot use `Self` as a generic parameter because it is reserved for associated items") + .emit(); + + this.eat(&token::Comma); + } + let param = if this.check_lifetime() { let lifetime = this.expect_lifetime(); // Parse lifetime parameter. diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 24a8df49ac..ade441b0e7 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -15,6 +15,7 @@ use rustc_ast::{MacArgs, MacCall, MacDelimiter}; use rustc_ast_pretty::pprust; use rustc_errors::{struct_span_err, Applicability, PResult, StashKey}; use rustc_span::edition::{Edition, LATEST_STABLE_EDITION}; +use rustc_span::lev_distance::lev_distance; use rustc_span::source_map::{self, Span}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -26,7 +27,7 @@ impl<'a> Parser<'a> { /// Parses a source module as a crate. This is the main entry point for the parser. pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> { let (attrs, items, span) = self.parse_mod(&token::Eof)?; - Ok(ast::Crate { attrs, items, span }) + Ok(ast::Crate { attrs, items, span, id: DUMMY_NODE_ID, is_placeholder: false }) } /// Parses a `mod { ... }` or `mod ;` item. @@ -78,16 +79,17 @@ pub(super) type ItemInfo = (Ident, ItemKind); impl<'a> Parser<'a> { pub fn parse_item(&mut self, force_collect: ForceCollect) -> PResult<'a, Option>> { - self.parse_item_(|_| true, force_collect).map(|i| i.map(P)) + let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true }; + self.parse_item_(fn_parse_mode, force_collect).map(|i| i.map(P)) } fn parse_item_( &mut self, - req_name: ReqName, + fn_parse_mode: FnParseMode, force_collect: ForceCollect, ) -> PResult<'a, Option> { let attrs = self.parse_outer_attributes()?; - self.parse_item_common(attrs, true, false, req_name, force_collect) + self.parse_item_common(attrs, true, false, fn_parse_mode, force_collect) } pub(super) fn parse_item_common( @@ -95,7 +97,7 @@ impl<'a> Parser<'a> { attrs: AttrWrapper, mac_allowed: bool, attrs_allowed: bool, - req_name: ReqName, + fn_parse_mode: FnParseMode, force_collect: ForceCollect, ) -> PResult<'a, Option> { // Don't use `maybe_whole` so that we have precise control @@ -113,7 +115,8 @@ impl<'a> Parser<'a> { let mut unclosed_delims = vec![]; let item = self.collect_tokens_trailing_token(attrs, force_collect, |this: &mut Self, attrs| { - let item = this.parse_item_common_(attrs, mac_allowed, attrs_allowed, req_name); + let item = + this.parse_item_common_(attrs, mac_allowed, attrs_allowed, fn_parse_mode); unclosed_delims.append(&mut this.unclosed_delims); Ok((item?, TrailingToken::None)) })?; @@ -127,12 +130,13 @@ impl<'a> Parser<'a> { mut attrs: Vec, mac_allowed: bool, attrs_allowed: bool, - req_name: ReqName, + fn_parse_mode: FnParseMode, ) -> PResult<'a, Option> { let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; let mut def = self.parse_defaultness(); - let kind = self.parse_item_kind(&mut attrs, mac_allowed, lo, &vis, &mut def, req_name)?; + let kind = + self.parse_item_kind(&mut attrs, mac_allowed, lo, &vis, &mut def, fn_parse_mode)?; if let Some((ident, kind)) = kind { self.error_on_unconsumed_default(def, &kind); let span = lo.to(self.prev_token.span); @@ -192,7 +196,7 @@ impl<'a> Parser<'a> { lo: Span, vis: &Visibility, def: &mut Defaultness, - req_name: ReqName, + fn_parse_mode: FnParseMode, ) -> PResult<'a, Option> { let def_final = def == &Defaultness::Final; let mut def = || mem::replace(def, Defaultness::Final); @@ -219,7 +223,7 @@ impl<'a> Parser<'a> { (Ident::empty(), ItemKind::Use(tree)) } else if self.check_fn_front_matter(def_final) { // FUNCTION ITEM - let (ident, sig, generics, body) = self.parse_fn(attrs, req_name, lo)?; + let (ident, sig, generics, body) = self.parse_fn(attrs, fn_parse_mode, lo, vis)?; (ident, ItemKind::Fn(Box::new(Fn { defaultness: def(), sig, generics, body }))) } else if self.eat_keyword(kw::Extern) { if self.eat_keyword(kw::Crate) { @@ -407,10 +411,30 @@ impl<'a> Parser<'a> { fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, MacCall> { let path = self.parse_path(PathStyle::Mod)?; // `foo::bar` self.expect(&token::Not)?; // `!` - let args = self.parse_mac_args()?; // `( .. )` or `[ .. ]` (followed by `;`), or `{ .. }`. - self.eat_semi_for_macro_if_needed(&args); - self.complain_if_pub_macro(vis, false); - Ok(MacCall { path, args, prior_type_ascription: self.last_type_ascription }) + match self.parse_mac_args() { + // `( .. )` or `[ .. ]` (followed by `;`), or `{ .. }`. + Ok(args) => { + self.eat_semi_for_macro_if_needed(&args); + self.complain_if_pub_macro(vis, false); + Ok(MacCall { path, args, prior_type_ascription: self.last_type_ascription }) + } + + Err(mut err) => { + // Maybe the user misspelled `macro_rules` (issue #91227) + if self.token.is_ident() + && path.segments.len() == 1 + && lev_distance("macro_rules", &path.segments[0].ident.to_string()) <= 3 + { + err.span_suggestion( + path.span, + "perhaps you meant to define a macro", + "macro_rules".to_string(), + Applicability::MachineApplicable, + ); + } + Err(err) + } + } } /// Recover if we parsed attributes and expected an item but there was none. @@ -733,23 +757,26 @@ impl<'a> Parser<'a> { &mut self, force_collect: ForceCollect, ) -> PResult<'a, Option>>> { - self.parse_assoc_item(|_| true, force_collect) + let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true }; + self.parse_assoc_item(fn_parse_mode, force_collect) } pub fn parse_trait_item( &mut self, force_collect: ForceCollect, ) -> PResult<'a, Option>>> { - self.parse_assoc_item(|edition| edition >= Edition::Edition2018, force_collect) + let fn_parse_mode = + FnParseMode { req_name: |edition| edition >= Edition::Edition2018, req_body: false }; + self.parse_assoc_item(fn_parse_mode, force_collect) } /// Parses associated items. fn parse_assoc_item( &mut self, - req_name: ReqName, + fn_parse_mode: FnParseMode, force_collect: ForceCollect, ) -> PResult<'a, Option>>> { - Ok(self.parse_item_(req_name, force_collect)?.map( + Ok(self.parse_item_(fn_parse_mode, force_collect)?.map( |Item { attrs, id, span, vis, ident, kind, tokens }| { let kind = match AssocItemKind::try_from(kind) { Ok(kind) => kind, @@ -767,6 +794,44 @@ impl<'a> Parser<'a> { )) } + /// Emits an error that the where clause at the end of a type alias is not + /// allowed and suggests moving it. + fn error_ty_alias_where( + &self, + before_where_clause_present: bool, + before_where_clause_span: Span, + after_predicates: &[WherePredicate], + after_where_clause_span: Span, + ) { + let mut err = + self.struct_span_err(after_where_clause_span, "where clause not allowed here"); + if !after_predicates.is_empty() { + let mut state = crate::pprust::State::new(); + if !before_where_clause_present { + state.space(); + state.word_space("where"); + } else { + state.word_space(","); + } + let mut first = true; + for p in after_predicates.iter() { + if !first { + state.word_space(","); + } + first = false; + state.print_where_predicate(p); + } + let suggestion = state.s.eof(); + err.span_suggestion( + before_where_clause_span.shrink_to_hi(), + "move it here", + suggestion, + Applicability::MachineApplicable, + ); + } + err.emit() + } + /// Parses a `type` alias with the following grammar: /// ``` /// TypeAlias = "type" Ident Generics {":" GenericBounds}? {"=" Ty}? ";" ; @@ -779,9 +844,24 @@ impl<'a> Parser<'a> { // Parse optional colon and param bounds. let bounds = if self.eat(&token::Colon) { self.parse_generic_bounds(None)? } else { Vec::new() }; + generics.where_clause = self.parse_where_clause()?; let ty = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None }; + + if self.token.is_keyword(kw::Where) { + let after_where_clause = self.parse_where_clause()?; + + self.error_ty_alias_where( + generics.where_clause.has_where_token, + generics.where_clause.span, + &after_where_clause.predicates, + after_where_clause.span, + ); + + generics.where_clause.predicates.extend(after_where_clause.predicates.into_iter()); + } + self.expect_semi()?; Ok((ident, ItemKind::TyAlias(Box::new(TyAlias { defaultness, generics, bounds, ty })))) @@ -944,7 +1024,8 @@ impl<'a> Parser<'a> { &mut self, force_collect: ForceCollect, ) -> PResult<'a, Option>>> { - Ok(self.parse_item_(|_| true, force_collect)?.map( + let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: false }; + Ok(self.parse_item_(fn_parse_mode, force_collect)?.map( |Item { attrs, id, span, vis, ident, kind, tokens }| { let kind = match ForeignItemKind::try_from(kind) { Ok(kind) => kind, @@ -1483,8 +1564,16 @@ impl<'a> Parser<'a> { let (ident, is_raw) = self.ident_or_err()?; if !is_raw && ident.is_reserved() { let err = if self.check_fn_front_matter(false) { + let inherited_vis = Visibility { + span: rustc_span::DUMMY_SP, + kind: VisibilityKind::Inherited, + tokens: None, + }; // We use `parse_fn` to get a span for the function - if let Err(mut db) = self.parse_fn(&mut Vec::new(), |_| true, lo) { + let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true }; + if let Err(mut db) = + self.parse_fn(&mut Vec::new(), fn_parse_mode, lo, &inherited_vis) + { db.delay_as_bug(); } let mut err = self.struct_span_err( @@ -1698,25 +1787,83 @@ impl<'a> Parser<'a> { /// The parsing configuration used to parse a parameter list (see `parse_fn_params`). /// /// The function decides if, per-parameter `p`, `p` must have a pattern or just a type. +/// +/// This function pointer accepts an edition, because in edition 2015, trait declarations +/// were allowed to omit parameter names. In 2018, they became required. type ReqName = fn(Edition) -> bool; +/// Parsing configuration for functions. +/// +/// The syntax of function items is slightly different within trait definitions, +/// impl blocks, and modules. It is still parsed using the same code, just with +/// different flags set, so that even when the input is wrong and produces a parse +/// error, it still gets into the AST and the rest of the parser and +/// type checker can run. +#[derive(Clone, Copy)] +pub(crate) struct FnParseMode { + /// A function pointer that decides if, per-parameter `p`, `p` must have a + /// pattern or just a type. This field affects parsing of the parameters list. + /// + /// ```text + /// fn foo(alef: A) -> X { X::new() } + /// -----^^ affects parsing this part of the function signature + /// | + /// if req_name returns false, then this name is optional + /// + /// fn bar(A) -> X; + /// ^ + /// | + /// if req_name returns true, this is an error + /// ``` + /// + /// Calling this function pointer should only return false if: + /// + /// * The item is being parsed inside of a trait definition. + /// Within an impl block or a module, it should always evaluate + /// to true. + /// * The span is from Edition 2015. In particular, you can get a + /// 2015 span inside a 2021 crate using macros. + pub req_name: ReqName, + /// If this flag is set to `true`, then plain, semicolon-terminated function + /// prototypes are not allowed here. + /// + /// ```text + /// fn foo(alef: A) -> X { X::new() } + /// ^^^^^^^^^^^^ + /// | + /// this is always allowed + /// + /// fn bar(alef: A, bet: B) -> X; + /// ^ + /// | + /// if req_body is set to true, this is an error + /// ``` + /// + /// This field should only be set to false if the item is inside of a trait + /// definition or extern block. Within an impl block or a module, it should + /// always be set to true. + pub req_body: bool, +} + /// Parsing of functions and methods. impl<'a> Parser<'a> { /// Parse a function starting from the front matter (`const ...`) to the body `{ ... }` or `;`. fn parse_fn( &mut self, attrs: &mut Vec, - req_name: ReqName, + fn_parse_mode: FnParseMode, sig_lo: Span, + vis: &Visibility, ) -> PResult<'a, (Ident, FnSig, Generics, Option>)> { - let header = self.parse_fn_front_matter()?; // `const ... fn` + let header = self.parse_fn_front_matter(vis)?; // `const ... fn` let ident = self.parse_ident()?; // `foo` let mut generics = self.parse_generics()?; // `<'a, T, ...>` - let decl = self.parse_fn_decl(req_name, AllowPlus::Yes, RecoverReturnSign::Yes)?; // `(p: u8, ...)` + let decl = + self.parse_fn_decl(fn_parse_mode.req_name, AllowPlus::Yes, RecoverReturnSign::Yes)?; // `(p: u8, ...)` generics.where_clause = self.parse_where_clause()?; // `where T: Ord` let mut sig_hi = self.prev_token.span; - let body = self.parse_fn_body(attrs, &ident, &mut sig_hi)?; // `;` or `{ ... }`. + let body = self.parse_fn_body(attrs, &ident, &mut sig_hi, fn_parse_mode.req_body)?; // `;` or `{ ... }`. let fn_sig_span = sig_lo.to(sig_hi); Ok((ident, FnSig { header, decl, span: fn_sig_span }, generics, body)) } @@ -1729,9 +1876,17 @@ impl<'a> Parser<'a> { attrs: &mut Vec, ident: &Ident, sig_hi: &mut Span, + req_body: bool, ) -> PResult<'a, Option>> { - let (inner_attrs, body) = if self.eat(&token::Semi) { + let has_semi = if req_body { + self.token.kind == TokenKind::Semi + } else { + // Only include `;` in list of expected tokens if body is not required + self.check(&TokenKind::Semi) + }; + let (inner_attrs, body) = if has_semi { // Include the trailing semicolon in the span of the signature + self.expect_semi()?; *sig_hi = self.prev_token.span; (Vec::new(), None) } else if self.check(&token::OpenDelim(token::Brace)) || self.token.is_whole_block() { @@ -1752,9 +1907,12 @@ impl<'a> Parser<'a> { .emit(); (Vec::new(), Some(self.mk_block_err(span))) } else { - if let Err(mut err) = - self.expected_one_of_not_found(&[], &[token::Semi, token::OpenDelim(token::Brace)]) - { + let expected = if req_body { + &[token::OpenDelim(token::Brace)][..] + } else { + &[token::Semi, token::OpenDelim(token::Brace)] + }; + if let Err(mut err) = self.expected_one_of_not_found(&[], &expected) { if self.token.kind == token::CloseDelim(token::Brace) { // The enclosing `mod`, `trait` or `impl` is being closed, so keep the `fn` in // the AST for typechecking. @@ -1806,12 +1964,15 @@ impl<'a> Parser<'a> { /// Parses all the "front matter" (or "qualifiers") for a `fn` declaration, /// up to and including the `fn` keyword. The formal grammar is: /// - /// ``` + /// ```text /// Extern = "extern" StringLit? ; /// FnQual = "const"? "async"? "unsafe"? Extern? ; /// FnFrontMatter = FnQual "fn" ; /// ``` - pub(super) fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> { + /// + /// `vis` represents the visibility that was already parsed, if any. Use + /// `Visibility::Inherited` when no visibility is known. + pub(super) fn parse_fn_front_matter(&mut self, orig_vis: &Visibility) -> PResult<'a, FnHeader> { let sp_start = self.token.span; let constness = self.parse_constness(); @@ -1837,51 +1998,94 @@ impl<'a> Parser<'a> { Ok(false) => unreachable!(), Err(mut err) => { // Qualifier keywords ordering check + enum WrongKw { + Duplicated(Span), + Misplaced(Span), + } - // This will allow the machine fix to directly place the keyword in the correct place - let current_qual_sp = if self.check_keyword(kw::Const) { - Some(async_start_sp) + // This will allow the machine fix to directly place the keyword in the correct place or to indicate + // that the keyword is already present and the second instance should be removed. + let wrong_kw = if self.check_keyword(kw::Const) { + match constness { + Const::Yes(sp) => Some(WrongKw::Duplicated(sp)), + Const::No => Some(WrongKw::Misplaced(async_start_sp)), + } } else if self.check_keyword(kw::Async) { - Some(unsafe_start_sp) + match asyncness { + Async::Yes { span, .. } => Some(WrongKw::Duplicated(span)), + Async::No => Some(WrongKw::Misplaced(unsafe_start_sp)), + } } else if self.check_keyword(kw::Unsafe) { - Some(ext_start_sp) + match unsafety { + Unsafe::Yes(sp) => Some(WrongKw::Duplicated(sp)), + Unsafe::No => Some(WrongKw::Misplaced(ext_start_sp)), + } } else { None }; - if let Some(current_qual_sp) = current_qual_sp { - let current_qual_sp = current_qual_sp.to(self.prev_token.span); - if let Ok(current_qual) = self.span_to_snippet(current_qual_sp) { - let invalid_qual_sp = self.token.uninterpolated_span(); - let invalid_qual = self.span_to_snippet(invalid_qual_sp).unwrap(); + // The keyword is already present, suggest removal of the second instance + if let Some(WrongKw::Duplicated(original_sp)) = wrong_kw { + let original_kw = self + .span_to_snippet(original_sp) + .expect("Span extracted directly from keyword should always work"); + + err.span_suggestion( + self.token.uninterpolated_span(), + &format!("`{}` already used earlier, remove this one", original_kw), + "".to_string(), + Applicability::MachineApplicable, + ) + .span_note(original_sp, &format!("`{}` first seen here", original_kw)); + } + // The keyword has not been seen yet, suggest correct placement in the function front matter + else if let Some(WrongKw::Misplaced(correct_pos_sp)) = wrong_kw { + let correct_pos_sp = correct_pos_sp.to(self.prev_token.span); + if let Ok(current_qual) = self.span_to_snippet(correct_pos_sp) { + let misplaced_qual_sp = self.token.uninterpolated_span(); + let misplaced_qual = self.span_to_snippet(misplaced_qual_sp).unwrap(); err.span_suggestion( - current_qual_sp.to(invalid_qual_sp), - &format!("`{}` must come before `{}`", invalid_qual, current_qual), - format!("{} {}", invalid_qual, current_qual), - Applicability::MachineApplicable, - ).note("keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`"); + correct_pos_sp.to(misplaced_qual_sp), + &format!("`{}` must come before `{}`", misplaced_qual, current_qual), + format!("{} {}", misplaced_qual, current_qual), + Applicability::MachineApplicable, + ).note("keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`"); } } - // Recover incorrect visibility order such as `async pub`. + // Recover incorrect visibility order such as `async pub` else if self.check_keyword(kw::Pub) { let sp = sp_start.to(self.prev_token.span); if let Ok(snippet) = self.span_to_snippet(sp) { - let vis = match self.parse_visibility(FollowedByType::No) { + let current_vis = match self.parse_visibility(FollowedByType::No) { Ok(v) => v, Err(mut d) => { d.cancel(); return Err(err); } }; - let vs = pprust::vis_to_string(&vis); + let vs = pprust::vis_to_string(¤t_vis); let vs = vs.trim_end(); - err.span_suggestion( - sp_start.to(self.prev_token.span), - &format!("visibility `{}` must come before `{}`", vs, snippet), - format!("{} {}", vs, snippet), - Applicability::MachineApplicable, - ); + + // There was no explicit visibility + if matches!(orig_vis.kind, VisibilityKind::Inherited) { + err.span_suggestion( + sp_start.to(self.prev_token.span), + &format!("visibility `{}` must come before `{}`", vs, snippet), + format!("{} {}", vs, snippet), + Applicability::MachineApplicable, + ); + } + // There was an explicit visibility + else { + err.span_suggestion( + current_vis.span, + "there is already a visibility modifier, remove one", + "".to_string(), + Applicability::MachineApplicable, + ) + .span_note(orig_vis.span, "explicit visibility first seen here"); + } } } return Err(err); diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 9212aaa87d..6d534bece4 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -14,6 +14,7 @@ use crate::lexer::UnmatchedBrace; pub use attr_wrapper::AttrWrapper; pub use diagnostics::AttemptLocalParseRecovery; use diagnostics::Error; +pub(crate) use item::FnParseMode; pub use pat::{RecoverColon, RecoverComma}; pub use path::PathStyle; diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index bb3947bb47..ac3123c40e 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -3,14 +3,16 @@ use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor}; use rustc_ast::ptr::P; use rustc_ast::token; -use rustc_ast::{self as ast, AttrVec, Attribute, MacCall, Pat, PatField, PatKind, RangeEnd}; -use rustc_ast::{BindingMode, Expr, ExprKind, Mutability, Path, QSelf, RangeSyntax}; +use rustc_ast::{ + self as ast, AttrVec, Attribute, BindingMode, Expr, ExprKind, MacCall, Mutability, Pat, + PatField, PatKind, Path, QSelf, RangeEnd, RangeSyntax, +}; use rustc_ast_pretty::pprust; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, PResult}; use rustc_span::source_map::{respan, Span, Spanned}; use rustc_span::symbol::{kw, sym, Ident}; -type Expected = Option<&'static str>; +pub(super) type Expected = Option<&'static str>; /// `Expected` for function and lambda parameter patterns. pub(super) const PARAM_EXPECTED: Expected = Some("parameter name"); @@ -98,55 +100,9 @@ impl<'a> Parser<'a> { // If we parsed a leading `|` which should be gated, // then we should really gate the leading `|`. // This complicated procedure is done purely for diagnostics UX. - let mut first_pat = first_pat; - if let (RecoverColon::Yes, token::Colon) = (ra, &self.token.kind) { - if matches!( - first_pat.kind, - PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, None) - | PatKind::Path(..) - ) && self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident()) - { - // The pattern looks like it might be a path with a `::` -> `:` typo: - // `match foo { bar:baz => {} }` - let span = self.token.span; - // We only emit "unexpected `:`" error here if we can successfully parse the - // whole pattern correctly in that case. - let snapshot = self.clone(); - - // Create error for "unexpected `:`". - match self.expected_one_of_not_found(&[], &[]) { - Err(mut err) => { - self.bump(); // Skip the `:`. - match self.parse_pat_no_top_alt(expected) { - Err(mut inner_err) => { - // Carry on as if we had not done anything, callers will emit a - // reasonable error. - inner_err.cancel(); - err.cancel(); - *self = snapshot; - } - Ok(pat) => { - // We've parsed the rest of the pattern. - err.span_suggestion( - span, - "maybe write a path separator here", - "::".to_string(), - Applicability::MachineApplicable, - ); - err.emit(); - first_pat = - self.mk_pat(first_pat.span.to(pat.span), PatKind::Wild); - } - } - } - _ => { - // Carry on as if we had not done anything. This should be unreachable. - *self = snapshot; - } - }; - } - } + // Check if the user wrote `foo:bar` instead of `foo::bar`. + let first_pat = self.maybe_recover_colon_colon_in_pat_typo(first_pat, ra, expected); if let Some(leading_vert_span) = leading_vert_span { // If there was a leading vert, treat this as an or-pattern. This improves @@ -321,57 +277,6 @@ impl<'a> Parser<'a> { err.emit(); } - /// Some special error handling for the "top-level" patterns in a match arm, - /// `for` loop, `let`, &c. (in contrast to subpatterns within such). - fn maybe_recover_unexpected_comma(&mut self, lo: Span, rc: RecoverComma) -> PResult<'a, ()> { - if rc == RecoverComma::No || self.token != token::Comma { - return Ok(()); - } - - // An unexpected comma after a top-level pattern is a clue that the - // user (perhaps more accustomed to some other language) forgot the - // parentheses in what should have been a tuple pattern; return a - // suggestion-enhanced error here rather than choking on the comma later. - let comma_span = self.token.span; - self.bump(); - if let Err(mut err) = self.skip_pat_list() { - // We didn't expect this to work anyway; we just wanted to advance to the - // end of the comma-sequence so we know the span to suggest parenthesizing. - err.cancel(); - } - let seq_span = lo.to(self.prev_token.span); - let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern"); - if let Ok(seq_snippet) = self.span_to_snippet(seq_span) { - const MSG: &str = "try adding parentheses to match on a tuple..."; - - err.span_suggestion( - seq_span, - MSG, - format!("({})", seq_snippet), - Applicability::MachineApplicable, - ); - err.span_suggestion( - seq_span, - "...or a vertical bar to match on multiple alternatives", - seq_snippet.replace(",", " |"), - Applicability::MachineApplicable, - ); - } - Err(err) - } - - /// Parse and throw away a parenthesized comma separated - /// sequence of patterns until `)` is reached. - fn skip_pat_list(&mut self) -> PResult<'a, ()> { - while !self.check(&token::CloseDelim(token::Paren)) { - self.parse_pat_no_top_alt(None)?; - if !self.eat(&token::Comma) { - return Ok(()); - } - } - Ok(()) - } - /// A `|` or possibly `||` token shouldn't be here. Ban it. fn ban_illegal_vert(&mut self, lo: Option, pos: &str, ctx: &str) { let span = self.token.span; @@ -1168,7 +1073,7 @@ impl<'a> Parser<'a> { self.mk_pat(span, PatKind::Ident(bm, ident, None)) } - fn mk_pat(&self, span: Span, kind: PatKind) -> P { + pub(super) fn mk_pat(&self, span: Span, kind: PatKind) -> P { P(Pat { kind, span, id: ast::DUMMY_NODE_ID, tokens: None }) } } diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 01e751ea8b..d3e7d1690c 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -4,7 +4,9 @@ use super::expr::LhsExpr; use super::pat::RecoverComma; use super::path::PathStyle; use super::TrailingToken; -use super::{AttrWrapper, BlockMode, ForceCollect, Parser, Restrictions, SemiColonMode}; +use super::{ + AttrWrapper, BlockMode, FnParseMode, ForceCollect, Parser, Restrictions, SemiColonMode, +}; use crate::maybe_whole; use rustc_ast as ast; @@ -79,9 +81,13 @@ impl<'a> Parser<'a> { } else { self.parse_stmt_path_start(lo, attrs) }? - } else if let Some(item) = - self.parse_item_common(attrs.clone(), false, true, |_| true, force_collect)? - { + } else if let Some(item) = self.parse_item_common( + attrs.clone(), + false, + true, + FnParseMode { req_name: |_| true, req_body: true }, + force_collect, + )? { // FIXME: Bad copy of attrs self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item))) } else if self.eat(&token::Semi) { diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 9bfde0e390..02a774ba12 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -474,7 +474,13 @@ impl<'a> Parser<'a> { params: Vec, recover_return_sign: RecoverReturnSign, ) -> PResult<'a, TyKind> { - let ast::FnHeader { ext, unsafety, constness, asyncness } = self.parse_fn_front_matter()?; + let inherited_vis = rustc_ast::Visibility { + span: rustc_span::DUMMY_SP, + kind: rustc_ast::VisibilityKind::Inherited, + tokens: None, + }; + let ast::FnHeader { ext, unsafety, constness, asyncness } = + self.parse_fn_front_matter(&inherited_vis)?; let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?; let whole_span = lo.to(self.prev_token.span); if let ast::Const::Yes(span) = constness { diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index f761eaae5a..d7b0069949 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -32,7 +32,7 @@ pub(crate) fn target_from_impl_item<'tcx>( match impl_item.kind { hir::ImplItemKind::Const(..) => Target::AssocConst, hir::ImplItemKind::Fn(..) => { - let parent_hir_id = tcx.hir().get_parent_item(impl_item.hir_id()); + let parent_hir_id = tcx.hir().get_parent_item(impl_item.hir_id()).expect_owner(); let containing_item = tcx.hir().expect_item(parent_hir_id); let containing_impl_is_for_trait = match &containing_item.kind { hir::ItemKind::Impl(impl_) => impl_.of_trait.is_some(), @@ -58,7 +58,7 @@ struct CheckAttrVisitor<'tcx> { tcx: TyCtxt<'tcx>, } -impl CheckAttrVisitor<'tcx> { +impl CheckAttrVisitor<'_> { /// Checks any attribute. fn check_attributes( &self, @@ -382,7 +382,7 @@ impl CheckAttrVisitor<'tcx> { &self, hir_id: HirId, attr_span: &Span, - attrs: &'hir [Attribute], + attrs: &[Attribute], span: &Span, target: Target, ) -> bool { @@ -582,7 +582,7 @@ impl CheckAttrVisitor<'tcx> { Target::Impl => Some("implementation block"), Target::ForeignMod => Some("extern block"), Target::AssocTy => { - let parent_hir_id = self.tcx.hir().get_parent_item(hir_id); + let parent_hir_id = self.tcx.hir().get_parent_item(hir_id).expect_owner(); let containing_item = self.tcx.hir().expect_item(parent_hir_id); if Target::from_item(containing_item) == Target::Impl { Some("type alias in implementation block") @@ -591,7 +591,7 @@ impl CheckAttrVisitor<'tcx> { } } Target::AssocConst => { - let parent_hir_id = self.tcx.hir().get_parent_item(hir_id); + let parent_hir_id = self.tcx.hir().get_parent_item(hir_id).expect_owner(); let containing_item = self.tcx.hir().expect_item(parent_hir_id); // We can't link to trait impl's consts. let err = "associated constant in trait implementation block"; @@ -607,7 +607,7 @@ impl CheckAttrVisitor<'tcx> { return err_fn(meta.span(), &format!("isn't allowed on {}", err)); } let item_name = self.tcx.hir().name(hir_id); - if &*item_name.as_str() == doc_alias { + if item_name.as_str() == doc_alias { return err_fn(meta.span(), "is the same as the item's name"); } let span = meta.span(); @@ -636,7 +636,7 @@ impl CheckAttrVisitor<'tcx> { LitKind::Str(s, _) => { if !self.check_doc_alias_value( v, - &s.as_str(), + s.as_str(), hir_id, target, true, @@ -1481,7 +1481,7 @@ impl CheckAttrVisitor<'tcx> { /// Checks if the `#[repr]` attributes on `item` are valid. fn check_repr( &self, - attrs: &'hir [Attribute], + attrs: &[Attribute], span: &Span, target: Target, item: Option>, @@ -1663,7 +1663,7 @@ impl CheckAttrVisitor<'tcx> { } } - fn check_used(&self, attrs: &'hir [Attribute], target: Target) { + fn check_used(&self, attrs: &[Attribute], target: Target) { for attr in attrs { if attr.has_name(sym::used) && target != Target::Static { self.tcx @@ -1842,7 +1842,7 @@ impl CheckAttrVisitor<'tcx> { } } -impl Visitor<'tcx> for CheckAttrVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { type Map = Map<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -1953,7 +1953,12 @@ fn is_c_like_enum(item: &Item<'_>) -> bool { } } +// FIXME: Fix "Cannot determine resolution" error and remove built-in macros +// from this check. fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { + // Check for builtin attributes at the crate level + // which were unsuccessfully resolved due to cannot determine + // resolution for the attribute macro error. const ATTRS_TO_CHECK: &[Symbol] = &[ sym::macro_export, sym::repr, @@ -1961,20 +1966,39 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { sym::automatically_derived, sym::start, sym::rustc_main, + sym::derive, + sym::test, + sym::test_case, + sym::global_allocator, + sym::bench, ]; for attr in attrs { - for attr_to_check in ATTRS_TO_CHECK { - if attr.has_name(*attr_to_check) { - tcx.sess - .struct_span_err( + // This function should only be called with crate attributes + // which are inner attributes always but lets check to make sure + if attr.style == AttrStyle::Inner { + for attr_to_check in ATTRS_TO_CHECK { + if attr.has_name(*attr_to_check) { + let mut err = tcx.sess.struct_span_err( attr.span, &format!( "`{}` attribute cannot be used at crate level", attr_to_check.to_ident_string() ), - ) - .emit(); + ); + // Only emit an error with a suggestion if we can create a + // string out of the attribute span + if let Ok(src) = tcx.sess.source_map().span_to_snippet(attr.span) { + let replacement = src.replace("#!", "#"); + err.span_suggestion_verbose( + attr.span, + "perhaps you meant to use an outer attribute", + replacement, + rustc_errors::Applicability::MachineApplicable, + ); + } + err.emit() + } } } } diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index 9ccf76b570..a5a6574070 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -78,7 +78,7 @@ impl<'tcx> CheckConstTraitVisitor<'tcx> { impl<'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for CheckConstTraitVisitor<'tcx> { /// check for const trait impls, and errors if the impl uses provided/default functions /// of the trait being implemented; as those provided functions can be non-const. - fn visit_item(&mut self, item: &'hir hir::Item<'hir>) { + fn visit_item<'hir>(&mut self, item: &'hir hir::Item<'hir>) { let _: Option<_> = try { if let hir::ItemKind::Impl(ref imp) = item.kind { if let hir::Constness::Const = imp.constness { @@ -134,11 +134,11 @@ impl<'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for CheckConstTraitVisitor< }; } - fn visit_trait_item(&mut self, _: &'hir hir::TraitItem<'hir>) {} + fn visit_trait_item<'hir>(&mut self, _: &'hir hir::TraitItem<'hir>) {} - fn visit_impl_item(&mut self, _: &'hir hir::ImplItem<'hir>) {} + fn visit_impl_item<'hir>(&mut self, _: &'hir hir::ImplItem<'hir>) {} - fn visit_foreign_item(&mut self, _: &'hir hir::ForeignItem<'hir>) {} + fn visit_foreign_item<'hir>(&mut self, _: &'hir hir::ForeignItem<'hir>) {} } #[derive(Copy, Clone)] diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 7727913240..3b15332c67 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -150,7 +150,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { #[allow(dead_code)] // FIXME(81658): should be used + lint reinstated after #83171 relands. fn check_for_self_assign(&mut self, assign: &'tcx hir::Expr<'tcx>) { - fn check_for_self_assign_helper( + fn check_for_self_assign_helper<'tcx>( tcx: TyCtxt<'tcx>, typeck_results: &'tcx ty::TypeckResults<'tcx>, lhs: &'tcx hir::Expr<'tcx>, @@ -600,7 +600,7 @@ struct DeadVisitor<'tcx> { live_symbols: FxHashSet, } -impl DeadVisitor<'tcx> { +impl<'tcx> DeadVisitor<'tcx> { fn should_warn_about_item(&mut self, item: &hir::Item<'_>) -> bool { let should_warn = matches!( item.kind, @@ -672,7 +672,7 @@ impl DeadVisitor<'tcx> { } } -impl Visitor<'tcx> for DeadVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for DeadVisitor<'tcx> { type Map = Map<'tcx>; /// Walk nested items in place so that we don't report dead-code diff --git a/compiler/rustc_passes/src/intrinsicck.rs b/compiler/rustc_passes/src/intrinsicck.rs index 008b856ebf..064c469662 100644 --- a/compiler/rustc_passes/src/intrinsicck.rs +++ b/compiler/rustc_passes/src/intrinsicck.rs @@ -62,7 +62,7 @@ fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { ty } -impl ExprVisitor<'tcx> { +impl<'tcx> ExprVisitor<'tcx> { fn def_id_is_transmute(&self, def_id: DefId) -> bool { self.tcx.fn_sig(def_id).abi() == RustIntrinsic && self.tcx.item_name(def_id) == sym::transmute @@ -487,7 +487,7 @@ impl ExprVisitor<'tcx> { } } -impl Visitor<'tcx> for ItemVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for ItemVisitor<'tcx> { type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -504,7 +504,7 @@ impl Visitor<'tcx> for ItemVisitor<'tcx> { } } -impl Visitor<'tcx> for ExprVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for ExprVisitor<'tcx> { type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 388c33917c..a808d6c834 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -28,7 +28,7 @@ struct LanguageItemCollector<'tcx> { tcx: TyCtxt<'tcx>, } -impl ItemLikeVisitor<'v> for LanguageItemCollector<'tcx> { +impl<'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'tcx> { fn visit_item(&mut self, item: &hir::Item<'_>) { self.check_for_lang(Target::from_item(item), item.hir_id()); @@ -50,7 +50,7 @@ impl ItemLikeVisitor<'v> for LanguageItemCollector<'tcx> { fn visit_foreign_item(&mut self, _: &hir::ForeignItem<'_>) {} } -impl LanguageItemCollector<'tcx> { +impl<'tcx> LanguageItemCollector<'tcx> { fn new(tcx: TyCtxt<'tcx>) -> LanguageItemCollector<'tcx> { LanguageItemCollector { tcx, items: LanguageItems::new() } } diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs index 558d8958b1..00e8eb5eb2 100644 --- a/compiler/rustc_passes/src/layout_test.rs +++ b/compiler/rustc_passes/src/layout_test.rs @@ -20,7 +20,7 @@ struct LayoutTest<'tcx> { tcx: TyCtxt<'tcx>, } -impl ItemLikeVisitor<'tcx> for LayoutTest<'tcx> { +impl<'tcx> ItemLikeVisitor<'tcx> for LayoutTest<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { match item.kind { ItemKind::TyAlias(..) @@ -42,7 +42,7 @@ impl ItemLikeVisitor<'tcx> for LayoutTest<'tcx> { fn visit_foreign_item(&mut self, _: &'tcx hir::ForeignItem<'tcx>) {} } -impl LayoutTest<'tcx> { +impl<'tcx> LayoutTest<'tcx> { fn dump_layout_of(&self, item_def_id: LocalDefId, item: &hir::Item<'tcx>, attr: &Attribute) { let tcx = self.tcx; let param_env = self.tcx.param_env(item_def_id); @@ -114,7 +114,7 @@ struct UnwrapLayoutCx<'tcx> { param_env: ParamEnv<'tcx>, } -impl LayoutOfHelpers<'tcx> for UnwrapLayoutCx<'tcx> { +impl<'tcx> LayoutOfHelpers<'tcx> for UnwrapLayoutCx<'tcx> { type LayoutOfResult = TyAndLayout<'tcx>; fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! { @@ -127,19 +127,19 @@ impl LayoutOfHelpers<'tcx> for UnwrapLayoutCx<'tcx> { } } -impl HasTyCtxt<'tcx> for UnwrapLayoutCx<'tcx> { +impl<'tcx> HasTyCtxt<'tcx> for UnwrapLayoutCx<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } } -impl HasParamEnv<'tcx> for UnwrapLayoutCx<'tcx> { +impl<'tcx> HasParamEnv<'tcx> for UnwrapLayoutCx<'tcx> { fn param_env(&self) -> ParamEnv<'tcx> { self.param_env } } -impl HasDataLayout for UnwrapLayoutCx<'tcx> { +impl<'tcx> HasDataLayout for UnwrapLayoutCx<'tcx> { fn data_layout(&self) -> &TargetDataLayout { self.tcx.data_layout() } diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index af1c724410..8a411f01d6 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -6,9 +6,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(crate_visibility_modifier)] -#![feature(in_band_lifetimes)] -#![cfg_attr(bootstrap, feature(format_args_capture))] -#![feature(iter_zip)] #![feature(map_try_insert)] #![feature(min_specialization)] #![feature(nll)] diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs index ff8bd37238..40d12c4a22 100644 --- a/compiler/rustc_passes/src/lib_features.rs +++ b/compiler/rustc_passes/src/lib_features.rs @@ -4,7 +4,7 @@ // and `#[unstable (..)]`), but are not declared in one single location // (unlike lang features), which means we need to collect them instead. -use rustc_ast::{Attribute, MetaItem, MetaItemKind}; +use rustc_ast::{Attribute, MetaItemKind}; use rustc_errors::struct_span_err; use rustc_hir::intravisit::{NestedVisitorMap, Visitor}; use rustc_middle::hir::map::Map; @@ -23,7 +23,7 @@ pub struct LibFeatureCollector<'tcx> { lib_features: LibFeatures, } -impl LibFeatureCollector<'tcx> { +impl<'tcx> LibFeatureCollector<'tcx> { fn new(tcx: TyCtxt<'tcx>) -> LibFeatureCollector<'tcx> { LibFeatureCollector { tcx, lib_features: new_lib_features() } } @@ -34,8 +34,8 @@ impl LibFeatureCollector<'tcx> { // Find a stability attribute (i.e., `#[stable (..)]`, `#[unstable (..)]`, // `#[rustc_const_unstable (..)]`). if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| attr.has_name(**stab_attr)) { - let meta_item = attr.meta(); - if let Some(MetaItem { kind: MetaItemKind::List(ref metas), .. }) = meta_item { + let meta_kind = attr.meta_kind(); + if let Some(MetaItemKind::List(ref metas)) = meta_kind { let mut feature = None; let mut since = None; for meta in metas { @@ -110,7 +110,7 @@ impl LibFeatureCollector<'tcx> { } } -impl Visitor<'tcx> for LibFeatureCollector<'tcx> { +impl<'tcx> Visitor<'tcx> for LibFeatureCollector<'tcx> { type Map = Map<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -124,12 +124,12 @@ impl Visitor<'tcx> for LibFeatureCollector<'tcx> { } } -fn get_lib_features(tcx: TyCtxt<'_>, (): ()) -> LibFeatures { +fn lib_features(tcx: TyCtxt<'_>, (): ()) -> LibFeatures { let mut collector = LibFeatureCollector::new(tcx); tcx.hir().walk_attributes(&mut collector); collector.lib_features } pub fn provide(providers: &mut Providers) { - providers.get_lib_features = get_lib_features; + providers.lib_features = lib_features; } diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 3d7a215754..9ee305b712 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -198,7 +198,7 @@ struct IrMaps<'tcx> { lnks: IndexVec, } -impl IrMaps<'tcx> { +impl<'tcx> IrMaps<'tcx> { fn new(tcx: TyCtxt<'tcx>) -> IrMaps<'tcx> { IrMaps { tcx, @@ -429,8 +429,8 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> { intravisit::walk_expr(self, expr); } - hir::ExprKind::Let(ref pat, ..) => { - self.add_from_pat(pat); + hir::ExprKind::Let(let_expr) => { + self.add_from_pat(let_expr.pat); intravisit::walk_expr(self, expr); } @@ -856,9 +856,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { }) } - hir::ExprKind::Let(ref pat, ref scrutinee, _) => { - let succ = self.propagate_through_expr(scrutinee, succ); - self.define_bindings_in_pat(pat, succ) + hir::ExprKind::Let(let_expr) => { + let succ = self.propagate_through_expr(let_expr.init, succ); + self.define_bindings_in_pat(let_expr.pat, succ) } // Note that labels have been resolved, so we don't need to look @@ -1401,8 +1401,8 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) { } } - hir::ExprKind::Let(ref pat, ..) => { - this.check_unused_vars_in_pat(pat, None, |_, _, _, _| {}); + hir::ExprKind::Let(let_expr) => { + this.check_unused_vars_in_pat(let_expr.pat, None, |_, _, _, _| {}); } // no correctness conditions related to liveness @@ -1464,7 +1464,7 @@ impl<'tcx> Liveness<'_, 'tcx> { if name == kw::Empty { return None; } - let name: &str = &name.as_str(); + let name = name.as_str(); if name.as_bytes()[0] == b'_' { return None; } diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs index d3ecd18a93..07cb165d79 100644 --- a/compiler/rustc_passes/src/naked_functions.rs +++ b/compiler/rustc_passes/src/naked_functions.rs @@ -37,7 +37,7 @@ impl<'tcx> Visitor<'tcx> for CheckNakedFunctions<'tcx> { fn visit_fn( &mut self, - fk: FnKind<'v>, + fk: FnKind<'_>, _fd: &'tcx hir::FnDecl<'tcx>, body_id: hir::BodyId, span: Span, diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index bd1e9520ee..707e6b123d 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -22,7 +22,7 @@ use rustc_target::spec::abi::Abi; // Returns true if the given item must be inlined because it may be // monomorphized or it was marked with `#[inline]`. This will only return // true for functions. -fn item_might_be_inlined(tcx: TyCtxt<'tcx>, item: &hir::Item<'_>, attrs: &CodegenFnAttrs) -> bool { +fn item_might_be_inlined(tcx: TyCtxt<'_>, item: &hir::Item<'_>, attrs: &CodegenFnAttrs) -> bool { if attrs.requests_inline() { return true; } @@ -173,8 +173,7 @@ impl<'tcx> ReachableContext<'tcx> { // Check the impl. If the generics on the self // type of the impl require inlining, this method // does too. - let impl_hir_id = self.tcx.hir().local_def_id_to_hir_id(impl_did); - match self.tcx.hir().expect_item(impl_hir_id).kind { + match self.tcx.hir().expect_item(impl_did).kind { hir::ItemKind::Impl { .. } => { let generics = self.tcx.generics_of(impl_did); generics.requires_monomorphization(self.tcx) diff --git a/compiler/rustc_passes/src/region.rs b/compiler/rustc_passes/src/region.rs index 6a8feb041d..8968c16398 100644 --- a/compiler/rustc_passes/src/region.rs +++ b/compiler/rustc_passes/src/region.rs @@ -11,7 +11,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; -use rustc_hir::{Arm, Block, Expr, Local, Node, Pat, PatKind, Stmt}; +use rustc_hir::{Arm, Block, Expr, Local, Pat, PatKind, Stmt}; use rustc_index::vec::Idx; use rustc_middle::middle::region::*; use rustc_middle::ty::query::Providers; @@ -421,11 +421,14 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h // Mark this expr's scope and all parent scopes as containing `yield`. let mut scope = Scope { id: expr.hir_id.local_id, data: ScopeData::Node }; loop { - let data = YieldData { - span: expr.span, - expr_and_pat_count: visitor.expr_and_pat_count, - source: *source, + let span = match expr.kind { + hir::ExprKind::Yield(expr, hir::YieldSource::Await { .. }) => { + expr.span.shrink_to_hi().to(expr.span) + } + _ => expr.span, }; + let data = + YieldData { span, expr_and_pat_count: visitor.expr_and_pat_count, source: *source }; visitor.scope_tree.yield_in_scope.insert(scope, data); if visitor.pessimistic_yield { debug!("resolve_expr in pessimistic_yield - marking scope {:?} for fixup", scope); @@ -837,19 +840,7 @@ fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree { let body = tcx.hir().body(body_id); visitor.scope_tree.root_body = Some(body.value.hir_id); - - // If the item is an associated const or a method, - // record its impl/trait parent, as it can also have - // lifetime parameters free in this body. - match tcx.hir().get(id) { - Node::ImplItem(_) | Node::TraitItem(_) => { - visitor.scope_tree.root_parent = Some(tcx.hir().get_parent_item(id)); - } - _ => {} - } - visitor.visit_body(body); - visitor.scope_tree } else { ScopeTree::default() diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 8c9f04bef1..5f19991f9c 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -655,7 +655,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { // stable (assuming they have not inherited instability from their parent). } -fn stability_index(tcx: TyCtxt<'tcx>, (): ()) -> Index<'tcx> { +fn stability_index<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> Index<'tcx> { let is_staged_api = tcx.sess.opts.debugging_opts.force_unstable_if_unmarked || tcx.features().staged_api; let mut staged_api = FxHashMap::default(); @@ -737,7 +737,7 @@ struct Checker<'tcx> { tcx: TyCtxt<'tcx>, } -impl Visitor<'tcx> for Checker<'tcx> { +impl<'tcx> Visitor<'tcx> for Checker<'tcx> { type Map = Map<'tcx>; /// Because stability levels are scoped lexically, we want to walk @@ -866,7 +866,7 @@ struct CheckTraitImplStable<'tcx> { fully_stable: bool, } -impl Visitor<'tcx> for CheckTraitImplStable<'tcx> { +impl<'tcx> Visitor<'tcx> for CheckTraitImplStable<'tcx> { type Map = Map<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -970,7 +970,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { // We always collect the lib features declared in the current crate, even if there are // no unknown features, because the collection also does feature attribute validation. - let local_defined_features = tcx.lib_features().to_vec(); + let local_defined_features = tcx.lib_features(()).to_vec(); if !remaining_lib_features.is_empty() { check_features(&mut remaining_lib_features, &local_defined_features); diff --git a/compiler/rustc_passes/src/upvars.rs b/compiler/rustc_passes/src/upvars.rs index 91b8ae0763..2d84c8caad 100644 --- a/compiler/rustc_passes/src/upvars.rs +++ b/compiler/rustc_passes/src/upvars.rs @@ -42,7 +42,7 @@ struct LocalCollector { locals: FxHashSet, } -impl Visitor<'tcx> for LocalCollector { +impl<'tcx> Visitor<'tcx> for LocalCollector { type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -71,7 +71,7 @@ impl CaptureCollector<'_, '_> { } } -impl Visitor<'tcx> for CaptureCollector<'a, 'tcx> { +impl<'tcx> Visitor<'tcx> for CaptureCollector<'_, 'tcx> { type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs index c6c32e69aa..61c82f031d 100644 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ b/compiler/rustc_passes/src/weak_lang_items.rs @@ -67,10 +67,16 @@ fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) { } else if item == LangItem::Oom { if !tcx.features().default_alloc_error_handler { tcx.sess.err("`#[alloc_error_handler]` function required, but not found"); - tcx.sess.note_without_error("Use `#![feature(default_alloc_error_handler)]` for a default error handler"); + tcx.sess.note_without_error("use `#![feature(default_alloc_error_handler)]` for a default error handler"); } } else { - tcx.sess.err(&format!("language item required, but not found: `{}`", name)); + tcx + .sess + .diagnostic() + .struct_err(&format!("language item required, but not found: `{}`", name)) + .note(&format!("this can occur when a binary crate with `#![no_std]` is compiled for a target where `{}` is defined in the standard library", name)) + .help(&format!("you may be able to compile for a target that doesn't need `{}`, specify a target with `--target` or in `.cargo/config`", name)) + .emit(); } } } diff --git a/compiler/rustc_plugin_impl/Cargo.toml b/compiler/rustc_plugin_impl/Cargo.toml index 4e666e7e93..f5071eb6e8 100644 --- a/compiler/rustc_plugin_impl/Cargo.toml +++ b/compiler/rustc_plugin_impl/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" doctest = false [dependencies] +libloading = "0.7.1" rustc_middle = { path = "../rustc_middle" } rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } diff --git a/compiler/rustc_plugin_impl/src/load.rs b/compiler/rustc_plugin_impl/src/load.rs index c21075a443..618682da4e 100644 --- a/compiler/rustc_plugin_impl/src/load.rs +++ b/compiler/rustc_plugin_impl/src/load.rs @@ -1,6 +1,7 @@ //! Used by `rustc` when loading a plugin. use crate::Registry; +use libloading::Library; use rustc_ast::Crate; use rustc_errors::struct_span_err; use rustc_metadata::locator; @@ -56,37 +57,28 @@ fn load_plugin( ident: Ident, ) { let lib = locator::find_plugin_registrar(sess, metadata_loader, ident.span, ident.name); - let fun = dylink_registrar(sess, ident.span, lib); + let fun = dylink_registrar(lib).unwrap_or_else(|err| { + // This is fatal: there are almost certainly macros we need inside this crate, so + // continuing would spew "macro undefined" errors. + sess.span_fatal(ident.span, &err.to_string()); + }); plugins.push(fun); } -// Dynamically link a registrar function into the compiler process. -fn dylink_registrar(sess: &Session, span: Span, path: PathBuf) -> PluginRegistrarFn { - use rustc_metadata::dynamic_lib::DynamicLibrary; - +/// Dynamically link a registrar function into the compiler process. +fn dylink_registrar(lib_path: PathBuf) -> Result { // Make sure the path contains a / or the linker will search for it. - let path = env::current_dir().unwrap().join(&path); + let lib_path = env::current_dir().unwrap().join(&lib_path); - let lib = match DynamicLibrary::open(&path) { - Ok(lib) => lib, - // this is fatal: there are almost certainly macros we need - // inside this crate, so continue would spew "macro undefined" - // errors - Err(err) => sess.span_fatal(span, &err), - }; + let lib = unsafe { Library::new(&lib_path) }?; - unsafe { - let registrar = match lib.symbol("__rustc_plugin_registrar") { - Ok(registrar) => mem::transmute::<*mut u8, PluginRegistrarFn>(registrar), - // again fatal if we can't register macros - Err(err) => sess.span_fatal(span, &err), - }; + let registrar_sym = unsafe { lib.get::(b"__rustc_plugin_registrar") }?; - // Intentionally leak the dynamic library. We can't ever unload it - // since the library can make things that will live arbitrarily long - // (e.g., an Rc cycle or a thread). - mem::forget(lib); + // Intentionally leak the dynamic library. We can't ever unload it + // since the library can make things that will live arbitrarily long + // (e.g., an Rc cycle or a thread). + let registrar_sym = unsafe { registrar_sym.into_raw() }; + mem::forget(lib); - registrar - } + Ok(*registrar_sym) } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 11668146f7..183a5a205e 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1,5 +1,4 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![feature(in_band_lifetimes)] #![feature(nll)] #![feature(control_flow_enum)] #![feature(try_blocks)] @@ -310,7 +309,7 @@ struct PubRestrictedVisitor<'tcx> { has_pub_restricted: bool, } -impl Visitor<'tcx> for PubRestrictedVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for PubRestrictedVisitor<'tcx> { type Map = Map<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -432,7 +431,7 @@ struct ReachEverythingInTheInterfaceVisitor<'a, 'tcx> { ev: &'a mut EmbargoVisitor<'tcx>, } -impl EmbargoVisitor<'tcx> { +impl<'tcx> EmbargoVisitor<'tcx> { fn get(&self, def_id: LocalDefId) -> Option { self.access_levels.map.get(&def_id).copied() } @@ -559,8 +558,7 @@ impl EmbargoVisitor<'tcx> { // have normal hygine, so we can treat them like other items without type // privacy and mark them reachable. DefKind::Macro(_) => { - let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); - let item = self.tcx.hir().expect_item(hir_id); + let item = self.tcx.hir().expect_item(def_id); if let hir::ItemKind::Macro(MacroDef { macro_rules: false, .. }) = item.kind { if vis.is_accessible_from(module.to_def_id(), self.tcx) { self.update(def_id, level); @@ -581,8 +579,7 @@ impl EmbargoVisitor<'tcx> { DefKind::Struct | DefKind::Union => { // While structs and unions have type privacy, their fields do not. if vis.is_public() { - let item = - self.tcx.hir().expect_item(self.tcx.hir().local_def_id_to_hir_id(def_id)); + let item = self.tcx.hir().expect_item(def_id); if let hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) = item.kind { @@ -653,9 +650,7 @@ impl EmbargoVisitor<'tcx> { // If the module is `self`, i.e. the current crate, // there will be no corresponding item. .filter(|def_id| def_id.index != CRATE_DEF_INDEX || def_id.krate != LOCAL_CRATE) - .and_then(|def_id| { - def_id.as_local().map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id)) - }) + .and_then(|def_id| def_id.as_local()) .map(|module_hir_id| self.tcx.hir().expect_item(module_hir_id)) { if let hir::ItemKind::Mod(m) = &item.kind { @@ -678,7 +673,7 @@ impl EmbargoVisitor<'tcx> { } } -impl Visitor<'tcx> for EmbargoVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { type Map = Map<'tcx>; /// We want to visit items in the context of their containing @@ -948,7 +943,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { } } -impl ReachEverythingInTheInterfaceVisitor<'_, 'tcx> { +impl ReachEverythingInTheInterfaceVisitor<'_, '_> { fn generics(&mut self) -> &mut Self { for param in &self.ev.tcx.generics_of(self.item_def_id).params { match param.kind { @@ -987,7 +982,7 @@ impl ReachEverythingInTheInterfaceVisitor<'_, 'tcx> { } } -impl DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> { +impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.ev.tcx } @@ -1417,7 +1412,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { } } -impl DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> { +impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -1804,7 +1799,7 @@ struct SearchInterfaceForPrivateItemsVisitor<'tcx> { in_assoc_ty: bool, } -impl SearchInterfaceForPrivateItemsVisitor<'tcx> { +impl SearchInterfaceForPrivateItemsVisitor<'_> { fn generics(&mut self) -> &mut Self { for param in &self.tcx.generics_of(self.item_def_id).params { match param.kind { @@ -1925,7 +1920,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'tcx> { } } -impl DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> { +impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -2069,7 +2064,11 @@ impl<'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'tcx> { // Subitems of trait impls have inherited publicity. hir::ItemKind::Impl(ref impl_) => { let impl_vis = ty::Visibility::of_impl(item.def_id, tcx, &Default::default()); - self.check(item.def_id, impl_vis).generics().predicates(); + // check that private components do not appear in the generics or predicates of inherent impls + // this check is intentionally NOT performed for impls of traits, per #90586 + if impl_.of_trait.is_none() { + self.check(item.def_id, impl_vis).generics().predicates(); + } for impl_item_ref in impl_.items { let impl_item_vis = if impl_.of_trait.is_none() { min(tcx.visibility(impl_item_ref.id.def_id), impl_vis, tcx) diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index 3448928759..581a2bce2e 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -151,7 +151,7 @@ impl Key for (DefId, DefId) { } } -impl Key for (ty::Instance<'tcx>, LocalDefId) { +impl<'tcx> Key for (ty::Instance<'tcx>, LocalDefId) { #[inline(always)] fn query_crate_is_local(&self) -> bool { true diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 440b6f1983..de9d425353 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -2,7 +2,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(crate_visibility_modifier)] -#![feature(in_band_lifetimes)] #![feature(nll)] #![feature(min_specialization)] #![feature(once_cell)] diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs index 552906aac3..6a88e12353 100644 --- a/compiler/rustc_query_impl/src/on_disk_cache.rs +++ b/compiler/rustc_query_impl/src/on_disk_cache.rs @@ -158,7 +158,7 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { // Wrap in a scope so we can borrow `data`. let footer: Footer = { - let mut decoder = opaque::Decoder::new(&data[..], start_pos); + let mut decoder = opaque::Decoder::new(&data, start_pos); // Decode the *position* of the footer, which can be found in the // last 8 bytes of the file. @@ -212,7 +212,7 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> { /// Cache promotions require invoking queries, which needs to read the serialized data. /// In order to serialize the new on-disk cache, the former on-disk cache file needs to be /// deleted, hence we won't be able to refer to its memmapped data. - fn drop_serialized_data(&self, tcx: TyCtxt<'tcx>) { + fn drop_serialized_data(&self, tcx: TyCtxt<'_>) { // Load everything into memory so we can write it out to the on-disk // cache. The vast majority of cacheable query results should already // be in memory, so this should be a cheap operation. @@ -495,6 +495,20 @@ impl<'a, 'tcx> CacheDecoder<'a, 'tcx> { .entry(index) .or_insert_with(|| { let stable_id = file_index_to_stable_id[&index].translate(tcx); + + // If this `SourceFile` is from a foreign crate, then make sure + // that we've imported all of the source files from that crate. + // This has usually already been done during macro invocation. + // However, when encoding query results like `TypeckResults`, + // we might encode an `AdtDef` for a foreign type (because it + // was referenced in the body of the function). There is no guarantee + // that we will load the source files from that crate during macro + // expansion, so we use `import_source_files` to ensure that the foreign + // source files are actually imported before we call `source_file_by_stable_id`. + if stable_id.cnum != LOCAL_CRATE { + self.tcx.cstore_untracked().import_source_files(self.tcx.sess, stable_id.cnum); + } + source_map .source_file_by_stable_id(stable_id) .expect("failed to lookup `SourceFile` in new context") diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 81a36e0d59..6d76d09f61 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -31,7 +31,7 @@ impl<'tcx> std::ops::Deref for QueryCtxt<'tcx> { } } -impl HasDepContext for QueryCtxt<'tcx> { +impl<'tcx> HasDepContext for QueryCtxt<'tcx> { type DepKind = rustc_middle::dep_graph::DepKind; type DepContext = TyCtxt<'tcx>; @@ -41,7 +41,7 @@ impl HasDepContext for QueryCtxt<'tcx> { } } -impl QueryContext for QueryCtxt<'tcx> { +impl QueryContext for QueryCtxt<'_> { fn current_query_job(&self) -> Option> { tls::with_related_context(**self, |icx| icx.query) } @@ -130,7 +130,7 @@ impl<'tcx> QueryCtxt<'tcx> { pub(super) fn encode_query_results( self, - encoder: &mut on_disk_cache::CacheEncoder<'a, 'tcx, opaque::FileEncoder>, + encoder: &mut on_disk_cache::CacheEncoder<'_, 'tcx, opaque::FileEncoder>, query_result_index: &mut on_disk_cache::EncodedDepNodeIndex, ) -> opaque::FileEncodeResult { macro_rules! encode_queries { @@ -231,6 +231,16 @@ macro_rules! get_provider { }; } +macro_rules! opt_remap_env_constness { + ([][$name:ident]) => {}; + ([(remap_env_constness) $($rest:tt)*][$name:ident]) => { + let $name = $name.without_const(); + }; + ([$other:tt $($modifiers:tt)*][$name:ident]) => { + opt_remap_env_constness!([$($modifiers)*][$name]) + }; +} + macro_rules! define_queries { (<$tcx:tt> $($(#[$attr:meta])* @@ -247,6 +257,7 @@ macro_rules! define_queries { // Create an eponymous constructor for each query. $(#[allow(nonstandard_style)] $(#[$attr])* pub fn $name<$tcx>(tcx: QueryCtxt<$tcx>, key: query_keys::$name<$tcx>) -> QueryStackFrame { + opt_remap_env_constness!([$($modifiers)*][key]); let kind = dep_graph::DepKind::$name; let name = stringify!($name); // Disable visible paths printing for performance reasons. @@ -500,7 +511,7 @@ macro_rules! define_queries_struct { } } - impl QueryEngine<'tcx> for Queries<'tcx> { + impl<'tcx> QueryEngine<'tcx> for Queries<'tcx> { fn as_any(&'tcx self) -> &'tcx dyn std::any::Any { let this = unsafe { std::mem::transmute::<&Queries<'_>, &Queries<'_>>(self) }; this as _ @@ -521,6 +532,7 @@ macro_rules! define_queries_struct { lookup: QueryLookup, mode: QueryMode, ) -> Option> { + opt_remap_env_constness!([$($modifiers)*][key]); let qcx = QueryCtxt { tcx, queries: self }; get_query::, _>(qcx, span, key, lookup, mode) })* diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs index 95edc1e93a..da318fc762 100644 --- a/compiler/rustc_query_impl/src/profiling_support.rs +++ b/compiler/rustc_query_impl/src/profiling_support.rs @@ -61,8 +61,8 @@ impl<'p, 'c, 'tcx> QueryKeyStringBuilder<'p, 'c, 'tcx> { match def_key.disambiguated_data.data { DefPathData::CrateRoot => { - crate_name = self.tcx.crate_name(def_id.krate).as_str(); - name = &*crate_name; + crate_name = self.tcx.crate_name(def_id.krate); + name = crate_name.as_str(); dis = ""; end_index = 3; } @@ -295,7 +295,7 @@ fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>( /// If we are recording only summary data, the ids will point to /// just the query names. If we are recording query keys too, we /// allocate the corresponding strings here. -pub fn alloc_self_profile_query_strings(tcx: TyCtxt<'tcx>) { +pub fn alloc_self_profile_query_strings(tcx: TyCtxt<'_>) { if !tcx.prof.enabled() { return; } diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index a8be1ca34c..7bc3fd718e 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -88,6 +88,11 @@ struct DepGraphData { previous_work_products: FxHashMap, dep_node_debug: Lock, String>>, + + /// Used by incremental compilation tests to assert that + /// a particular query result was decoded from disk + /// (not just marked green) + debug_loaded_from_disk: Lock>>, } pub fn hash_result(hcx: &mut StableHashingContext<'_>, result: &R) -> Fingerprint @@ -135,6 +140,7 @@ impl DepGraph { processed_side_effects: Default::default(), previous: prev_graph, colors: DepNodeColorMap::new(prev_graph_node_count), + debug_loaded_from_disk: Default::default(), })), virtual_dep_node_index: Lrc::new(AtomicU32::new(0)), } @@ -438,6 +444,14 @@ impl DepGraph { &self.data.as_ref().unwrap().previous_work_products } + pub fn mark_debug_loaded_from_disk(&self, dep_node: DepNode) { + self.data.as_ref().unwrap().debug_loaded_from_disk.lock().insert(dep_node); + } + + pub fn debug_was_loaded_from_disk(&self, dep_node: DepNode) -> bool { + self.data.as_ref().unwrap().debug_loaded_from_disk.lock().contains(&dep_node) + } + #[inline(always)] pub fn register_dep_node_debug_str(&self, dep_node: DepNode, debug_str_gen: F) where diff --git a/compiler/rustc_query_system/src/ich/impls_hir.rs b/compiler/rustc_query_system/src/ich/impls_hir.rs index 3a0aab81fd..3117140a5b 100644 --- a/compiler/rustc_query_system/src/ich/impls_hir.rs +++ b/compiler/rustc_query_system/src/ich/impls_hir.rs @@ -3,8 +3,7 @@ use crate::ich::hcx::BodyResolver; use crate::ich::{NodeIdHashingMode, StableHashingContext}; -use rustc_data_structures::fingerprint::Fingerprint; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir as hir; use std::mem; @@ -47,28 +46,6 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { }) } - #[inline] - fn hash_hir_mod(&mut self, module: &hir::Mod<'_>, hasher: &mut StableHasher) { - let hcx = self; - let hir::Mod { inner: ref inner_span, ref item_ids } = *module; - - inner_span.hash_stable(hcx, hasher); - - // Combining the `DefPathHash`s directly is faster than feeding them - // into the hasher. Because we use a commutative combine, we also don't - // have to sort the array. - let item_ids_hash = item_ids - .iter() - .map(|id| { - let def_path_hash = id.to_stable_hash_key(hcx); - def_path_hash.0 - }) - .fold(Fingerprint::ZERO, |a, b| a.combine_commutative(b)); - - item_ids.len().hash_stable(hcx, hasher); - item_ids_hash.hash_stable(hcx, hasher); - } - fn hash_hir_expr(&mut self, expr: &hir::Expr<'_>, hasher: &mut StableHasher) { self.while_hashing_hir_bodies(true, |hcx| { let hir::Expr { hir_id: _, ref span, ref kind } = *expr; diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index b1295ba48c..0436e07e2d 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -2,10 +2,8 @@ #![feature(bool_to_option)] #![feature(core_intrinsics)] #![feature(hash_raw_entry)] -#![feature(iter_zip)] #![feature(let_else)] #![feature(min_specialization)] -#![feature(thread_local_const_init)] #![feature(extern_types)] #[macro_use] diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index b08db39e24..33732f9df7 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -519,6 +519,10 @@ where prof_timer.finish_with_query_invocation_id(dep_node_index.into()); if let Some(result) = result { + if unlikely!(tcx.dep_context().sess().opts.debugging_opts.query_dep_graph) { + dep_graph.mark_debug_loaded_from_disk(*dep_node) + } + let prev_fingerprint = tcx .dep_context() .dep_graph() diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 3cf9d324a3..39074f811a 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -108,7 +108,7 @@ impl<'a> Resolver<'a> { /// Reachable macros with block module parents exist due to `#[macro_export] macro_rules!`, /// but they cannot use def-site hygiene, so the assumption holds /// (). - fn get_nearest_non_block_module(&mut self, mut def_id: DefId) -> Module<'a> { + crate fn get_nearest_non_block_module(&mut self, mut def_id: DefId) -> Module<'a> { loop { match self.get_module(def_id) { Some(module) => return module, @@ -651,11 +651,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { /// Constructs the reduced graph for one item. fn build_reduced_graph_for_item(&mut self, item: &'b Item) { - if matches!(item.kind, ItemKind::Mod(..)) && item.ident.name == kw::Empty { - // Fake crate root item from expand. - return; - } - let parent_scope = &self.parent_scope; let parent = parent_scope.module; let expansion = parent_scope.expansion; @@ -683,75 +678,13 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } ItemKind::ExternCrate(orig_name) => { - let module = if orig_name.is_none() && ident.name == kw::SelfLower { - self.r - .session - .struct_span_err(item.span, "`extern crate self;` requires renaming") - .span_suggestion( - item.span, - "try", - "extern crate self as name;".into(), - Applicability::HasPlaceholders, - ) - .emit(); - return; - } else if orig_name == Some(kw::SelfLower) { - self.r.graph_root - } else { - let crate_id = self.r.crate_loader.process_extern_crate( - item, - &self.r.definitions, - local_def_id, - ); - self.r.extern_crate_map.insert(local_def_id, crate_id); - self.r.expect_module(crate_id.as_def_id()) - }; - - let used = self.process_macro_use_imports(item, module); - let binding = - (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.r.arenas); - let import = self.r.arenas.alloc_import(Import { - kind: ImportKind::ExternCrate { source: orig_name, target: ident }, - root_id: item.id, - id: item.id, - parent_scope: self.parent_scope, - imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))), - has_attributes: !item.attrs.is_empty(), - use_span_with_attributes: item.span_with_attributes(), - use_span: item.span, - root_span: item.span, - span: item.span, - module_path: Vec::new(), - vis: Cell::new(vis), - used: Cell::new(used), - }); - self.r.potentially_unused_imports.push(import); - let imported_binding = self.r.import(binding, import); - if ptr::eq(parent, self.r.graph_root) { - if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0()) - { - if expansion != LocalExpnId::ROOT - && orig_name.is_some() - && entry.extern_crate_item.is_none() - { - let msg = "macro-expanded `extern crate` items cannot \ - shadow names passed with `--extern`"; - self.r.session.span_err(item.span, msg); - } - } - let entry = - self.r.extern_prelude.entry(ident.normalize_to_macros_2_0()).or_insert( - ExternPreludeEntry { - extern_crate_item: None, - introduced_by_item: true, - }, - ); - entry.extern_crate_item = Some(imported_binding); - if orig_name.is_some() { - entry.introduced_by_item = true; - } - } - self.r.define(parent, ident, TypeNS, imported_binding); + self.build_reduced_graph_for_extern_crate( + orig_name, + item, + local_def_id, + vis, + parent, + ); } ItemKind::Mod(..) => { @@ -889,6 +822,87 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } } + fn build_reduced_graph_for_extern_crate( + &mut self, + orig_name: Option, + item: &Item, + local_def_id: LocalDefId, + vis: ty::Visibility, + parent: Module<'a>, + ) { + let ident = item.ident; + let sp = item.span; + let parent_scope = self.parent_scope; + let expansion = parent_scope.expansion; + + let (used, module, binding) = if orig_name.is_none() && ident.name == kw::SelfLower { + self.r + .session + .struct_span_err(item.span, "`extern crate self;` requires renaming") + .span_suggestion( + item.span, + "rename the `self` crate to be able to import it", + "extern crate self as name;".into(), + Applicability::HasPlaceholders, + ) + .emit(); + return; + } else if orig_name == Some(kw::SelfLower) { + Some(self.r.graph_root) + } else { + self.r.crate_loader.process_extern_crate(item, &self.r.definitions, local_def_id).map( + |crate_id| { + self.r.extern_crate_map.insert(local_def_id, crate_id); + self.r.expect_module(crate_id.as_def_id()) + }, + ) + } + .map(|module| { + let used = self.process_macro_use_imports(item, module); + let binding = + (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.r.arenas); + (used, Some(ModuleOrUniformRoot::Module(module)), binding) + }) + .unwrap_or((true, None, self.r.dummy_binding)); + let import = self.r.arenas.alloc_import(Import { + kind: ImportKind::ExternCrate { source: orig_name, target: ident }, + root_id: item.id, + id: item.id, + parent_scope: self.parent_scope, + imported_module: Cell::new(module), + has_attributes: !item.attrs.is_empty(), + use_span_with_attributes: item.span_with_attributes(), + use_span: item.span, + root_span: item.span, + span: item.span, + module_path: Vec::new(), + vis: Cell::new(vis), + used: Cell::new(used), + }); + self.r.potentially_unused_imports.push(import); + let imported_binding = self.r.import(binding, import); + if ptr::eq(parent, self.r.graph_root) { + if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0()) { + if expansion != LocalExpnId::ROOT + && orig_name.is_some() + && entry.extern_crate_item.is_none() + { + let msg = "macro-expanded `extern crate` items cannot \ + shadow names passed with `--extern`"; + self.r.session.span_err(item.span, msg); + } + } + let entry = self.r.extern_prelude.entry(ident.normalize_to_macros_2_0()).or_insert( + ExternPreludeEntry { extern_crate_item: None, introduced_by_item: true }, + ); + entry.extern_crate_item = Some(imported_binding); + if orig_name.is_some() { + entry.introduced_by_item = true; + } + } + self.r.define(parent, ident, TypeNS, imported_binding); + } + /// Constructs the reduced graph for one foreign item. fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem) { let local_def_id = self.r.local_def_id(item.id); @@ -1002,10 +1016,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.insert_field_names(def_id, field_names); } Res::Def(DefKind::AssocFn, def_id) => { - if cstore - .associated_item_cloned_untracked(def_id, self.r.session) - .fn_has_self_parameter - { + if cstore.fn_has_self_parameter_untracked(def_id) { self.r.has_self.insert(def_id); } } @@ -1499,4 +1510,13 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { visit::walk_variant(self, variant); } + + fn visit_crate(&mut self, krate: &'b ast::Crate) { + if krate.is_placeholder { + self.visit_invoc_in_module(krate.id); + } else { + visit::walk_crate(self, krate); + self.contains_macro_use(&krate.attrs); + } + } } diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 63699128e9..601f2d96ff 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -24,6 +24,7 @@ // in the last step use crate::imports::ImportKind; +use crate::module_to_string; use crate::Resolver; use rustc_ast as ast; @@ -314,12 +315,29 @@ impl Resolver<'_> { "remove the unused import" }; + let parent_module = visitor.r.get_nearest_non_block_module( + visitor.r.local_def_id(unused.use_tree_id).to_def_id(), + ); + let test_module_span = match module_to_string(parent_module) { + Some(module) + if module == "test" + || module == "tests" + || module.starts_with("test_") + || module.starts_with("tests_") + || module.ends_with("_test") + || module.ends_with("_tests") => + { + Some(parent_module.span) + } + _ => None, + }; + visitor.r.lint_buffer.buffer_lint_with_diagnostic( UNUSED_IMPORTS, unused.use_tree_id, ms, &msg, - BuiltinLintDiagnostics::UnusedImports(fix_msg.into(), fixes), + BuiltinLintDiagnostics::UnusedImports(fix_msg.into(), fixes, test_module_span), ); } } diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 5879cb1daa..8ea5dca6f1 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -7,7 +7,7 @@ use rustc_expand::expand::AstFragment; use rustc_hir::def_id::LocalDefId; use rustc_hir::definitions::*; use rustc_span::hygiene::LocalExpnId; -use rustc_span::symbol::{kw, sym}; +use rustc_span::symbol::sym; use rustc_span::Span; use tracing::debug; @@ -92,10 +92,7 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> { // information we encapsulate into, the better let def_data = match &i.kind { ItemKind::Impl { .. } => DefPathData::Impl, - ItemKind::Mod(..) if i.ident.name == kw::Empty => { - // Fake crate root item from expand. - return visit::walk_item(self, i); - } + ItemKind::ForeignMod(..) => DefPathData::ForeignMod, ItemKind::Mod(..) | ItemKind::Trait(..) | ItemKind::TraitAlias(..) @@ -103,7 +100,6 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> { | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::ExternCrate(..) - | ItemKind::ForeignMod(..) | ItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name), ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => { DefPathData::ValueNs(i.ident.name) @@ -346,4 +342,12 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> { fn visit_field_def(&mut self, field: &'a FieldDef) { self.collect_field(field, None); } + + fn visit_crate(&mut self, krate: &'a Crate) { + if krate.is_placeholder { + self.visit_macro_invoc(krate.id) + } else { + visit::walk_crate(self, krate) + } + } } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 2e4cb4ff72..4feeae5cab 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1,4 +1,3 @@ -use std::cmp::Reverse; use std::ptr; use rustc_ast::{self as ast, Path}; @@ -784,7 +783,7 @@ impl<'a> Resolver<'a> { }); // Make sure error reporting is deterministic. - suggestions.sort_by_cached_key(|suggestion| suggestion.candidate.as_str()); + suggestions.sort_by(|a, b| a.candidate.as_str().partial_cmp(b.candidate.as_str()).unwrap()); match find_best_match_for_name( &suggestions.iter().map(|suggestion| suggestion.candidate).collect::>(), @@ -896,8 +895,11 @@ impl<'a> Resolver<'a> { // a note about editions let note = if let Some(did) = did { let requires_note = !did.is_local() - && this.cstore().item_attrs(did, this.session).iter().any( - |attr| { + && this + .cstore() + .item_attrs_untracked(did, this.session) + .iter() + .any(|attr| { if attr.has_name(sym::rustc_diagnostic_item) { [sym::TryInto, sym::TryFrom, sym::FromIterator] .map(|x| Some(x)) @@ -905,8 +907,7 @@ impl<'a> Resolver<'a> { } else { false } - }, - ); + }); requires_note.then(|| { format!( @@ -1178,7 +1179,7 @@ impl<'a> Resolver<'a> { fn binding_description(&self, b: &NameBinding<'_>, ident: Ident, from_prelude: bool) -> String { let res = b.res(); - if b.span.is_dummy() { + if b.span.is_dummy() || self.session.source_map().span_to_snippet(b.span).is_err() { // These already contain the "built-in" prefix or look bad with it. let add_built_in = !matches!(b.res(), Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod); @@ -1186,7 +1187,7 @@ impl<'a> Resolver<'a> { ("", " from prelude") } else if b.is_extern_crate() && !b.is_import() - && self.session.opts.externs.get(&ident.as_str()).is_some() + && self.session.opts.externs.get(ident.as_str()).is_some() { ("", " passed with `--extern`") } else if add_built_in { @@ -1481,12 +1482,12 @@ impl<'a, 'b> ImportResolver<'a, 'b> { return None; } - // Sort extern crate names in reverse order to get + // Sort extern crate names in *reverse* order to get // 1) some consistent ordering for emitted diagnostics, and // 2) `std` suggestions before `core` suggestions. let mut extern_crate_names = self.r.extern_prelude.iter().map(|(ident, _)| ident.name).collect::>(); - extern_crate_names.sort_by_key(|name| Reverse(name.as_str())); + extern_crate_names.sort_by(|a, b| b.as_str().partial_cmp(a.as_str()).unwrap()); for name in extern_crate_names.into_iter() { // Replace first ident with a crate name and check if that is valid. diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 12123c946c..5730502313 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1603,10 +1603,13 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { pat_src: PatternSource, bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet); 1]>, ) { + // We walk the pattern before declaring the pattern's inner bindings, + // so that we avoid resolving a literal expression to a binding defined + // by the pattern. + visit::walk_pat(self, pat); self.resolve_pattern_inner(pat, pat_src, bindings); // This has to happen *after* we determine which pat_idents are variants: self.check_consistent_bindings_top(pat); - visit::walk_pat(self, pat); } /// Resolve bindings in a pattern. This is a helper to `resolve_pattern`. @@ -2376,7 +2379,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ExprKind::While(ref cond, ref block, label) => { self.with_resolved_label(label, expr.id, |this| { this.with_rib(ValueNS, NormalRibKind, |this| { + let old = this.diagnostic_metadata.in_if_condition.replace(cond); this.visit_expr(cond); + this.diagnostic_metadata.in_if_condition = old; this.visit_block(block); }) }); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index d506931b51..4cd1b34bed 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -231,7 +231,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { let is_assoc_fn = self.self_type_is_available(span); // Emit help message for fake-self from other languages (e.g., `this` in Javascript). - if ["this", "my"].contains(&&*item_str.as_str()) && is_assoc_fn { + if ["this", "my"].contains(&item_str.as_str()) && is_assoc_fn { err.span_suggestion_short( span, "you might have meant to use `self` here instead", @@ -298,11 +298,16 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { .get(0) .map(|p| (p.span.shrink_to_lo(), "&self, ")) .unwrap_or_else(|| { + // Try to look for the "(" after the function name, if possible. + // This avoids placing the suggestion into the visibility specifier. + let span = fn_kind + .ident() + .map_or(*span, |ident| span.with_lo(ident.span.hi())); ( self.r .session .source_map() - .span_through_char(*span, '(') + .span_through_char(span, '(') .shrink_to_hi(), "&self", ) @@ -1353,7 +1358,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { let name = path[path.len() - 1].ident.name; // Make sure error reporting is deterministic. - names.sort_by_cached_key(|suggestion| suggestion.candidate.as_str()); + names.sort_by(|a, b| a.candidate.as_str().partial_cmp(b.candidate.as_str()).unwrap()); match find_best_match_for_name( &names.iter().map(|suggestion| suggestion.candidate).collect::>(), @@ -1372,7 +1377,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { fn likely_rust_type(path: &[Segment]) -> Option { let name = path[path.len() - 1].ident.as_str(); // Common Java types - Some(match &*name { + Some(match name { "byte" => sym::u8, // In Java, bytes are signed, but in practice one almost always wants unsigned bytes. "short" => sym::i16, "boolean" => sym::bool, @@ -1735,7 +1740,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { (generics.span, format!("<{}>", ident)) }; // Do not suggest if this is coming from macro expansion. - if !span.from_expansion() { + if span.can_be_used_for_suggestions() { return Some(( span.shrink_to_hi(), msg, @@ -1803,7 +1808,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { ); err.span_label(lifetime_ref.span, "undeclared lifetime"); let mut suggests_in_band = false; - let mut suggest_note = true; + let mut suggested_spans = vec![]; for missing in &self.missing_named_lifetime_spots { match missing { MissingLifetimeSpot::Generics(generics) => { @@ -1821,23 +1826,17 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { suggests_in_band = true; (generics.span, format!("<{}>", lifetime_ref)) }; - if !span.from_expansion() { + if suggested_spans.contains(&span) { + continue; + } + suggested_spans.push(span); + if span.can_be_used_for_suggestions() { err.span_suggestion( span, &format!("consider introducing lifetime `{}` here", lifetime_ref), sugg, Applicability::MaybeIncorrect, ); - } else if suggest_note { - suggest_note = false; // Avoid displaying the same help multiple times. - err.span_label( - span, - &format!( - "lifetime `{}` is missing in item created through this procedural \ - macro", - lifetime_ref, - ), - ); } } MissingLifetimeSpot::HigherRanked { span, span_type } => { @@ -1871,6 +1870,117 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { err.emit(); } + /// Returns whether to add `'static` lifetime to the suggested lifetime list. + crate fn report_elision_failure( + &mut self, + db: &mut DiagnosticBuilder<'_>, + params: &[ElisionFailureInfo], + ) -> bool { + let mut m = String::new(); + let len = params.len(); + + let elided_params: Vec<_> = + params.iter().cloned().filter(|info| info.lifetime_count > 0).collect(); + + let elided_len = elided_params.len(); + + for (i, info) in elided_params.into_iter().enumerate() { + let ElisionFailureInfo { parent, index, lifetime_count: n, have_bound_regions, span } = + info; + + db.span_label(span, ""); + let help_name = if let Some(ident) = + parent.and_then(|body| self.tcx.hir().body(body).params[index].pat.simple_ident()) + { + format!("`{}`", ident) + } else { + format!("argument {}", index + 1) + }; + + m.push_str( + &(if n == 1 { + help_name + } else { + format!( + "one of {}'s {} {}lifetimes", + help_name, + n, + if have_bound_regions { "free " } else { "" } + ) + })[..], + ); + + if elided_len == 2 && i == 0 { + m.push_str(" or "); + } else if i + 2 == elided_len { + m.push_str(", or "); + } else if i != elided_len - 1 { + m.push_str(", "); + } + } + + if len == 0 { + db.help( + "this function's return type contains a borrowed value, \ + but there is no value for it to be borrowed from", + ); + true + } else if elided_len == 0 { + db.help( + "this function's return type contains a borrowed value with \ + an elided lifetime, but the lifetime cannot be derived from \ + the arguments", + ); + true + } else if elided_len == 1 { + db.help(&format!( + "this function's return type contains a borrowed value, \ + but the signature does not say which {} it is borrowed from", + m + )); + false + } else { + db.help(&format!( + "this function's return type contains a borrowed value, \ + but the signature does not say whether it is borrowed from {}", + m + )); + false + } + } + + crate fn report_elided_lifetime_in_ty(&self, lifetime_refs: &[&hir::Lifetime]) { + let Some(missing_lifetime) = lifetime_refs.iter().find(|lt| { + lt.name == hir::LifetimeName::Implicit(true) + }) else { return }; + + let mut spans: Vec<_> = lifetime_refs.iter().map(|lt| lt.span).collect(); + spans.sort(); + let mut spans_dedup = spans.clone(); + spans_dedup.dedup(); + let spans_with_counts: Vec<_> = spans_dedup + .into_iter() + .map(|sp| (sp, spans.iter().filter(|nsp| *nsp == &sp).count())) + .collect(); + + self.tcx.struct_span_lint_hir( + rustc_session::lint::builtin::ELIDED_LIFETIMES_IN_PATHS, + missing_lifetime.hir_id, + spans, + |lint| { + let mut db = lint.build("hidden lifetime parameters in types are deprecated"); + self.add_missing_lifetime_specifiers_label( + &mut db, + spans_with_counts, + &FxHashSet::from_iter([kw::UnderscoreLifetime]), + Vec::new(), + &[], + ); + db.emit() + }, + ); + } + // FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const // generics. We are disallowing this until we can decide on how we want to handle non-'static // lifetimes in const generics. See issue #74052 for discussion. @@ -2005,11 +2115,19 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { let spans_suggs: Vec<_> = formatters .into_iter() .zip(spans_with_counts.iter()) - .filter_map(|(fmt, (span, _))| { - if let Some(formatter) = fmt { Some((formatter, span)) } else { None } + .filter_map(|(formatter, (span, _))| { + if let Some(formatter) = formatter { + Some((*span, formatter(name))) + } else { + None + } }) - .map(|(formatter, span)| (*span, formatter(name))) .collect(); + if spans_suggs.is_empty() { + // If all the spans come from macros, we cannot extract snippets and then + // `formatters` only contains None and `spans_suggs` is empty. + return; + } err.multipart_suggestion_verbose( &format!( "consider using the `{}` lifetime", @@ -2230,7 +2348,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { _ => None, }); } - suggest_existing(err, &name.as_str()[..], suggs); + suggest_existing(err, name.as_str(), suggs); } [] => { let mut suggs = Vec::new(); @@ -2297,7 +2415,9 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { ); let is_allowed_lifetime = matches!( lifetime_ref.name, - hir::LifetimeName::Implicit | hir::LifetimeName::Static | hir::LifetimeName::Underscore + hir::LifetimeName::Implicit(_) + | hir::LifetimeName::Static + | hir::LifetimeName::Underscore ); if !self.tcx.lazy_normalization() && is_anon_const && !is_allowed_lifetime { diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 39e710cb77..3322e36502 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -357,11 +357,11 @@ enum Elide { #[derive(Clone, Debug)] crate struct ElisionFailureInfo { /// Where we can find the argument pattern. - parent: Option, + crate parent: Option, /// The index of the argument in the original definition. - index: usize, - lifetime_count: usize, - have_bound_regions: bool, + crate index: usize, + crate lifetime_count: usize, + crate have_bound_regions: bool, crate span: Span, } @@ -445,7 +445,7 @@ fn do_resolve( trait_definition_only: bool, with_scope_for_path: bool, ) -> NamedRegionMap { - let item = tcx.hir().expect_item(tcx.hir().local_def_id_to_hir_id(local_def_id)); + let item = tcx.hir().expect_item(local_def_id); let mut named_region_map = NamedRegionMap { defs: Default::default(), late_bound: Default::default(), @@ -689,11 +689,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { hir_id: hir::HirId, ) { let name = match fk { - intravisit::FnKind::ItemFn(id, _, _, _) => id.as_str(), - intravisit::FnKind::Method(id, _, _) => id.as_str(), - intravisit::FnKind::Closure => Symbol::intern("closure").as_str(), + intravisit::FnKind::ItemFn(id, _, _, _) => id.name, + intravisit::FnKind::Method(id, _, _) => id.name, + intravisit::FnKind::Closure => sym::closure, }; - let name: &str = &name; + let name = name.as_str(); let span = span!(Level::DEBUG, "visit_fn", name); let _enter = span.enter(); match fk { @@ -923,7 +923,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } }); match lifetime.name { - LifetimeName::Implicit => { + LifetimeName::Implicit(_) => { // For types like `dyn Foo`, we should // generate a special form of elided. span_bug!(ty.span, "object-lifetime-default expected, not implicit",); @@ -968,7 +968,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let (generics, bounds) = match opaque_ty.kind { // Named opaque `impl Trait` types are reached via `TyKind::Path`. // This arm is for `impl Trait` in the types of statics, constants and locals. - hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: None, .. }) => { + hir::ItemKind::OpaqueTy(hir::OpaqueTy { + origin: hir::OpaqueTyOrigin::TyAlias, + .. + }) => { intravisit::walk_ty(self, ty); // Elided lifetimes are not allowed in non-return @@ -985,7 +988,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } // RPIT (return position impl trait) hir::ItemKind::OpaqueTy(hir::OpaqueTy { - impl_trait_fn: Some(_), + origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..), ref generics, bounds, .. @@ -1134,7 +1137,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { self.missing_named_lifetime_spots.push((&trait_item.generics).into()); let tcx = self.tcx; self.visit_early_late( - Some(tcx.hir().get_parent_item(trait_item.hir_id())), + Some(tcx.hir().get_parent_did(trait_item.hir_id())), trait_item.hir_id(), &sig.decl, &trait_item.generics, @@ -1203,7 +1206,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { self.missing_named_lifetime_spots.push((&impl_item.generics).into()); let tcx = self.tcx; self.visit_early_late( - Some(tcx.hir().get_parent_item(impl_item.hir_id())), + Some(tcx.hir().get_parent_did(impl_item.hir_id())), impl_item.hir_id(), &sig.decl, &impl_item.generics, @@ -1347,11 +1350,14 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { this.visit_ty(&ty); } } - GenericParamKind::Const { ref ty, .. } => { + GenericParamKind::Const { ref ty, default } => { let was_in_const_generic = this.is_in_const_generic; this.is_in_const_generic = true; walk_list!(this, visit_param_bound, param.bounds); this.visit_ty(&ty); + if let Some(default) = default { + this.visit_body(this.tcx.hir().body(default.body)); + } this.is_in_const_generic = was_in_const_generic; } } @@ -1695,7 +1701,11 @@ fn compute_object_lifetime_defaults( hir::ItemKind::Struct(_, ref generics) | hir::ItemKind::Union(_, ref generics) | hir::ItemKind::Enum(_, ref generics) - | hir::ItemKind::OpaqueTy(hir::OpaqueTy { ref generics, impl_trait_fn: None, .. }) + | hir::ItemKind::OpaqueTy(hir::OpaqueTy { + ref generics, + origin: hir::OpaqueTyOrigin::TyAlias, + .. + }) | hir::ItemKind::TyAlias(_, ref generics) | hir::ItemKind::Trait(_, _, ref generics, ..) => { let result = object_lifetime_defaults_for_item(tcx, generics); @@ -2002,7 +2012,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } }; - let mut def_ids: Vec<_> = defined_by + let def_ids: Vec<_> = defined_by .values() .flat_map(|region| match region { Region::EarlyBound(_, def_id, _) @@ -2013,9 +2023,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { }) .collect(); - // ensure that we issue lints in a repeatable order - def_ids.sort_by_cached_key(|&def_id| self.tcx.def_path_hash(def_id)); - 'lifetimes: for def_id in def_ids { debug!("check_uses_for_lifetimes_defined_by_scope: def_id = {:?}", def_id); @@ -2067,7 +2074,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { .. }) = self.tcx.hir().get(parent_hir_id) { - if opaque.origin != hir::OpaqueTyOrigin::AsyncFn { + if !matches!(opaque.origin, hir::OpaqueTyOrigin::AsyncFn(..)) { continue 'lifetimes; } // We want to do this only if the liftime identifier is already defined @@ -2176,7 +2183,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { /// ordering is not important there. fn visit_early_late( &mut self, - parent_id: Option, + parent_id: Option, hir_id: hir::HirId, decl: &'tcx hir::FnDecl<'tcx>, generics: &'tcx hir::Generics<'tcx>, @@ -2534,8 +2541,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { GenericParamDefKind::Type { object_lifetime_default, .. } => { Some(object_lifetime_default) } - GenericParamDefKind::Lifetime - | GenericParamDefKind::Const { .. } => None, + GenericParamDefKind::Const { .. } => Some(Set1::Empty), + GenericParamDefKind::Lifetime => None, }) .collect() }) @@ -2562,12 +2569,11 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } GenericArg::Const(ct) => { self.visit_anon_const(&ct.value); + i += 1; } GenericArg::Infer(inf) => { self.visit_id(inf.hir_id); - if inf.kind.is_type() { - i += 1; - } + i += 1; } } } @@ -2758,7 +2764,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Fn(_, ref m), .. }) => { if let hir::ItemKind::Trait(.., ref trait_items) = - self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind + self.tcx.hir().expect_item(self.tcx.hir().get_parent_did(parent)).kind { assoc_item_kind = trait_items.iter().find(|ti| ti.id.hir_id() == parent).map(|ti| ti.kind); @@ -2771,7 +2777,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body), .. }) => { if let hir::ItemKind::Impl(hir::Impl { ref self_ty, ref items, .. }) = - self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind + self.tcx.hir().expect_item(self.tcx.hir().get_parent_did(parent)).kind { impl_self = Some(self_ty); assoc_item_kind = @@ -3057,9 +3063,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let error = loop { match *scope { // Do not assign any resolution, it will be inferred. - Scope::Body { .. } => return, + Scope::Body { .. } => break Ok(()), - Scope::Root => break None, + Scope::Root => break Err(None), Scope::Binder { s, ref lifetimes, scope_type, .. } => { // collect named lifetimes for suggestions @@ -3076,50 +3082,54 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { scope = s; } - Scope::Elision { ref elide, ref s, .. } => { - let lifetime = match *elide { - Elide::FreshLateAnon(named_late_bound_vars, ref counter) => { - for lifetime_ref in lifetime_refs { - let lifetime = Region::late_anon(named_late_bound_vars, counter) - .shifted(late_depth); + Scope::Elision { + elide: Elide::FreshLateAnon(named_late_bound_vars, ref counter), + .. + } => { + for lifetime_ref in lifetime_refs { + let lifetime = + Region::late_anon(named_late_bound_vars, counter).shifted(late_depth); - self.insert_lifetime(lifetime_ref, lifetime); - } - return; - } - Elide::Exact(l) => l.shifted(late_depth), - Elide::Error(ref e) => { - let mut scope = s; - loop { - match scope { - Scope::Binder { ref lifetimes, s, .. } => { - // Collect named lifetimes for suggestions. - for name in lifetimes.keys() { - if let hir::ParamName::Plain(name) = name { - lifetime_names.insert(name.name); - lifetime_spans.push(name.span); - } - } - scope = s; - } - Scope::ObjectLifetimeDefault { ref s, .. } - | Scope::Elision { ref s, .. } - | Scope::TraitRefBoundary { ref s, .. } => { - scope = s; - } - _ => break, - } - } - break Some(&e[..]); - } - Elide::Forbid => break None, - }; + self.insert_lifetime(lifetime_ref, lifetime); + } + break Ok(()); + } + + Scope::Elision { elide: Elide::Exact(l), .. } => { + let lifetime = l.shifted(late_depth); for lifetime_ref in lifetime_refs { self.insert_lifetime(lifetime_ref, lifetime); } - return; + break Ok(()); } + Scope::Elision { elide: Elide::Error(ref e), ref s, .. } => { + let mut scope = s; + loop { + match scope { + Scope::Binder { ref lifetimes, s, .. } => { + // Collect named lifetimes for suggestions. + for name in lifetimes.keys() { + if let hir::ParamName::Plain(name) = name { + lifetime_names.insert(name.name); + lifetime_spans.push(name.span); + } + } + scope = s; + } + Scope::ObjectLifetimeDefault { ref s, .. } + | Scope::Elision { ref s, .. } + | Scope::TraitRefBoundary { ref s, .. } => { + scope = s; + } + _ => break, + } + } + break Err(Some(&e[..])); + } + + Scope::Elision { elide: Elide::Forbid, .. } => break Err(None), + Scope::ObjectLifetimeDefault { s, .. } | Scope::Supertrait { s, .. } | Scope::TraitRefBoundary { s, .. } => { @@ -3128,6 +3138,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } }; + let error = match error { + Ok(()) => { + self.report_elided_lifetime_in_ty(lifetime_refs); + return; + } + Err(error) => error, + }; + // If we specifically need the `scope_for_path` map, then we're in the // diagnostic pass and we don't want to emit more errors. if self.map.scope_for_path.is_some() { @@ -3166,84 +3184,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { err.emit(); } - fn report_elision_failure( - &mut self, - db: &mut DiagnosticBuilder<'_>, - params: &[ElisionFailureInfo], - ) -> bool /* add `'static` lifetime to lifetime list */ { - let mut m = String::new(); - let len = params.len(); - - let elided_params: Vec<_> = - params.iter().cloned().filter(|info| info.lifetime_count > 0).collect(); - - let elided_len = elided_params.len(); - - for (i, info) in elided_params.into_iter().enumerate() { - let ElisionFailureInfo { parent, index, lifetime_count: n, have_bound_regions, span } = - info; - - db.span_label(span, ""); - let help_name = if let Some(ident) = - parent.and_then(|body| self.tcx.hir().body(body).params[index].pat.simple_ident()) - { - format!("`{}`", ident) - } else { - format!("argument {}", index + 1) - }; - - m.push_str( - &(if n == 1 { - help_name - } else { - format!( - "one of {}'s {} {}lifetimes", - help_name, - n, - if have_bound_regions { "free " } else { "" } - ) - })[..], - ); - - if elided_len == 2 && i == 0 { - m.push_str(" or "); - } else if i + 2 == elided_len { - m.push_str(", or "); - } else if i != elided_len - 1 { - m.push_str(", "); - } - } - - if len == 0 { - db.help( - "this function's return type contains a borrowed value, \ - but there is no value for it to be borrowed from", - ); - true - } else if elided_len == 0 { - db.help( - "this function's return type contains a borrowed value with \ - an elided lifetime, but the lifetime cannot be derived from \ - the arguments", - ); - true - } else if elided_len == 1 { - db.help(&format!( - "this function's return type contains a borrowed value, \ - but the signature does not say which {} it is borrowed from", - m - )); - false - } else { - db.help(&format!( - "this function's return type contains a borrowed value, \ - but the signature does not say whether it is borrowed from {}", - m - )); - false - } - } - fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) { debug!("resolve_object_lifetime_default(lifetime_ref={:?})", lifetime_ref); let mut late_depth = 0; @@ -3348,7 +3288,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { )) .emit(); } - hir::LifetimeName::Param(_) | hir::LifetimeName::Implicit => { + hir::LifetimeName::Param(_) | hir::LifetimeName::Implicit(_) => { self.resolve_lifetime_ref(lt); } hir::LifetimeName::ImplicitObjectLifetimeDefault => { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index d17e8875a1..b46a93c067 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -13,8 +13,6 @@ #![feature(drain_filter)] #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] -#![cfg_attr(bootstrap, feature(format_args_capture))] -#![feature(iter_zip)] #![feature(let_else)] #![feature(never_type)] #![feature(nll)] @@ -70,7 +68,7 @@ use smallvec::{smallvec, SmallVec}; use std::cell::{Cell, RefCell}; use std::collections::{BTreeMap, BTreeSet}; use std::ops::ControlFlow; -use std::{cmp, fmt, iter, ptr}; +use std::{cmp, fmt, iter, mem, ptr}; use tracing::debug; use diagnostics::{extend_span_to_previous_binding, find_span_of_binding_until_next_binding}; @@ -1396,7 +1394,7 @@ impl<'a> Resolver<'a> { .chain(features.declared_lang_features.iter().map(|(feat, ..)| *feat)) .collect(), lint_buffer: LintBuffer::default(), - next_node_id: NodeId::from_u32(1), + next_node_id: CRATE_NODE_ID, node_id_to_def_id, def_id_to_node_id, placeholder_field_indices: Default::default(), @@ -1430,13 +1428,9 @@ impl<'a> Resolver<'a> { } pub fn next_node_id(&mut self) -> NodeId { - let next = self - .next_node_id - .as_usize() - .checked_add(1) - .expect("input too large; ran out of NodeIds"); - self.next_node_id = ast::NodeId::from_usize(next); - self.next_node_id + let next = + self.next_node_id.as_u32().checked_add(1).expect("input too large; ran out of NodeIds"); + mem::replace(&mut self.next_node_id, ast::NodeId::from_u32(next)) } pub fn lint_buffer(&mut self) -> &mut LintBuffer { @@ -3288,7 +3282,9 @@ impl<'a> Resolver<'a> { Some(binding) } else { let crate_id = if !speculative { - self.crate_loader.process_path_extern(ident.name, ident.span) + let Some(crate_id) = + self.crate_loader.process_path_extern(ident.name, ident.span) else { return Some(self.dummy_binding); }; + crate_id } else { self.crate_loader.maybe_process_path_extern(ident.name)? }; @@ -3422,27 +3418,21 @@ impl<'a> Resolver<'a> { return v.clone(); } - let parse_attrs = || { - let attrs = self.cstore().item_attrs(def_id, self.session); - let attr = - attrs.iter().find(|a| a.has_name(sym::rustc_legacy_const_generics))?; - let mut ret = vec![]; - for meta in attr.meta_item_list()? { - match meta.literal()?.kind { - LitKind::Int(a, _) => { - ret.push(a as usize); - } - _ => panic!("invalid arg index"), - } + let attr = self + .cstore() + .item_attrs_untracked(def_id, self.session) + .into_iter() + .find(|a| a.has_name(sym::rustc_legacy_const_generics))?; + let mut ret = Vec::new(); + for meta in attr.meta_item_list()? { + match meta.literal()?.kind { + LitKind::Int(a, _) => ret.push(a as usize), + _ => panic!("invalid arg index"), } - Some(ret) - }; - - // Cache the lookup to avoid parsing attributes for an iterm - // multiple times. - let ret = parse_attrs(); - self.legacy_const_generic_args.insert(def_id, ret.clone()); - return ret; + } + // Cache the lookup to avoid parsing attributes for an iterm multiple times. + self.legacy_const_generic_args.insert(def_id, Some(ret.clone())); + return Some(ret); } } None @@ -3484,7 +3474,7 @@ fn names_to_string(names: &[Symbol]) -> String { if Ident::with_dummy_span(*name).is_raw_guess() { result.push_str("r#"); } - result.push_str(&name.as_str()); + result.push_str(name.as_str()); } result } diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 28dbce0471..52685ec697 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -105,7 +105,7 @@ fn fast_print_path(path: &ast::Path) -> Symbol { path_str.push_str("::"); } if segment.ident.name != kw::PathRoot { - path_str.push_str(&segment.ident.as_str()) + path_str.push_str(segment.ident.as_str()) } } Symbol::intern(&path_str) diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index f1a5282b08..23f5b17fa7 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -1326,12 +1326,18 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { } intravisit::walk_qpath(self, path, t.hir_id, t.span); } - hir::TyKind::Array(ref ty, ref anon_const) => { + hir::TyKind::Array(ref ty, ref length) => { self.visit_ty(ty); let map = self.tcx.hir(); - self.nest_typeck_results(self.tcx.hir().local_def_id(anon_const.hir_id), |v| { - v.visit_expr(&map.body(anon_const.body).value) - }); + match length { + // FIXME(generic_arg_infer): We probably want to + // output the inferred type here? :shrug: + hir::ArrayLen::Infer(..) => {} + hir::ArrayLen::Body(anon_const) => self + .nest_typeck_results(self.tcx.hir().local_def_id(anon_const.hir_id), |v| { + v.visit_expr(&map.body(anon_const.body).value) + }), + } } hir::TyKind::OpaqueDef(item_id, _) => { let item = self.tcx.hir().item(item_id); @@ -1390,12 +1396,18 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { v.visit_expr(&body.value) }); } - hir::ExprKind::Repeat(ref expr, ref anon_const) => { + hir::ExprKind::Repeat(ref expr, ref length) => { self.visit_expr(expr); let map = self.tcx.hir(); - self.nest_typeck_results(self.tcx.hir().local_def_id(anon_const.hir_id), |v| { - v.visit_expr(&map.body(anon_const.body).value) - }); + match length { + // FIXME(generic_arg_infer): We probably want to + // output the inferred type here? :shrug: + hir::ArrayLen::Infer(..) => {} + hir::ArrayLen::Body(anon_const) => self + .nest_typeck_results(self.tcx.hir().local_def_id(anon_const.hir_id), |v| { + v.visit_expr(&map.body(anon_const.body).value) + }), + } } // In particular, we take this branch for call and path expressions, // where we'll index the idents involved just by continuing to walk. diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index c7f8fe3a88..7ec619e07f 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -825,7 +825,7 @@ impl<'tcx> SaveContext<'tcx> { for attr in attrs { if let Some(val) = attr.doc_str() { // FIXME: Should save-analysis beautify doc strings itself or leave it to users? - result.push_str(&beautify_doc_string(val).as_str()); + result.push_str(beautify_doc_string(val).as_str()); result.push('\n'); } } @@ -1036,7 +1036,7 @@ fn find_config(supplied: Option) -> Config { // Helper function to escape quotes in a string fn escape(s: String) -> String { - s.replace("\"", "\"\"") + s.replace('\"', "\"\"") } // Helper function to determine if a span came from a diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs index 7864b47ab0..4971bb6d1a 100644 --- a/compiler/rustc_save_analysis/src/sig.rs +++ b/compiler/rustc_save_analysis/src/sig.rs @@ -286,7 +286,7 @@ impl<'hir> Sig for hir::Ty<'hir> { refs: vec![SigElement { id, start, end }], }) } - hir::TyKind::Path(hir::QPath::LangItem(lang_item, _)) => { + hir::TyKind::Path(hir::QPath::LangItem(lang_item, _, _)) => { Ok(text_sig(format!("#[lang = \"{}\"]", lang_item.name()))) } hir::TyKind::TraitObject(bounds, ..) => { @@ -310,9 +310,9 @@ impl<'hir> Sig for hir::Ty<'hir> { let nested = bounds_to_string(&bounds); Ok(text_sig(nested)) } - hir::TyKind::Array(ref ty, ref anon_const) => { + hir::TyKind::Array(ref ty, ref length) => { let nested_ty = ty.make(offset + 1, id, scx)?; - let expr = id_to_string(&scx.tcx.hir(), anon_const.body.hir_id).replace('\n', " "); + let expr = id_to_string(&scx.tcx.hir(), length.hir_id()).replace('\n', " "); let text = format!("[{}; {}]", nested_ty.text, expr); Ok(replace_text(nested_ty, text)) } @@ -616,7 +616,7 @@ impl<'hir> Sig for hir::Generics<'hir> { if let hir::GenericParamKind::Const { .. } = param.kind { param_text.push_str("const "); } - param_text.push_str(¶m.name.ident().as_str()); + param_text.push_str(param.name.ident().as_str()); defs.push(SigElement { id: id_from_hir_id(param.hir_id, scx), start: offset + text.len(), diff --git a/compiler/rustc_serialize/src/json.rs b/compiler/rustc_serialize/src/json.rs index df78e1bcbf..cb9df3c338 100644 --- a/compiler/rustc_serialize/src/json.rs +++ b/compiler/rustc_serialize/src/json.rs @@ -2320,12 +2320,12 @@ impl crate::Decoder for Decoder { let name = match self.pop() { Json::String(s) => s, Json::Object(mut o) => { - let n = match o.remove(&"variant".to_owned()) { + let n = match o.remove("variant") { Some(Json::String(s)) => s, Some(val) => return Err(ExpectedError("String".to_owned(), val.to_string())), None => return Err(MissingFieldError("variant".to_owned())), }; - match o.remove(&"fields".to_string()) { + match o.remove("fields") { Some(Json::Array(l)) => { self.stack.extend(l.into_iter().rev()); } @@ -2365,7 +2365,7 @@ impl crate::Decoder for Decoder { { let mut obj = expect!(self.pop(), Object)?; - let value = match obj.remove(&name.to_string()) { + let value = match obj.remove(name) { None => { // Add a Null and try to parse it as an Option<_> // to get None as a default value. diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs index 6e36184aff..f2ef148168 100644 --- a/compiler/rustc_serialize/src/opaque.rs +++ b/compiler/rustc_serialize/src/opaque.rs @@ -55,6 +55,13 @@ macro_rules! write_leb128 { }}; } +/// A byte that [cannot occur in UTF8 sequences][utf8]. Used to mark the end of a string. +/// This way we can skip validation and still be relatively sure that deserialization +/// did not desynchronize. +/// +/// [utf8]: https://en.wikipedia.org/w/index.php?title=UTF-8&oldid=1058865525#Codepage_layout +const STR_SENTINEL: u8 = 0xC1; + impl serialize::Encoder for Encoder { type Error = !; @@ -85,7 +92,8 @@ impl serialize::Encoder for Encoder { #[inline] fn emit_u16(&mut self, v: u16) -> EncodeResult { - write_leb128!(self, v, u16, write_u16_leb128) + self.data.extend_from_slice(&v.to_le_bytes()); + Ok(()) } #[inline] @@ -116,7 +124,8 @@ impl serialize::Encoder for Encoder { #[inline] fn emit_i16(&mut self, v: i16) -> EncodeResult { - write_leb128!(self, v, i16, write_i16_leb128) + self.data.extend_from_slice(&v.to_le_bytes()); + Ok(()) } #[inline] @@ -150,7 +159,8 @@ impl serialize::Encoder for Encoder { #[inline] fn emit_str(&mut self, v: &str) -> EncodeResult { self.emit_usize(v.len())?; - self.emit_raw_bytes(v.as_bytes()) + self.emit_raw_bytes(v.as_bytes())?; + self.emit_u8(STR_SENTINEL) } #[inline] @@ -438,7 +448,7 @@ impl serialize::Encoder for FileEncoder { #[inline] fn emit_u16(&mut self, v: u16) -> FileEncodeResult { - file_encoder_write_leb128!(self, v, u16, write_u16_leb128) + self.write_all(&v.to_le_bytes()) } #[inline] @@ -468,13 +478,12 @@ impl serialize::Encoder for FileEncoder { #[inline] fn emit_i16(&mut self, v: i16) -> FileEncodeResult { - file_encoder_write_leb128!(self, v, i16, write_i16_leb128) + self.write_all(&v.to_le_bytes()) } #[inline] fn emit_i8(&mut self, v: i8) -> FileEncodeResult { - let as_u8: u8 = unsafe { std::mem::transmute(v) }; - self.emit_u8(as_u8) + self.emit_u8(v as u8) } #[inline] @@ -502,7 +511,8 @@ impl serialize::Encoder for FileEncoder { #[inline] fn emit_str(&mut self, v: &str) -> FileEncodeResult { self.emit_usize(v.len())?; - self.emit_raw_bytes(v.as_bytes()) + self.emit_raw_bytes(v.as_bytes())?; + self.emit_u8(STR_SENTINEL) } #[inline] @@ -582,7 +592,10 @@ impl<'a> serialize::Decoder for Decoder<'a> { #[inline] fn read_u16(&mut self) -> Result { - read_leb128!(self, read_u16_leb128) + let bytes = [self.data[self.position], self.data[self.position + 1]]; + let value = u16::from_le_bytes(bytes); + self.position += 2; + Ok(value) } #[inline] @@ -614,7 +627,10 @@ impl<'a> serialize::Decoder for Decoder<'a> { #[inline] fn read_i16(&mut self) -> Result { - read_leb128!(self, read_i16_leb128) + let bytes = [self.data[self.position], self.data[self.position + 1]]; + let value = i16::from_le_bytes(bytes); + self.position += 2; + Ok(value) } #[inline] @@ -656,8 +672,12 @@ impl<'a> serialize::Decoder for Decoder<'a> { #[inline] fn read_str(&mut self) -> Result, Self::Error> { let len = self.read_usize()?; - let s = std::str::from_utf8(&self.data[self.position..self.position + len]).unwrap(); - self.position += len; + let sentinel = self.data[self.position + len]; + assert!(sentinel == STR_SENTINEL); + let s = unsafe { + std::str::from_utf8_unchecked(&self.data[self.position..self.position + len]) + }; + self.position += len + 1; Ok(Cow::Borrowed(s)) } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index ab3c122053..08bcea26eb 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -231,6 +231,37 @@ pub enum DebugInfo { Full, } +/// Split debug-information is enabled by `-C split-debuginfo`, this enum is only used if split +/// debug-information is enabled (in either `Packed` or `Unpacked` modes), and the platform +/// uses DWARF for debug-information. +/// +/// Some debug-information requires link-time relocation and some does not. LLVM can partition +/// the debuginfo into sections depending on whether or not it requires link-time relocation. Split +/// DWARF provides a mechanism which allows the linker to skip the sections which don't require +/// link-time relocation - either by putting those sections in DWARF object files, or by keeping +/// them in the object file in such a way that the linker will skip them. +#[derive(Clone, Copy, Debug, PartialEq, Hash)] +pub enum SplitDwarfKind { + /// Sections which do not require relocation are written into object file but ignored by the + /// linker. + Single, + /// Sections which do not require relocation are written into a DWARF object (`.dwo`) file + /// which is ignored by the linker. + Split, +} + +impl FromStr for SplitDwarfKind { + type Err = (); + + fn from_str(s: &str) -> Result { + Ok(match s { + "single" => SplitDwarfKind::Single, + "split" => SplitDwarfKind::Split, + _ => return Err(()), + }) + } +} + #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] #[derive(Encodable, Decodable)] pub enum OutputType { @@ -378,7 +409,7 @@ impl OutputTypes { self.0.len() } - // Returns `true` if any of the output types require codegen or linking. + /// Returns `true` if any of the output types require codegen or linking. pub fn should_codegen(&self) -> bool { self.0.keys().any(|k| match *k { OutputType::Bitcode @@ -391,7 +422,7 @@ impl OutputTypes { }) } - // Returns `true` if any of the output types require linking. + /// Returns `true` if any of the output types require linking. pub fn should_link(&self) -> bool { self.0.keys().any(|k| match *k { OutputType::Bitcode @@ -681,18 +712,23 @@ impl OutputFilenames { pub fn split_dwarf_path( &self, split_debuginfo_kind: SplitDebuginfo, + split_dwarf_kind: SplitDwarfKind, cgu_name: Option<&str>, ) -> Option { let obj_out = self.temp_path(OutputType::Object, cgu_name); let dwo_out = self.temp_path_dwo(cgu_name); - match split_debuginfo_kind { - SplitDebuginfo::Off => None, + match (split_debuginfo_kind, split_dwarf_kind) { + (SplitDebuginfo::Off, SplitDwarfKind::Single | SplitDwarfKind::Split) => None, // Single mode doesn't change how DWARF is emitted, but does add Split DWARF attributes // (pointing at the path which is being determined here). Use the path to the current // object file. - SplitDebuginfo::Packed => Some(obj_out), + (SplitDebuginfo::Packed | SplitDebuginfo::Unpacked, SplitDwarfKind::Single) => { + Some(obj_out) + } // Split mode emits the DWARF into a different file, use that path. - SplitDebuginfo::Unpacked => Some(dwo_out), + (SplitDebuginfo::Packed | SplitDebuginfo::Unpacked, SplitDwarfKind::Split) => { + Some(dwo_out) + } } } } @@ -746,6 +782,7 @@ impl Default for Options { edition: DEFAULT_EDITION, json_artifact_notifications: false, json_unused_externs: false, + json_future_incompat: false, pretty: None, working_dir: RealFileName::LocalPath(std::env::current_dir().unwrap()), } @@ -780,6 +817,10 @@ impl Options { }, } } + + pub fn get_symbol_mangling_version(&self) -> SymbolManglingVersion { + self.cg.symbol_mangling_version.unwrap_or(SymbolManglingVersion::Legacy) + } } impl DebuggingOptions { @@ -793,10 +834,6 @@ impl DebuggingOptions { deduplicate_diagnostics: self.deduplicate_diagnostics, } } - - pub fn get_symbol_mangling_version(&self) -> SymbolManglingVersion { - self.symbol_mangling_version.unwrap_or(SymbolManglingVersion::Legacy) - } } // The type of entry function, so users can have their own entry functions @@ -820,6 +857,18 @@ pub enum CrateType { impl_stable_hash_via_hash!(CrateType); +impl CrateType { + /// When generated, is this crate type an archive? + pub fn is_archive(&self) -> bool { + match *self { + CrateType::Rlib | CrateType::Staticlib => true, + CrateType::Executable | CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro => { + false + } + } + } +} + #[derive(Clone, Hash, Debug, PartialEq, Eq)] pub enum Passes { Some(Vec), @@ -833,6 +882,13 @@ impl Passes { Passes::All => false, } } + + pub fn extend(&mut self, passes: impl IntoIterator) { + match *self { + Passes::Some(ref mut v) => v.extend(passes), + Passes::All => {} + } + } } pub const fn default_lib_output() -> CrateType { @@ -872,7 +928,7 @@ fn default_configuration(sess: &Session) -> CrateConfig { ret.insert((sym::target_env, Some(Symbol::intern(env)))); ret.insert((sym::target_abi, Some(Symbol::intern(abi)))); ret.insert((sym::target_vendor, Some(Symbol::intern(vendor)))); - if sess.target.has_elf_tls { + if sess.target.has_thread_local { ret.insert((sym::target_thread_local, None)); } for (i, align) in [ @@ -1205,7 +1261,7 @@ pub fn get_cmd_lint_options( if lint_name == "help" { describe_lints = true; } else { - lint_opts_with_position.push((arg_pos, lint_name.replace("-", "_"), level)); + lint_opts_with_position.push((arg_pos, lint_name.replace('-', "_"), level)); } } } @@ -1250,6 +1306,7 @@ pub struct JsonConfig { pub json_rendered: HumanReadableErrorType, pub json_artifact_notifications: bool, pub json_unused_externs: bool, + pub json_future_incompat: bool, } /// Parse the `--json` flag. @@ -1262,6 +1319,7 @@ pub fn parse_json(matches: &getopts::Matches) -> JsonConfig { let mut json_color = ColorConfig::Never; let mut json_artifact_notifications = false; let mut json_unused_externs = false; + let mut json_future_incompat = false; for option in matches.opt_strs("json") { // For now conservatively forbid `--color` with `--json` since `--json` // won't actually be emitting any colors and anything colorized is @@ -1279,6 +1337,7 @@ pub fn parse_json(matches: &getopts::Matches) -> JsonConfig { "diagnostic-rendered-ansi" => json_color = ColorConfig::Always, "artifacts" => json_artifact_notifications = true, "unused-externs" => json_unused_externs = true, + "future-incompat" => json_future_incompat = true, s => early_error( ErrorOutputType::default(), &format!("unknown `--json` option `{}`", s), @@ -1291,6 +1350,7 @@ pub fn parse_json(matches: &getopts::Matches) -> JsonConfig { json_rendered: json_rendered(json_color), json_artifact_notifications, json_unused_externs, + json_future_incompat, } } @@ -1723,7 +1783,7 @@ fn parse_native_lib_modifiers( ) -> (NativeLibKind, Option) { let mut verbatim = None; for modifier in modifiers.split(',') { - let (modifier, value) = match modifier.strip_prefix(&['+', '-'][..]) { + let (modifier, value) = match modifier.strip_prefix(&['+', '-']) { Some(m) => (m, modifier.starts_with('+')), None => early_error( error_format, @@ -2004,14 +2064,18 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let edition = parse_crate_edition(matches); - let JsonConfig { json_rendered, json_artifact_notifications, json_unused_externs } = - parse_json(matches); + let JsonConfig { + json_rendered, + json_artifact_notifications, + json_unused_externs, + json_future_incompat, + } = parse_json(matches); let error_format = parse_error_format(matches, color, json_rendered); let unparsed_crate_types = matches.opt_strs("crate-type"); let crate_types = parse_crate_types_from_list(unparsed_crate_types) - .unwrap_or_else(|e| early_error(error_format, &e[..])); + .unwrap_or_else(|e| early_error(error_format, &e)); let mut debugging_opts = DebuggingOptions::build(matches, error_format); let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); @@ -2038,7 +2102,12 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { check_thread_count(&debugging_opts, error_format); - let incremental = cg.incremental.as_ref().map(PathBuf::from); + let incremental = + if std::env::var_os("RUSTC_FORCE_INCREMENTAL").map(|v| v == "1").unwrap_or(false) { + cg.incremental.as_ref().map(PathBuf::from) + } else { + None + }; let assert_incr_state = parse_assert_incr_state(&debugging_opts.assert_incr_state, error_format); @@ -2076,6 +2145,34 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { ); } + // Handle both `-Z symbol-mangling-version` and `-C symbol-mangling-version`; the latter takes + // precedence. + match (cg.symbol_mangling_version, debugging_opts.symbol_mangling_version) { + (Some(smv_c), Some(smv_z)) if smv_c != smv_z => { + early_error( + error_format, + "incompatible values passed for `-C symbol-mangling-version` \ + and `-Z symbol-mangling-version`", + ); + } + (Some(SymbolManglingVersion::V0), _) => {} + (Some(_), _) if !debugging_opts.unstable_options => { + early_error( + error_format, + "`-C symbol-mangling-version=legacy` requires `-Z unstable-options`", + ); + } + (None, None) => {} + (None, smv) => { + early_warn( + error_format, + "`-Z symbol-mangling-version` is deprecated; use `-C symbol-mangling-version`", + ); + cg.symbol_mangling_version = smv; + } + _ => {} + } + if debugging_opts.instrument_coverage.is_some() && debugging_opts.instrument_coverage != Some(InstrumentCoverage::Off) { @@ -2087,19 +2184,17 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { ); } - // `-Z instrument-coverage` implies `-Z symbol-mangling-version=v0` - to ensure consistent + // `-Z instrument-coverage` implies `-C symbol-mangling-version=v0` - to ensure consistent // and reversible name mangling. Note, LLVM coverage tools can analyze coverage over // multiple runs, including some changes to source code; so mangled names must be consistent // across compilations. - match debugging_opts.symbol_mangling_version { - None => { - debugging_opts.symbol_mangling_version = Some(SymbolManglingVersion::V0); - } + match cg.symbol_mangling_version { + None => cg.symbol_mangling_version = Some(SymbolManglingVersion::V0), Some(SymbolManglingVersion::Legacy) => { early_warn( error_format, "-Z instrument-coverage requires symbol mangling version `v0`, \ - but `-Z symbol-mangling-version=legacy` was specified", + but `-C symbol-mangling-version=legacy` was specified", ); } Some(SymbolManglingVersion::V0) => {} @@ -2135,7 +2230,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { let mut search_paths = vec![]; for s in &matches.opt_strs("L") { - search_paths.push(SearchPath::from_cli_opt(&s[..], error_format)); + search_paths.push(SearchPath::from_cli_opt(&s, error_format)); } let libs = parse_libs(matches, error_format); @@ -2241,6 +2336,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { edition, json_artifact_notifications, json_unused_externs, + json_future_incompat, pretty, working_dir, } diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs index 59e7abc2ea..281fc88763 100644 --- a/compiler/rustc_session/src/cstore.rs +++ b/compiler/rustc_session/src/cstore.rs @@ -201,6 +201,12 @@ pub trait CrateStore: std::fmt::Debug { index_guess: u32, hash: ExpnHash, ) -> ExpnId; + + /// Imports all `SourceFile`s from the given crate into the current session. + /// This normally happens automatically when we decode a `Span` from + /// that crate's metadata - however, the incr comp cache needs + /// to trigger this manually when decoding a foreign `Span` + fn import_source_files(&self, sess: &Session, cnum: CrateNum); } pub type CrateStoreDyn = dyn CrateStore + sync::Sync; diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index 9359a55e55..357190178c 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -4,6 +4,7 @@ pub use self::FileMatch::*; use std::env; use std::fs; +use std::iter::FromIterator; use std::path::{Path, PathBuf}; use crate::search_paths::{PathKind, SearchPath, SearchPathFile}; @@ -91,8 +92,7 @@ impl<'a> FileSearch<'a> { pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf { let rustlib_path = rustc_target::target_rustlib_path(sysroot, target_triple); - std::array::IntoIter::new([sysroot, Path::new(&rustlib_path), Path::new("lib")]) - .collect::() + PathBuf::from_iter([sysroot, Path::new(&rustlib_path), Path::new("lib")]) } /// This function checks if sysroot is found using env::args().next(), and if it diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 4165e750df..c8ae005e21 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -101,6 +101,29 @@ macro_rules! top_level_options { ); } +impl Options { + pub fn mir_opt_level(&self) -> usize { + self.debugging_opts + .mir_opt_level + .unwrap_or_else(|| if self.optimize != OptLevel::No { 2 } else { 1 }) + } + + pub fn instrument_coverage(&self) -> bool { + self.debugging_opts.instrument_coverage.unwrap_or(InstrumentCoverage::Off) + != InstrumentCoverage::Off + } + + pub fn instrument_coverage_except_unused_generics(&self) -> bool { + self.debugging_opts.instrument_coverage.unwrap_or(InstrumentCoverage::Off) + == InstrumentCoverage::ExceptUnusedGenerics + } + + pub fn instrument_coverage_except_unused_functions(&self) -> bool { + self.debugging_opts.instrument_coverage.unwrap_or(InstrumentCoverage::Off) + == InstrumentCoverage::ExceptUnusedFunctions + } +} + top_level_options!( /// The top-level command-line options struct. /// @@ -205,6 +228,9 @@ top_level_options!( /// `true` if we're emitting a JSON blob containing the unused externs json_unused_externs: bool [UNTRACKED], + /// `true` if we're emitting a JSON job containg a future-incompat report for lints + json_future_incompat: bool [TRACKED], + pretty: Option [UNTRACKED], /// The (potentially remapped) working directory @@ -309,7 +335,7 @@ fn build_options( Some((k, v)) => (k.to_string(), Some(v)), }; - let option_to_lookup = key.replace("-", "_"); + let option_to_lookup = key.replace('-', "_"); match descrs.iter().find(|(name, ..)| *name == option_to_lookup) { Some((_, setter, type_desc, _)) => { if !setter(&mut op, value) { @@ -386,6 +412,8 @@ mod desc { pub const parse_wasi_exec_model: &str = "either `command` or `reactor`"; pub const parse_split_debuginfo: &str = "one of supported split-debuginfo modes (`off`, `packed`, or `unpacked`)"; + pub const parse_split_dwarf_kind: &str = + "one of supported split dwarf modes (`split` or `single`)"; pub const parse_gcc_ld: &str = "one of: no value, `lld`"; pub const parse_stack_protector: &str = "one of (`none` (default), `basic`, `strong`, or `all`)"; @@ -567,7 +595,7 @@ mod parse { v => { let mut passes = vec![]; if parse_list(&mut passes, v) { - *slot = Passes::Some(passes); + slot.extend(passes); true } else { false @@ -913,6 +941,14 @@ mod parse { true } + crate fn parse_split_dwarf_kind(slot: &mut SplitDwarfKind, v: Option<&str>) -> bool { + match v.and_then(|s| SplitDwarfKind::from_str(s).ok()) { + Some(e) => *slot = e, + _ => return false, + } + true + } + crate fn parse_gcc_ld(slot: &mut Option, v: Option<&str>) -> bool { match v { None => *slot = None, @@ -1029,6 +1065,9 @@ options! { "how to handle split-debuginfo, a platform-specific option"), strip: Strip = (Strip::None, parse_strip, [UNTRACKED], "tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"), + symbol_mangling_version: Option = (None, + parse_symbol_mangling_version, [TRACKED], + "which mangling version to use for symbol names ('legacy' (default) or 'v0')"), target_cpu: Option = (None, parse_opt_string, [TRACKED], "select target processor (`rustc --print target-cpus` for details)"), target_feature: String = (String::new(), parse_target_feature, [TRACKED], @@ -1124,8 +1163,6 @@ options! { computed `block` spans (one span encompassing a block's terminator and \ all statements). If `-Z instrument-coverage` is also enabled, create \ an additional `.html` file showing the computed coverage spans."), - emit_future_incompat_report: bool = (false, parse_bool, [UNTRACKED], - "emits a future-incompatibility report for lints (RFC 2834)"), emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED], "emit a section containing stack size metadata (default: no)"), fewer_names: Option = (None, parse_opt_bool, [TRACKED], @@ -1173,7 +1210,7 @@ options! { instrument_coverage: Option = (None, parse_instrument_coverage, [TRACKED], "instrument the generated code to support LLVM source-based code coverage \ reports (note, the compiler build config must include `profiler = true`); \ - implies `-Z symbol-mangling-version=v0`. Optional values are: + implies `-C symbol-mangling-version=v0`. Optional values are: `=all` (implicit value) `=except-unused-generics` `=except-unused-functions` @@ -1297,6 +1334,8 @@ options! { "print some statistics about the query system (default: no)"), randomize_layout: bool = (false, parse_bool, [TRACKED], "randomize the layout of types (default: no)"), + layout_seed: Option = (None, parse_opt_number, [TRACKED], + "seed layout randomization"), relax_elf_relocations: Option = (None, parse_opt_bool, [TRACKED], "whether ELF relocations can be relaxed"), relro_level: Option = (None, parse_relro_level, [TRACKED], @@ -1344,6 +1383,14 @@ options! { "control stack smash protection strategy (`rustc --print stack-protector-strategies` for details)"), strip: Strip = (Strip::None, parse_strip, [UNTRACKED], "tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"), + split_dwarf_kind: SplitDwarfKind = (SplitDwarfKind::Split, parse_split_dwarf_kind, [UNTRACKED], + "split dwarf variant (only if -Csplit-debuginfo is enabled and on relevant platform) + (default: `split`) + + `split`: sections which do not require relocation are written into a DWARF object (`.dwo`) + file which is ignored by the linker + `single`: sections which do not require relocation are written into object file but ignored + by the linker"), split_dwarf_inlining: bool = (true, parse_bool, [UNTRACKED], "provide minimal debug info in the object/executable to facilitate online \ symbolication/stack traces in the absence of .dwo/.dwp files when using Split DWARF"), diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs index cc1e4bb198..bca19e84cf 100644 --- a/compiler/rustc_session/src/output.rs +++ b/compiler/rustc_session/src/output.rs @@ -60,7 +60,7 @@ pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input) if let Some(ref s) = sess.opts.crate_name { if let Some((attr, name)) = attr_crate_name { - if name.as_str() != *s { + if name.as_str() != s { let msg = format!( "`--crate-name` and `#[crate_name]` are \ required to match, but `{}` != `{}`", @@ -85,7 +85,7 @@ pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input) ); sess.err(&msg); } else { - return validate(s.replace("-", "_"), None); + return validate(s.replace('-', "_"), None); } } } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 54109559a3..730e79a564 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -280,7 +280,7 @@ impl Session { } fn emit_future_breakage(&self) { - if !self.opts.debugging_opts.emit_future_incompat_report { + if !self.opts.json_future_incompat { return; } @@ -562,10 +562,7 @@ impl Session { self.opts.debugging_opts.binary_dep_depinfo } pub fn mir_opt_level(&self) -> usize { - self.opts - .debugging_opts - .mir_opt_level - .unwrap_or_else(|| if self.opts.optimize != config::OptLevel::No { 2 } else { 1 }) + self.opts.mir_opt_level() } /// Gets the features enabled for the current compilation session. @@ -795,12 +792,11 @@ impl Session { /// Returns a list of directories where target-specific tool binaries are located. pub fn get_tools_search_paths(&self, self_contained: bool) -> Vec { let rustlib_path = rustc_target::target_rustlib_path(&self.sysroot, &config::host_triple()); - let p = std::array::IntoIter::new([ + let p = PathBuf::from_iter([ Path::new(&self.sysroot), Path::new(&rustlib_path), Path::new("bin"), - ]) - .collect::(); + ]); if self_contained { vec![p.clone(), p.join("self-contained")] } else { vec![p] } } @@ -1047,18 +1043,15 @@ impl Session { } pub fn instrument_coverage(&self) -> bool { - self.opts.debugging_opts.instrument_coverage.unwrap_or(config::InstrumentCoverage::Off) - != config::InstrumentCoverage::Off + self.opts.instrument_coverage() } pub fn instrument_coverage_except_unused_generics(&self) -> bool { - self.opts.debugging_opts.instrument_coverage.unwrap_or(config::InstrumentCoverage::Off) - == config::InstrumentCoverage::ExceptUnusedGenerics + self.opts.instrument_coverage_except_unused_generics() } pub fn instrument_coverage_except_unused_functions(&self) -> bool { - self.opts.debugging_opts.instrument_coverage.unwrap_or(config::InstrumentCoverage::Off) - == config::InstrumentCoverage::ExceptUnusedFunctions + self.opts.instrument_coverage_except_unused_functions() } pub fn is_proc_macro_attr(&self, attr: &Attribute) -> bool { diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index 64baf94cc0..24d2a8ac07 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -7,6 +7,7 @@ use rustc_macros::HashStable_Generic; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use std::borrow::Borrow; use std::fmt; +use std::hash::{Hash, Hasher}; rustc_index::newtype_index! { pub struct CrateNum { @@ -126,14 +127,17 @@ impl Borrow for DefPathHash { } } -/// A [StableCrateId] is a 64 bit hash of the crate name combined with all -/// `-Cmetadata` arguments. It is to [CrateNum] what [DefPathHash] is to -/// [DefId]. It is stable across compilation sessions. +/// A [`StableCrateId`] is a 64-bit hash of a crate name, together with all +/// `-Cmetadata` arguments, and some other data. It is to [`CrateNum`] what [`DefPathHash`] is to +/// [`DefId`]. It is stable across compilation sessions. /// -/// Since the ID is a hash value there is a (very small) chance that two crates -/// end up with the same [StableCrateId]. The compiler will check for such +/// Since the ID is a hash value, there is a small chance that two crates +/// end up with the same [`StableCrateId`]. The compiler will check for such /// collisions when loading crates and abort compilation in order to avoid /// further trouble. +/// +/// For more information on the possibility of hash collisions in rustc, +/// see the discussion in [`DefId`]. #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)] #[derive(HashStable_Generic, Encodable, Decodable)] pub struct StableCrateId(pub(crate) u64); @@ -146,13 +150,10 @@ impl StableCrateId { /// Computes the stable ID for a crate with the given name and /// `-Cmetadata` arguments. pub fn new(crate_name: &str, is_exe: bool, mut metadata: Vec) -> StableCrateId { - use std::hash::Hash; - use std::hash::Hasher; - let mut hasher = StableHasher::new(); crate_name.hash(&mut hasher); - // We don't want the stable crate id to dependent on the order + // We don't want the stable crate ID to depend on the order of // -C metadata arguments, so sort them: metadata.sort(); // Every distinct -C metadata value is only incorporated once: @@ -171,6 +172,18 @@ impl StableCrateId { // linking against a library of the same name, if this is an executable. hasher.write(if is_exe { b"exe" } else { b"lib" }); + // Also incorporate the rustc version. Otherwise, with -Zsymbol-mangling-version=v0 + // and no -Cmetadata, symbols from the same crate compiled with different versions of + // rustc are named the same. + // + // RUSTC_FORCE_INCR_COMP_ARTIFACT_HEADER is used to inject rustc version information + // during testing. + if let Some(val) = std::env::var_os("RUSTC_FORCE_INCR_COMP_ARTIFACT_HEADER") { + hasher.write(val.to_string_lossy().into_owned().as_bytes()) + } else { + hasher.write(option_env!("CFG_VERSION").unwrap_or("unknown version").as_bytes()); + } + StableCrateId(hasher.finish()) } } @@ -205,10 +218,38 @@ impl Decodable for DefIndex { /// index and a def index. /// /// You can create a `DefId` from a `LocalDefId` using `local_def_id.to_def_id()`. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Copy)] +// On below-64 bit systems we can simply use the derived `Hash` impl +#[cfg_attr(not(target_pointer_width = "64"), derive(Hash))] +// Note that the order is essential here, see below why pub struct DefId { - pub krate: CrateNum, pub index: DefIndex, + pub krate: CrateNum, +} + +// On 64-bit systems, we can hash the whole `DefId` as one `u64` instead of two `u32`s. This +// improves performance without impairing `FxHash` quality. So the below code gets compiled to a +// noop on little endian systems because the memory layout of `DefId` is as follows: +// +// ``` +// +-1--------------31-+-32-------------63-+ +// ! index ! krate ! +// +-------------------+-------------------+ +// ``` +// +// The order here has direct impact on `FxHash` quality because we have far more `DefIndex` per +// crate than we have `Crate`s within one compilation. Or in other words, this arrangement puts +// more entropy in the low bits than the high bits. The reason this matters is that `FxHash`, which +// is used throughout rustc, has problems distributing the entropy from the high bits, so reversing +// the order would lead to a large number of collisions and thus far worse performance. +// +// On 64-bit big-endian systems, this compiles to a 64-bit rotation by 32 bits, which is still +// faster than another `FxHash` round. +#[cfg(target_pointer_width = "64")] +impl Hash for DefId { + fn hash(&self, h: &mut H) { + (((self.krate.as_u32() as u64) << 32) | (self.index.as_u32() as u64)).hash(h) + } } impl DefId { @@ -275,17 +316,23 @@ impl fmt::Debug for DefId { rustc_data_structures::define_id_collections!(DefIdMap, DefIdSet, DefId); -/// A LocalDefId is equivalent to a DefId with `krate == LOCAL_CRATE`. Since +/// A `LocalDefId` is equivalent to a `DefId` with `krate == LOCAL_CRATE`. Since /// we encode this information in the type, we can ensure at compile time that -/// no DefIds from upstream crates get thrown into the mix. There are quite a -/// few cases where we know that only DefIds from the local crate are expected -/// and a DefId from a different crate would signify a bug somewhere. This -/// is when LocalDefId comes in handy. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +/// no `DefId`s from upstream crates get thrown into the mix. There are quite a +/// few cases where we know that only `DefId`s from the local crate are expected; +/// a `DefId` from a different crate would signify a bug somewhere. This +/// is when `LocalDefId` comes in handy. +#[derive(Clone, Copy, PartialEq, Eq, Hash)] pub struct LocalDefId { pub local_def_index: DefIndex, } +// To ensure correctness of incremental compilation, +// `LocalDefId` must not implement `Ord` or `PartialOrd`. +// See https://github.com/rust-lang/rust/issues/90317. +impl !Ord for LocalDefId {} +impl !PartialOrd for LocalDefId {} + pub const CRATE_DEF_ID: LocalDefId = LocalDefId { local_def_index: CRATE_DEF_INDEX }; impl Idx for LocalDefId { diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index d590776676..315b706fbc 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -264,7 +264,15 @@ impl ExpnId { HygieneData::with(|data| data.expn_data(self).clone()) } + #[inline] pub fn is_descendant_of(self, ancestor: ExpnId) -> bool { + // a few "fast path" cases to avoid locking HygieneData + if ancestor == ExpnId::root() || ancestor == self { + return true; + } + if ancestor.krate != self.krate { + return false; + } HygieneData::with(|data| data.is_descendant_of(self, ancestor)) } @@ -376,13 +384,22 @@ impl HygieneData { } fn is_descendant_of(&self, mut expn_id: ExpnId, ancestor: ExpnId) -> bool { - while expn_id != ancestor { + // a couple "fast path" cases to avoid traversing parents in the loop below + if ancestor == ExpnId::root() { + return true; + } + if expn_id.krate != ancestor.krate { + return false; + } + loop { + if expn_id == ancestor { + return true; + } if expn_id == ExpnId::root() { return false; } expn_id = self.expn_data(expn_id).parent; } - true } fn normalize_to_macros_2_0(&self, ctxt: SyntaxContext) -> SyntaxContext { @@ -1223,6 +1240,7 @@ pub fn register_expn_id( data: ExpnData, hash: ExpnHash, ) -> ExpnId { + debug_assert!(data.parent == ExpnId::root() || krate == data.parent.krate); let expn_id = ExpnId { krate, local_id }; HygieneData::with(|hygiene_data| { let _old_data = hygiene_data.foreign_expn_data.insert(expn_id, data); diff --git a/compiler/rustc_span/src/lev_distance.rs b/compiler/rustc_span/src/lev_distance.rs index c10968e06d..aed699e483 100644 --- a/compiler/rustc_span/src/lev_distance.rs +++ b/compiler/rustc_span/src/lev_distance.rs @@ -55,7 +55,7 @@ pub fn find_best_match_for_name( lookup: Symbol, dist: Option, ) -> Option { - let lookup = &lookup.as_str(); + let lookup = lookup.as_str(); let max_dist = dist.unwrap_or_else(|| cmp::max(lookup.len(), 3) / 3); // Priority of matches: @@ -70,7 +70,7 @@ pub fn find_best_match_for_name( let levenshtein_match = name_vec .iter() .filter_map(|&name| { - let dist = lev_distance(lookup, &name.as_str()); + let dist = lev_distance(lookup, name.as_str()); if dist <= max_dist { Some((name, dist)) } else { None } }) // Here we are collecting the next structure: @@ -88,7 +88,7 @@ pub fn find_best_match_for_name( fn find_match_by_sorted_words(iter_names: &[Symbol], lookup: &str) -> Option { iter_names.iter().fold(None, |result, candidate| { - if sort_by_words(&candidate.as_str()) == sort_by_words(lookup) { + if sort_by_words(candidate.as_str()) == sort_by_words(lookup) { Some(*candidate) } else { result diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 66c01140ab..3bbf2a0e45 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -20,7 +20,6 @@ #![feature(negative_impls)] #![feature(nll)] #![feature(min_specialization)] -#![feature(thread_local_const_init)] #[macro_use] extern crate rustc_macros; @@ -425,7 +424,7 @@ impl FileName { /// `SpanData` is public because `Span` uses a thread-local interner and can't be /// sent to other threads, but some pieces of performance infra run in a separate thread. /// Using `Span` is generally preferred. -#[derive(Clone, Copy, Hash, PartialEq, Eq, Ord, PartialOrd)] +#[derive(Clone, Copy, Hash, PartialEq, Eq)] pub struct SpanData { pub lo: BytePos, pub hi: BytePos, @@ -435,6 +434,36 @@ pub struct SpanData { pub parent: Option, } +// Order spans by position in the file. +impl Ord for SpanData { + fn cmp(&self, other: &Self) -> Ordering { + let SpanData { + lo: s_lo, + hi: s_hi, + ctxt: s_ctxt, + // `LocalDefId` does not implement `Ord`. + // The other fields are enough to determine in-file order. + parent: _, + } = self; + let SpanData { + lo: o_lo, + hi: o_hi, + ctxt: o_ctxt, + // `LocalDefId` does not implement `Ord`. + // The other fields are enough to determine in-file order. + parent: _, + } = other; + + (s_lo, s_hi, s_ctxt).cmp(&(o_lo, o_hi, o_ctxt)) + } +} + +impl PartialOrd for SpanData { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + impl SpanData { #[inline] pub fn span(&self) -> Span { @@ -551,6 +580,16 @@ impl Span { matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _)) } + /// Gate suggestions that would not be appropriate in a context the user didn't write. + pub fn can_be_used_for_suggestions(self) -> bool { + !self.from_expansion() + // FIXME: If this span comes from a `derive` macro but it points at code the user wrote, + // the callsite span and the span will be pointing at different places. It also means that + // we can safely provide suggestions on this span. + || (matches!(self.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _)) + && self.parent_callsite().map(|p| (p.lo(), p.hi())) != Some((self.lo(), self.hi()))) + } + #[inline] pub fn with_root_ctxt(lo: BytePos, hi: BytePos) -> Span { Span::new(lo, hi, SyntaxContext::root(), None) @@ -1374,7 +1413,7 @@ impl Encodable for SourceFile { // Encode the first element. lines[0].encode(s)?; - let diff_iter = lines[..].array_windows().map(|&[fst, snd]| snd - fst); + let diff_iter = lines.array_windows().map(|&[fst, snd]| snd - fst); match bytes_per_diff { 1 => { @@ -1497,7 +1536,7 @@ impl SourceFile { assert!(end_pos <= u32::MAX as usize); let (lines, multibyte_chars, non_narrow_chars) = - analyze_source_file::analyze_source_file(&src[..], start_pos); + analyze_source_file::analyze_source_file(&src, start_pos); SourceFile { name, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 247d69d6ee..e008224ec0 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -196,6 +196,7 @@ symbols! { Implied, Input, Into, + IntoFuture, IntoIterator, IoRead, IoWrite, @@ -331,6 +332,7 @@ symbols! { asm_const, asm_experimental_arch, asm_sym, + asm_unwind, assert, assert_inhabited, assert_macro, @@ -437,6 +439,7 @@ symbols! { compiler_builtins, compiler_fence, concat, + concat_bytes, concat_idents, conservative_impl_trait, console, @@ -497,6 +500,7 @@ symbols! { core_panic_macro, cosf32, cosf64, + count, cr, crate_id, crate_in_paths, @@ -627,6 +631,7 @@ symbols! { fdiv_fast, feature, fence, + ferris: "🦀", fetch_update, ffi, ffi_const, @@ -737,6 +742,7 @@ symbols! { inout, instruction_set, intel, + into_future, into_iter, intra_doc_pointers, intrinsics, @@ -782,6 +788,7 @@ symbols! { literal, llvm_asm, load, + loaded_from_disk, local, local_inner_macros, log10f32, @@ -815,6 +822,7 @@ symbols! { maxnumf32, maxnumf64, may_dangle, + may_unwind, maybe_uninit, maybe_uninit_uninit, maybe_uninit_zeroed, @@ -1048,8 +1056,11 @@ symbols! { reg64, reg_abcd, reg_byte, + reg_iw, reg_nonzero, - reg_thumb, + reg_pair, + reg_ptr, + reg_upper, register_attr, register_tool, relaxed_adts, @@ -1377,7 +1388,13 @@ symbols! { unmarked_api, unpin, unreachable, + unreachable_2015, + unreachable_2015_macro, + unreachable_2021, + unreachable_2021_macro, unreachable_code, + unreachable_display, + unreachable_macro, unrestricted_attribute_tokens, unsafe_block_in_unsafe_fn, unsafe_cell, @@ -1502,9 +1519,12 @@ impl Ident { Ident::new(self.name, self.span.normalize_to_macro_rules()) } - /// Convert the name to a `SymbolStr`. This is a slowish operation because - /// it requires locking the symbol interner. - pub fn as_str(self) -> SymbolStr { + /// Access the underlying string. This is a slowish operation because it + /// requires locking the symbol interner. + /// + /// Note that the lifetime of the return value is a lie. See + /// `Symbol::as_str()` for details. + pub fn as_str(&self) -> &str { self.name.as_str() } } @@ -1640,12 +1660,17 @@ impl Symbol { with_session_globals(|session_globals| session_globals.symbol_interner.intern(string)) } - /// Convert to a `SymbolStr`. This is a slowish operation because it + /// Access the underlying string. This is a slowish operation because it /// requires locking the symbol interner. - pub fn as_str(self) -> SymbolStr { - with_session_globals(|session_globals| { - let symbol_str = session_globals.symbol_interner.get(self); - unsafe { SymbolStr { string: std::mem::transmute::<&str, &str>(symbol_str) } } + /// + /// Note that the lifetime of the return value is a lie. It's not the same + /// as `&self`, but actually tied to the lifetime of the underlying + /// interner. Interners are long-lived, and there are very few of them, and + /// this function is typically used for short-lived things, so in practice + /// it works out ok. + pub fn as_str(&self) -> &str { + with_session_globals(|session_globals| unsafe { + std::mem::transmute::<&str, &str>(session_globals.symbol_interner.get(*self)) }) } @@ -1668,19 +1693,19 @@ impl Symbol { impl fmt::Debug for Symbol { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&self.as_str(), f) + fmt::Debug::fmt(self.as_str(), f) } } impl fmt::Display for Symbol { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&self.as_str(), f) + fmt::Display::fmt(self.as_str(), f) } } impl Encodable for Symbol { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_str(&self.as_str()) + s.emit_str(self.as_str()) } } @@ -1699,11 +1724,10 @@ impl HashStable for Symbol { } impl ToStableHashKey for Symbol { - type KeyType = SymbolStr; - + type KeyType = String; #[inline] - fn to_stable_hash_key(&self, _: &CTX) -> SymbolStr { - self.as_str() + fn to_stable_hash_key(&self, _: &CTX) -> String { + self.as_str().to_string() } } @@ -1716,8 +1740,9 @@ pub(crate) struct Interner(Lock); // found that to regress performance up to 2% in some cases. This might be // revisited after further improvements to `indexmap`. // -// This type is private to prevent accidentally constructing more than one `Interner` on the same -// thread, which makes it easy to mixup `Symbol`s between `Interner`s. +// This type is private to prevent accidentally constructing more than one +// `Interner` on the same thread, which makes it easy to mixup `Symbol`s +// between `Interner`s. #[derive(Default)] struct InternerInner { arena: DroplessArena, @@ -1743,14 +1768,20 @@ impl Interner { let name = Symbol::new(inner.strings.len() as u32); - // `from_utf8_unchecked` is safe since we just allocated a `&str` which is known to be - // UTF-8. + // SAFETY: we convert from `&str` to `&[u8]`, clone it into the arena, + // and immediately convert the clone back to `&[u8], all because there + // is no `inner.arena.alloc_str()` method. This is clearly safe. let string: &str = unsafe { str::from_utf8_unchecked(inner.arena.alloc_slice(string.as_bytes())) }; - // It is safe to extend the arena allocation to `'static` because we only access - // these while the arena is still alive. + + // SAFETY: we can extend the arena allocation to `'static` because we + // only access these while the arena is still alive. let string: &'static str = unsafe { &*(string as *const str) }; inner.strings.push(string); + + // This second hash table lookup can be avoided by using `RawEntryMut`, + // but this code path isn't hot enough for it to be worth it. See + // #91445 for details. inner.names.insert(string, name); name } @@ -1888,70 +1919,3 @@ impl Ident { self.name.can_be_raw() && self.is_reserved() } } - -/// An alternative to [`Symbol`], useful when the chars within the symbol need to -/// be accessed. It deliberately has limited functionality and should only be -/// used for temporary values. -/// -/// Because the interner outlives any thread which uses this type, we can -/// safely treat `string` which points to interner data, as an immortal string, -/// as long as this type never crosses between threads. -// -// FIXME: ensure that the interner outlives any thread which uses `SymbolStr`, -// by creating a new thread right after constructing the interner. -#[derive(Clone, Eq, PartialOrd, Ord)] -pub struct SymbolStr { - string: &'static str, -} - -// This impl allows a `SymbolStr` to be directly equated with a `String` or -// `&str`. -impl> std::cmp::PartialEq for SymbolStr { - fn eq(&self, other: &T) -> bool { - self.string == other.deref() - } -} - -impl !Send for SymbolStr {} -impl !Sync for SymbolStr {} - -/// This impl means that if `ss` is a `SymbolStr`: -/// - `*ss` is a `str`; -/// - `&*ss` is a `&str` (and `match &*ss { ... }` is a common pattern). -/// - `&ss as &str` is a `&str`, which means that `&ss` can be passed to a -/// function expecting a `&str`. -impl std::ops::Deref for SymbolStr { - type Target = str; - #[inline] - fn deref(&self) -> &str { - self.string - } -} - -impl fmt::Debug for SymbolStr { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(self.string, f) - } -} - -impl fmt::Display for SymbolStr { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self.string, f) - } -} - -impl HashStable for SymbolStr { - #[inline] - fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { - self.string.hash_stable(hcx, hasher) - } -} - -impl ToStableHashKey for SymbolStr { - type KeyType = SymbolStr; - - #[inline] - fn to_stable_hash_key(&self, _: &CTX) -> SymbolStr { - self.clone() - } -} diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index de18614360..eebf618a5d 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -13,7 +13,7 @@ use tracing::debug; use std::fmt::{self, Write}; use std::mem::{self, discriminant}; -pub(super) fn mangle( +pub(super) fn mangle<'tcx>( tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, instantiating_crate: Option, @@ -199,7 +199,7 @@ struct SymbolPrinter<'tcx> { // `PrettyPrinter` aka pretty printing of e.g. types in paths, // symbol names should have their own printing machinery. -impl Printer<'tcx> for &mut SymbolPrinter<'tcx> { +impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { type Error = fmt::Error; type Path = Self; @@ -255,7 +255,7 @@ impl Printer<'tcx> for &mut SymbolPrinter<'tcx> { } fn path_crate(self, cnum: CrateNum) -> Result { - self.write_str(&self.tcx.crate_name(cnum).as_str())?; + self.write_str(self.tcx.crate_name(cnum).as_str())?; Ok(self) } fn path_qualified( @@ -311,8 +311,8 @@ impl Printer<'tcx> for &mut SymbolPrinter<'tcx> { ) -> Result { self = print_prefix(self)?; - // Skip `::{{constructor}}` on tuple/unit structs. - if let DefPathData::Ctor = disambiguated_data.data { + // Skip `::{{extern}}` blocks and `::{{constructor}}` on tuple/unit structs. + if let DefPathData::ForeignMod | DefPathData::Ctor = disambiguated_data.data { return Ok(self); } @@ -345,7 +345,7 @@ impl Printer<'tcx> for &mut SymbolPrinter<'tcx> { } } -impl PrettyPrinter<'tcx> for &mut SymbolPrinter<'tcx> { +impl<'tcx> PrettyPrinter<'tcx> for &mut SymbolPrinter<'tcx> { fn region_should_not_be_omitted(&self, _region: ty::Region<'_>) -> bool { false } diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index bb7b452955..1f38240ee4 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -90,8 +90,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(never_type)] #![feature(nll)] -#![feature(in_band_lifetimes)] -#![feature(iter_zip)] #![recursion_limit = "256"] #[macro_use] @@ -117,7 +115,7 @@ pub mod test; /// This function computes the symbol name for the given `instance` and the /// given instantiating crate. That is, if you know that instance X is /// instantiated in crate Y, this is the symbol name this instance would have. -pub fn symbol_name_for_instance_in_crate( +pub fn symbol_name_for_instance_in_crate<'tcx>( tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, instantiating_crate: CrateNum, @@ -132,7 +130,7 @@ pub fn provide(providers: &mut Providers) { // The `symbol_name` query provides the symbol name for calling a given // instance from the local crate. In particular, it will also look up the // correct symbol name of instances from upstream crates. -fn symbol_name_provider(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> ty::SymbolName<'tcx> { +fn symbol_name_provider<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> ty::SymbolName<'tcx> { let symbol_name = compute_symbol_name(tcx, instance, || { // This closure determines the instantiating crate for instances that // need an instantiating-crate-suffix for their symbol name, in order @@ -152,14 +150,14 @@ fn symbol_name_provider(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> ty::Symb } /// This function computes the typeid for the given function ABI. -pub fn typeid_for_fnabi(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> String { +pub fn typeid_for_fnabi<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> String { v0::mangle_typeid_for_fnabi(tcx, fn_abi) } /// Computes the symbol name for the given instance. This function will call /// `compute_instantiating_crate` if it needs to factor the instantiating crate /// into the symbol name. -fn compute_symbol_name( +fn compute_symbol_name<'tcx>( tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, compute_instantiating_crate: impl FnOnce() -> CrateNum, @@ -239,7 +237,7 @@ fn compute_symbol_name( // Pick the crate responsible for the symbol mangling version, which has to: // 1. be stable for each instance, whether it's being defined or imported - // 2. obey each crate's own `-Z symbol-mangling-version`, as much as possible + // 2. obey each crate's own `-C symbol-mangling-version`, as much as possible // We solve these as follows: // 1. because symbol names depend on both `def_id` and `instantiating_crate`, // both their `CrateNum`s are stable for any given instance, so we can pick @@ -247,7 +245,7 @@ fn compute_symbol_name( // 2. we favor `instantiating_crate` where possible (i.e. when `Some`) let mangling_version_crate = instantiating_crate.unwrap_or(def_id.krate); let mangling_version = if mangling_version_crate == LOCAL_CRATE { - tcx.sess.opts.debugging_opts.get_symbol_mangling_version() + tcx.sess.opts.get_symbol_mangling_version() } else { tcx.symbol_mangling_version(mangling_version_crate) }; diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs index f7d68b5cc7..700765a351 100644 --- a/compiler/rustc_symbol_mangling/src/test.rs +++ b/compiler/rustc_symbol_mangling/src/test.rs @@ -31,7 +31,7 @@ struct SymbolNamesTest<'tcx> { tcx: TyCtxt<'tcx>, } -impl SymbolNamesTest<'tcx> { +impl SymbolNamesTest<'_> { fn process_attrs(&mut self, def_id: LocalDefId) { let tcx = self.tcx; for attr in tcx.get_attrs(def_id.to_def_id()).iter() { @@ -59,7 +59,7 @@ impl SymbolNamesTest<'tcx> { } } -impl hir::itemlikevisit::ItemLikeVisitor<'tcx> for SymbolNamesTest<'tcx> { +impl<'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for SymbolNamesTest<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { self.process_attrs(item.def_id); } diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 0363ddb0e6..c2519adcbe 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -9,6 +9,7 @@ use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::print::{Print, Printer}; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst}; use rustc_middle::ty::{self, FloatTy, Instance, IntTy, Ty, TyCtxt, TypeFoldable, UintTy}; +use rustc_span::symbol::kw; use rustc_target::abi::call::FnAbi; use rustc_target::abi::Integer; use rustc_target::spec::abi::Abi; @@ -17,7 +18,7 @@ use std::fmt::Write; use std::iter; use std::ops::Range; -pub(super) fn mangle( +pub(super) fn mangle<'tcx>( tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, instantiating_crate: Option, @@ -56,7 +57,7 @@ pub(super) fn mangle( std::mem::take(&mut cx.out) } -pub(super) fn mangle_typeid_for_fnabi( +pub(super) fn mangle_typeid_for_fnabi<'tcx>( _tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, ) -> String { @@ -118,7 +119,7 @@ struct SymbolMangler<'tcx> { consts: FxHashMap<&'tcx ty::Const<'tcx>, usize>, } -impl SymbolMangler<'tcx> { +impl<'tcx> SymbolMangler<'tcx> { fn push(&mut self, s: &str) { self.out.push_str(s); } @@ -250,7 +251,7 @@ impl SymbolMangler<'tcx> { } } -impl Printer<'tcx> for &mut SymbolMangler<'tcx> { +impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { type Error = !; type Path = Self; @@ -559,7 +560,7 @@ impl Printer<'tcx> for &mut SymbolMangler<'tcx> { ty::ExistentialPredicate::Projection(projection) => { let name = cx.tcx.associated_item(projection.item_def_id).ident; cx.push("p"); - cx.push_ident(&name.as_str()); + cx.push_ident(name.as_str()); cx = projection.ty.print(cx)?; } ty::ExistentialPredicate::AutoTrait(def_id) => { @@ -702,12 +703,11 @@ impl Printer<'tcx> for &mut SymbolMangler<'tcx> { // just to be able to handle disambiguators. let disambiguated_field = self.tcx.def_key(field_def.did).disambiguated_data; - let field_name = - disambiguated_field.data.get_opt_name().map(|s| s.as_str()); + let field_name = disambiguated_field.data.get_opt_name(); self.push_disambiguator( disambiguated_field.disambiguator as u64, ); - self.push_ident(&field_name.as_ref().map_or("", |s| &s[..])); + self.push_ident(field_name.unwrap_or(kw::Empty).as_str()); self = field.print(self)?; } @@ -736,8 +736,8 @@ impl Printer<'tcx> for &mut SymbolMangler<'tcx> { self.push("C"); let stable_crate_id = self.tcx.def_path_hash(cnum.as_def_id()).stable_crate_id(); self.push_disambiguator(stable_crate_id.to_u64()); - let name = self.tcx.crate_name(cnum).as_str(); - self.push_ident(&name); + let name = self.tcx.crate_name(cnum); + self.push_ident(name.as_str()); Ok(self) } @@ -771,6 +771,10 @@ impl Printer<'tcx> for &mut SymbolMangler<'tcx> { disambiguated_data: &DisambiguatedDefPathData, ) -> Result { let ns = match disambiguated_data.data { + // FIXME: It shouldn't be necessary to add anything for extern block segments, + // but we add 't' for backward compatibility. + DefPathData::ForeignMod => 't', + // Uppercase categories are more stable than lowercase ones. DefPathData::TypeNs(_) => 't', DefPathData::ValueNs(_) => 'v', @@ -789,13 +793,13 @@ impl Printer<'tcx> for &mut SymbolMangler<'tcx> { } }; - let name = disambiguated_data.data.get_opt_name().map(|s| s.as_str()); + let name = disambiguated_data.data.get_opt_name(); self.path_append_ns( print_prefix, ns, disambiguated_data.disambiguator as u64, - name.as_ref().map_or("", |s| &s[..]), + name.unwrap_or(kw::Empty).as_str(), ) } diff --git a/compiler/rustc_target/src/abi/call/mips64.rs b/compiler/rustc_target/src/abi/call/mips64.rs index 2e00ffc7e1..1ac454be5e 100644 --- a/compiler/rustc_target/src/abi/call/mips64.rs +++ b/compiler/rustc_target/src/abi/call/mips64.rs @@ -1,4 +1,6 @@ -use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform}; +use crate::abi::call::{ + ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, PassMode, Reg, Uniform, +}; use crate::abi::{self, HasDataLayout, Size, TyAbiInterface}; fn extend_integer_width_mips(arg: &mut ArgAbi<'_, Ty>, bits: u64) { @@ -115,7 +117,7 @@ where for _ in 0..((offset - last_offset).bits() / 64) .min((prefix.len() - prefix_index) as u64) { - prefix[prefix_index] = Some(RegKind::Integer); + prefix[prefix_index] = Some(Reg::i64()); prefix_index += 1; } @@ -123,7 +125,7 @@ where break; } - prefix[prefix_index] = Some(RegKind::Float); + prefix[prefix_index] = Some(Reg::f64()); prefix_index += 1; last_offset = offset + Reg::f64().size; } @@ -137,8 +139,13 @@ where let rest_size = size - Size::from_bytes(8) * prefix_index as u64; arg.cast_to(CastTarget { prefix, - prefix_chunk_size: Size::from_bytes(8), rest: Uniform { unit: Reg::i64(), total: rest_size }, + attrs: ArgAttributes { + regular: ArgAttribute::default(), + arg_ext: ArgExtension::None, + pointee_size: Size::ZERO, + pointee_align: None, + }, }); } diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 4768c9e2db..735b7e76e3 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -214,9 +214,9 @@ impl Uniform { #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct CastTarget { - pub prefix: [Option; 8], - pub prefix_chunk_size: Size, + pub prefix: [Option; 8], pub rest: Uniform, + pub attrs: ArgAttributes, } impl From for CastTarget { @@ -227,29 +227,48 @@ impl From for CastTarget { impl From for CastTarget { fn from(uniform: Uniform) -> CastTarget { - CastTarget { prefix: [None; 8], prefix_chunk_size: Size::ZERO, rest: uniform } + CastTarget { + prefix: [None; 8], + rest: uniform, + attrs: ArgAttributes { + regular: ArgAttribute::default(), + arg_ext: ArgExtension::None, + pointee_size: Size::ZERO, + pointee_align: None, + }, + } } } impl CastTarget { pub fn pair(a: Reg, b: Reg) -> CastTarget { CastTarget { - prefix: [Some(a.kind), None, None, None, None, None, None, None], - prefix_chunk_size: a.size, + prefix: [Some(a), None, None, None, None, None, None, None], rest: Uniform::from(b), + attrs: ArgAttributes { + regular: ArgAttribute::default(), + arg_ext: ArgExtension::None, + pointee_size: Size::ZERO, + pointee_align: None, + }, } } - pub fn size(&self, cx: &C) -> Size { - (self.prefix_chunk_size * self.prefix.iter().filter(|x| x.is_some()).count() as u64) - .align_to(self.rest.align(cx)) - + self.rest.total + pub fn size(&self, _cx: &C) -> Size { + let mut size = self.rest.total; + for i in 0..self.prefix.iter().count() { + match self.prefix[i] { + Some(v) => size += Size { raw: v.size.bytes() }, + None => {} + } + } + return size; } pub fn align(&self, cx: &C) -> Align { self.prefix .iter() - .filter_map(|x| x.map(|kind| Reg { kind, size: self.prefix_chunk_size }.align(cx))) + .filter_map(|x| x.map(|reg| reg.align(cx))) .fold(cx.data_layout().aggregate_align.abi.max(self.rest.align(cx)), |acc, align| { acc.max(align) }) diff --git a/compiler/rustc_target/src/abi/call/sparc64.rs b/compiler/rustc_target/src/abi/call/sparc64.rs index 5d74c94e2c..39d80c4c7e 100644 --- a/compiler/rustc_target/src/abi/call/sparc64.rs +++ b/compiler/rustc_target/src/abi/call/sparc64.rs @@ -1,7 +1,9 @@ // FIXME: This needs an audit for correctness and completeness. -use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform}; -use crate::abi::{HasDataLayout, TyAbiInterface}; +use crate::abi::call::{ + ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, Reg, RegKind, Uniform, +}; +use crate::abi::{self, HasDataLayout, Size, TyAbiInterface}; fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option where @@ -16,7 +18,7 @@ where let valid_unit = match unit.kind { RegKind::Integer => false, - RegKind::Float => true, + RegKind::Float => false, RegKind::Vector => arg.layout.size.bits() == 128, }; @@ -24,33 +26,7 @@ where }) } -fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>) -where - Ty: TyAbiInterface<'a, C> + Copy, - C: HasDataLayout, -{ - if !ret.layout.is_aggregate() { - ret.extend_integer_width_to(64); - return; - } - - if let Some(uniform) = is_homogeneous_aggregate(cx, ret) { - ret.cast_to(uniform); - return; - } - let size = ret.layout.size; - let bits = size.bits(); - if bits <= 256 { - let unit = Reg::i64(); - ret.cast_to(Uniform { unit, total: size }); - return; - } - - // don't return aggregates in registers - ret.make_indirect(); -} - -fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) +fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, in_registers_max: Size) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout, @@ -60,13 +36,97 @@ where return; } + // This doesn't intentionally handle structures with floats which needs + // special care below. if let Some(uniform) = is_homogeneous_aggregate(cx, arg) { arg.cast_to(uniform); return; } + if let abi::FieldsShape::Arbitrary { .. } = arg.layout.fields { + let dl = cx.data_layout(); + let size = arg.layout.size; + let mut prefix = [None; 8]; + let mut prefix_index = 0; + let mut last_offset = Size::ZERO; + let mut has_float = false; + let mut arg_attribute = ArgAttribute::default(); + + for i in 0..arg.layout.fields.count() { + let field = arg.layout.field(cx, i); + let offset = arg.layout.fields.offset(i); + + if let abi::Abi::Scalar(scalar) = &field.abi { + if scalar.value == abi::F32 || scalar.value == abi::F64 { + has_float = true; + + if !last_offset.is_aligned(dl.f64_align.abi) && last_offset < offset { + if prefix_index == prefix.len() { + break; + } + prefix[prefix_index] = Some(Reg::i32()); + prefix_index += 1; + last_offset = last_offset + Reg::i32().size; + } + + for _ in 0..((offset - last_offset).bits() / 64) + .min((prefix.len() - prefix_index) as u64) + { + prefix[prefix_index] = Some(Reg::i64()); + prefix_index += 1; + last_offset = last_offset + Reg::i64().size; + } + + if last_offset < offset { + if prefix_index == prefix.len() { + break; + } + prefix[prefix_index] = Some(Reg::i32()); + prefix_index += 1; + last_offset = last_offset + Reg::i32().size; + } + + if prefix_index == prefix.len() { + break; + } + + if scalar.value == abi::F32 { + arg_attribute = ArgAttribute::InReg; + prefix[prefix_index] = Some(Reg::f32()); + last_offset = offset + Reg::f32().size; + } else { + prefix[prefix_index] = Some(Reg::f64()); + last_offset = offset + Reg::f64().size; + } + prefix_index += 1; + } + } + } + + if has_float && arg.layout.size <= in_registers_max { + let mut rest_size = size - last_offset; + + if (rest_size.raw % 8) != 0 && prefix_index < prefix.len() { + prefix[prefix_index] = Some(Reg::i32()); + rest_size = rest_size - Reg::i32().size; + } + + arg.cast_to(CastTarget { + prefix, + rest: Uniform { unit: Reg::i64(), total: rest_size }, + attrs: ArgAttributes { + regular: arg_attribute, + arg_ext: ArgExtension::None, + pointee_size: Size::ZERO, + pointee_align: None, + }, + }); + return; + } + } + let total = arg.layout.size; - if total.bits() > 128 { + if total > in_registers_max { arg.make_indirect(); return; } @@ -80,13 +140,13 @@ where C: HasDataLayout, { if !fn_abi.ret.is_ignore() { - classify_ret(cx, &mut fn_abi.ret); + classify_arg(cx, &mut fn_abi.ret, Size { raw: 32 }); } for arg in &mut fn_abi.args { if arg.is_ignore() { continue; } - classify_arg(cx, arg); + classify_arg(cx, arg, Size { raw: 16 }); } } diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs index 76e5067831..4bf909ce46 100644 --- a/compiler/rustc_target/src/asm/aarch64.rs +++ b/compiler/rustc_target/src/asm/aarch64.rs @@ -1,4 +1,5 @@ use super::{InlineAsmArch, InlineAsmType}; +use crate::spec::Target; use rustc_macros::HashStable_Generic; use std::fmt; @@ -70,6 +71,22 @@ impl AArch64InlineAsmRegClass { } } +pub fn reserved_x18( + _arch: InlineAsmArch, + _has_feature: impl FnMut(&str) -> bool, + target: &Target, +) -> Result<(), &'static str> { + if target.os == "android" + || target.is_like_fuchsia + || target.is_like_osx + || target.is_like_windows + { + Err("x18 is a reserved register on this target") + } else { + Ok(()) + } +} + def_regs! { AArch64 AArch64InlineAsmReg AArch64InlineAsmRegClass { x0: reg = ["x0", "w0"], @@ -90,6 +107,7 @@ def_regs! { x15: reg = ["x15", "w15"], x16: reg = ["x16", "w16"], x17: reg = ["x17", "w17"], + x18: reg = ["x18", "w18"] % reserved_x18, x20: reg = ["x20", "w20"], x21: reg = ["x21", "w21"], x22: reg = ["x22", "w22"], @@ -149,8 +167,6 @@ def_regs! { p14: preg = ["p14"], p15: preg = ["p15"], ffr: preg = ["ffr"], - #error = ["x18", "w18"] => - "x18 is used as a reserved register on some targets and cannot be used as an operand for inline asm", #error = ["x19", "w19"] => "x19 is used internally by LLVM and cannot be used as an operand for inline asm", #error = ["x29", "w29", "fp", "wfp"] => diff --git a/compiler/rustc_target/src/asm/arm.rs b/compiler/rustc_target/src/asm/arm.rs index 4c323fc35d..b03594b315 100644 --- a/compiler/rustc_target/src/asm/arm.rs +++ b/compiler/rustc_target/src/asm/arm.rs @@ -6,7 +6,6 @@ use std::fmt; def_reg_class! { Arm ArmInlineAsmRegClass { reg, - reg_thumb, sreg, sreg_low16, dreg, @@ -47,7 +46,7 @@ impl ArmInlineAsmRegClass { _arch: InlineAsmArch, ) -> &'static [(InlineAsmType, Option<&'static str>)] { match self { - Self::reg | Self::reg_thumb => types! { _: I8, I16, I32, F32; }, + Self::reg => types! { _: I8, I16, I32, F32; }, Self::sreg | Self::sreg_low16 => types! { "vfp2": I32, F32; }, Self::dreg | Self::dreg_low16 | Self::dreg_low8 => types! { "vfp2": I64, F64, VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2); @@ -88,20 +87,49 @@ fn frame_pointer_r7( } } +fn not_thumb1( + _arch: InlineAsmArch, + mut has_feature: impl FnMut(&str) -> bool, + _target: &Target, +) -> Result<(), &'static str> { + if has_feature("thumb-mode") && !has_feature("thumb2") { + Err("high registers (r8+) cannot be used in Thumb-1 code") + } else { + Ok(()) + } +} + +fn reserved_r9( + arch: InlineAsmArch, + mut has_feature: impl FnMut(&str) -> bool, + target: &Target, +) -> Result<(), &'static str> { + not_thumb1(arch, &mut has_feature, target)?; + + // We detect this using the reserved-r9 feature instead of using the target + // because the relocation model can be changed with compiler options. + if has_feature("reserved-r9") { + Err("the RWPI static base register (r9) cannot be used as an operand for inline asm") + } else { + Ok(()) + } +} + def_regs! { Arm ArmInlineAsmReg ArmInlineAsmRegClass { - r0: reg, reg_thumb = ["r0", "a1"], - r1: reg, reg_thumb = ["r1", "a2"], - r2: reg, reg_thumb = ["r2", "a3"], - r3: reg, reg_thumb = ["r3", "a4"], - r4: reg, reg_thumb = ["r4", "v1"], - r5: reg, reg_thumb = ["r5", "v2"], - r7: reg, reg_thumb = ["r7", "v4"] % frame_pointer_r7, - r8: reg = ["r8", "v5"], - r10: reg = ["r10", "sl"], + r0: reg = ["r0", "a1"], + r1: reg = ["r1", "a2"], + r2: reg = ["r2", "a3"], + r3: reg = ["r3", "a4"], + r4: reg = ["r4", "v1"], + r5: reg = ["r5", "v2"], + r7: reg = ["r7", "v4"] % frame_pointer_r7, + r8: reg = ["r8", "v5"] % not_thumb1, + r9: reg = ["r9", "v6", "rfp"] % reserved_r9, + r10: reg = ["r10", "sl"] % not_thumb1, r11: reg = ["r11", "fp"] % frame_pointer_r11, - r12: reg = ["r12", "ip"], - r14: reg = ["r14", "lr"], + r12: reg = ["r12", "ip"] % not_thumb1, + r14: reg = ["r14", "lr"] % not_thumb1, s0: sreg, sreg_low16 = ["s0"], s1: sreg, sreg_low16 = ["s1"], s2: sreg, sreg_low16 = ["s2"], @@ -184,8 +212,6 @@ def_regs! { q15: qreg = ["q15"], #error = ["r6", "v3"] => "r6 is used internally by LLVM and cannot be used as an operand for inline asm", - #error = ["r9", "v6", "rfp"] => - "r9 is used internally by LLVM and cannot be used as an operand for inline asm", #error = ["r13", "sp"] => "the stack pointer cannot be used as an operand for inline asm", #error = ["r15", "pc"] => diff --git a/compiler/rustc_target/src/asm/avr.rs b/compiler/rustc_target/src/asm/avr.rs new file mode 100644 index 0000000000..82a4f8bacb --- /dev/null +++ b/compiler/rustc_target/src/asm/avr.rs @@ -0,0 +1,196 @@ +use super::{InlineAsmArch, InlineAsmType}; +use rustc_macros::HashStable_Generic; +use std::fmt; + +def_reg_class! { + Avr AvrInlineAsmRegClass { + reg, + reg_upper, + reg_pair, + reg_iw, + reg_ptr, + } +} + +impl AvrInlineAsmRegClass { + pub fn valid_modifiers(self, _arch: InlineAsmArch) -> &'static [char] { + match self { + Self::reg_pair | Self::reg_iw | Self::reg_ptr => &['h', 'l'], + _ => &[], + } + } + + pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option { + None + } + + pub fn suggest_modifier( + self, + _arch: InlineAsmArch, + _ty: InlineAsmType, + ) -> Option<(char, &'static str)> { + None + } + + pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> { + None + } + + pub fn supported_types( + self, + _arch: InlineAsmArch, + ) -> &'static [(InlineAsmType, Option<&'static str>)] { + match self { + Self::reg => types! { _: I8; }, + Self::reg_upper => types! { _: I8; }, + Self::reg_pair => types! { _: I16; }, + Self::reg_iw => types! { _: I16; }, + Self::reg_ptr => types! { _: I16; }, + } + } +} + +def_regs! { + Avr AvrInlineAsmReg AvrInlineAsmRegClass { + r2: reg = ["r2"], + r3: reg = ["r3"], + r4: reg = ["r4"], + r5: reg = ["r5"], + r6: reg = ["r6"], + r7: reg = ["r7"], + r8: reg = ["r8"], + r9: reg = ["r9"], + r10: reg = ["r10"], + r11: reg = ["r11"], + r12: reg = ["r12"], + r13: reg = ["r13"], + r14: reg = ["r14"], + r15: reg = ["r15"], + r16: reg, reg_upper = ["r16"], + r17: reg, reg_upper = ["r17"], + r18: reg, reg_upper = ["r18"], + r19: reg, reg_upper = ["r19"], + r20: reg, reg_upper = ["r20"], + r21: reg, reg_upper = ["r21"], + r22: reg, reg_upper = ["r22"], + r23: reg, reg_upper = ["r23"], + r24: reg, reg_upper = ["r24"], + r25: reg, reg_upper = ["r25"], + r26: reg, reg_upper = ["r26", "XL"], + r27: reg, reg_upper = ["r27", "XH"], + r30: reg, reg_upper = ["r30", "ZL"], + r31: reg, reg_upper = ["r31", "ZH"], + + r3r2: reg_pair = ["r3r2"], + r5r4: reg_pair = ["r5r4"], + r7r6: reg_pair = ["r7r6"], + r9r8: reg_pair = ["r9r8"], + r11r10: reg_pair = ["r11r10"], + r13r12: reg_pair = ["r13r12"], + r15r14: reg_pair = ["r15r14"], + r17r16: reg_pair = ["r17r16"], + r19r18: reg_pair = ["r19r18"], + r21r20: reg_pair = ["r21r20"], + r23r22: reg_pair = ["r23r22"], + + r25r24: reg_iw, reg_pair = ["r25r24"], + + X: reg_ptr, reg_iw, reg_pair = ["r27r26", "X"], + Z: reg_ptr, reg_iw, reg_pair = ["r31r30", "Z"], + + #error = ["Y", "YL", "YH"] => + "the frame pointer cannot be used as an operand for inline asm", + #error = ["SP", "SPL", "SPH"] => + "the stack pointer cannot be used as an operand for inline asm", + #error = ["r0", "r1", "r1r0"] => + "r0 and r1 are not available due to an issue in LLVM", + } +} + +macro_rules! emit_pairs { + ( + $self:ident $modifier:ident, + $($pair:ident $name:literal $hi:literal $lo:literal,)* + ) => { + match ($self, $modifier) { + $( + (AvrInlineAsmReg::$pair, Some('h')) => $hi, + (AvrInlineAsmReg::$pair, Some('l')) => $lo, + (AvrInlineAsmReg::$pair, _) => $name, + )* + _ => $self.name(), + } + }; +} + +impl AvrInlineAsmReg { + pub fn emit( + self, + out: &mut dyn fmt::Write, + _arch: InlineAsmArch, + modifier: Option, + ) -> fmt::Result { + let name = emit_pairs! { + self modifier, + Z "Z" "ZH" "ZL", + X "X" "XH" "XL", + r25r24 "r25:r24" "r25" "r24", + r23r22 "r23:r22" "r23" "r22", + r21r20 "r21:r20" "r21" "r20", + r19r18 "r19:r18" "r19" "r18", + r17r16 "r17:r16" "r17" "r16", + r15r14 "r15:r14" "r15" "r14", + r13r12 "r13:r12" "r13" "r12", + r11r10 "r11:r10" "r11" "r10", + r9r8 "r9:r8" "r9" "r8", + r7r6 "r7:r6" "r7" "r6", + r5r4 "r5:r4" "r5" "r4", + r3r2 "r3:r2" "r3" "r2", + }; + out.write_str(name) + } + + pub fn overlapping_regs(self, mut cb: impl FnMut(AvrInlineAsmReg)) { + cb(self); + + macro_rules! reg_conflicts { + ( + $( + $pair:ident : $hi:ident $lo:ident, + )* + ) => { + match self { + $( + Self::$pair => { + cb(Self::$hi); + cb(Self::$lo); + } + Self::$hi => { + cb(Self::$pair); + } + Self::$lo => { + cb(Self::$pair); + } + )* + } + }; + } + + reg_conflicts! { + Z : r31 r30, + X : r27 r26, + r25r24 : r25 r24, + r23r22 : r23 r22, + r21r20 : r21 r20, + r19r18 : r19 r18, + r17r16 : r17 r16, + r15r14 : r15 r14, + r13r12 : r13 r12, + r11r10 : r11 r10, + r9r8 : r9 r8, + r7r6 : r7 r6, + r5r4 : r5 r4, + r3r2 : r3 r2, + } + } +} diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index bff1324652..9128e54682 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -148,6 +148,7 @@ macro_rules! types { mod aarch64; mod arm; +mod avr; mod bpf; mod hexagon; mod mips; @@ -161,6 +162,7 @@ mod x86; pub use aarch64::{AArch64InlineAsmReg, AArch64InlineAsmRegClass}; pub use arm::{ArmInlineAsmReg, ArmInlineAsmRegClass}; +pub use avr::{AvrInlineAsmReg, AvrInlineAsmRegClass}; pub use bpf::{BpfInlineAsmReg, BpfInlineAsmRegClass}; pub use hexagon::{HexagonInlineAsmReg, HexagonInlineAsmRegClass}; pub use mips::{MipsInlineAsmReg, MipsInlineAsmRegClass}; @@ -191,6 +193,7 @@ pub enum InlineAsmArch { Wasm32, Wasm64, Bpf, + Avr, } impl FromStr for InlineAsmArch { @@ -215,6 +218,7 @@ impl FromStr for InlineAsmArch { "wasm32" => Ok(Self::Wasm32), "wasm64" => Ok(Self::Wasm64), "bpf" => Ok(Self::Bpf), + "avr" => Ok(Self::Avr), _ => Err(()), } } @@ -245,6 +249,7 @@ pub enum InlineAsmReg { SpirV(SpirVInlineAsmReg), Wasm(WasmInlineAsmReg), Bpf(BpfInlineAsmReg), + Avr(AvrInlineAsmReg), // Placeholder for invalid register constraints for the current target Err, } @@ -261,6 +266,7 @@ impl InlineAsmReg { Self::Mips(r) => r.name(), Self::S390x(r) => r.name(), Self::Bpf(r) => r.name(), + Self::Avr(r) => r.name(), Self::Err => "", } } @@ -276,6 +282,7 @@ impl InlineAsmReg { Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()), Self::S390x(r) => InlineAsmRegClass::S390x(r.reg_class()), Self::Bpf(r) => InlineAsmRegClass::Bpf(r.reg_class()), + Self::Avr(r) => InlineAsmRegClass::Avr(r.reg_class()), Self::Err => InlineAsmRegClass::Err, } } @@ -291,40 +298,43 @@ impl InlineAsmReg { let name = name.as_str(); Ok(match arch { InlineAsmArch::X86 | InlineAsmArch::X86_64 => { - Self::X86(X86InlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::X86(X86InlineAsmReg::parse(arch, has_feature, target, name)?) } InlineAsmArch::Arm => { - Self::Arm(ArmInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::Arm(ArmInlineAsmReg::parse(arch, has_feature, target, name)?) } InlineAsmArch::AArch64 => { - Self::AArch64(AArch64InlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::AArch64(AArch64InlineAsmReg::parse(arch, has_feature, target, name)?) } InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => { - Self::RiscV(RiscVInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::RiscV(RiscVInlineAsmReg::parse(arch, has_feature, target, name)?) } InlineAsmArch::Nvptx64 => { - Self::Nvptx(NvptxInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::Nvptx(NvptxInlineAsmReg::parse(arch, has_feature, target, name)?) } InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => { - Self::PowerPC(PowerPCInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::PowerPC(PowerPCInlineAsmReg::parse(arch, has_feature, target, name)?) } InlineAsmArch::Hexagon => { - Self::Hexagon(HexagonInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::Hexagon(HexagonInlineAsmReg::parse(arch, has_feature, target, name)?) } InlineAsmArch::Mips | InlineAsmArch::Mips64 => { - Self::Mips(MipsInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::Mips(MipsInlineAsmReg::parse(arch, has_feature, target, name)?) } InlineAsmArch::S390x => { - Self::S390x(S390xInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::S390x(S390xInlineAsmReg::parse(arch, has_feature, target, name)?) } InlineAsmArch::SpirV => { - Self::SpirV(SpirVInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::SpirV(SpirVInlineAsmReg::parse(arch, has_feature, target, name)?) } InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => { - Self::Wasm(WasmInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::Wasm(WasmInlineAsmReg::parse(arch, has_feature, target, name)?) } InlineAsmArch::Bpf => { - Self::Bpf(BpfInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::Bpf(BpfInlineAsmReg::parse(arch, has_feature, target, name)?) + } + InlineAsmArch::Avr => { + Self::Avr(AvrInlineAsmReg::parse(arch, has_feature, target, name)?) } }) } @@ -347,6 +357,7 @@ impl InlineAsmReg { Self::Mips(r) => r.emit(out, arch, modifier), Self::S390x(r) => r.emit(out, arch, modifier), Self::Bpf(r) => r.emit(out, arch, modifier), + Self::Avr(r) => r.emit(out, arch, modifier), Self::Err => unreachable!("Use of InlineAsmReg::Err"), } } @@ -362,6 +373,7 @@ impl InlineAsmReg { Self::Mips(_) => cb(self), Self::S390x(_) => cb(self), Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))), + Self::Avr(r) => r.overlapping_regs(|r| cb(Self::Avr(r))), Self::Err => unreachable!("Use of InlineAsmReg::Err"), } } @@ -392,6 +404,7 @@ pub enum InlineAsmRegClass { SpirV(SpirVInlineAsmRegClass), Wasm(WasmInlineAsmRegClass), Bpf(BpfInlineAsmRegClass), + Avr(AvrInlineAsmRegClass), // Placeholder for invalid register constraints for the current target Err, } @@ -411,6 +424,7 @@ impl InlineAsmRegClass { Self::SpirV(r) => r.name(), Self::Wasm(r) => r.name(), Self::Bpf(r) => r.name(), + Self::Avr(r) => r.name(), Self::Err => rustc_span::symbol::sym::reg, } } @@ -432,6 +446,7 @@ impl InlineAsmRegClass { Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV), Self::Wasm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Wasm), Self::Bpf(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Bpf), + Self::Avr(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Avr), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } @@ -460,6 +475,7 @@ impl InlineAsmRegClass { Self::SpirV(r) => r.suggest_modifier(arch, ty), Self::Wasm(r) => r.suggest_modifier(arch, ty), Self::Bpf(r) => r.suggest_modifier(arch, ty), + Self::Avr(r) => r.suggest_modifier(arch, ty), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } @@ -484,6 +500,7 @@ impl InlineAsmRegClass { Self::SpirV(r) => r.default_modifier(arch), Self::Wasm(r) => r.default_modifier(arch), Self::Bpf(r) => r.default_modifier(arch), + Self::Avr(r) => r.default_modifier(arch), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } @@ -507,6 +524,7 @@ impl InlineAsmRegClass { Self::SpirV(r) => r.supported_types(arch), Self::Wasm(r) => r.supported_types(arch), Self::Bpf(r) => r.supported_types(arch), + Self::Avr(r) => r.supported_types(arch), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } @@ -535,6 +553,7 @@ impl InlineAsmRegClass { Self::Wasm(WasmInlineAsmRegClass::parse(arch, name)?) } InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmRegClass::parse(arch, name)?), + InlineAsmArch::Avr => Self::Avr(AvrInlineAsmRegClass::parse(arch, name)?), }) } @@ -554,6 +573,7 @@ impl InlineAsmRegClass { Self::SpirV(r) => r.valid_modifiers(arch), Self::Wasm(r) => r.valid_modifiers(arch), Self::Bpf(r) => r.valid_modifiers(arch), + Self::Avr(r) => r.valid_modifiers(arch), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } @@ -739,6 +759,11 @@ pub fn allocatable_registers( bpf::fill_reg_map(arch, has_feature, target, &mut map); map } + InlineAsmArch::Avr => { + let mut map = avr::regclass_map(); + avr::fill_reg_map(arch, has_feature, target, &mut map); + map + } } } @@ -760,6 +785,7 @@ pub enum InlineAsmClobberAbi { X86_64SysV, Arm, AArch64, + AArch64NoX18, RiscV, } @@ -768,10 +794,11 @@ impl InlineAsmClobberAbi { /// clobber ABIs for the target. pub fn parse( arch: InlineAsmArch, + has_feature: impl FnMut(&str) -> bool, target: &Target, name: Symbol, ) -> Result { - let name = &*name.as_str(); + let name = name.as_str(); match arch { InlineAsmArch::X86 => match name { "C" | "system" | "efiapi" | "cdecl" | "stdcall" | "fastcall" => { @@ -791,7 +818,13 @@ impl InlineAsmClobberAbi { _ => Err(&["C", "system", "efiapi", "aapcs"]), }, InlineAsmArch::AArch64 => match name { - "C" | "system" | "efiapi" => Ok(InlineAsmClobberAbi::AArch64), + "C" | "system" | "efiapi" => { + Ok(if aarch64::reserved_x18(arch, has_feature, target).is_err() { + InlineAsmClobberAbi::AArch64NoX18 + } else { + InlineAsmClobberAbi::AArch64 + }) + } _ => Err(&["C", "system", "efiapi"]), }, InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => match name { @@ -866,8 +899,25 @@ impl InlineAsmClobberAbi { AArch64 AArch64InlineAsmReg { x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, - // x18 is platform-reserved or temporary, but we exclude it - // here since it is a reserved register. + x16, x17, x18, x30, + + // Technically the low 64 bits of v8-v15 are preserved, but + // we have no way of expressing this using clobbers. + v0, v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, + v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, + + p0, p1, p2, p3, p4, p5, p6, p7, + p8, p9, p10, p11, p12, p13, p14, p15, + ffr, + + } + }, + InlineAsmClobberAbi::AArch64NoX18 => clobbered_regs! { + AArch64 AArch64InlineAsmReg { + x0, x1, x2, x3, x4, x5, x6, x7, + x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x30, // Technically the low 64 bits of v8-v15 are preserved, but @@ -885,7 +935,8 @@ impl InlineAsmClobberAbi { }, InlineAsmClobberAbi::Arm => clobbered_regs! { Arm ArmInlineAsmReg { - // r9 is platform-reserved and is treated as callee-saved. + // r9 is either platform-reserved or callee-saved. Either + // way we don't need to clobber it. r0, r1, r2, r3, r12, r14, // The finest-grained register variant is used here so that diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index 23d5d575d9..b18d17c1b7 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -16,6 +16,7 @@ #![feature(min_specialization)] #![feature(step_trait)] +use std::iter::FromIterator; use std::path::{Path, PathBuf}; #[macro_use] @@ -47,12 +48,11 @@ const RUST_LIB_DIR: &str = "rustlib"; /// `"lib*/rustlib/x86_64-unknown-linux-gnu"`. pub fn target_rustlib_path(sysroot: &Path, target_triple: &str) -> PathBuf { let libdir = find_libdir(sysroot); - std::array::IntoIter::new([ + PathBuf::from_iter([ Path::new(libdir.as_ref()), Path::new(RUST_LIB_DIR), Path::new(target_triple), ]) - .collect::() } /// The name of the directory rustc expects libraries to be located. diff --git a/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs index 1369d9d079..a9a0977e70 100644 --- a/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/aarch64_pc_windows_msvc.rs @@ -3,7 +3,6 @@ use crate::spec::Target; pub fn target() -> Target { let mut base = super::windows_msvc_base::opts(); base.max_atomic_width = Some(64); - base.has_elf_tls = true; base.features = "+neon,+fp-armv8".to_string(); Target { diff --git a/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs index e0a81df2b0..db4eb204e0 100644 --- a/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/aarch64_uwp_windows_msvc.rs @@ -3,7 +3,6 @@ use crate::spec::Target; pub fn target() -> Target { let mut base = super::windows_uwp_msvc_base::opts(); base.max_atomic_width = Some(64); - base.has_elf_tls = true; Target { llvm_target: "aarch64-pc-windows-msvc".to_string(), diff --git a/compiler/rustc_target/src/spec/android_base.rs b/compiler/rustc_target/src/spec/android_base.rs index 0f01a78c8c..e982b3565b 100644 --- a/compiler/rustc_target/src/spec/android_base.rs +++ b/compiler/rustc_target/src/spec/android_base.rs @@ -11,7 +11,7 @@ pub fn opts() -> TargetOptions { .push("-Wl,--allow-multiple-definition".to_string()); base.dwarf_version = Some(2); base.position_independent_executables = true; - base.has_elf_tls = false; + base.has_thread_local = false; // This is for backward compatibility, see https://github.com/rust-lang/rust/issues/49867 // for context. (At that time, there was no `-C force-unwind-tables`, so the only solution // was to always emit `uwtable`). diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs index db6aee59a5..a4488f695f 100644 --- a/compiler/rustc_target/src/spec/apple_base.rs +++ b/compiler/rustc_target/src/spec/apple_base.rs @@ -16,7 +16,7 @@ pub fn opts(os: &str) -> TargetOptions { // TLS is flagged as enabled if it looks to be supported. The architecture // only matters for default deployment target which is 11.0 for ARM64 and // 10.7 for everything else. - let has_elf_tls = macos_deployment_target("x86_64") >= (10, 7); + let has_thread_local = macos_deployment_target("x86_64") >= (10, 7); TargetOptions { os: os.to_string(), @@ -33,7 +33,7 @@ pub fn opts(os: &str) -> TargetOptions { has_rpath: true, dll_suffix: ".dylib".to_string(), archive_format: "darwin".to_string(), - has_elf_tls, + has_thread_local, abi_return_struct_as_int: true, emit_debug_gdb_scripts: false, eh_frame_header: false, diff --git a/compiler/rustc_target/src/spec/apple_sdk_base.rs b/compiler/rustc_target/src/spec/apple_sdk_base.rs index 39bc699eef..874e9b56aa 100644 --- a/compiler/rustc_target/src/spec/apple_sdk_base.rs +++ b/compiler/rustc_target/src/spec/apple_sdk_base.rs @@ -53,7 +53,7 @@ pub fn opts(os: &str, arch: Arch) -> TargetOptions { dynamic_linking: false, executables: true, link_env_remove: link_env_remove(arch), - has_elf_tls: false, + has_thread_local: false, ..super::apple_base::opts(os) } } diff --git a/compiler/rustc_target/src/spec/fuchsia_base.rs b/compiler/rustc_target/src/spec/fuchsia_base.rs index 23a2e65749..4a7686ae1a 100644 --- a/compiler/rustc_target/src/spec/fuchsia_base.rs +++ b/compiler/rustc_target/src/spec/fuchsia_base.rs @@ -35,7 +35,7 @@ pub fn opts() -> TargetOptions { (LinkOutputKind::StaticPicExe, &["Scrt1.o"]), ]), position_independent_executables: true, - has_elf_tls: true, + has_thread_local: true, ..Default::default() } } diff --git a/compiler/rustc_target/src/spec/hermit_base.rs b/compiler/rustc_target/src/spec/hermit_base.rs index 75ca1f79b1..b0b1d80ab3 100644 --- a/compiler/rustc_target/src/spec/hermit_base.rs +++ b/compiler/rustc_target/src/spec/hermit_base.rs @@ -12,7 +12,7 @@ pub fn opts() -> TargetOptions { linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), linker: Some("rust-lld".to_owned()), executables: true, - has_elf_tls: true, + has_thread_local: true, pre_link_args, panic_strategy: PanicStrategy::Abort, position_independent_executables: true, diff --git a/compiler/rustc_target/src/spec/i686_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/i686_uwp_windows_msvc.rs index ce6200be81..05f204c560 100644 --- a/compiler/rustc_target/src/spec/i686_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/i686_uwp_windows_msvc.rs @@ -4,7 +4,6 @@ pub fn target() -> Target { let mut base = super::windows_uwp_msvc_base::opts(); base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); - base.has_elf_tls = true; Target { llvm_target: "i686-pc-windows-msvc".to_string(), diff --git a/compiler/rustc_target/src/spec/illumos_base.rs b/compiler/rustc_target/src/spec/illumos_base.rs index f598f0f38f..aeb40f7712 100644 --- a/compiler/rustc_target/src/spec/illumos_base.rs +++ b/compiler/rustc_target/src/spec/illumos_base.rs @@ -45,7 +45,7 @@ pub fn opts() -> TargetOptions { // (see src/libstd/sys/unix/fast_thread_local.rs) that is currently // missing in illumos. For now at least, we must fallback to using // pthread_{get,set}specific. - //has_elf_tls: true, + //has_thread_local: true, // FIXME: Currently, rust is invoking cc to link, which ends up // causing these to get included twice. We should eventually transition diff --git a/compiler/rustc_target/src/spec/linux_base.rs b/compiler/rustc_target/src/spec/linux_base.rs index af81bc714c..e53d465e20 100644 --- a/compiler/rustc_target/src/spec/linux_base.rs +++ b/compiler/rustc_target/src/spec/linux_base.rs @@ -9,7 +9,7 @@ pub fn opts() -> TargetOptions { has_rpath: true, position_independent_executables: true, relro_level: RelroLevel::Full, - has_elf_tls: true, + has_thread_local: true, crt_static_respected: true, ..Default::default() } diff --git a/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs index fff7b25a34..5671b59c63 100644 --- a/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/m68k_unknown_linux_gnu.rs @@ -2,7 +2,7 @@ use crate::abi::Endian; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let mut base = super::linux_base::opts(); + let mut base = super::linux_gnu_base::opts(); base.max_atomic_width = Some(32); Target { diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 0d49c7f6ee..ca1949b9f7 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -42,6 +42,7 @@ use rustc_serialize::json::{Json, ToJson}; use rustc_span::symbol::{sym, Symbol}; use std::collections::BTreeMap; use std::convert::TryFrom; +use std::iter::FromIterator; use std::ops::{Deref, DerefMut}; use std::path::{Path, PathBuf}; use std::str::FromStr; @@ -478,7 +479,7 @@ pub enum SplitDebuginfo { /// /// * Windows - not supported /// * macOS - supported, scattered object files - /// * ELF - supported, scattered `*.dwo` files + /// * ELF - supported, scattered `*.dwo` or `*.o` files (see `SplitDwarfKind`) Unpacked, } @@ -866,6 +867,7 @@ supported_targets! { ("powerpc-unknown-freebsd", powerpc_unknown_freebsd), ("powerpc64-unknown-freebsd", powerpc64_unknown_freebsd), ("powerpc64le-unknown-freebsd", powerpc64le_unknown_freebsd), + ("riscv64gc-unknown-freebsd", riscv64gc_unknown_freebsd), ("x86_64-unknown-freebsd", x86_64_unknown_freebsd), ("x86_64-unknown-dragonfly", x86_64_unknown_dragonfly), @@ -1277,9 +1279,8 @@ pub struct TargetOptions { /// `argc` and `argv` values. pub main_needs_argc_argv: bool, - /// Flag indicating whether ELF TLS (e.g., #[thread_local]) is available for - /// this target. - pub has_elf_tls: bool, + /// Flag indicating whether #[thread_local] is available for this target. + pub has_thread_local: bool, // This is mainly for easy compatibility with emscripten. // If we give emcc .o files that are actually .bc files it // will 'just work'. @@ -1485,7 +1486,7 @@ impl Default for TargetOptions { archive_format: "gnu".to_string(), main_needs_argc_argv: true, allow_asm: true, - has_elf_tls: false, + has_thread_local: false, obj_is_bitcode: false, forces_embed_bitcode: false, bitcode_llvm_cmdline: String::new(), @@ -2072,7 +2073,7 @@ impl Target { key!(archive_format); key!(allow_asm, bool); key!(main_needs_argc_argv, bool); - key!(has_elf_tls, bool); + key!(has_thread_local, bool); key!(obj_is_bitcode, bool); key!(forces_embed_bitcode, bool); key!(bitcode_llvm_cmdline); @@ -2173,12 +2174,11 @@ impl Target { // Additionally look in the sysroot under `lib/rustlib//target.json` // as a fallback. let rustlib_path = crate::target_rustlib_path(&sysroot, &target_triple); - let p = std::array::IntoIter::new([ + let p = PathBuf::from_iter([ Path::new(sysroot), Path::new(&rustlib_path), Path::new("target.json"), - ]) - .collect::(); + ]); if p.is_file() { return load_file(&p); } @@ -2314,7 +2314,7 @@ impl ToJson for Target { target_option_val!(archive_format); target_option_val!(allow_asm); target_option_val!(main_needs_argc_argv); - target_option_val!(has_elf_tls); + target_option_val!(has_thread_local); target_option_val!(obj_is_bitcode); target_option_val!(forces_embed_bitcode); target_option_val!(bitcode_llvm_cmdline); diff --git a/compiler/rustc_target/src/spec/redox_base.rs b/compiler/rustc_target/src/spec/redox_base.rs index fcf5db3746..bcb536b37a 100644 --- a/compiler/rustc_target/src/spec/redox_base.rs +++ b/compiler/rustc_target/src/spec/redox_base.rs @@ -10,7 +10,7 @@ pub fn opts() -> TargetOptions { has_rpath: true, position_independent_executables: true, relro_level: RelroLevel::Full, - has_elf_tls: true, + has_thread_local: true, crt_static_default: true, crt_static_respected: true, ..Default::default() diff --git a/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs new file mode 100644 index 0000000000..1ea1b9bea2 --- /dev/null +++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_freebsd.rs @@ -0,0 +1,18 @@ +use crate::spec::{CodeModel, Target, TargetOptions}; + +pub fn target() -> Target { + Target { + llvm_target: "riscv64-unknown-freebsd".to_string(), + pointer_width: 64, + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".to_string(), + arch: "riscv64".to_string(), + options: TargetOptions { + code_model: Some(CodeModel::Medium), + cpu: "generic-rv64".to_string(), + features: "+m,+a,+f,+d,+c".to_string(), + llvm_abiname: "lp64d".to_string(), + max_atomic_width: Some(64), + ..super::freebsd_base::opts() + }, + } +} diff --git a/compiler/rustc_target/src/spec/solid_base.rs b/compiler/rustc_target/src/spec/solid_base.rs index c6a279d92e..421cfc4011 100644 --- a/compiler/rustc_target/src/spec/solid_base.rs +++ b/compiler/rustc_target/src/spec/solid_base.rs @@ -6,7 +6,7 @@ pub fn opts(kernel: &str) -> TargetOptions { os: format!("solid_{}", kernel), vendor: "kmc".to_string(), frame_pointer: FramePointer::NonLeaf, - has_elf_tls: true, + has_thread_local: true, ..Default::default() } } diff --git a/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs index b44c008500..72d39ef9a9 100644 --- a/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/thumbv7a_uwp_windows_msvc.rs @@ -9,7 +9,6 @@ pub fn target() -> Target { options: TargetOptions { features: "+vfp3,+neon".to_string(), max_atomic_width: Some(64), - has_elf_tls: true, // FIXME(jordanrh): use PanicStrategy::Unwind when SEH is // implemented for windows/arm in LLVM panic_strategy: PanicStrategy::Abort, diff --git a/compiler/rustc_target/src/spec/vxworks_base.rs b/compiler/rustc_target/src/spec/vxworks_base.rs index a91e771786..3f709e7023 100644 --- a/compiler/rustc_target/src/spec/vxworks_base.rs +++ b/compiler/rustc_target/src/spec/vxworks_base.rs @@ -11,7 +11,7 @@ pub fn opts() -> TargetOptions { executables: true, families: vec!["unix".to_string()], has_rpath: true, - has_elf_tls: true, + has_thread_local: true, crt_static_default: true, crt_static_respected: true, crt_static_allows_dylibs: true, diff --git a/compiler/rustc_target/src/spec/wasm_base.rs b/compiler/rustc_target/src/spec/wasm_base.rs index 24e9c62516..71aa279144 100644 --- a/compiler/rustc_target/src/spec/wasm_base.rs +++ b/compiler/rustc_target/src/spec/wasm_base.rs @@ -120,9 +120,9 @@ pub fn options() -> TargetOptions { // When the atomics feature is activated then these two keys matter, // otherwise they're basically ignored by the standard library. In this // mode, however, the `#[thread_local]` attribute works (i.e. - // `has_elf_tls`) and we need to get it to work by specifying + // `has_thread_local`) and we need to get it to work by specifying // `local-exec` as that's all that's implemented in LLVM today for wasm. - has_elf_tls: true, + has_thread_local: true, tls_model: TlsModel::LocalExec, // gdb scripts don't work on wasm blobs diff --git a/compiler/rustc_target/src/spec/windows_msvc_base.rs b/compiler/rustc_target/src/spec/windows_msvc_base.rs index 0d58618a44..063b6538d9 100644 --- a/compiler/rustc_target/src/spec/windows_msvc_base.rs +++ b/compiler/rustc_target/src/spec/windows_msvc_base.rs @@ -27,6 +27,7 @@ pub fn opts() -> TargetOptions { // linking some libraries which require a specific agreement, so it may // not ever be possible for us to pass this flag. no_default_libraries: false, + has_thread_local: true, ..base } diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs index 72bbb10323..1c4ccebb48 100644 --- a/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/x86_64_pc_windows_msvc.rs @@ -4,7 +4,6 @@ pub fn target() -> Target { let mut base = super::windows_msvc_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.has_elf_tls = true; Target { llvm_target: "x86_64-pc-windows-msvc".to_string(), diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs index 1ffaa9b78c..109f86d3a4 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs @@ -8,7 +8,7 @@ pub fn target() -> Target { base.pre_link_args.entry(LinkerFlavor::Gcc).or_default().push("-mx32".to_string()); // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved base.stack_probes = StackProbeType::Call; - base.has_elf_tls = false; + base.has_thread_local = false; // BUG(GabrielMajeri): disabling the PLT on x86_64 Linux with x32 ABI // breaks code gen. See LLVM bug 36743 base.needs_plt = true; diff --git a/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs index 27c579ed5b..06ccc27230 100644 --- a/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/x86_64_uwp_windows_msvc.rs @@ -4,7 +4,6 @@ pub fn target() -> Target { let mut base = super::windows_uwp_msvc_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.has_elf_tls = true; Target { llvm_target: "x86_64-pc-windows-msvc".to_string(), diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs index 4c80483fc1..46c74660f8 100644 --- a/compiler/rustc_trait_selection/src/autoderef.rs +++ b/compiler/rustc_trait_selection/src/autoderef.rs @@ -3,7 +3,7 @@ use crate::traits::{self, TraitEngine}; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_infer::infer::InferCtxt; -use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, WithConstness}; +use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt}; use rustc_middle::ty::{ToPredicate, TypeFoldable}; use rustc_session::{DiagnosticMessageId, Limit}; use rustc_span::def_id::LOCAL_CRATE; diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 70816b5722..f135f0c1b1 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -9,7 +9,6 @@ use rustc_middle::infer::canonical::{Canonical, CanonicalizedQueryResponse, Quer use rustc_middle::traits::query::Fallible; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::ToPredicate; -use rustc_middle::ty::WithConstness; use rustc_middle::ty::{self, Ty, TypeFoldable}; use rustc_span::{Span, DUMMY_SP}; diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 1820e33b19..17e7b48189 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -16,8 +16,7 @@ #![feature(drain_filter)] #![feature(derive_default_enum)] #![feature(hash_drain_filter)] -#![feature(in_band_lifetimes)] -#![feature(iter_zip)] +#![feature(label_break_value)] #![feature(let_else)] #![feature(never_type)] #![feature(crate_visibility_modifier)] diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 75d57d78e3..ea0ac6318b 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -97,7 +97,7 @@ struct ReverseMapper<'tcx> { span: Span, } -impl ReverseMapper<'tcx> { +impl<'tcx> ReverseMapper<'tcx> { fn new( tcx: TyCtxt<'tcx>, tainted_by_errors: bool, @@ -134,7 +134,7 @@ impl ReverseMapper<'tcx> { } } -impl TypeFolder<'tcx> for ReverseMapper<'tcx> { +impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -338,7 +338,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { /// Requires that trait definitions have been processed so that we can /// elaborate predicates and walk supertraits. #[instrument(skip(tcx, predicates), level = "debug")] -crate fn required_region_bounds( +crate fn required_region_bounds<'tcx>( tcx: TyCtxt<'tcx>, erased_self_ty: Ty<'tcx>, predicates: impl Iterator>, diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 54f7b91080..05d2a373dc 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -219,7 +219,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { } } -impl AutoTraitFinder<'tcx> { +impl<'tcx> AutoTraitFinder<'tcx> { /// The core logic responsible for computing the bounds for our synthesized impl. /// /// To calculate the bounds, we call `SelectionContext.select` in a loop. Like @@ -370,12 +370,17 @@ impl AutoTraitFinder<'tcx> { computed_preds.clone().chain(user_computed_preds.iter().cloned()), ) .map(|o| o.predicate); - new_env = ty::ParamEnv::new(tcx.mk_predicates(normalized_preds), param_env.reveal()); + new_env = ty::ParamEnv::new( + tcx.mk_predicates(normalized_preds), + param_env.reveal(), + param_env.constness(), + ); } let final_user_env = ty::ParamEnv::new( tcx.mk_predicates(user_computed_preds.into_iter()), user_env.reveal(), + user_env.constness(), ); debug!( "evaluate_nested_obligations(ty={:?}, trait_did={:?}): succeeded with '{:?}' \ @@ -834,7 +839,17 @@ impl AutoTraitFinder<'tcx> { _ => return false, } } - _ => panic!("Unexpected predicate {:?} {:?}", ty, predicate), + // There's not really much we can do with these predicates - + // we start out with a `ParamEnv` with no inference variables, + // and these don't correspond to adding any new bounds to + // the `ParamEnv`. + ty::PredicateKind::WellFormed(..) + | ty::PredicateKind::ObjectSafe(..) + | ty::PredicateKind::ClosureKind(..) + | ty::PredicateKind::Subtype(..) + | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::Coerce(..) + | ty::PredicateKind::TypeWellFormedFromEnv(..) => {} }; } true diff --git a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs index 2ccb253491..34fc4ca8fe 100644 --- a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs @@ -16,7 +16,7 @@ pub struct FulfillmentContext<'tcx> { relationships: FxHashMap, } -impl FulfillmentContext<'tcx> { +impl FulfillmentContext<'_> { crate fn new() -> Self { FulfillmentContext { obligations: FxIndexSet::default(), @@ -25,7 +25,7 @@ impl FulfillmentContext<'tcx> { } } -impl TraitEngine<'tcx> for FulfillmentContext<'tcx> { +impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { fn normalize_projection_type( &mut self, infcx: &InferCtxt<'_, 'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs index bdd4fdd404..848aba7c91 100644 --- a/compiler/rustc_trait_selection/src/traits/codegen.rs +++ b/compiler/rustc_trait_selection/src/traits/codegen.rs @@ -107,7 +107,7 @@ pub fn codegen_fulfill_obligation<'tcx>( /// type inference variables that appear in `result` to be /// unified, and hence we need to process those obligations to get /// the complete picture of the type. -fn drain_fulfillment_cx_or_panic( +fn drain_fulfillment_cx_or_panic<'tcx, T>( infcx: &InferCtxt<'_, 'tcx>, fulfill_cx: &mut FulfillmentContext<'tcx>, result: T, diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 42d3194aed..290426aa82 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -12,9 +12,10 @@ use crate::traits::{ self, Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext, }; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences}; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::Subst; -use rustc_middle::ty::{self, fast_reject, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::symbol::sym; use rustc_span::DUMMY_SP; use std::iter; @@ -82,12 +83,11 @@ where impl2_ref.iter().flat_map(|tref| tref.substs.types()), ) .any(|(ty1, ty2)| { - let t1 = fast_reject::simplify_type(tcx, ty1, false); - let t2 = fast_reject::simplify_type(tcx, ty2, false); + let t1 = fast_reject::simplify_type(tcx, ty1, SimplifyParams::No, StripReferences::No); + let t2 = fast_reject::simplify_type(tcx, ty2, SimplifyParams::No, StripReferences::No); if let (Some(t1), Some(t2)) = (t1, t2) { // Simplified successfully - // Types cannot unify if they differ in their reference mutability or simplify to different types - t1 != t2 || ty1.ref_mutability() != ty2.ref_mutability() + t1 != t2 } else { // Types might unify false @@ -154,18 +154,24 @@ fn overlap<'cx, 'tcx>( }) } -fn overlap_within_probe( +fn overlap_within_probe<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, skip_leak_check: SkipLeakCheck, a_def_id: DefId, b_def_id: DefId, snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> Option> { - fn loose_check(selcx: &mut SelectionContext<'cx, 'tcx>, o: &PredicateObligation<'tcx>) -> bool { + fn loose_check<'cx, 'tcx>( + selcx: &mut SelectionContext<'cx, 'tcx>, + o: &PredicateObligation<'tcx>, + ) -> bool { !selcx.predicate_may_hold_fatal(o) } - fn strict_check(selcx: &SelectionContext<'cx, 'tcx>, o: &PredicateObligation<'tcx>) -> bool { + fn strict_check<'cx, 'tcx>( + selcx: &SelectionContext<'cx, 'tcx>, + o: &PredicateObligation<'tcx>, + ) -> bool { let infcx = selcx.infcx(); let tcx = infcx.tcx; o.flip_polarity(tcx) @@ -498,9 +504,7 @@ fn orphan_check_trait_ref<'tcx>( return Err(OrphanCheckErr::UncoveredTy(input_ty, local_type)); } - for input_ty in non_local_tys { - non_local_spans.push((input_ty, i == 0)); - } + non_local_spans.extend(non_local_tys.into_iter().map(|input_ty| (input_ty, i == 0))); } // If we exit above loop, never found a local type. debug!("orphan_check_trait_ref: no local type"); @@ -520,7 +524,11 @@ fn orphan_check_trait_ref<'tcx>( /// - for `Foo`, where `Foo` is a local type, this returns `[]`. /// - `&mut u32` returns `[u32]`, as `&mut` is a fundamental type, similar to `Box`. /// - `Box>` returns `[]`, as `Box` is a fundamental type and `Foo` is local. -fn contained_non_local_types(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, in_crate: InCrate) -> Vec> { +fn contained_non_local_types<'tcx>( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, + in_crate: InCrate, +) -> Vec> { if ty_is_local_constructor(ty, in_crate) { Vec::new() } else { @@ -536,7 +544,7 @@ fn contained_non_local_types(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, in_crate: InCrate) /// For `#[fundamental]` ADTs and `&T` / `&mut T`, returns `Some` with the /// type parameters of the ADT, or `T`, respectively. For non-fundamental /// types, returns `None`. -fn fundamental_ty_inner_tys( +fn fundamental_ty_inner_tys<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, ) -> Option>> { diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 6b5d37c0f4..0ea3a18ca3 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -399,13 +399,25 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { let arg = self.recurse_build(source)?; self.nodes.push(Node::Cast(abstract_const::CastKind::As, arg, node.ty)) } + ExprKind::Borrow{ arg, ..} => { + let arg_node = &self.body.exprs[*arg]; + // Skip reborrows for now until we allow Deref/Borrow/AddressOf + // expressions. + // FIXME(generic_const_exprs): Verify/explain why this is sound + if let ExprKind::Deref {arg} = arg_node.kind { + self.recurse_build(arg)? + } else { + self.maybe_supported_error( + node.span, + "borrowing is not supported in generic constants", + )? + } + } // FIXME(generic_const_exprs): We may want to support these. - ExprKind::AddressOf { .. } - | ExprKind::Borrow { .. } - | ExprKind::Deref { .. } => self.maybe_supported_error( + ExprKind::AddressOf { .. } | ExprKind::Deref {..}=> self.maybe_supported_error( node.span, - "dereferencing is not supported in generic constants", + "dereferencing or taking the address is not supported in generic constants", )?, ExprKind::Repeat { .. } | ExprKind::Array { .. } => self.maybe_supported_error( node.span, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index f8df0e2595..a9ae0ec53c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -21,10 +21,10 @@ use rustc_hir::Item; use rustc_hir::Node; use rustc_middle::thir::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::ExpectedFound; +use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences}; use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::{ - self, fast_reject, AdtKind, SubtypePredicate, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, - TypeFoldable, WithConstness, + self, AdtKind, SubtypePredicate, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, }; use rustc_session::DiagnosticMessageId; use rustc_span::symbol::{kw, sym}; @@ -205,7 +205,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { self.note_obligation_cause_code( &mut err, &obligation.predicate, - &obligation.cause.code, + obligation.cause.code(), &mut vec![], &mut Default::default(), ); @@ -255,7 +255,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // If this obligation was generated as a result of well-formedness checking, see if we // can get a better error message by performing HIR-based well-formedness checking. if let ObligationCauseCode::WellFormed(Some(wf_loc)) = - root_obligation.cause.code.peel_derives() + root_obligation.cause.code().peel_derives() { if let Some(cause) = self .tcx @@ -272,7 +272,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { | ObligationCauseCode::CompareImplTypeObligation { impl_item_def_id, trait_item_def_id, - } = obligation.cause.code + } = *obligation.cause.code() { self.report_extra_impl_obligation( span, @@ -295,7 +295,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } let trait_ref = trait_predicate.to_poly_trait_ref(); let (post_message, pre_message, type_def) = self - .get_parent_trait_ref(&obligation.cause.code) + .get_parent_trait_ref(obligation.cause.code()) .map(|(t, s)| { ( format!(" in `{}`", t), @@ -376,17 +376,18 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } } - let explanation = - if obligation.cause.code == ObligationCauseCode::MainFunctionType { - "consider using `()`, or a `Result`".to_owned() - } else { - format!( - "{}the trait `{}` is not implemented for `{}`", - pre_message, - trait_ref.print_only_trait_path(), - trait_ref.skip_binder().self_ty(), - ) - }; + let explanation = if let ObligationCauseCode::MainFunctionType = + obligation.cause.code() + { + "consider using `()`, or a `Result`".to_owned() + } else { + format!( + "{}the trait `{}` is not implemented for `{}`", + pre_message, + trait_ref.print_only_trait_path(), + trait_ref.skip_binder().self_ty(), + ) + }; if self.suggest_add_reference_to_arg( &obligation, @@ -439,6 +440,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { self.suggest_remove_reference(&obligation, &mut err, trait_ref); self.suggest_semicolon_removal(&obligation, &mut err, span, trait_ref); self.note_version_mismatch(&mut err, &trait_ref); + self.suggest_remove_await(&obligation, &mut err); if Some(trait_ref.def_id()) == tcx.lang_items().try_trait() { self.suggest_await_before_try(&mut err, &obligation, trait_ref, span); @@ -539,11 +541,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // is otherwise overwhelming and unhelpful (see #85844 for an // example). - let trait_is_debug = - self.tcx.is_diagnostic_item(sym::Debug, trait_ref.def_id()); - let trait_is_display = - self.tcx.is_diagnostic_item(sym::Display, trait_ref.def_id()); - let in_std_macro = match obligation.cause.span.ctxt().outer_expn_data().macro_def_id { Some(macro_def_id) => { @@ -553,7 +550,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { None => false, }; - if in_std_macro && (trait_is_debug || trait_is_display) { + if in_std_macro + && matches!( + self.tcx.get_diagnostic_name(trait_ref.def_id()), + Some(sym::Debug | sym::Display) + ) + { err.emit(); return; } @@ -1062,7 +1064,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } } -trait InferCtxtPrivExt<'tcx> { +trait InferCtxtPrivExt<'hir, 'tcx> { // returns if `cond` not occurring implies that `error` does not occur - i.e., that // `error` occurring implies that `cond` occurs. fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool; @@ -1173,7 +1175,7 @@ trait InferCtxtPrivExt<'tcx> { ) -> bool; } -impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { +impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { // returns if `cond` not occurring implies that `error` does not occur - i.e., that // `error` occurring implies that `cond` occurs. fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool { @@ -1304,7 +1306,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { ); let is_normalized_ty_expected = !matches!( - obligation.cause.code.peel_derives(), + obligation.cause.code().peel_derives(), ObligationCauseCode::ItemObligation(_) | ObligationCauseCode::BindingObligation(_, _) | ObligationCauseCode::ObjectCastObligation(_) @@ -1338,7 +1340,46 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { "type mismatch resolving `{}`", predicate ); - self.note_type_err(&mut diag, &obligation.cause, None, values, err); + let secondary_span = match predicate.kind().skip_binder() { + ty::PredicateKind::Projection(proj) => self + .tcx + .opt_associated_item(proj.projection_ty.item_def_id) + .and_then(|trait_assoc_item| { + self.tcx + .trait_of_item(proj.projection_ty.item_def_id) + .map(|id| (trait_assoc_item, id)) + }) + .and_then(|(trait_assoc_item, id)| { + self.tcx.find_map_relevant_impl( + id, + proj.projection_ty.self_ty(), + |did| { + self.tcx + .associated_items(did) + .in_definition_order() + .filter(|assoc| assoc.ident == trait_assoc_item.ident) + .next() + }, + ) + }) + .and_then(|item| match self.tcx.hir().get_if_local(item.def_id) { + Some( + hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Type(_, Some(ty)), + .. + }) + | hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::TyAlias(ty), + .. + }), + ) => { + Some((ty.span, format!("type mismatch resolving `{}`", predicate))) + } + _ => None, + }), + _ => None, + }; + self.note_type_err(&mut diag, &obligation.cause, secondary_span, values, err, true); self.note_obligation_cause(&mut diag, obligation); diag.emit(); } @@ -1400,14 +1441,32 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { &self, trait_ref: ty::PolyTraitRef<'tcx>, ) -> Vec> { - let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true); + // We simplify params and strip references here. + // + // This both removes a lot of unhelpful suggestions, e.g. + // when searching for `&Foo: Trait` it doesn't suggestion `impl Trait for &Bar`, + // while also suggesting impls for `&Foo` when we're looking for `Foo: Trait`. + // + // The second thing isn't necessarily always a good thing, but + // any other simple setup results in a far worse output, so 🤷 + let simp = fast_reject::simplify_type( + self.tcx, + trait_ref.skip_binder().self_ty(), + SimplifyParams::Yes, + StripReferences::Yes, + ); let all_impls = self.tcx.all_impls(trait_ref.def_id()); match simp { Some(simp) => all_impls .filter_map(|def_id| { let imp = self.tcx.impl_trait_ref(def_id).unwrap(); - let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true); + let imp_simp = fast_reject::simplify_type( + self.tcx, + imp.self_ty(), + SimplifyParams::Yes, + StripReferences::Yes, + ); if let Some(imp_simp) = imp_simp { if simp != imp_simp { return None; @@ -1508,14 +1567,14 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { self.tcx.find_map_relevant_impl(trait_def_id, trait_ref.skip_binder().self_ty(), Some) }; let required_trait_path = self.tcx.def_path_str(trait_ref.def_id()); - let all_traits = self.tcx.all_traits(()); - let traits_with_same_path: std::collections::BTreeSet<_> = all_traits - .iter() - .filter(|trait_def_id| **trait_def_id != trait_ref.def_id()) - .filter(|trait_def_id| self.tcx.def_path_str(**trait_def_id) == required_trait_path) + let traits_with_same_path: std::collections::BTreeSet<_> = self + .tcx + .all_traits() + .filter(|trait_def_id| *trait_def_id != trait_ref.def_id()) + .filter(|trait_def_id| self.tcx.def_path_str(*trait_def_id) == required_trait_path) .collect(); for trait_with_same_path in traits_with_same_path { - if let Some(impl_def_id) = get_trait_impl(*trait_with_same_path) { + if let Some(impl_def_id) = get_trait_impl(trait_with_same_path) { let impl_span = self.tcx.def_span(impl_def_id); err.span_help(impl_span, "trait impl with same name found"); let trait_crate = self.tcx.crate_name(trait_with_same_path.krate); @@ -1562,9 +1621,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { let predicate = self.resolve_vars_if_possible(obligation.predicate); let span = obligation.cause.span; - debug!( - ?predicate, ?obligation.cause.code, - ); + debug!(?predicate, obligation.cause.code = tracing::field::debug(&obligation.cause.code())); // Ambiguity errors are often caused as fallout from earlier errors. // We ignore them if this `infcx` is tainted in some cases below. @@ -1659,13 +1716,13 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { } } - if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code { + if let ObligationCauseCode::ItemObligation(def_id) = *obligation.cause.code() { self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id()); } else if let ( Ok(ref snippet), ObligationCauseCode::BindingObligation(ref def_id, _), ) = - (self.tcx.sess.source_map().span_to_snippet(span), &obligation.cause.code) + (self.tcx.sess.source_map().span_to_snippet(span), obligation.cause.code()) { let generics = self.tcx.generics_of(*def_id); if generics.params.iter().any(|p| p.name != kw::SelfUpper) @@ -1948,7 +2005,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { self.note_obligation_cause_code( err, &obligation.predicate, - &obligation.cause.code, + obligation.cause.code(), &mut vec![], &mut Default::default(), ); @@ -1961,15 +2018,16 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { err: &mut DiagnosticBuilder<'tcx>, obligation: &PredicateObligation<'tcx>, ) { - let (pred, item_def_id, span) = - match (obligation.predicate.kind().skip_binder(), obligation.cause.code.peel_derives()) - { - ( - ty::PredicateKind::Trait(pred), - &ObligationCauseCode::BindingObligation(item_def_id, span), - ) => (pred, item_def_id, span), - _ => return, - }; + let (pred, item_def_id, span) = match ( + obligation.predicate.kind().skip_binder(), + obligation.cause.code().peel_derives(), + ) { + ( + ty::PredicateKind::Trait(pred), + &ObligationCauseCode::BindingObligation(item_def_id, span), + ) => (pred, item_def_id, span), + _ => return, + }; debug!( "suggest_unsized_bound_if_applicable: pred={:?} item_def_id={:?} span={:?}", pred, item_def_id, span @@ -1984,7 +2042,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { self.maybe_suggest_unsized_generics(err, span, node); } - fn maybe_suggest_unsized_generics( + fn maybe_suggest_unsized_generics<'hir>( &self, err: &mut DiagnosticBuilder<'tcx>, span: Span, @@ -2025,9 +2083,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { debug!("maybe_suggest_unsized_generics: param={:?}", param); match node { hir::Node::Item( - item - @ - hir::Item { + item @ hir::Item { // Only suggest indirection for uses of type parameters in ADTs. kind: hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Union(..), @@ -2053,7 +2109,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { ); } - fn maybe_indirection_for_unsized( + fn maybe_indirection_for_unsized<'hir>( &self, err: &mut DiagnosticBuilder<'tcx>, item: &'hir Item<'hir>, @@ -2097,10 +2153,21 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { ) -> bool { if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code { let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_ref); - - if obligated_types.iter().any(|ot| ot == &parent_trait_ref.skip_binder().self_ty()) { + let self_ty = parent_trait_ref.skip_binder().self_ty(); + if obligated_types.iter().any(|ot| ot == &self_ty) { return true; } + if let ty::Adt(def, substs) = self_ty.kind() { + if let [arg] = &substs[..] { + if let ty::subst::GenericArgKind::Type(ty) = arg.unpack() { + if let ty::Adt(inner_def, _) = ty.kind() { + if inner_def == def { + return true; + } + } + } + } + } } false } @@ -2156,7 +2223,7 @@ impl<'v> Visitor<'v> for FindTypeParam { } pub fn recursive_type_with_infinite_size_error( - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, type_def_id: DefId, spans: Vec, ) { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index 6128c119b6..1540725246 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -129,7 +129,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { self.describe_enclosure(obligation.cause.body_id).map(|s| s.to_owned()), )]; - match obligation.cause.code { + match obligation.cause.code() { ObligationCauseCode::BuiltinDerivedObligation(..) | ObligationCauseCode::ImplDerivedObligation(..) | ObligationCauseCode::DerivedObligation(..) => {} @@ -141,7 +141,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } if let ObligationCauseCode::ItemObligation(item) - | ObligationCauseCode::BindingObligation(item, _) = obligation.cause.code + | ObligationCauseCode::BindingObligation(item, _) = *obligation.cause.code() { // FIXME: maybe also have some way of handling methods // from other traits? That would require name resolution, @@ -231,7 +231,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { if let Ok(Some(command)) = OnUnimplementedDirective::of_item(self.tcx, trait_ref.def_id, def_id) { - command.evaluate(self.tcx, trait_ref, &flags[..]) + command.evaluate(self.tcx, trait_ref, &flags) } else { OnUnimplementedNote::default() } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index a90140a9b5..0f276718c1 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -9,7 +9,6 @@ use crate::traits::normalize_projection_type; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_data_structures::sync::Lrc; use rustc_errors::{ error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style, }; @@ -21,7 +20,7 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node}; use rustc_middle::ty::{ self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree, - Infer, InferTy, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, + Infer, InferTy, ToPredicate, Ty, TyCtxt, TypeFoldable, }; use rustc_middle::ty::{TypeAndMut, TypeckResults}; use rustc_session::Limit; @@ -89,6 +88,12 @@ pub trait InferCtxtExt<'tcx> { trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, ); + fn suggest_remove_await( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut DiagnosticBuilder<'_>, + ); + fn suggest_change_mut( &self, obligation: &PredicateObligation<'tcx>, @@ -192,7 +197,7 @@ fn predicate_constraint(generics: &hir::Generics<'_>, pred: String) -> (Span, St /// Type parameter needs more bounds. The trivial case is `T` `where T: Bound`, but /// it can also be an `impl Trait` param that needs to be decomposed to a type /// param for cleaner code. -fn suggest_restriction( +fn suggest_restriction<'tcx>( tcx: TyCtxt<'tcx>, generics: &hir::Generics<'tcx>, msg: &str, @@ -262,8 +267,8 @@ fn suggest_restriction( match generics .params .iter() - .map(|p| p.bounds_span().unwrap_or(p.span)) - .filter(|&span| generics.span.contains(span) && span.desugaring_kind().is_none()) + .map(|p| p.bounds_span_for_suggestions().unwrap_or(p.span.shrink_to_hi())) + .filter(|&span| generics.span.contains(span) && span.can_be_used_for_suggestions()) .max_by_key(|span| span.hi()) { // `fn foo(t: impl Trait)` @@ -271,7 +276,7 @@ fn suggest_restriction( None => (generics.span, format!("<{}>", type_param)), // `fn foo(t: impl Trait)` // ^^^ suggest `` here - Some(span) => (span.shrink_to_hi(), format!(", {}", type_param)), + Some(span) => (span, format!(", {}", type_param)), }, // `fn foo(t: impl Trait)` // ^ suggest `where ::A: Bound` @@ -491,7 +496,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ) { // It only make sense when suggesting dereferences for arguments let code = if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } = - &obligation.cause.code + obligation.cause.code() { parent_code.clone() } else { @@ -656,7 +661,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } _ => return, }; - if matches!(obligation.cause.code, ObligationCauseCode::FunctionArgumentObligation { .. }) { + if matches!(obligation.cause.code(), ObligationCauseCode::FunctionArgumentObligation { .. }) + { // When the obligation error has been ensured to have been caused by // an argument, the `obligation.cause.span` points at the expression // of the argument, so we can provide a suggestion. Otherwise, we give @@ -682,13 +688,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let span = obligation.cause.span; let code = if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } = - &obligation.cause.code + obligation.cause.code() { - parent_code.clone() + &parent_code } else if let ExpnKind::Desugaring(DesugaringKind::ForLoop) = span.ctxt().outer_expn_data().kind { - Lrc::new(obligation.cause.code.clone()) + obligation.cause.code() } else { return false; }; @@ -741,7 +747,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let msg = format!( "the trait bound `{}: {}` is not satisfied", - orig_ty.to_string(), + orig_ty, old_ref.print_only_trait_path(), ); if has_custom_message { @@ -799,12 +805,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { return false; }; - if let ObligationCauseCode::ImplDerivedObligation(obligation) = &*code { + if let ObligationCauseCode::ImplDerivedObligation(obligation) = code { try_borrowing(obligation.parent_trait_ref, &[]) } else if let ObligationCauseCode::BindingObligation(_, _) - | ObligationCauseCode::ItemObligation(_) = &*code + | ObligationCauseCode::ItemObligation(_) = code { - try_borrowing(*poly_trait_ref, &never_suggest_borrow[..]) + try_borrowing(*poly_trait_ref, &never_suggest_borrow) } else { false } @@ -873,6 +879,63 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } } + fn suggest_remove_await( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut DiagnosticBuilder<'_>, + ) { + let span = obligation.cause.span; + + if let ObligationCauseCode::AwaitableExpr(hir_id) = obligation.cause.code().peel_derives() { + let hir = self.tcx.hir(); + if let Some(node) = hir_id.and_then(|hir_id| hir.find(hir_id)) { + if let hir::Node::Expr(expr) = node { + // FIXME: use `obligation.predicate.kind()...trait_ref.self_ty()` to see if we have `()` + // and if not maybe suggest doing something else? If we kept the expression around we + // could also check if it is an fn call (very likely) and suggest changing *that*, if + // it is from the local crate. + err.span_suggestion_verbose( + expr.span.shrink_to_hi().with_hi(span.hi()), + "remove the `.await`", + String::new(), + Applicability::MachineApplicable, + ); + // FIXME: account for associated `async fn`s. + if let hir::Expr { span, kind: hir::ExprKind::Call(base, _), .. } = expr { + if let ty::PredicateKind::Trait(pred) = + obligation.predicate.kind().skip_binder() + { + err.span_label( + *span, + &format!("this call returns `{}`", pred.self_ty()), + ); + } + if let Some(typeck_results) = + self.in_progress_typeck_results.map(|t| t.borrow()) + { + let ty = typeck_results.expr_ty_adjusted(base); + if let ty::FnDef(def_id, _substs) = ty.kind() { + if let Some(hir::Node::Item(hir::Item { span, ident, .. })) = + hir.get_if_local(*def_id) + { + err.span_suggestion_verbose( + span.shrink_to_lo(), + &format!( + "alternatively, consider making `fn {}` asynchronous", + ident + ), + "async ".to_string(), + Applicability::MaybeIncorrect, + ); + } + } + } + } + } + } + } + } + /// Check if the trait bound is implemented for a different mutability and note it in the /// final error. fn suggest_change_mut( @@ -882,7 +945,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, ) { let points_at_arg = matches!( - obligation.cause.code, + obligation.cause.code(), ObligationCauseCode::FunctionArgumentObligation { .. }, ); @@ -1009,7 +1072,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { obligation: &PredicateObligation<'tcx>, trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, ) -> bool { - match obligation.cause.code.peel_derives() { + match obligation.cause.code().peel_derives() { // Only suggest `impl Trait` if the return type is unsized because it is `dyn Trait`. ObligationCauseCode::SizedReturnType => {} _ => return false, @@ -1132,7 +1195,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { "; let has_dyn = snippet.split_whitespace().next().map_or(false, |s| s == "dyn"); - let trait_obj = if has_dyn { &snippet[4..] } else { &snippet[..] }; + let trait_obj = if has_dyn { &snippet[4..] } else { &snippet }; if only_never_return { // No return paths, probably using `panic!()` or similar. // Suggest `-> T`, `-> impl Trait`, and if `Trait` is object safe, `-> Box`. @@ -1204,7 +1267,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { err: &mut DiagnosticBuilder<'_>, obligation: &PredicateObligation<'tcx>, ) { - match obligation.cause.code.peel_derives() { + match obligation.cause.code().peel_derives() { ObligationCauseCode::SizedReturnType => {} _ => return, } @@ -1398,7 +1461,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { }; let mut generator = None; let mut outer_generator = None; - let mut next_code = Some(&obligation.cause.code); + let mut next_code = Some(obligation.cause.code()); let mut seen_upvar_tys_infer_tuple = false; @@ -1654,130 +1717,63 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { format!("does not implement `{}`", trait_ref.print_only_trait_path()) }; - let mut explain_yield = - |interior_span: Span, yield_span: Span, scope_span: Option| { - let mut span = MultiSpan::from_span(yield_span); - if let Ok(snippet) = source_map.span_to_snippet(interior_span) { - // #70935: If snippet contains newlines, display "the value" instead - // so that we do not emit complex diagnostics. - let snippet = &format!("`{}`", snippet); - let snippet = if snippet.contains('\n') { "the value" } else { snippet }; - // The multispan can be complex here, like: - // note: future is not `Send` as this value is used across an await - // --> $DIR/issue-70935-complex-spans.rs:13:9 - // | - // LL | baz(|| async{ - // | __________^___- - // | | _________| - // | || - // LL | || foo(tx.clone()); - // LL | || }).await; - // | || - ^- value is later dropped here - // | ||_________|______| - // | |__________| await occurs here, with value maybe used later - // | has type `closure` which is not `Send` - // - // So, detect it and separate into some notes, like: - // - // note: future is not `Send` as this value is used across an await - // --> $DIR/issue-70935-complex-spans.rs:13:9 - // | - // LL | / baz(|| async{ - // LL | | foo(tx.clone()); - // LL | | }).await; - // | |________________^ first, await occurs here, with the value maybe used later... - // note: the value is later dropped here - // --> $DIR/issue-70935-complex-spans.rs:15:17 - // | - // LL | }).await; - // | ^ - // - // If available, use the scope span to annotate the drop location. - if let Some(scope_span) = scope_span { - let scope_span = source_map.end_point(scope_span); - let is_overlapped = - yield_span.overlaps(scope_span) || yield_span.overlaps(interior_span); - if is_overlapped { - span.push_span_label( - yield_span, - format!( - "first, {} occurs here, with {} maybe used later...", - await_or_yield, snippet - ), - ); - err.span_note( - span, - &format!( - "{} {} as this value is used across {}", - future_or_generator, trait_explanation, an_await_or_yield - ), - ); - if source_map.is_multiline(interior_span) { - err.span_note( - scope_span, - &format!("{} is later dropped here", snippet), - ); - err.span_note( - interior_span, - &format!( - "this has type `{}` which {}", - target_ty, trait_explanation - ), - ); - } else { - let mut span = MultiSpan::from_span(scope_span); - span.push_span_label( - interior_span, - format!("has type `{}` which {}", target_ty, trait_explanation), - ); - err.span_note(span, &format!("{} is later dropped here", snippet)); - } - } else { - span.push_span_label( - yield_span, - format!( - "{} occurs here, with {} maybe used later", - await_or_yield, snippet - ), - ); - span.push_span_label( - scope_span, - format!("{} is later dropped here", snippet), - ); - span.push_span_label( - interior_span, - format!("has type `{}` which {}", target_ty, trait_explanation), - ); - err.span_note( - span, - &format!( - "{} {} as this value is used across {}", - future_or_generator, trait_explanation, an_await_or_yield - ), - ); - } + let mut explain_yield = |interior_span: Span, + yield_span: Span, + scope_span: Option| { + let mut span = MultiSpan::from_span(yield_span); + if let Ok(snippet) = source_map.span_to_snippet(interior_span) { + // #70935: If snippet contains newlines, display "the value" instead + // so that we do not emit complex diagnostics. + let snippet = &format!("`{}`", snippet); + let snippet = if snippet.contains('\n') { "the value" } else { snippet }; + // note: future is not `Send` as this value is used across an await + // --> $DIR/issue-70935-complex-spans.rs:13:9 + // | + // LL | baz(|| async { + // | ______________- + // | | + // | | + // LL | | foo(tx.clone()); + // LL | | }).await; + // | | - ^^^^^^ await occurs here, with value maybe used later + // | |__________| + // | has type `closure` which is not `Send` + // note: value is later dropped here + // LL | | }).await; + // | | ^ + // + span.push_span_label( + yield_span, + format!("{} occurs here, with {} maybe used later", await_or_yield, snippet), + ); + span.push_span_label( + interior_span, + format!("has type `{}` which {}", target_ty, trait_explanation), + ); + // If available, use the scope span to annotate the drop location. + let mut scope_note = None; + if let Some(scope_span) = scope_span { + let scope_span = source_map.end_point(scope_span); + + let msg = format!("{} is later dropped here", snippet); + if source_map.is_multiline(yield_span.between(scope_span)) { + span.push_span_label(scope_span, msg); } else { - span.push_span_label( - yield_span, - format!( - "{} occurs here, with {} maybe used later", - await_or_yield, snippet - ), - ); - span.push_span_label( - interior_span, - format!("has type `{}` which {}", target_ty, trait_explanation), - ); - err.span_note( - span, - &format!( - "{} {} as this value is used across {}", - future_or_generator, trait_explanation, an_await_or_yield - ), - ); + scope_note = Some((scope_span, msg)); } } - }; + err.span_note( + span, + &format!( + "{} {} as this value is used across {}", + future_or_generator, trait_explanation, an_await_or_yield + ), + ); + if let Some((span, msg)) = scope_note { + err.span_note(span, &msg); + } + } + }; match interior_or_upvar_span { GeneratorInteriorOrUpvar::Interior(interior_span) => { if let Some((scope_span, yield_span, expr, from_awaited_ty)) = interior_extra_info { @@ -1935,6 +1931,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { | ObligationCauseCode::ReturnType | ObligationCauseCode::ReturnValue(_) | ObligationCauseCode::BlockTailExpression(_) + | ObligationCauseCode::AwaitableExpr(_) + | ObligationCauseCode::ForLoopIterator + | ObligationCauseCode::QuestionMark | ObligationCauseCode::LetElse => {} ObligationCauseCode::SliceOrArrayElem => { err.note("slice and array elements must have `Sized` type"); @@ -2186,6 +2185,16 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { seen_requirements, ) }); + } else { + ensure_sufficient_stack(|| { + self.note_obligation_cause_code( + err, + &parent_predicate, + &cause_code.peel_derives(), + obligated_types, + seen_requirements, + ) + }); } } ObligationCauseCode::ImplDerivedObligation(ref data) => { diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index e121837c98..42e3f0db15 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -4,7 +4,7 @@ use rustc_data_structures::obligation_forest::ProcessResult; use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome}; use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor}; use rustc_errors::ErrorReported; -use rustc_hir as hir; +use rustc_infer::traits::ProjectionCacheKey; use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation}; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::thir::abstract_const::NotConstEvaluatable; @@ -21,12 +21,14 @@ use super::wf; use super::CodeAmbiguity; use super::CodeProjectionError; use super::CodeSelectionError; +use super::EvaluationResult; use super::Unimplemented; use super::{FulfillmentError, FulfillmentErrorCode}; use super::{ObligationCause, PredicateObligation}; use crate::traits::error_reporting::InferCtxtExt as _; use crate::traits::project::PolyProjectionObligation; +use crate::traits::project::ProjectionCacheKeyExt as _; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> { @@ -94,7 +96,7 @@ pub struct PendingPredicateObligation<'tcx> { // `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(PendingPredicateObligation<'_>, 56); +static_assert_size!(PendingPredicateObligation<'_>, 72); impl<'a, 'tcx> FulfillmentContext<'tcx> { /// Creates a new fulfillment context. @@ -231,21 +233,6 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect() } - fn select_all_with_constness_or_error( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - constness: rustc_hir::Constness, - ) -> Vec> { - { - let errors = self.select_with_constness_where_possible(infcx, constness); - if !errors.is_empty() { - return errors; - } - } - - self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect() - } - fn select_where_possible( &mut self, infcx: &InferCtxt<'_, 'tcx>, @@ -254,15 +241,6 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { self.select(&mut selcx) } - fn select_with_constness_where_possible( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - constness: hir::Constness, - ) -> Vec> { - let mut selcx = SelectionContext::with_constness(infcx, constness); - self.select(&mut selcx) - } - fn pending_obligations(&self) -> Vec> { self.predicates.map_pending_obligations(|o| o.obligation.clone()) } @@ -277,7 +255,7 @@ struct FulfillProcessor<'a, 'b, 'tcx> { register_region_obligations: bool, } -fn mk_pending(os: Vec>) -> Vec> { +fn mk_pending(os: Vec>) -> Vec> { os.into_iter() .map(|o| PendingPredicateObligation { obligation: o, stalled_on: vec![] }) .collect() @@ -679,12 +657,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { if obligation.predicate.is_known_global() { // no type variables present, can use evaluation for better caching. // FIXME: consider caching errors too. - // - // If the predicate is considered const, then we cannot use this because - // it will cause false negatives in the ui tests. - if !self.selcx.is_predicate_const(obligation.predicate) - && infcx.predicate_must_hold_considering_regions(obligation) - { + if infcx.predicate_must_hold_considering_regions(obligation) { debug!( "selecting trait at depth {} evaluated to holds", obligation.recursion_depth @@ -738,12 +711,21 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { if obligation.predicate.is_global(tcx) { // no type variables present, can use evaluation for better caching. // FIXME: consider caching errors too. - // - // If the predicate is considered const, then we cannot use this because - // it will cause false negatives in the ui tests. - if !self.selcx.is_predicate_const(obligation.predicate) - && self.selcx.infcx().predicate_must_hold_considering_regions(obligation) - { + if self.selcx.infcx().predicate_must_hold_considering_regions(obligation) { + if let Some(key) = ProjectionCacheKey::from_poly_projection_predicate( + &mut self.selcx, + project_obligation.predicate, + ) { + // If `predicate_must_hold_considering_regions` succeeds, then we've + // evaluated all sub-obligations. We can therefore mark the 'root' + // obligation as complete, and skip evaluating sub-obligations. + self.selcx + .infcx() + .inner + .borrow_mut() + .projection_cache() + .complete(key, EvaluationResult::EvaluatedToOk); + } return ProcessResult::Changed(vec![]); } else { tracing::debug!("Does NOT hold: {:?}", obligation); diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index fa8890fc35..b23dce8a58 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -16,7 +16,7 @@ pub enum CopyImplementationError<'tcx> { HasDestructor, } -pub fn can_type_implement_copy( +pub fn can_type_implement_copy<'tcx>( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, self_type: Ty<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 4bc22d5d73..a8f26982d2 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -33,8 +33,7 @@ use rustc_hir::lang_items::LangItem; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; use rustc_middle::ty::{ - self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry, WithConstness, - COMMON_VTABLE_ENTRIES, + self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry, COMMON_VTABLE_ENTRIES, }; use rustc_span::{sym, Span}; use smallvec::SmallVec; @@ -307,8 +306,11 @@ pub fn normalize_param_env_or_error<'tcx>( debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates); - let elaborated_env = - ty::ParamEnv::new(tcx.intern_predicates(&predicates), unnormalized_env.reveal()); + let elaborated_env = ty::ParamEnv::new( + tcx.intern_predicates(&predicates), + unnormalized_env.reveal(), + unnormalized_env.constness(), + ); // HACK: we are trying to normalize the param-env inside *itself*. The problem is that // normalization expects its param-env to be already normalized, which means we have @@ -360,8 +362,11 @@ pub fn normalize_param_env_or_error<'tcx>( // predicates here anyway. Keeping them here anyway because it seems safer. let outlives_env: Vec<_> = non_outlives_predicates.iter().chain(&outlives_predicates).cloned().collect(); - let outlives_env = - ty::ParamEnv::new(tcx.intern_predicates(&outlives_env), unnormalized_env.reveal()); + let outlives_env = ty::ParamEnv::new( + tcx.intern_predicates(&outlives_env), + unnormalized_env.reveal(), + unnormalized_env.constness(), + ); let outlives_predicates = match do_normalize_predicates( tcx, region_context, @@ -381,7 +386,11 @@ pub fn normalize_param_env_or_error<'tcx>( let mut predicates = non_outlives_predicates; predicates.extend(outlives_predicates); debug!("normalize_param_env_or_error: final predicates={:?}", predicates); - ty::ParamEnv::new(tcx.intern_predicates(&predicates), unnormalized_env.reveal()) + ty::ParamEnv::new( + tcx.intern_predicates(&predicates), + unnormalized_env.reveal(), + unnormalized_env.constness(), + ) } pub fn fully_normalize<'a, 'tcx, T>( @@ -564,14 +573,17 @@ fn prepare_vtable_segments<'tcx, T>( .predicates .into_iter() .filter_map(move |(pred, _)| { - pred.subst_supertrait(tcx, &inner_most_trait_ref).to_opt_poly_trait_ref() + pred.subst_supertrait(tcx, &inner_most_trait_ref).to_opt_poly_trait_pred() }); 'diving_in_skip_visited_traits: loop { if let Some(next_super_trait) = direct_super_traits_iter.next() { if visited.insert(next_super_trait.to_predicate(tcx)) { + // We're throwing away potential constness of super traits here. + // FIXME: handle ~const super traits + let next_super_trait = next_super_trait.map_bound(|t| t.trait_ref); stack.push(( - next_super_trait.value, + next_super_trait, emit_vptr_on_new_entry, Some(direct_super_traits_iter), )); @@ -603,7 +615,11 @@ fn prepare_vtable_segments<'tcx, T>( if let Some(siblings) = siblings_opt { if let Some(next_inner_most_trait_ref) = siblings.next() { if visited.insert(next_inner_most_trait_ref.to_predicate(tcx)) { - *inner_most_trait_ref = next_inner_most_trait_ref.value; + // We're throwing away potential constness of super traits here. + // FIXME: handle ~const super traits + let next_inner_most_trait_ref = + next_inner_most_trait_ref.map_bound(|t| t.trait_ref); + *inner_most_trait_ref = next_inner_most_trait_ref; *emit_vptr = emit_vptr_on_new_entry; break 'exiting_out; } else { @@ -785,7 +801,7 @@ fn vtable_trait_first_method_offset<'tcx>( } /// Find slot offset for trait vptr within vtable entries of another trait -pub fn vtable_trait_upcasting_coercion_new_vptr_slot( +pub fn vtable_trait_upcasting_coercion_new_vptr_slot<'tcx>( tcx: TyCtxt<'tcx>, key: ( Ty<'tcx>, // trait object type whose trait owning vtable diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index afc546540d..4e84849bc1 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -18,14 +18,13 @@ use rustc_errors::FatalError; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::ty::subst::{GenericArg, InternalSubsts, Subst}; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitor, WithConstness}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitor}; use rustc_middle::ty::{Predicate, ToPredicate}; use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY; use rustc_span::symbol::Symbol; use rustc_span::{MultiSpan, Span}; use smallvec::SmallVec; -use std::array; use std::iter; use std::ops::ControlFlow; @@ -51,10 +50,7 @@ pub fn astconv_object_safety_violations( violations } -fn object_safety_violations( - tcx: TyCtxt<'tcx>, - trait_def_id: DefId, -) -> &'tcx [ObjectSafetyViolation] { +fn object_safety_violations(tcx: TyCtxt<'_>, trait_def_id: DefId) -> &'_ [ObjectSafetyViolation] { debug_assert!(tcx.generics_of(trait_def_id).has_self); debug!("object_safety_violations: {:?}", trait_def_id); @@ -273,7 +269,7 @@ fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span .collect() } -fn predicate_references_self( +fn predicate_references_self<'tcx>( tcx: TyCtxt<'tcx>, (predicate, sp): (ty::Predicate<'tcx>, Span), ) -> Option { @@ -692,13 +688,14 @@ fn receiver_is_dispatchable<'tcx>( .to_predicate(tcx) }; - let caller_bounds: Vec> = param_env - .caller_bounds() - .iter() - .chain(array::IntoIter::new([unsize_predicate, trait_predicate])) - .collect(); + let caller_bounds: Vec> = + param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]).collect(); - ty::ParamEnv::new(tcx.intern_predicates(&caller_bounds), param_env.reveal()) + ty::ParamEnv::new( + tcx.intern_predicates(&caller_bounds), + param_env.reveal(), + param_env.constness(), + ) }; // Receiver: DispatchFromDyn U]> diff --git a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs index 85ca4db7d7..4840995275 100644 --- a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs @@ -269,7 +269,7 @@ impl<'tcx> OnUnimplementedFormatString { let name = tcx.item_name(trait_def_id); let generics = tcx.generics_of(trait_def_id); let s = self.0.as_str(); - let parser = Parser::new(&s, None, None, false, ParseMode::Format); + let parser = Parser::new(s, None, None, false, ParseMode::Format); let mut result = Ok(()); for token in parser { match token { @@ -347,7 +347,7 @@ impl<'tcx> OnUnimplementedFormatString { let empty_string = String::new(); let s = self.0.as_str(); - let parser = Parser::new(&s, None, None, false, ParseMode::Format); + let parser = Parser::new(s, None, None, false, ParseMode::Format); let item_context = (options.get(&sym::ItemContext)).unwrap_or(&empty_string); parser .map(|p| match p { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 4a23206402..23f615a961 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -10,7 +10,6 @@ use super::PredicateObligation; use super::Selection; use super::SelectionContext; use super::SelectionError; -use super::TraitQueryMode; use super::{ ImplSourceClosureData, ImplSourceDiscriminantKindData, ImplSourceFnPointerData, ImplSourceGeneratorData, ImplSourcePointeeData, ImplSourceUserDefinedData, @@ -28,7 +27,7 @@ use rustc_hir::lang_items::LangItem; use rustc_infer::infer::resolve::OpportunisticRegionResolver; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; use rustc_middle::ty::subst::Subst; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; use rustc_span::symbol::sym; use std::collections::BTreeMap; @@ -570,7 +569,7 @@ impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> { } } -impl TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> { +impl<'tcx> TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { self.infcx.tcx } @@ -678,7 +677,7 @@ impl<'me, 'tcx> PlaceholderReplacer<'me, 'tcx> { } } -impl TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> { +impl<'tcx> TypeFolder<'tcx> for PlaceholderReplacer<'_, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { self.infcx.tcx } @@ -889,7 +888,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( debug!("recur cache"); return Err(InProgress); } - Err(ProjectionCacheEntry::NormalizedTy(ty)) => { + Err(ProjectionCacheEntry::NormalizedTy { ty, complete: _ }) => { // This is the hottest path in this function. // // If we find the value in the cache, then return it along @@ -946,27 +945,11 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( }; let mut deduped: SsoHashSet<_> = Default::default(); - let mut canonical = - SelectionContext::with_query_mode(selcx.infcx(), TraitQueryMode::Canonical); - result.obligations.drain_filter(|projected_obligation| { if !deduped.insert(projected_obligation.clone()) { return true; } - // If any global obligations always apply, considering regions, then we don't - // need to include them. The `is_global` check rules out inference variables, - // so there's no need for the caller of `opt_normalize_projection_type` - // to evaluate them. - // Note that we do *not* discard obligations that evaluate to - // `EvaluatedtoOkModuloRegions`. Evaluating these obligations - // inside of a query (e.g. `evaluate_obligation`) can change - // the result to `EvaluatedToOkModuloRegions`, while an - // `EvaluatedToOk` obligation will never change the result. - // See #85360 for more details - projected_obligation.is_global(canonical.tcx()) - && canonical - .evaluate_root_obligation(projected_obligation) - .map_or(false, |res| res.must_apply_considering_regions()) + false }); if use_cache { @@ -1937,14 +1920,14 @@ fn assoc_ty_def( } } -crate trait ProjectionCacheKeyExt<'tcx>: Sized { +crate trait ProjectionCacheKeyExt<'cx, 'tcx>: Sized { fn from_poly_projection_predicate( selcx: &mut SelectionContext<'cx, 'tcx>, predicate: ty::PolyProjectionPredicate<'tcx>, ) -> Option; } -impl<'tcx> ProjectionCacheKeyExt<'tcx> for ProjectionCacheKey<'tcx> { +impl<'cx, 'tcx> ProjectionCacheKeyExt<'cx, 'tcx> for ProjectionCacheKey<'tcx> { fn from_poly_projection_predicate( selcx: &mut SelectionContext<'cx, 'tcx>, predicate: ty::PolyProjectionPredicate<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs index 2fa6c0c025..4874ba6f58 100644 --- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs +++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs @@ -1,3 +1,5 @@ +use rustc_middle::ty; + use crate::infer::canonical::OriginalQueryValues; use crate::infer::InferCtxt; use crate::traits::{ @@ -64,10 +66,21 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { obligation: &PredicateObligation<'tcx>, ) -> Result { let mut _orig_values = OriginalQueryValues::default(); - let c_pred = self.canonicalize_query_keep_static( - obligation.param_env.and(obligation.predicate), - &mut _orig_values, - ); + + let param_env = match obligation.predicate.kind().skip_binder() { + ty::PredicateKind::Trait(pred) => { + // we ignore the value set to it. + let mut _constness = pred.constness; + obligation + .param_env + .with_constness(_constness.and(obligation.param_env.constness())) + } + // constness has no effect on the given predicate. + _ => obligation.param_env.without_const(), + }; + + let c_pred = self + .canonicalize_query_keep_static(param_env.and(obligation.predicate), &mut _orig_values); // Run canonical query. If overflow occurs, rerun from scratch but this time // in standard trait query mode so that overflow is handled appropriately // within `SelectionContext`. diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 1364cf1c99..26bacf787e 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -12,7 +12,7 @@ use rustc_data_structures::sso::SsoHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_infer::traits::Normalized; use rustc_middle::mir; -use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; +use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder}; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor}; @@ -61,7 +61,6 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> { cause: self.cause, param_env: self.param_env, obligations: vec![], - error: false, cache: SsoHashMap::new(), anon_depth: 0, universes: vec![], @@ -88,7 +87,7 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> { normalizer.universes.extend((0..max_visitor.escaping).map(|_| None)); } } - let result = value.fold_with(&mut normalizer); + let result = value.try_fold_with(&mut normalizer); info!( "normalize::<{}>: result={:?} with {} obligations", std::any::type_name::(), @@ -100,11 +99,7 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> { std::any::type_name::(), normalizer.obligations, ); - if normalizer.error { - Err(NoSolution) - } else { - Ok(Normalized { value: result, obligations: normalizer.obligations }) - } + result.map(|value| Normalized { value, obligations: normalizer.obligations }) } } @@ -171,34 +166,37 @@ struct QueryNormalizer<'cx, 'tcx> { param_env: ty::ParamEnv<'tcx>, obligations: Vec>, cache: SsoHashMap, Ty<'tcx>>, - error: bool, anon_depth: usize, universes: Vec>, } impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { + type Error = NoSolution; + fn tcx<'c>(&'c self) -> TyCtxt<'tcx> { self.infcx.tcx } +} - fn fold_binder>( +impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { + fn try_fold_binder>( &mut self, t: ty::Binder<'tcx, T>, - ) -> ty::Binder<'tcx, T> { + ) -> Result, Self::Error> { self.universes.push(None); - let t = t.super_fold_with(self); + let t = t.try_super_fold_with(self); self.universes.pop(); t } #[instrument(level = "debug", skip(self))] - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result, Self::Error> { if !needs_normalization(&ty, self.param_env.reveal()) { - return ty; + return Ok(ty); } if let Some(ty) = self.cache.get(&ty) { - return ty; + return Ok(ty); } // See note in `rustc_trait_selection::traits::project` about why we @@ -212,10 +210,10 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { // Only normalize `impl Trait` after type-checking, usually in codegen. match self.param_env.reveal() { - Reveal::UserFacing => ty.super_fold_with(self), + Reveal::UserFacing => ty.try_super_fold_with(self), Reveal::All => { - let substs = substs.super_fold_with(self); + let substs = substs.try_super_fold_with(self)?; let recursion_limit = self.tcx().recursion_limit(); if !recursion_limit.value_within_limit(self.anon_depth) { let obligation = Obligation::with_depth( @@ -240,7 +238,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { ty ); } - let folded_ty = ensure_sufficient_stack(|| self.fold_ty(concrete_ty)); + let folded_ty = ensure_sufficient_stack(|| self.try_fold_ty(concrete_ty)); self.anon_depth -= 1; folded_ty } @@ -252,7 +250,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { // we don't need to replace them with placeholders (see branch below). let tcx = self.infcx.tcx; - let data = data.super_fold_with(self); + let data = data.try_super_fold_with(self)?; let mut orig_values = OriginalQueryValues::default(); // HACK(matthewjasper) `'static` is special-cased in selection, @@ -262,39 +260,22 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { .canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values); debug!("QueryNormalizer: c_data = {:#?}", c_data); debug!("QueryNormalizer: orig_values = {:#?}", orig_values); - match tcx.normalize_projection_ty(c_data) { - Ok(result) => { - // We don't expect ambiguity. - if result.is_ambiguous() { - self.error = true; - return ty.super_fold_with(self); - } - - match self.infcx.instantiate_query_response_and_region_obligations( - self.cause, - self.param_env, - &orig_values, - result, - ) { - Ok(InferOk { value: result, obligations }) => { - debug!("QueryNormalizer: result = {:#?}", result); - debug!("QueryNormalizer: obligations = {:#?}", obligations); - self.obligations.extend(obligations); - result.normalized_ty - } - - Err(_) => { - self.error = true; - ty.super_fold_with(self) - } - } - } - - Err(NoSolution) => { - self.error = true; - ty.super_fold_with(self) - } + let result = tcx.normalize_projection_ty(c_data)?; + // We don't expect ambiguity. + if result.is_ambiguous() { + return Err(NoSolution); } + let InferOk { value: result, obligations } = + self.infcx.instantiate_query_response_and_region_obligations( + self.cause, + self.param_env, + &orig_values, + result, + )?; + debug!("QueryNormalizer: result = {:#?}", result); + debug!("QueryNormalizer: obligations = {:#?}", obligations); + self.obligations.extend(obligations); + Ok(result.normalized_ty) } ty::Projection(data) => { @@ -308,7 +289,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { &mut self.universes, data, ); - let data = data.super_fold_with(self); + let data = data.try_super_fold_with(self)?; let mut orig_values = OriginalQueryValues::default(); // HACK(matthewjasper) `'static` is special-cased in selection, @@ -318,57 +299,49 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { .canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values); debug!("QueryNormalizer: c_data = {:#?}", c_data); debug!("QueryNormalizer: orig_values = {:#?}", orig_values); - match tcx.normalize_projection_ty(c_data) { - Ok(result) => { - // We don't expect ambiguity. - if result.is_ambiguous() { - self.error = true; - return ty.super_fold_with(self); - } - match self.infcx.instantiate_query_response_and_region_obligations( - self.cause, - self.param_env, - &orig_values, - result, - ) { - Ok(InferOk { value: result, obligations }) => { - debug!("QueryNormalizer: result = {:#?}", result); - debug!("QueryNormalizer: obligations = {:#?}", obligations); - self.obligations.extend(obligations); - crate::traits::project::PlaceholderReplacer::replace_placeholders( - infcx, - mapped_regions, - mapped_types, - mapped_consts, - &self.universes, - result.normalized_ty, - ) - } - Err(_) => { - self.error = true; - ty.super_fold_with(self) - } - } - } - Err(NoSolution) => { - self.error = true; - ty.super_fold_with(self) - } + let result = tcx.normalize_projection_ty(c_data)?; + // We don't expect ambiguity. + if result.is_ambiguous() { + return Err(NoSolution); } + let InferOk { value: result, obligations } = + self.infcx.instantiate_query_response_and_region_obligations( + self.cause, + self.param_env, + &orig_values, + result, + )?; + debug!("QueryNormalizer: result = {:#?}", result); + debug!("QueryNormalizer: obligations = {:#?}", obligations); + self.obligations.extend(obligations); + Ok(crate::traits::project::PlaceholderReplacer::replace_placeholders( + infcx, + mapped_regions, + mapped_types, + mapped_consts, + &self.universes, + result.normalized_ty, + )) } - _ => ty.super_fold_with(self), - })(); + _ => ty.try_super_fold_with(self), + })()?; self.cache.insert(ty, res); - res + Ok(res) } - fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { - let constant = constant.super_fold_with(self); - constant.eval(self.infcx.tcx, self.param_env) + fn try_fold_const( + &mut self, + constant: &'tcx ty::Const<'tcx>, + ) -> Result<&'tcx ty::Const<'tcx>, Self::Error> { + let constant = constant.try_super_fold_with(self)?; + Ok(constant.eval(self.infcx.tcx, self.param_env)) } - fn fold_mir_const(&mut self, constant: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> { - constant.super_fold_with(self) + fn try_fold_mir_const( + &mut self, + constant: mir::ConstantKind<'tcx>, + ) -> Result, Self::Error> { + constant.try_super_fold_with(self) } } diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs index 729b66ac21..e92ca7325d 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs @@ -31,7 +31,7 @@ pub trait Normalizable<'tcx>: fmt::Debug + TypeFoldable<'tcx> + Lift<'tcx> + Cop ) -> Fallible>; } -impl Normalizable<'tcx> for Ty<'tcx> { +impl<'tcx> Normalizable<'tcx> for Ty<'tcx> { fn type_op_method( tcx: TyCtxt<'tcx>, canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Normalize>>, @@ -40,7 +40,7 @@ impl Normalizable<'tcx> for Ty<'tcx> { } } -impl Normalizable<'tcx> for ty::Predicate<'tcx> { +impl<'tcx> Normalizable<'tcx> for ty::Predicate<'tcx> { fn type_op_method( tcx: TyCtxt<'tcx>, canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Normalize>>, @@ -49,7 +49,7 @@ impl Normalizable<'tcx> for ty::Predicate<'tcx> { } } -impl Normalizable<'tcx> for ty::PolyFnSig<'tcx> { +impl<'tcx> Normalizable<'tcx> for ty::PolyFnSig<'tcx> { fn type_op_method( tcx: TyCtxt<'tcx>, canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Normalize>>, @@ -58,7 +58,7 @@ impl Normalizable<'tcx> for ty::PolyFnSig<'tcx> { } } -impl Normalizable<'tcx> for ty::FnSig<'tcx> { +impl<'tcx> Normalizable<'tcx> for ty::FnSig<'tcx> { fn type_op_method( tcx: TyCtxt<'tcx>, canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Normalize>>, diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs index 5a27e57860..82f147f814 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs @@ -14,7 +14,7 @@ impl<'tcx> DropckOutlives<'tcx> { } } -impl super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> { +impl<'tcx> super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> { type QueryResponse = DropckOutlivesResult<'tcx>; fn try_fast_path( diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs index 02e9b4d0f0..081308ac73 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs @@ -30,8 +30,14 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> { fn perform_query( tcx: TyCtxt<'tcx>, - canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>, + mut canonicalized: Canonicalized<'tcx, ParamEnvAnd<'tcx, Self>>, ) -> Fallible> { + match canonicalized.value.value.predicate.kind().skip_binder() { + ty::PredicateKind::Trait(pred) => { + canonicalized.value.param_env.remap_constness_with(pred.constness); + } + _ => canonicalized.value.param_env = canonicalized.value.param_env.without_const(), + } tcx.type_op_prove_predicate(canonicalized) } } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 6e3e3b9b14..017f47d435 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -11,7 +11,7 @@ use rustc_infer::traits::TraitEngine; use rustc_infer::traits::{Obligation, SelectionError, TraitObligation}; use rustc_lint_defs::builtin::DEREF_INTO_DYN_SUPERTRAIT; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable}; use rustc_target::spec::abi::Abi; use crate::traits; @@ -303,7 +303,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } else if lang_items.drop_trait() == Some(def_id) && obligation.predicate.skip_binder().constness == ty::BoundConstness::ConstIfConst { - if self.is_in_const_context { + if obligation.param_env.constness() == hir::Constness::Const { self.assemble_const_drop_candidates(obligation, stack, &mut candidates)?; } else { debug!("passing ~const Drop bound; in non-const context"); @@ -362,9 +362,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .infcx .probe(|_| self.match_projection_obligation_against_definition_bounds(obligation)); - for predicate_index in result { - candidates.vec.push(ProjectionCandidate(predicate_index)); - } + candidates.vec.extend(result.into_iter().map(ProjectionCandidate)); } /// Given an obligation like ``, searches the obligations that the caller @@ -383,17 +381,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .param_env .caller_bounds() .iter() - .filter_map(|o| o.to_opt_poly_trait_ref()); + .filter_map(|o| o.to_opt_poly_trait_pred()); // Micro-optimization: filter out predicates relating to different traits. let matching_bounds = - all_bounds.filter(|p| p.value.def_id() == stack.obligation.predicate.def_id()); + all_bounds.filter(|p| p.def_id() == stack.obligation.predicate.def_id()); // Keep only those bounds which may apply, and propagate overflow if it occurs. for bound in matching_bounds { - let wc = self.evaluate_where_clause(stack, bound.value)?; + // FIXME(oli-obk): it is suspicious that we are dropping the constness and + // polarity here. + let wc = self.evaluate_where_clause(stack, bound.map_bound(|t| t.trait_ref))?; if wc.may_apply() { - candidates.vec.push(ParamCandidate((bound, stack.obligation.polarity()))); + candidates.vec.push(ParamCandidate(bound)); } } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 2f1f7971a7..b7fc578ea3 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -8,12 +8,13 @@ //! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::lang_items::LangItem; +use rustc_hir::Constness; use rustc_index::bit_set::GrowableBitSet; use rustc_infer::infer::InferOk; use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef}; use rustc_middle::ty::{self, Ty}; -use rustc_middle::ty::{ToPolyTraitRef, ToPredicate, WithConstness}; +use rustc_middle::ty::{ToPolyTraitRef, ToPredicate}; use rustc_span::def_id::DefId; use crate::traits::project::{normalize_with_depth, normalize_with_depth_to}; @@ -51,6 +52,38 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, candidate: SelectionCandidate<'tcx>, ) -> Result, SelectionError<'tcx>> { + let mut obligation = obligation; + let new_obligation; + + // HACK(const_trait_impl): the surrounding environment is remapped to a non-const context + // because nested obligations might be actually `~const` then (incorrectly) requiring + // const impls. for example: + // ``` + // pub trait Super {} + // pub trait Sub: Super {} + // + // impl const Super for &A where A: ~const Super {} + // impl const Sub for &A where A: ~const Sub {} + // ``` + // + // The procedure to check the code above without the remapping code is as follows: + // ``` + // CheckWf(impl const Sub for &A where A: ~const Sub) // <- const env + // CheckPredicate(&A: Super) + // CheckPredicate(A: ~const Super) // <- still const env, failure + // ``` + if obligation.param_env.constness() == Constness::Const + && obligation.predicate.skip_binder().constness == ty::BoundConstness::NotConst + { + new_obligation = TraitObligation { + cause: obligation.cause.clone(), + param_env: obligation.param_env.without_const(), + ..*obligation + }; + + obligation = &new_obligation; + } + match candidate { BuiltinCandidate { has_nested } => { let data = self.confirm_builtin_candidate(obligation, has_nested); @@ -58,8 +91,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ParamCandidate(param) => { - let obligations = self.confirm_param_candidate(obligation, param.0.value); - Ok(ImplSource::Param(obligations, param.0.constness)) + let obligations = + self.confirm_param_candidate(obligation, param.map_bound(|t| t.trait_ref)); + Ok(ImplSource::Param(obligations, param.skip_binder().constness)) } ImplCandidate(impl_def_id) => { @@ -139,7 +173,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let trait_predicate = self.infcx.shallow_resolve(obligation.predicate); let placeholder_trait_predicate = - self.infcx().replace_bound_vars_with_placeholders(trait_predicate); + self.infcx().replace_bound_vars_with_placeholders(trait_predicate).trait_ref; let placeholder_self_ty = placeholder_trait_predicate.self_ty(); let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate); let (def_id, substs) = match *placeholder_self_ty.kind() { @@ -150,8 +184,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let candidate_predicate = tcx.item_bounds(def_id)[idx].subst(tcx, substs); let candidate = candidate_predicate - .to_opt_poly_trait_ref() - .expect("projection candidate is not a trait predicate"); + .to_opt_poly_trait_pred() + .expect("projection candidate is not a trait predicate") + .map_bound(|t| t.trait_ref); let mut obligations = Vec::new(); let candidate = normalize_with_depth_to( self, @@ -165,7 +200,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligations.extend(self.infcx.commit_if_ok(|_| { self.infcx .at(&obligation.cause, obligation.param_env) - .sup(placeholder_trait_predicate.to_poly_trait_ref(), candidate.value) + .sup(placeholder_trait_predicate, candidate) .map(|InferOk { obligations, .. }| obligations) .map_err(|_| Unimplemented) })?); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 2aa214694c..fa88c8ee37 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -25,9 +25,10 @@ use super::{ObligationCause, PredicateObligation, TraitObligation}; use crate::infer::{InferCtxt, InferOk, TypeFreshener}; use crate::traits::error_reporting::InferCtxtExt; +use crate::traits::project::ProjectionCacheKeyExt; +use crate::traits::ProjectionCacheKey; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_data_structures::sync::Lrc; use rustc_errors::ErrorReported; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -35,11 +36,10 @@ use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_middle::dep_graph::{DepKind, DepNodeIndex}; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::thir::abstract_const::NotConstEvaluatable; -use rustc_middle::ty::fast_reject; +use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef}; -use rustc_middle::ty::WithConstness; use rustc_middle::ty::{self, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate}; use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable}; use rustc_span::symbol::sym; @@ -128,9 +128,6 @@ pub struct SelectionContext<'cx, 'tcx> { /// and a negative impl allow_negative_impls: bool, - /// Are we in a const context that needs `~const` bounds to be const? - is_in_const_context: bool, - /// The mode that trait queries run in, which informs our error handling /// policy. In essence, canonicalized queries need their errors propagated /// rather than immediately reported because we do not have accurate spans. @@ -141,9 +138,9 @@ pub struct SelectionContext<'cx, 'tcx> { struct TraitObligationStack<'prev, 'tcx> { obligation: &'prev TraitObligation<'tcx>, - /// The trait ref from `obligation` but "freshened" with the + /// The trait predicate from `obligation` but "freshened" with the /// selection-context's freshener. Used to check for recursion. - fresh_trait_ref: ty::ConstnessAnd>, + fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, /// Starts out equal to `depth` -- if, during evaluation, we /// encounter a cycle, then we will set this flag to the minimum @@ -222,7 +219,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { intercrate: false, intercrate_ambiguity_causes: None, allow_negative_impls: false, - is_in_const_context: false, query_mode: TraitQueryMode::Standard, } } @@ -234,7 +230,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { intercrate: true, intercrate_ambiguity_causes: None, allow_negative_impls: false, - is_in_const_context: false, query_mode: TraitQueryMode::Standard, } } @@ -250,7 +245,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { intercrate: false, intercrate_ambiguity_causes: None, allow_negative_impls, - is_in_const_context: false, query_mode: TraitQueryMode::Standard, } } @@ -266,26 +260,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { intercrate: false, intercrate_ambiguity_causes: None, allow_negative_impls: false, - is_in_const_context: false, query_mode, } } - pub fn with_constness( - infcx: &'cx InferCtxt<'cx, 'tcx>, - constness: hir::Constness, - ) -> SelectionContext<'cx, 'tcx> { - SelectionContext { - infcx, - freshener: infcx.freshener_keep_static(), - intercrate: false, - intercrate_ambiguity_causes: None, - allow_negative_impls: false, - is_in_const_context: matches!(constness, hir::Constness::Const), - query_mode: TraitQueryMode::Standard, - } - } - /// Enables tracking of intercrate ambiguity causes. These are /// used in coherence to give improved diagnostics. We don't do /// this until we detect a coherence error because it can lead to @@ -318,20 +296,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.intercrate } - /// Returns `true` if the trait predicate is considerd `const` to this selection context. - pub fn is_trait_predicate_const(&self, pred: ty::TraitPredicate<'_>) -> bool { - matches!(pred.constness, ty::BoundConstness::ConstIfConst) && self.is_in_const_context - } - - /// Returns `true` if the predicate is considered `const` to - /// this selection context. - pub fn is_predicate_const(&self, pred: ty::Predicate<'_>) -> bool { - match pred.kind().skip_binder() { - ty::PredicateKind::Trait(pred) => self.is_trait_predicate_const(pred), - _ => false, - } - } - /////////////////////////////////////////////////////////////////////////// // Selection // @@ -558,7 +522,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }, ty::PredicateKind::TypeOutlives(pred) => { - if pred.0.is_known_global() { + // A global type with no late-bound regions can only + // contain the "'static" lifetime (any other lifetime + // would either be late-bound or local), so it is guaranteed + // to outlive any other lifetime + if pred.0.is_global(self.infcx.tcx) && !pred.0.has_late_bound_regions() { Ok(EvaluatedToOk) } else { Ok(EvaluatedToOkModuloRegions) @@ -583,8 +551,54 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let project_obligation = obligation.with(data); match project::poly_project_and_unify_type(self, &project_obligation) { Ok(Ok(Some(mut subobligations))) => { - self.add_depth(subobligations.iter_mut(), obligation.recursion_depth); - self.evaluate_predicates_recursively(previous_stack, subobligations) + 'compute_res: { + // If we've previously marked this projection as 'complete', thne + // use the final cached result (either `EvaluatedToOk` or + // `EvaluatedToOkModuloRegions`), and skip re-evaluating the + // sub-obligations. + if let Some(key) = + ProjectionCacheKey::from_poly_projection_predicate(self, data) + { + if let Some(cached_res) = self + .infcx + .inner + .borrow_mut() + .projection_cache() + .is_complete(key) + { + break 'compute_res Ok(cached_res); + } + } + + self.add_depth( + subobligations.iter_mut(), + obligation.recursion_depth, + ); + let res = self.evaluate_predicates_recursively( + previous_stack, + subobligations, + ); + if let Ok(res) = res { + if res == EvaluatedToOk || res == EvaluatedToOkModuloRegions { + if let Some(key) = + ProjectionCacheKey::from_poly_projection_predicate( + self, data, + ) + { + // If the result is something that we can cache, then mark this + // entry as 'complete'. This will allow us to skip evaluating the + // suboligations at all the next time we evaluate the projection + // predicate. + self.infcx + .inner + .borrow_mut() + .projection_cache() + .complete(key, res); + } + } + } + res + } } Ok(Ok(None)) => Ok(EvaluatedToAmbig), Ok(Err(project::InProgress)) => Ok(EvaluatedToRecur), @@ -712,20 +726,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } let stack = self.push_stack(previous_stack, &obligation); - let fresh_trait_ref = stack.fresh_trait_ref; + let mut fresh_trait_pred = stack.fresh_trait_pred; + let mut param_env = obligation.param_env; - debug!(?fresh_trait_ref); + fresh_trait_pred = fresh_trait_pred.map_bound(|mut pred| { + pred.remap_constness(self.tcx(), &mut param_env); + pred + }); - if let Some(result) = self.check_evaluation_cache( - obligation.param_env, - fresh_trait_ref, - obligation.polarity(), - ) { + debug!(?fresh_trait_pred); + + if let Some(result) = self.check_evaluation_cache(param_env, fresh_trait_pred) { debug!(?result, "CACHE HIT"); return Ok(result); } - if let Some(result) = stack.cache().get_provisional(fresh_trait_ref) { + if let Some(result) = stack.cache().get_provisional(fresh_trait_pred) { debug!(?result, "PROVISIONAL CACHE HIT"); stack.update_reached_depth(result.reached_depth); return Ok(result.result); @@ -750,19 +766,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let reached_depth = stack.reached_depth.get(); if reached_depth >= stack.depth { debug!(?result, "CACHE MISS"); - self.insert_evaluation_cache( - obligation.param_env, - fresh_trait_ref, - obligation.polarity(), - dep_node, - result, - ); + self.insert_evaluation_cache(param_env, fresh_trait_pred, dep_node, result); - stack.cache().on_completion(stack.dfn, |fresh_trait_ref, provisional_result| { + stack.cache().on_completion(stack.dfn, |fresh_trait_pred, provisional_result| { self.insert_evaluation_cache( - obligation.param_env, - fresh_trait_ref, - obligation.polarity(), + param_env, + fresh_trait_pred, dep_node, provisional_result.max(result), ); @@ -772,10 +781,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!( "caching provisionally because {:?} \ is a cycle participant (at depth {}, reached depth {})", - fresh_trait_ref, stack.depth, reached_depth, + fresh_trait_pred, stack.depth, reached_depth, ); - stack.cache().insert_provisional(stack.dfn, reached_depth, fresh_trait_ref, result); + stack.cache().insert_provisional(stack.dfn, reached_depth, fresh_trait_pred, result); } Ok(result) @@ -809,7 +818,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .skip(1) // Skip top-most frame. .find(|prev| { stack.obligation.param_env == prev.obligation.param_env - && stack.fresh_trait_ref == prev.fresh_trait_ref + && stack.fresh_trait_pred == prev.fresh_trait_pred }) .map(|stack| stack.depth) { @@ -872,7 +881,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // terms of `Fn` etc, but we could probably make this more // precise still. let unbound_input_types = - stack.fresh_trait_ref.value.skip_binder().substs.types().any(|ty| ty.is_fresh()); + stack.fresh_trait_pred.skip_binder().trait_ref.substs.types().any(|ty| ty.is_fresh()); if stack.obligation.polarity() != ty::ImplPolarity::Negative { // This check was an imperfect workaround for a bug in the old @@ -910,8 +919,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { && stack.iter().skip(1).any(|prev| { stack.obligation.param_env == prev.obligation.param_env && self.match_fresh_trait_refs( - stack.fresh_trait_ref, - prev.fresh_trait_ref, + stack.fresh_trait_pred, + prev.fresh_trait_pred, prev.obligation.param_env, ) }) @@ -989,7 +998,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // not just the lifetime choice for this particular (non-erased) // predicate. // See issue #80691 - if stack.fresh_trait_ref.has_erased_regions() { + if stack.fresh_trait_pred.has_erased_regions() { result = result.max(EvaluatedToOkModuloRegions); } @@ -1000,8 +1009,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn check_evaluation_cache( &self, param_env: ty::ParamEnv<'tcx>, - trait_ref: ty::ConstnessAnd>, - polarity: ty::ImplPolarity, + trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> Option { // Neither the global nor local cache is aware of intercrate // mode, so don't do any caching. In particular, we might @@ -1013,19 +1021,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tcx = self.tcx(); if self.can_use_global_caches(param_env) { - if let Some(res) = tcx.evaluation_cache.get(&(param_env.and(trait_ref), polarity), tcx) - { + if let Some(res) = tcx.evaluation_cache.get(¶m_env.and(trait_pred), tcx) { return Some(res); } } - self.infcx.evaluation_cache.get(&(param_env.and(trait_ref), polarity), tcx) + self.infcx.evaluation_cache.get(¶m_env.and(trait_pred), tcx) } fn insert_evaluation_cache( &mut self, param_env: ty::ParamEnv<'tcx>, - trait_ref: ty::ConstnessAnd>, - polarity: ty::ImplPolarity, + trait_pred: ty::PolyTraitPredicate<'tcx>, dep_node: DepNodeIndex, result: EvaluationResult, ) { @@ -1044,23 +1050,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } if self.can_use_global_caches(param_env) { - if !trait_ref.needs_infer() { - debug!(?trait_ref, ?result, "insert_evaluation_cache global"); + if !trait_pred.needs_infer() { + debug!(?trait_pred, ?result, "insert_evaluation_cache global"); // This may overwrite the cache with the same value // FIXME: Due to #50507 this overwrites the different values // This should be changed to use HashMapExt::insert_same // when that is fixed - self.tcx().evaluation_cache.insert( - (param_env.and(trait_ref), polarity), - dep_node, - result, - ); + self.tcx().evaluation_cache.insert(param_env.and(trait_pred), dep_node, result); return; } } - debug!(?trait_ref, ?result, "insert_evaluation_cache"); - self.infcx.evaluation_cache.insert((param_env.and(trait_ref), polarity), dep_node, result); + debug!(?trait_pred, ?result, "insert_evaluation_cache"); + self.infcx.evaluation_cache.insert(param_env.and(trait_pred), dep_node, result); } /// For various reasons, it's possible for a subobligation @@ -1138,16 +1140,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { for candidate in candidates { // Respect const trait obligations - if self.is_trait_predicate_const(obligation.predicate.skip_binder()) { + if obligation.is_const() { match candidate { // const impl ImplCandidate(def_id) if tcx.impl_constness(def_id) == hir::Constness::Const => {} // const param - ParamCandidate(( - ty::ConstnessAnd { constness: ty::BoundConstness::ConstIfConst, .. }, - _, - )) => {} + ParamCandidate(trait_pred) + if trait_pred.skip_binder().constness + == ty::BoundConstness::ConstIfConst => {} // auto trait impl AutoImplCandidate(..) => {} // generator, this will raise error in other places @@ -1256,7 +1257,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn check_candidate_cache( &mut self, - param_env: ty::ParamEnv<'tcx>, + mut param_env: ty::ParamEnv<'tcx>, cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> Option>> { // Neither the global nor local cache is aware of intercrate @@ -1267,19 +1268,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return None; } let tcx = self.tcx(); - let pred = &cache_fresh_trait_pred.skip_binder(); - let trait_ref = pred.trait_ref; + let mut pred = cache_fresh_trait_pred.skip_binder(); + pred.remap_constness(tcx, &mut param_env); + if self.can_use_global_caches(param_env) { - if let Some(res) = tcx - .selection_cache - .get(&(param_env.and(trait_ref).with_constness(pred.constness), pred.polarity), tcx) - { + if let Some(res) = tcx.selection_cache.get(¶m_env.and(pred), tcx) { return Some(res); } } - self.infcx - .selection_cache - .get(&(param_env.and(trait_ref).with_constness(pred.constness), pred.polarity), tcx) + self.infcx.selection_cache.get(¶m_env.and(pred), tcx) } /// Determines whether can we safely cache the result @@ -1317,43 +1314,36 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn insert_candidate_cache( &mut self, - param_env: ty::ParamEnv<'tcx>, + mut param_env: ty::ParamEnv<'tcx>, cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, dep_node: DepNodeIndex, candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>, ) { let tcx = self.tcx(); - let pred = cache_fresh_trait_pred.skip_binder(); - let trait_ref = pred.trait_ref; + let mut pred = cache_fresh_trait_pred.skip_binder(); + + pred.remap_constness(tcx, &mut param_env); if !self.can_cache_candidate(&candidate) { - debug!(?trait_ref, ?candidate, "insert_candidate_cache - candidate is not cacheable"); + debug!(?pred, ?candidate, "insert_candidate_cache - candidate is not cacheable"); return; } if self.can_use_global_caches(param_env) { if let Err(Overflow) = candidate { // Don't cache overflow globally; we only produce this in certain modes. - } else if !trait_ref.needs_infer() { + } else if !pred.needs_infer() { if !candidate.needs_infer() { - debug!(?trait_ref, ?candidate, "insert_candidate_cache global"); + debug!(?pred, ?candidate, "insert_candidate_cache global"); // This may overwrite the cache with the same value. - tcx.selection_cache.insert( - (param_env.and(trait_ref).with_constness(pred.constness), pred.polarity), - dep_node, - candidate, - ); + tcx.selection_cache.insert(param_env.and(pred), dep_node, candidate); return; } } } - debug!(?trait_ref, ?candidate, "insert_candidate_cache local"); - self.infcx.selection_cache.insert( - (param_env.and(trait_ref).with_constness(pred.constness), pred.polarity), - dep_node, - candidate, - ); + debug!(?pred, ?candidate, "insert_candidate_cache local"); + self.infcx.selection_cache.insert(param_env.and(pred), dep_node, candidate); } /// Matches a predicate against the bounds of its self type. @@ -1544,7 +1534,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Check if a bound would previously have been removed when normalizing // the param_env so that it can be given the lowest priority. See // #50825 for the motivation for this. - let is_global = |cand: &ty::PolyTraitRef<'tcx>| { + let is_global = |cand: &ty::PolyTraitPredicate<'tcx>| { cand.is_global(self.infcx.tcx) && !cand.has_late_bound_regions() }; @@ -1577,25 +1567,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ConstDropCandidate, ) => false, - ( - ParamCandidate((other, other_polarity)), - ParamCandidate((victim, victim_polarity)), - ) => { - let same_except_bound_vars = other.value.skip_binder() - == victim.value.skip_binder() - && other.constness == victim.constness - && other_polarity == victim_polarity - && !other.value.skip_binder().has_escaping_bound_vars(); + (ParamCandidate(other), ParamCandidate(victim)) => { + let same_except_bound_vars = other.skip_binder().trait_ref + == victim.skip_binder().trait_ref + && other.skip_binder().constness == victim.skip_binder().constness + && other.skip_binder().polarity == victim.skip_binder().polarity + && !other.skip_binder().trait_ref.has_escaping_bound_vars(); if same_except_bound_vars { // See issue #84398. In short, we can generate multiple ParamCandidates which are // the same except for unused bound vars. Just pick the one with the fewest bound vars // or the current one if tied (they should both evaluate to the same answer). This is // probably best characterized as a "hack", since we might prefer to just do our // best to *not* create essentially duplicate candidates in the first place. - other.value.bound_vars().len() <= victim.value.bound_vars().len() - } else if other.value == victim.value - && victim.constness == ty::BoundConstness::NotConst - && other_polarity == victim_polarity + other.bound_vars().len() <= victim.bound_vars().len() + } else if other.skip_binder().trait_ref == victim.skip_binder().trait_ref + && victim.skip_binder().constness == ty::BoundConstness::NotConst + && other.skip_binder().polarity == victim.skip_binder().polarity { // Drop otherwise equivalent non-const candidates in favor of const candidates. true @@ -1625,11 +1612,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | TraitAliasCandidate(..) | ObjectCandidate(_) | ProjectionCandidate(_), - ) => !is_global(&cand.0.value), + ) => !is_global(cand), (ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref cand)) => { // Prefer these to a global where-clause bound // (see issue #50825). - is_global(&cand.0.value) + is_global(cand) } ( ImplCandidate(_) @@ -1645,7 +1632,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) => { // Prefer these to a global where-clause bound // (see issue #50825). - is_global(&cand.0.value) && other.evaluation.must_apply_modulo_regions() + is_global(cand) && other.evaluation.must_apply_modulo_regions() } (ProjectionCandidate(i), ProjectionCandidate(j)) @@ -2149,10 +2136,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { |(obligation_arg, impl_arg)| { match (obligation_arg.unpack(), impl_arg.unpack()) { (GenericArgKind::Type(obligation_ty), GenericArgKind::Type(impl_ty)) => { - let simplified_obligation_ty = - fast_reject::simplify_type(self.tcx(), obligation_ty, true); - let simplified_impl_ty = - fast_reject::simplify_type(self.tcx(), impl_ty, false); + // Note, we simplify parameters for the obligation but not the + // impl so that we do not reject a blanket impl but do reject + // more concrete impls if we're searching for `T: Trait`. + let simplified_obligation_ty = fast_reject::simplify_type( + self.tcx(), + obligation_ty, + SimplifyParams::Yes, + StripReferences::No, + ); + let simplified_impl_ty = fast_reject::simplify_type( + self.tcx(), + impl_ty, + SimplifyParams::No, + StripReferences::No, + ); simplified_obligation_ty.is_some() && simplified_impl_ty.is_some() @@ -2205,8 +2203,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn match_fresh_trait_refs( &self, - previous: ty::ConstnessAnd>, - current: ty::ConstnessAnd>, + previous: ty::PolyTraitPredicate<'tcx>, + current: ty::PolyTraitPredicate<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> bool { let mut matcher = ty::_match::Match::new(self.tcx(), param_env); @@ -2218,17 +2216,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { previous_stack: TraitObligationStackList<'o, 'tcx>, obligation: &'o TraitObligation<'tcx>, ) -> TraitObligationStack<'o, 'tcx> { - let fresh_trait_ref = obligation - .predicate - .to_poly_trait_ref() - .fold_with(&mut self.freshener) - .with_constness(obligation.predicate.skip_binder().constness); + let fresh_trait_pred = obligation.predicate.fold_with(&mut self.freshener); let dfn = previous_stack.cache.next_dfn(); let depth = previous_stack.depth() + 1; TraitObligationStack { obligation, - fresh_trait_ref, + fresh_trait_pred, reached_depth: Cell::new(depth), previous: previous_stack, dfn, @@ -2389,7 +2383,7 @@ impl<'tcx> TraitObligationExt<'tcx> for TraitObligation<'tcx> { // by using -Z verbose or just a CLI argument. let derived_cause = DerivedObligationCause { parent_trait_ref: obligation.predicate.to_poly_trait_ref(), - parent_code: Lrc::new(obligation.cause.code.clone()), + parent_code: obligation.cause.clone_code(), }; let derived_code = variant(derived_cause); ObligationCause::new(obligation.cause.span, obligation.cause.body_id, derived_code) @@ -2422,7 +2416,7 @@ impl<'o, 'tcx> TraitObligationStack<'o, 'tcx> { debug!(reached_depth, "update_reached_depth"); let mut p = self; while reached_depth < p.depth { - debug!(?p.fresh_trait_ref, "update_reached_depth: marking as cycle participant"); + debug!(?p.fresh_trait_pred, "update_reached_depth: marking as cycle participant"); p.reached_depth.set(p.reached_depth.get().min(reached_depth)); p = p.previous.head.unwrap(); } @@ -2501,7 +2495,7 @@ struct ProvisionalEvaluationCache<'tcx> { /// - then we determine that `E` is in error -- we will then clear /// all cache values whose DFN is >= 4 -- in this case, that /// means the cached value for `F`. - map: RefCell>, ProvisionalEvaluation>>, + map: RefCell, ProvisionalEvaluation>>, } /// A cache value for the provisional cache: contains the depth-first @@ -2533,28 +2527,28 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> { /// `reached_depth` (from the returned value). fn get_provisional( &self, - fresh_trait_ref: ty::ConstnessAnd>, + fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> Option { debug!( - ?fresh_trait_ref, + ?fresh_trait_pred, "get_provisional = {:#?}", - self.map.borrow().get(&fresh_trait_ref), + self.map.borrow().get(&fresh_trait_pred), ); - Some(*self.map.borrow().get(&fresh_trait_ref)?) + Some(*self.map.borrow().get(&fresh_trait_pred)?) } /// Insert a provisional result into the cache. The result came /// from the node with the given DFN. It accessed a minimum depth - /// of `reached_depth` to compute. It evaluated `fresh_trait_ref` + /// of `reached_depth` to compute. It evaluated `fresh_trait_pred` /// and resulted in `result`. fn insert_provisional( &self, from_dfn: usize, reached_depth: usize, - fresh_trait_ref: ty::ConstnessAnd>, + fresh_trait_pred: ty::PolyTraitPredicate<'tcx>, result: EvaluationResult, ) { - debug!(?from_dfn, ?fresh_trait_ref, ?result, "insert_provisional"); + debug!(?from_dfn, ?fresh_trait_pred, ?result, "insert_provisional"); let mut map = self.map.borrow_mut(); @@ -2578,7 +2572,7 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> { } } - map.insert(fresh_trait_ref, ProvisionalEvaluation { from_dfn, reached_depth, result }); + map.insert(fresh_trait_pred, ProvisionalEvaluation { from_dfn, reached_depth, result }); } /// Invoked when the node with dfn `dfn` does not get a successful @@ -2629,16 +2623,16 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> { fn on_completion( &self, dfn: usize, - mut op: impl FnMut(ty::ConstnessAnd>, EvaluationResult), + mut op: impl FnMut(ty::PolyTraitPredicate<'tcx>, EvaluationResult), ) { debug!(?dfn, "on_completion"); - for (fresh_trait_ref, eval) in + for (fresh_trait_pred, eval) in self.map.borrow_mut().drain_filter(|_k, eval| eval.from_dfn >= dfn) { - debug!(?fresh_trait_ref, ?eval, "on_completion"); + debug!(?fresh_trait_pred, ?eval, "on_completion"); - op(fresh_trait_ref, eval.result); + op(fresh_trait_pred, eval.result); } } } diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index b64c555922..ab732f510f 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -508,9 +508,9 @@ crate fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option { fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId); fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId); @@ -44,11 +44,16 @@ trait ChildrenExt { ) -> Result; } -impl ChildrenExt for Children { +impl ChildrenExt<'_> for Children { /// Insert an impl into this set of children without comparing to any existing impls. - fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { + fn insert_blindly(&mut self, tcx: TyCtxt<'_>, impl_def_id: DefId) { let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); - if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) { + if let Some(st) = fast_reject::simplify_type( + tcx, + trait_ref.self_ty(), + SimplifyParams::No, + StripReferences::No, + ) { debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st); self.non_blanket_impls.entry(st).or_default().push(impl_def_id) } else { @@ -60,10 +65,15 @@ impl ChildrenExt for Children { /// Removes an impl from this set of children. Used when replacing /// an impl with a parent. The impl must be present in the list of /// children already. - fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { + fn remove_existing(&mut self, tcx: TyCtxt<'_>, impl_def_id: DefId) { let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); let vec: &mut Vec; - if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) { + if let Some(st) = fast_reject::simplify_type( + tcx, + trait_ref.self_ty(), + SimplifyParams::No, + StripReferences::No, + ) { debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st); vec = self.non_blanket_impls.get_mut(&st).unwrap(); } else { @@ -79,7 +89,7 @@ impl ChildrenExt for Children { /// specialization relationships. fn insert( &mut self, - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, impl_def_id: DefId, simplified_self: Option, ) -> Result { @@ -261,12 +271,12 @@ pub trait GraphExt { /// information about the area of overlap is returned in the `Err`. fn insert( &mut self, - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, impl_def_id: DefId, ) -> Result, OverlapError>; /// Insert cached metadata mapping from a child impl back to its parent. - fn record_impl_from_cstore(&mut self, tcx: TyCtxt<'tcx>, parent: DefId, child: DefId); + fn record_impl_from_cstore(&mut self, tcx: TyCtxt<'_>, parent: DefId, child: DefId); } impl GraphExt for Graph { @@ -275,7 +285,7 @@ impl GraphExt for Graph { /// information about the area of overlap is returned in the `Err`. fn insert( &mut self, - tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'_>, impl_def_id: DefId, ) -> Result, OverlapError> { assert!(impl_def_id.is_local()); @@ -306,7 +316,12 @@ impl GraphExt for Graph { let mut parent = trait_def_id; let mut last_lint = None; - let simplified = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false); + let simplified = fast_reject::simplify_type( + tcx, + trait_ref.self_ty(), + SimplifyParams::No, + StripReferences::No, + ); // Descend the specialization tree, where `parent` is the current parent node. loop { @@ -370,7 +385,7 @@ impl GraphExt for Graph { } /// Insert cached metadata mapping from a child impl back to its parent. - fn record_impl_from_cstore(&mut self, tcx: TyCtxt<'tcx>, parent: DefId, child: DefId) { + fn record_impl_from_cstore(&mut self, tcx: TyCtxt<'_>, parent: DefId, child: DefId) { if self.parent.insert(child, parent).is_some() { bug!( "When recording an impl from the crate store, information about its parent \ diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs index 3d71382227..55feb3c1de 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_match.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs @@ -66,7 +66,7 @@ pub fn search_for_structural_match_violation<'tcx>( /// /// Note that this does *not* recursively check if the substructure of `adt_ty` /// implements the traits. -fn type_marked_structural( +fn type_marked_structural<'tcx>( infcx: &InferCtxt<'_, 'tcx>, adt_ty: Ty<'tcx>, cause: ObligationCause<'tcx>, @@ -119,7 +119,7 @@ struct Search<'a, 'tcx> { seen: FxHashSet, } -impl Search<'a, 'tcx> { +impl<'a, 'tcx> Search<'a, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 6d2323abba..b6e653c0ee 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -6,7 +6,7 @@ use smallvec::SmallVec; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::DefId; use rustc_middle::ty::subst::{GenericArg, Subst, SubstsRef}; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext}; pub use rustc_infer::traits::{self, util::*}; @@ -126,8 +126,8 @@ impl<'tcx> TraitAliasExpander<'tcx> { let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| { pred.subst_supertrait(tcx, &trait_ref) - .to_opt_poly_trait_ref() - .map(|trait_ref| item.clone_and_push(trait_ref.value, *span)) + .to_opt_poly_trait_pred() + .map(|trait_ref| item.clone_and_push(trait_ref.map_bound(|t| t.trait_ref), *span)) }); debug!("expand_trait_aliases: items={:?}", items.clone()); @@ -172,7 +172,7 @@ pub fn supertrait_def_ids(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SupertraitDef } } -impl Iterator for SupertraitDefIds<'tcx> { +impl Iterator for SupertraitDefIds<'_> { type Item = DefId; fn next(&mut self) -> Option { @@ -183,8 +183,8 @@ impl Iterator for SupertraitDefIds<'tcx> { predicates .predicates .iter() - .filter_map(|(pred, _)| pred.to_opt_poly_trait_ref()) - .map(|trait_ref| trait_ref.value.def_id()) + .filter_map(|(pred, _)| pred.to_opt_poly_trait_pred()) + .map(|trait_ref| trait_ref.def_id()) .filter(|&super_def_id| visited.insert(super_def_id)), ); Some(def_id) @@ -232,7 +232,7 @@ pub fn predicates_for_generics<'tcx>( debug!("predicates_for_generics(generic_bounds={:?})", generic_bounds); iter::zip(generic_bounds.predicates, generic_bounds.spans).map(move |(predicate, span)| { - let cause = match cause.code { + let cause = match *cause.code() { traits::ItemObligation(def_id) if !span.is_dummy() => traits::ObligationCause::new( cause.span, cause.body_id, @@ -259,7 +259,7 @@ pub fn predicate_for_trait_ref<'tcx>( } } -pub fn predicate_for_trait_def( +pub fn predicate_for_trait_def<'tcx>( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, cause: ObligationCause<'tcx>, @@ -276,7 +276,7 @@ pub fn predicate_for_trait_def( /// Casts a trait reference into a reference to one of its super /// traits; returns `None` if `target_trait_def_id` is not a /// supertrait. -pub fn upcast_choices( +pub fn upcast_choices<'tcx>( tcx: TyCtxt<'tcx>, source_trait_ref: ty::PolyTraitRef<'tcx>, target_trait_def_id: DefId, @@ -291,7 +291,10 @@ pub fn upcast_choices( /// Given a trait `trait_ref`, returns the number of vtable entries /// that come from `trait_ref`, excluding its supertraits. Used in /// computing the vtable base for an upcast trait of a trait object. -pub fn count_own_vtable_entries(tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> usize { +pub fn count_own_vtable_entries<'tcx>( + tcx: TyCtxt<'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>, +) -> usize { let existential_trait_ref = trait_ref.map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)); let existential_trait_ref = tcx.erase_regions(existential_trait_ref); @@ -301,7 +304,7 @@ pub fn count_own_vtable_entries(tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<' /// Given an upcast trait object described by `object`, returns the /// index of the method `method_def_id` (which should be part of /// `object.upcast_trait_ref`) within the vtable for `object`. -pub fn get_vtable_index_of_object_method( +pub fn get_vtable_index_of_object_method<'tcx, N>( tcx: TyCtxt<'tcx>, object: &super::ImplSourceObjectData<'tcx, N>, method_def_id: DefId, @@ -323,7 +326,7 @@ pub fn get_vtable_index_of_object_method( object.vtable_base + index } -pub fn closure_trait_ref_and_return_type( +pub fn closure_trait_ref_and_return_type<'tcx>( tcx: TyCtxt<'tcx>, fn_trait_def_id: DefId, self_ty: Ty<'tcx>, @@ -342,7 +345,7 @@ pub fn closure_trait_ref_and_return_type( sig.map_bound(|sig| (trait_ref, sig.output())) } -pub fn generator_trait_ref_and_outputs( +pub fn generator_trait_ref_and_outputs<'tcx>( tcx: TyCtxt<'tcx>, fn_trait_def_id: DefId, self_ty: Ty<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 2a66684e2a..4bd73ef68a 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -1,12 +1,11 @@ use crate::infer::InferCtxt; use crate::opaque_types::required_region_bounds; use crate::traits; -use rustc_data_structures::sync::Lrc; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc_span::Span; use std::iter; @@ -227,7 +226,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>( if let Some(impl_item_span) = items.iter().find(|item| item.ident == trait_assoc_item.ident).map(fix_span) { - cause.make_mut().span = impl_item_span; + cause.span = impl_item_span; } } } @@ -242,7 +241,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>( items.iter().find(|i| i.ident == trait_assoc_item.ident).map(fix_span) }) { - cause.make_mut().span = impl_item_span; + cause.span = impl_item_span; } } } @@ -298,12 +297,13 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let extend = |obligation: traits::PredicateObligation<'tcx>| { let mut cause = cause.clone(); - if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_ref() { + if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_pred() { let derived_cause = traits::DerivedObligationCause { - parent_trait_ref: parent_trait_ref.value, - parent_code: Lrc::new(obligation.cause.code.clone()), + // FIXME(fee1-dead): when improving error messages, change this to PolyTraitPredicate + parent_trait_ref: parent_trait_ref.map_bound(|t| t.trait_ref), + parent_code: obligation.cause.clone_code(), }; - cause.make_mut().code = + *cause.make_mut_code() = traits::ObligationCauseCode::DerivedObligation(derived_cause); } extend_cause_with_original_assoc_item_obligation( @@ -342,7 +342,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { if let Some(hir::ItemKind::Impl(hir::Impl { self_ty, .. })) = item.map(|i| &i.kind) { - new_cause.make_mut().span = self_ty.span; + new_cause.span = self_ty.span; } } traits::Obligation::with_depth( diff --git a/compiler/rustc_traits/Cargo.toml b/compiler/rustc_traits/Cargo.toml index 2e56a1bf68..f22751dc74 100644 --- a/compiler/rustc_traits/Cargo.toml +++ b/compiler/rustc_traits/Cargo.toml @@ -12,9 +12,9 @@ rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } -chalk-ir = "0.55.0" -chalk-solve = "0.55.0" -chalk-engine = "0.55.0" +chalk-ir = "0.75.0" +chalk-engine = "0.75.0" +chalk-solve = "0.75.0" smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } rustc_infer = { path = "../rustc_infer" } rustc_trait_selection = { path = "../rustc_trait_selection" } diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index 1d457d6761..c38680651a 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -46,7 +46,9 @@ impl<'tcx> RustIrDatabase<'tcx> { .iter() .map(|(wc, _)| wc.subst(self.interner.tcx, bound_vars)) .map(|wc| wc.fold_with(&mut regions_substitutor)) - .filter_map(|wc| LowerInto::>>>::lower_into(wc, &self.interner)).collect() + .filter_map(|wc| LowerInto::< + Option>> + >::lower_into(wc, self.interner)).collect() } fn bounds_for(&self, def_id: DefId, bound_vars: SubstsRef<'tcx>) -> Vec @@ -58,14 +60,14 @@ impl<'tcx> RustIrDatabase<'tcx> { .explicit_item_bounds(def_id) .iter() .map(|(bound, _)| bound.subst(self.interner.tcx, &bound_vars)) - .filter_map(|bound| LowerInto::>::lower_into(bound, &self.interner)) + .filter_map(|bound| LowerInto::>::lower_into(bound, self.interner)) .collect() } } impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'tcx> { - fn interner(&self) -> &RustInterner<'tcx> { - &self.interner + fn interner(&self) -> RustInterner<'tcx> { + self.interner } fn associated_ty_data( @@ -83,7 +85,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t _ => unimplemented!("Not possible??"), } let bound_vars = bound_vars_for_item(self.interner.tcx, def_id); - let binders = binders_for(&self.interner, bound_vars); + let binders = binders_for(self.interner, bound_vars); let where_clauses = self.where_clauses_for(def_id, bound_vars); let bounds = self.bounds_for(def_id, bound_vars); @@ -107,7 +109,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let trait_def = self.interner.tcx.trait_def(def_id); let bound_vars = bound_vars_for_item(self.interner.tcx, def_id); - let binders = binders_for(&self.interner, bound_vars); + let binders = binders_for(self.interner, bound_vars); let where_clauses = self.where_clauses_for(def_id, bound_vars); @@ -170,7 +172,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let adt_def = adt_id.0; let bound_vars = bound_vars_for_item(self.interner.tcx, adt_def.did); - let binders = binders_for(&self.interner, bound_vars); + let binders = binders_for(self.interner, bound_vars); let where_clauses = self.where_clauses_for(adt_def.did, bound_vars); @@ -181,7 +183,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t fields: variant .fields .iter() - .map(|field| field.ty(self.interner.tcx, bound_vars).lower_into(&self.interner)) + .map(|field| field.ty(self.interner.tcx, bound_vars).lower_into(self.interner)) .collect(), }) .collect(); @@ -209,8 +211,8 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t adt_id: chalk_ir::AdtId>, ) -> Arc>> { let adt_def = adt_id.0; - let int = |i| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Int(i)).intern(&self.interner); - let uint = |i| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Uint(i)).intern(&self.interner); + let int = |i| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Int(i)).intern(self.interner); + let uint = |i| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Uint(i)).intern(self.interner); Arc::new(chalk_solve::rust_ir::AdtRepr { c: adt_def.repr.c(), packed: adt_def.repr.packed(), @@ -241,25 +243,25 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t ) -> Arc>> { let def_id = fn_def_id.0; let bound_vars = bound_vars_for_item(self.interner.tcx, def_id); - let binders = binders_for(&self.interner, bound_vars); + let binders = binders_for(self.interner, bound_vars); let where_clauses = self.where_clauses_for(def_id, bound_vars); let sig = self.interner.tcx.fn_sig(def_id); let (inputs_and_output, iobinders, _) = crate::chalk::lowering::collect_bound_vars( - &self.interner, + self.interner, self.interner.tcx, sig.inputs_and_output().subst(self.interner.tcx, bound_vars), ); let argument_types = inputs_and_output[..inputs_and_output.len() - 1] .iter() - .map(|t| t.subst(self.interner.tcx, &bound_vars).lower_into(&self.interner)) + .map(|t| t.subst(self.interner.tcx, &bound_vars).lower_into(self.interner)) .collect(); let return_type = inputs_and_output[inputs_and_output.len() - 1] .subst(self.interner.tcx, &bound_vars) - .lower_into(&self.interner); + .lower_into(self.interner); let bound = chalk_solve::rust_ir::FnDefDatumBound { inputs_and_output: chalk_ir::Binders::new( @@ -270,7 +272,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t }; Arc::new(chalk_solve::rust_ir::FnDefDatum { id: fn_def_id, - sig: sig.lower_into(&self.interner), + sig: sig.lower_into(self.interner), binders: chalk_ir::Binders::new(binders, bound), }) } @@ -281,7 +283,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t ) -> Arc>> { let def_id = impl_id.0; let bound_vars = bound_vars_for_item(self.interner.tcx, def_id); - let binders = binders_for(&self.interner, bound_vars); + let binders = binders_for(self.interner, bound_vars); let trait_ref = self.interner.tcx.impl_trait_ref(def_id).expect("not an impl"); let trait_ref = trait_ref.subst(self.interner.tcx, bound_vars); @@ -292,7 +294,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let where_clauses = self.where_clauses_for(def_id, bound_vars); let value = chalk_solve::rust_ir::ImplDatumBound { - trait_ref: trait_ref.lower_into(&self.interner), + trait_ref: trait_ref.lower_into(self.interner), where_clauses, }; @@ -306,7 +308,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t .collect(); Arc::new(chalk_solve::rust_ir::ImplDatum { - polarity: self.interner.tcx.impl_polarity(def_id).lower_into(&self.interner), + polarity: self.interner.tcx.impl_polarity(def_id).lower_into(self.interner), binders: chalk_ir::Binders::new(binders, value), impl_type: chalk_solve::rust_ir::ImplType::Local, associated_ty_value_ids, @@ -336,10 +338,10 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let mut regions_substitutor = lowering::RegionsSubstitutor::new(self.interner.tcx, self.reempty_placeholder); let self_ty = self_ty.fold_with(&mut regions_substitutor); - let lowered_ty = self_ty.lower_into(&self.interner); + let lowered_ty = self_ty.lower_into(self.interner); - parameters[0].assert_ty_ref(&self.interner).could_match( - &self.interner, + parameters[0].assert_ty_ref(self.interner).could_match( + self.interner, self.unification_database(), &lowered_ty, ) @@ -452,13 +454,13 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t .find_by_name_and_kind(self.interner.tcx, assoc_item.ident, assoc_item.kind, trait_id) .unwrap(); let bound_vars = bound_vars_for_item(self.interner.tcx, def_id); - let binders = binders_for(&self.interner, bound_vars); + let binders = binders_for(self.interner, bound_vars); let ty = self .interner .tcx .type_of(def_id) .subst(self.interner.tcx, bound_vars) - .lower_into(&self.interner); + .lower_into(self.interner); Arc::new(chalk_solve::rust_ir::AssociatedTyValue { impl_id: chalk_ir::ImplId(impl_id), @@ -521,13 +523,13 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t .filter_map(|bound| { LowerInto::< Option>> - >::lower_into(bound, &self.interner) + >::lower_into(bound, self.interner) }) .collect(); // Binder for the bound variable representing the concrete impl Trait type. let existential_binder = chalk_ir::VariableKinds::from1( - &self.interner, + self.interner, chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), ); @@ -536,7 +538,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t where_clauses: chalk_ir::Binders::new(existential_binder, where_clauses), }; - let binders = binders_for(&self.interner, bound_vars); + let binders = binders_for(self.interner, bound_vars); Arc::new(chalk_solve::rust_ir::OpaqueTyDatum { opaque_ty_id, bound: chalk_ir::Binders::new(binders, value), @@ -568,6 +570,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t Unpin => lang_items.unpin_trait(), CoerceUnsized => lang_items.coerce_unsized_trait(), DiscriminantKind => lang_items.discriminant_kind_trait(), + Generator => lang_items.generator_return(), }; def_id.map(chalk_ir::TraitId) } @@ -584,7 +587,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t self.interner .tcx .mk_ty(ty::Tuple(self.interner.tcx.intern_substs(&[]))) - .lower_into(&self.interner) + .lower_into(self.interner) } fn closure_kind( @@ -592,8 +595,8 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t _closure_id: chalk_ir::ClosureId>, substs: &chalk_ir::Substitution>, ) -> chalk_solve::rust_ir::ClosureKind { - let kind = &substs.as_slice(&self.interner)[substs.len(&self.interner) - 3]; - match kind.assert_ty_ref(&self.interner).kind(&self.interner) { + let kind = &substs.as_slice(self.interner)[substs.len(self.interner) - 3]; + match kind.assert_ty_ref(self.interner).kind(self.interner) { chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Int(int_ty)) => match int_ty { chalk_ir::IntTy::I8 => chalk_solve::rust_ir::ClosureKind::Fn, chalk_ir::IntTy::I16 => chalk_solve::rust_ir::ClosureKind::FnMut, @@ -610,18 +613,17 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t substs: &chalk_ir::Substitution>, ) -> chalk_ir::Binders>> { - let sig = &substs.as_slice(&self.interner)[substs.len(&self.interner) - 2]; - match sig.assert_ty_ref(&self.interner).kind(&self.interner) { + let sig = &substs.as_slice(self.interner)[substs.len(self.interner) - 2]; + match sig.assert_ty_ref(self.interner).kind(self.interner) { chalk_ir::TyKind::Function(f) => { - let substitution = f.substitution.0.as_slice(&self.interner); - let return_type = - substitution.last().unwrap().assert_ty_ref(&self.interner).clone(); + let substitution = f.substitution.0.as_slice(self.interner); + let return_type = substitution.last().unwrap().assert_ty_ref(self.interner).clone(); // Closure arguments are tupled - let argument_tuple = substitution[0].assert_ty_ref(&self.interner); - let argument_types = match argument_tuple.kind(&self.interner) { + let argument_tuple = substitution[0].assert_ty_ref(self.interner); + let argument_types = match argument_tuple.kind(self.interner) { chalk_ir::TyKind::Tuple(_len, substitution) => substitution - .iter(&self.interner) - .map(|arg| arg.assert_ty_ref(&self.interner)) + .iter(self.interner) + .map(|arg| arg.assert_ty_ref(self.interner)) .cloned() .collect(), _ => bug!("Expecting closure FnSig args to be tupled."), @@ -629,7 +631,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t chalk_ir::Binders::new( chalk_ir::VariableKinds::from_iter( - &self.interner, + self.interner, (0..f.num_binders).map(|_| chalk_ir::VariableKind::Lifetime), ), chalk_solve::rust_ir::FnDefInputsAndOutputDatum { argument_types, return_type }, @@ -645,7 +647,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t substs: &chalk_ir::Substitution>, ) -> chalk_ir::Binders>> { let inputs_and_output = self.closure_inputs_and_output(_closure_id, substs); - let tuple = substs.as_slice(&self.interner).last().unwrap().assert_ty_ref(&self.interner); + let tuple = substs.as_slice(self.interner).last().unwrap().assert_ty_ref(self.interner); inputs_and_output.map_ref(|_| tuple.clone()) } @@ -654,8 +656,8 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t _closure_id: chalk_ir::ClosureId>, substs: &chalk_ir::Substitution>, ) -> chalk_ir::Substitution> { - let substitution = &substs.as_slice(&self.interner)[0..substs.len(&self.interner) - 3]; - chalk_ir::Substitution::from_iter(&self.interner, substitution) + let substitution = &substs.as_slice(self.interner)[0..substs.len(self.interner) - 3]; + chalk_ir::Substitution::from_iter(self.interner, substitution) } fn generator_datum( @@ -691,7 +693,7 @@ impl<'tcx> chalk_ir::UnificationDatabase> for RustIrDatabase< ) -> chalk_ir::Variances> { let variances = self.interner.tcx.variances_of(def_id.0); chalk_ir::Variances::from_iter( - &self.interner, + self.interner, variances.iter().map(|v| match v { ty::Variance::Invariant => chalk_ir::Variance::Invariant, ty::Variance::Covariant => chalk_ir::Variance::Covariant, @@ -707,7 +709,7 @@ impl<'tcx> chalk_ir::UnificationDatabase> for RustIrDatabase< ) -> chalk_ir::Variances> { let variances = self.interner.tcx.variances_of(def_id.0.did); chalk_ir::Variances::from_iter( - &self.interner, + self.interner, variances.iter().map(|v| match v { ty::Variance::Invariant => chalk_ir::Variance::Invariant, ty::Variance::Covariant => chalk_ir::Variance::Covariant, @@ -722,7 +724,7 @@ impl<'tcx> chalk_ir::UnificationDatabase> for RustIrDatabase< /// var bound at index `0`. For types, we use a `BoundVar` index equal to /// the type parameter index. For regions, we use the `BoundRegionKind::BrNamed` /// variant (which has a `DefId`). -fn bound_vars_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> { +fn bound_vars_for_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> { InternalSubsts::for_item(tcx, def_id, |param, substs| match param.kind { ty::GenericParamDefKind::Type { .. } => tcx .mk_ty(ty::Bound( @@ -752,7 +754,7 @@ fn bound_vars_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> { } fn binders_for<'tcx>( - interner: &RustInterner<'tcx>, + interner: RustInterner<'tcx>, bound_vars: SubstsRef<'tcx>, ) -> chalk_ir::VariableKinds> { chalk_ir::VariableKinds::from_iter( diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index e24f699adf..cc07bfc500 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -46,26 +46,26 @@ use std::ops::ControlFlow; /// Essentially an `Into` with a `&RustInterner` parameter crate trait LowerInto<'tcx, T> { /// Lower a rustc construct (e.g., `ty::TraitPredicate`) to a chalk type, consuming `self`. - fn lower_into(self, interner: &RustInterner<'tcx>) -> T; + fn lower_into(self, interner: RustInterner<'tcx>) -> T; } impl<'tcx> LowerInto<'tcx, chalk_ir::Substitution>> for SubstsRef<'tcx> { fn lower_into( self, - interner: &RustInterner<'tcx>, + interner: RustInterner<'tcx>, ) -> chalk_ir::Substitution> { chalk_ir::Substitution::from_iter(interner, self.iter().map(|s| s.lower_into(interner))) } } impl<'tcx> LowerInto<'tcx, SubstsRef<'tcx>> for &chalk_ir::Substitution> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> SubstsRef<'tcx> { + fn lower_into(self, interner: RustInterner<'tcx>) -> SubstsRef<'tcx> { interner.tcx.mk_substs(self.iter(interner).map(|subst| subst.lower_into(interner))) } } impl<'tcx> LowerInto<'tcx, chalk_ir::AliasTy>> for ty::ProjectionTy<'tcx> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::AliasTy> { + fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::AliasTy> { chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy { associated_ty_id: chalk_ir::AssocTypeId(self.item_def_id), substitution: self.substs.lower_into(interner), @@ -78,7 +78,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment, + interner: RustInterner<'tcx>, ) -> chalk_ir::InEnvironment>> { let clauses = self.environment.into_iter().map(|predicate| { let (predicate, binders, _named_regions) = @@ -122,18 +122,18 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment> = self.goal.lower_into(&interner); + let goal: chalk_ir::GoalData> = self.goal.lower_into(interner); chalk_ir::InEnvironment { environment: chalk_ir::Environment { - clauses: chalk_ir::ProgramClauses::from_iter(&interner, clauses), + clauses: chalk_ir::ProgramClauses::from_iter(interner, clauses), }, - goal: goal.intern(&interner), + goal: goal.intern(interner), } } } impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData>> for ty::Predicate<'tcx> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::GoalData> { + fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::GoalData> { let (predicate, binders, _named_regions) = collect_bound_vars(interner, interner.tcx, self.kind()); @@ -214,7 +214,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData>> for ty::Predi impl<'tcx> LowerInto<'tcx, chalk_ir::TraitRef>> for rustc_middle::ty::TraitRef<'tcx> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::TraitRef> { + fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::TraitRef> { chalk_ir::TraitRef { trait_id: chalk_ir::TraitId(self.def_id), substitution: self.substs.lower_into(interner), @@ -225,7 +225,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::TraitRef>> impl<'tcx> LowerInto<'tcx, chalk_ir::AliasEq>> for rustc_middle::ty::ProjectionPredicate<'tcx> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::AliasEq> { + fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::AliasEq> { chalk_ir::AliasEq { ty: self.ty.lower_into(interner), alias: self.projection_ty.lower_into(interner), @@ -234,7 +234,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::AliasEq>> } impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::Ty> { + fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::Ty> { let int = |i| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Int(i)); let uint = |i| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Uint(i)); let float = |f| chalk_ir::TyKind::Scalar(chalk_ir::Scalar::Float(f)); @@ -336,7 +336,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { } impl<'tcx> LowerInto<'tcx, Ty<'tcx>> for &chalk_ir::Ty> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> Ty<'tcx> { + fn lower_into(self, interner: RustInterner<'tcx>) -> Ty<'tcx> { use chalk_ir::TyKind; let kind = match self.kind(interner) { @@ -429,7 +429,7 @@ impl<'tcx> LowerInto<'tcx, Ty<'tcx>> for &chalk_ir::Ty> { } impl<'tcx> LowerInto<'tcx, chalk_ir::Lifetime>> for Region<'tcx> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::Lifetime> { + fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::Lifetime> { use rustc_middle::ty::RegionKind::*; match self { @@ -459,7 +459,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Lifetime>> for Region<'t } impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> Region<'tcx> { + fn lower_into(self, interner: RustInterner<'tcx>) -> Region<'tcx> { let kind = match self.data(interner) { chalk_ir::LifetimeData::BoundVar(var) => ty::RegionKind::ReLateBound( ty::DebruijnIndex::from_u32(var.debruijn.depth()), @@ -487,7 +487,7 @@ impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime LowerInto<'tcx, chalk_ir::Const>> for ty::Const<'tcx> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::Const> { + fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::Const> { let ty = self.ty.lower_into(interner); let value = match self.val { ty::ConstKind::Value(val) => { @@ -503,7 +503,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Const>> for ty::Const<'t } impl<'tcx> LowerInto<'tcx, ty::Const<'tcx>> for &chalk_ir::Const> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> ty::Const<'tcx> { + fn lower_into(self, interner: RustInterner<'tcx>) -> ty::Const<'tcx> { let data = self.data(interner); let ty = data.ty.lower_into(interner); let val = match data.value { @@ -520,7 +520,7 @@ impl<'tcx> LowerInto<'tcx, ty::Const<'tcx>> for &chalk_ir::Const LowerInto<'tcx, chalk_ir::GenericArg>> for GenericArg<'tcx> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> chalk_ir::GenericArg> { + fn lower_into(self, interner: RustInterner<'tcx>) -> chalk_ir::GenericArg> { match self.unpack() { ty::subst::GenericArgKind::Type(ty) => { chalk_ir::GenericArgData::Ty(ty.lower_into(interner)) @@ -539,7 +539,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GenericArg>> for Generic impl<'tcx> LowerInto<'tcx, ty::subst::GenericArg<'tcx>> for &chalk_ir::GenericArg> { - fn lower_into(self, interner: &RustInterner<'tcx>) -> ty::subst::GenericArg<'tcx> { + fn lower_into(self, interner: RustInterner<'tcx>) -> ty::subst::GenericArg<'tcx> { match self.data(interner) { chalk_ir::GenericArgData::Ty(ty) => { let t: Ty<'tcx> = ty.lower_into(interner); @@ -566,7 +566,7 @@ impl<'tcx> LowerInto<'tcx, Option, + interner: RustInterner<'tcx>, ) -> Option>> { let (predicate, binders, _named_regions) = collect_bound_vars(interner, interner.tcx, self.kind()); @@ -610,7 +610,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders, + interner: RustInterner<'tcx>, ) -> chalk_ir::Binders>> { // `Self` has one binder: // Binder<&'tcx ty::List>> @@ -680,7 +680,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders LowerInto<'tcx, chalk_ir::FnSig>> for ty::Binder<'tcx, ty::FnSig<'tcx>> { - fn lower_into(self, _interner: &RustInterner<'_>) -> FnSig> { + fn lower_into(self, _interner: RustInterner<'_>) -> FnSig> { chalk_ir::FnSig { abi: self.abi(), safety: match self.unsafety() { @@ -700,7 +700,7 @@ impl<'tcx> LowerInto<'tcx, Option, + interner: RustInterner<'tcx>, ) -> Option>> { let (predicate, binders, _named_regions) = collect_bound_vars(interner, interner.tcx, self.kind()); @@ -737,7 +737,7 @@ impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::TraitBound>> { fn lower_into( self, - interner: &RustInterner<'tcx>, + interner: RustInterner<'tcx>, ) -> chalk_solve::rust_ir::TraitBound> { chalk_solve::rust_ir::TraitBound { trait_id: chalk_ir::TraitId(self.def_id), @@ -747,7 +747,7 @@ impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::TraitBound>> } impl<'tcx> LowerInto<'tcx, chalk_ir::Mutability> for ast::Mutability { - fn lower_into(self, _interner: &RustInterner<'tcx>) -> chalk_ir::Mutability { + fn lower_into(self, _interner: RustInterner<'tcx>) -> chalk_ir::Mutability { match self { rustc_ast::Mutability::Mut => chalk_ir::Mutability::Mut, rustc_ast::Mutability::Not => chalk_ir::Mutability::Not, @@ -756,7 +756,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Mutability> for ast::Mutability { } impl<'tcx> LowerInto<'tcx, ast::Mutability> for chalk_ir::Mutability { - fn lower_into(self, _interner: &RustInterner<'tcx>) -> ast::Mutability { + fn lower_into(self, _interner: RustInterner<'tcx>) -> ast::Mutability { match self { chalk_ir::Mutability::Mut => ast::Mutability::Mut, chalk_ir::Mutability::Not => ast::Mutability::Not, @@ -765,7 +765,7 @@ impl<'tcx> LowerInto<'tcx, ast::Mutability> for chalk_ir::Mutability { } impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::Polarity> for ty::ImplPolarity { - fn lower_into(self, _interner: &RustInterner<'tcx>) -> chalk_solve::rust_ir::Polarity { + fn lower_into(self, _interner: RustInterner<'tcx>) -> chalk_solve::rust_ir::Polarity { match self { ty::ImplPolarity::Positive => chalk_solve::rust_ir::Polarity::Positive, ty::ImplPolarity::Negative => chalk_solve::rust_ir::Polarity::Negative, @@ -780,7 +780,7 @@ impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::AliasEqBound { fn lower_into( self, - interner: &RustInterner<'tcx>, + interner: RustInterner<'tcx>, ) -> chalk_solve::rust_ir::AliasEqBound> { let (trait_ref, own_substs) = self.projection_ty.trait_ref_and_own_substs(interner.tcx); chalk_solve::rust_ir::AliasEqBound { @@ -802,7 +802,7 @@ impl<'tcx> LowerInto<'tcx, chalk_solve::rust_ir::AliasEqBound /// late-bound regions, even outside of fn contexts, since this is the best way /// to prep types for chalk lowering. crate fn collect_bound_vars<'tcx, T: TypeFoldable<'tcx>>( - interner: &RustInterner<'tcx>, + interner: RustInterner<'tcx>, tcx: TyCtxt<'tcx>, ty: Binder<'tcx, T>, ) -> (T, chalk_ir::VariableKinds>, BTreeMap) { diff --git a/compiler/rustc_traits/src/chalk/mod.rs b/compiler/rustc_traits/src/chalk/mod.rs index b7275bac19..a4d844e2eb 100644 --- a/compiler/rustc_traits/src/chalk/mod.rs +++ b/compiler/rustc_traits/src/chalk/mod.rs @@ -63,7 +63,7 @@ crate fn evaluate_goal<'tcx>( > = chalk_ir::UCanonical { canonical: chalk_ir::Canonical { binders: chalk_ir::CanonicalVarKinds::from_iter( - &interner, + interner, obligation.variables.iter().map(|v| match v.kind { CanonicalVarKind::PlaceholderTy(_ty) => unimplemented!(), CanonicalVarKind::PlaceholderRegion(_ui) => unimplemented!(), @@ -89,7 +89,7 @@ crate fn evaluate_goal<'tcx>( CanonicalVarKind::PlaceholderConst(_pc) => unimplemented!(), }), ), - value: obligation.value.lower_into(&interner), + value: obligation.value.lower_into(interner), }, universes: max_universe + 1, }; @@ -110,11 +110,11 @@ crate fn evaluate_goal<'tcx>( use rustc_middle::infer::canonical::CanonicalVarInfo; let mut var_values: IndexVec> = IndexVec::new(); - subst.as_slice(&interner).iter().for_each(|p| { - var_values.push(p.lower_into(&interner)); + subst.as_slice(interner).iter().for_each(|p| { + var_values.push(p.lower_into(interner)); }); let variables: Vec<_> = binders - .iter(&interner) + .iter(interner) .map(|var| { let kind = match var.kind { chalk_ir::VariableKind::Ty(ty_kind) => CanonicalVarKind::Ty(match ty_kind { @@ -134,8 +134,7 @@ crate fn evaluate_goal<'tcx>( CanonicalVarInfo { kind } }) .collect(); - let max_universe = - binders.iter(&interner).map(|v| v.skip_kind().counter).max().unwrap_or(0); + let max_universe = binders.iter(interner).map(|v| v.skip_kind().counter).max().unwrap_or(0); let sol = Canonical { max_universe: ty::UniverseIndex::from_usize(max_universe), variables: tcx.intern_canonical_var_infos(&variables), diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs index 92f2760e62..90c698db8f 100644 --- a/compiler/rustc_traits/src/implied_outlives_bounds.rs +++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs @@ -138,7 +138,7 @@ fn compute_implied_outlives_bounds<'tcx>( /// this down to determine what relationships would have to hold for /// `T: 'a` to hold. We get to assume that the caller has validated /// those relationships. -fn implied_bounds_from_components( +fn implied_bounds_from_components<'tcx>( sub_region: ty::Region<'tcx>, sup_components: SmallVec<[Component<'tcx>; 4]>, ) -> Vec> { diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs index 8612499623..b814b984da 100644 --- a/compiler/rustc_traits/src/lib.rs +++ b/compiler/rustc_traits/src/lib.rs @@ -2,7 +2,6 @@ //! the guts are broken up into modules; see the comments in those modules. #![feature(crate_visibility_modifier)] -#![feature(in_band_lifetimes)] #![feature(nll)] #![recursion_limit = "256"] diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index 61ab5e28b6..46c2f7e4cf 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -8,27 +8,28 @@ use std::sync::atomic::Ordering; crate fn provide(p: &mut Providers) { *p = Providers { - normalize_generic_arg_after_erasing_regions: |tcx, goal| { - debug!("normalize_generic_arg_after_erasing_regions(goal={:#?})", goal); + try_normalize_generic_arg_after_erasing_regions: |tcx, goal| { + debug!("try_normalize_generic_arg_after_erasing_regions(goal={:#?}", goal); tcx.sess .perf_stats .normalize_generic_arg_after_erasing_regions .fetch_add(1, Ordering::Relaxed); - normalize_after_erasing_regions(tcx, goal) + + try_normalize_after_erasing_regions(tcx, goal) }, - normalize_mir_const_after_erasing_regions: |tcx, goal| { - normalize_after_erasing_regions(tcx, goal) + try_normalize_mir_const_after_erasing_regions: |tcx, goal| { + try_normalize_after_erasing_regions(tcx, goal) }, ..*p }; } #[instrument(level = "debug", skip(tcx))] -fn normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq + Copy>( +fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq + Copy>( tcx: TyCtxt<'tcx>, goal: ParamEnvAnd<'tcx, T>, -) -> T { +) -> Result { let ParamEnvAnd { param_env, value } = goal; tcx.infer_ctxt().enter(|infcx| { let cause = ObligationCause::dummy(); @@ -49,14 +50,14 @@ fn normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq + Cop debug_assert_eq!(normalized_value, resolved_value); let erased = infcx.tcx.erase_regions(resolved_value); debug_assert!(!erased.needs_infer(), "{:?}", erased); - erased + Ok(erased) } - Err(NoSolution) => bug!("could not fully normalize `{:?}`", value), + Err(NoSolution) => Err(NoSolution), } }) } -fn not_outlives_predicate(p: &ty::Predicate<'tcx>) -> bool { +fn not_outlives_predicate<'tcx>(p: &ty::Predicate<'tcx>) -> bool { match p.kind().skip_binder() { ty::PredicateKind::RegionOutlives(..) | ty::PredicateKind::TypeOutlives(..) => false, ty::PredicateKind::Trait(..) diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs index cc0b7d5817..6fcac9fcdc 100644 --- a/compiler/rustc_traits/src/type_op.rs +++ b/compiler/rustc_traits/src/type_op.rs @@ -70,7 +70,7 @@ struct AscribeUserTypeCx<'me, 'tcx> { fulfill_cx: &'me mut dyn TraitEngine<'tcx>, } -impl AscribeUserTypeCx<'me, 'tcx> { +impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> { fn normalize(&mut self, value: T) -> T where T: TypeFoldable<'tcx>, @@ -195,7 +195,7 @@ fn type_op_eq<'tcx>( }) } -fn type_op_normalize( +fn type_op_normalize<'tcx, T>( infcx: &InferCtxt<'_, 'tcx>, fulfill_cx: &mut dyn TraitEngine<'tcx>, key: ParamEnvAnd<'tcx, Normalize>, @@ -210,28 +210,28 @@ where Ok(value) } -fn type_op_normalize_ty( +fn type_op_normalize_ty<'tcx>( tcx: TyCtxt<'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize>>>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>, NoSolution> { tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize) } -fn type_op_normalize_predicate( +fn type_op_normalize_predicate<'tcx>( tcx: TyCtxt<'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize>>>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, Predicate<'tcx>>>, NoSolution> { tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize) } -fn type_op_normalize_fn_sig( +fn type_op_normalize_fn_sig<'tcx>( tcx: TyCtxt<'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize>>>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, FnSig<'tcx>>>, NoSolution> { tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize) } -fn type_op_normalize_poly_fn_sig( +fn type_op_normalize_poly_fn_sig<'tcx>( tcx: TyCtxt<'tcx>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize>>>, ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, PolyFnSig<'tcx>>>, NoSolution> { diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 595b623b02..fc309aa848 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -147,8 +147,10 @@ where Ok(tys) => tys, }; for required_ty in tys { - let required = - tcx.normalize_erasing_regions(self.param_env, required_ty); + let required = tcx + .try_normalize_erasing_regions(self.param_env, required_ty) + .unwrap_or(required_ty); + queue_type(self, required); } } diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index af3706f886..6c2657bd64 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -2,10 +2,8 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::subst::Subst; -use rustc_middle::ty::{ - self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt, WithConstness, -}; -use rustc_span::Span; +use rustc_middle::ty::{self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt}; +use rustc_span::{sym, Span}; use rustc_trait_selection::traits; fn sized_constraint_for_ty<'tcx>( @@ -123,7 +121,7 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem { let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); let parent_id = tcx.hir().get_parent_item(id); let parent_def_id = tcx.hir().local_def_id(parent_id); - let parent_item = tcx.hir().expect_item(parent_id); + let parent_item = tcx.hir().expect_item(parent_def_id); match parent_item.kind { hir::ItemKind::Impl(ref impl_) => { if let Some(impl_item_ref) = @@ -158,8 +156,7 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem { } fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - let item = tcx.hir().expect_item(hir_id); + let item = tcx.hir().expect_item(def_id.expect_local()); if let hir::ItemKind::Impl(impl_) = &item.kind { impl_.defaultness } else { @@ -168,8 +165,7 @@ fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness { } fn impl_constness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Constness { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - let item = tcx.hir().expect_item(hir_id); + let item = tcx.hir().expect_item(def_id.expect_local()); if let hir::ItemKind::Impl(impl_) = &item.kind { impl_.constness } else { @@ -202,8 +198,7 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AdtSizedConstrain } fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] { - let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - let item = tcx.hir().expect_item(id); + let item = tcx.hir().expect_item(def_id.expect_local()); match item.kind { hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter( trait_item_refs.iter().map(|trait_item_ref| trait_item_ref.id.def_id.to_def_id()), @@ -251,7 +246,7 @@ fn trait_of_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option { fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { // The param_env of an impl Trait type is its defining function's param_env if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) { - return param_env(tcx, parent); + return param_env(tcx, parent.to_def_id()); } // Compute the bounds on Self and the type parameters. @@ -285,16 +280,85 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { // issue #89334 predicates = tcx.expose_default_const_substs(predicates); - let unnormalized_env = - ty::ParamEnv::new(tcx.intern_predicates(&predicates), traits::Reveal::UserFacing); + let local_did = def_id.as_local(); + let hir_id = local_did.map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)); - debug!("unnormalized_env caller bounds: {:?}", unnormalized_env.caller_bounds()); - let body_id = def_id - .as_local() - .map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)) - .map_or(hir::CRATE_HIR_ID, |id| { - tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.hir_id) - }); + let constness = match hir_id { + Some(hir_id) => match tcx.hir().get(hir_id) { + hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) + if tcx.has_attr(def_id, sym::default_method_body_is_const) => + { + hir::Constness::Const + } + + hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(..), .. }) + | hir::Node::Item(hir::Item { kind: hir::ItemKind::Static(..), .. }) + | hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Const(..), .. + }) + | hir::Node::AnonConst(_) + | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) + | hir::Node::ImplItem(hir::ImplItem { + kind: + hir::ImplItemKind::Fn( + hir::FnSig { + header: hir::FnHeader { constness: hir::Constness::Const, .. }, + .. + }, + .., + ), + .. + }) => hir::Constness::Const, + + hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::TyAlias(..) | hir::ImplItemKind::Fn(..), + .. + }) => { + let parent_hir_id = tcx.hir().get_parent_node(hir_id); + match tcx.hir().get(parent_hir_id) { + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), + .. + }) => *constness, + _ => span_bug!( + tcx.def_span(parent_hir_id.owner), + "impl item's parent node is not an impl", + ), + } + } + + hir::Node::Item(hir::Item { + kind: + hir::ItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..), + .. + }) + | hir::Node::TraitItem(hir::TraitItem { + kind: + hir::TraitItemKind::Fn( + hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, + .., + ), + .. + }) + | hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), + .. + }) => *constness, + + _ => hir::Constness::NotConst, + }, + None => hir::Constness::NotConst, + }; + + let unnormalized_env = ty::ParamEnv::new( + tcx.intern_predicates(&predicates), + traits::Reveal::UserFacing, + constness, + ); + + let body_id = hir_id.map_or(hir::CRATE_HIR_ID, |id| { + tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.hir_id) + }); let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id); traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause) } @@ -316,7 +380,7 @@ fn well_formed_types_in_env<'tcx>( // The environment of an impl Trait type is its defining function's environment. if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) { - return well_formed_types_in_env(tcx, parent); + return well_formed_types_in_env(tcx, parent.to_def_id()); } // Compute the bounds on `Self` and the type parameters. diff --git a/compiler/rustc_typeck/src/astconv/errors.rs b/compiler/rustc_typeck/src/astconv/errors.rs index ec75e4a55d..ea54b85b2f 100644 --- a/compiler/rustc_typeck/src/astconv/errors.rs +++ b/compiler/rustc_typeck/src/astconv/errors.rs @@ -92,7 +92,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, span: Span, trait_def_id: DefId, - trait_segment: &'a hir::PathSegment<'a>, + trait_segment: &'_ hir::PathSegment<'_>, ) { let trait_def = self.tcx().trait_def(trait_def_id); diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index e8bd038fed..956696546d 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -104,7 +104,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }), GenericParamDefKind::Const { .. }, ) if tcx.type_of(param.def_id) == tcx.types.usize => { - let snippet = sess.source_map().span_to_snippet(tcx.hir().span(len.hir_id)); + let snippet = sess.source_map().span_to_snippet(tcx.hir().span(len.hir_id())); if let Ok(snippet) = snippet { err.span_suggestion( arg.span(), @@ -131,8 +131,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { _ => {} } - let kind_ord = param.kind.to_ord(tcx); - let arg_ord = arg.to_ord(tcx.features()); + let kind_ord = param.kind.to_ord(); + let arg_ord = arg.to_ord(); // This note is only true when generic parameters are strictly ordered by their kind. if possible_ordering_error && kind_ord.cmp(&arg_ord) != core::cmp::Ordering::Equal { @@ -298,26 +298,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .params .clone() .into_iter() - .map(|param| { - ( - match param.kind { - GenericParamDefKind::Lifetime => { - ParamKindOrd::Lifetime - } - GenericParamDefKind::Type { .. } => { - ParamKindOrd::Type - } - GenericParamDefKind::Const { .. } => { - ParamKindOrd::Const { - unordered: tcx - .features() - .unordered_const_ty_params(), - } - } - }, - param, - ) - }) + .map(|param| (param.kind.to_ord(), param)) .collect::>(); param_types_present.sort_by_key(|(ord, _)| *ord); let (mut param_types_present, ordered_params): ( @@ -330,16 +311,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx, arg, param, - !args_iter.clone().is_sorted_by_key(|arg| match arg { - GenericArg::Lifetime(_) => ParamKindOrd::Lifetime, - GenericArg::Type(_) => ParamKindOrd::Type, - GenericArg::Const(_) => ParamKindOrd::Const { - unordered: tcx - .features() - .unordered_const_ty_params(), - }, - GenericArg::Infer(_) => ParamKindOrd::Infer, - }), + !args_iter.clone().is_sorted_by_key(|arg| arg.to_ord()), Some(&format!( "reorder the arguments: {}: `<{}>`", param_types_present diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index da751f2075..8226ffbccc 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -13,6 +13,7 @@ use crate::errors::{ }; use crate::middle::resolve_lifetime as rl; use crate::require_c_abi_if_c_variadic; +use rustc_ast::TraitObjectSyntax; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{struct_span_err, Applicability, ErrorReported, FatalError}; use rustc_hir as hir; @@ -24,7 +25,8 @@ use rustc_hir::{GenericArg, GenericArgs}; use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, Subst, SubstsRef}; use rustc_middle::ty::GenericParamDefKind; use rustc_middle::ty::{self, Const, DefIdTree, Ty, TyCtxt, TypeFoldable}; -use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; +use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS}; +use rustc_span::edition::Edition; use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -35,7 +37,6 @@ use rustc_trait_selection::traits::error_reporting::report_object_safety_error; use rustc_trait_selection::traits::wf::object_region_bounds; use smallvec::SmallVec; -use std::array; use std::collections::BTreeSet; use std::slice; @@ -415,34 +416,40 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { arg: &GenericArg<'_>, ) -> subst::GenericArg<'tcx> { let tcx = self.astconv.tcx(); + + let mut handle_ty_args = |has_default, ty: &hir::Ty<'_>| { + if has_default { + tcx.check_optional_stability( + param.def_id, + Some(arg.id()), + arg.span(), + None, + |_, _| { + // Default generic parameters may not be marked + // with stability attributes, i.e. when the + // default parameter was defined at the same time + // as the rest of the type. As such, we ignore missing + // stability attributes. + }, + ) + } + if let (hir::TyKind::Infer, false) = (&ty.kind, self.astconv.allow_ty_infer()) { + self.inferred_params.push(ty.span); + tcx.ty_error().into() + } else { + self.astconv.ast_ty_to_ty(ty).into() + } + }; + match (¶m.kind, arg) { (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => { self.astconv.ast_region_to_region(lt, Some(param)).into() } (&GenericParamDefKind::Type { has_default, .. }, GenericArg::Type(ty)) => { - if has_default { - tcx.check_optional_stability( - param.def_id, - Some(arg.id()), - arg.span(), - None, - |_, _| { - // Default generic parameters may not be marked - // with stability attributes, i.e. when the - // default parameter was defined at the same time - // as the rest of the type. As such, we ignore missing - // stability attributes. - }, - ) - } - if let (hir::TyKind::Infer, false) = - (&ty.kind, self.astconv.allow_ty_infer()) - { - self.inferred_params.push(ty.span); - tcx.ty_error().into() - } else { - self.astconv.ast_ty_to_ty(ty).into() - } + handle_ty_args(has_default, ty) + } + (&GenericParamDefKind::Type { has_default, .. }, GenericArg::Infer(inf)) => { + handle_ty_args(has_default, &inf.to_ty()) } (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { ty::Const::from_opt_const_arg_anon_const( @@ -454,41 +461,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) .into() } - (&GenericParamDefKind::Const { has_default }, hir::GenericArg::Infer(inf)) => { - if has_default { - tcx.const_param_default(param.def_id).into() - } else if self.astconv.allow_ty_infer() { - // FIXME(const_generics): Actually infer parameter here? - todo!() - } else { - self.inferred_params.push(inf.span); - tcx.ty_error().into() - } - } - ( - &GenericParamDefKind::Type { has_default, .. }, - hir::GenericArg::Infer(inf), - ) => { - if has_default { - tcx.check_optional_stability( - param.def_id, - Some(arg.id()), - arg.span(), - None, - |_, _| { - // Default generic parameters may not be marked - // with stability attributes, i.e. when the - // default parameter was defined at the same time - // as the rest of the type. As such, we ignore missing - // stability attributes. - }, - ); - } + (&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => { + let ty = tcx.at(self.span).type_of(param.def_id); if self.astconv.allow_ty_infer() { - self.astconv.ast_ty_to_ty(&inf.to_ty()).into() + self.astconv.ct_infer(ty, Some(param), inf.span).into() } else { self.inferred_params.push(inf.span); - tcx.ty_error().into() + tcx.const_error(ty).into() } } _ => unreachable!(), @@ -1351,7 +1330,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx, span, item.trait_ref().def_id(), - &object_safety_violations[..], + &object_safety_violations, ) .emit(); return tcx.ty_error(); @@ -1588,7 +1567,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { traits::transitive_bounds_that_define_assoc_type( tcx, predicates.iter().filter_map(|(p, _)| { - p.to_opt_poly_trait_ref().map(|trait_ref| trait_ref.value) + Some(p.to_opt_poly_trait_pred()?.map_bound(|t| t.trait_ref)) }), assoc_name, ) @@ -1635,7 +1614,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { debug!("one_bound_for_assoc_type: bound2 = {:?}", bound2); let is_equality = is_equality(); - let bounds = array::IntoIter::new([bound, bound2]).chain(matching_candidates); + let bounds = IntoIterator::into_iter([bound, bound2]).chain(matching_candidates); let mut err = if is_equality.is_some() { // More specific Error Index entry. struct_span_err!( @@ -2289,13 +2268,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// Parses the programmer's textual representation of a type into our /// internal notion of a type. pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { - self.ast_ty_to_ty_inner(ast_ty, false) + self.ast_ty_to_ty_inner(ast_ty, false, false) + } + + /// Parses the programmer's textual representation of a type into our + /// internal notion of a type. This is meant to be used within a path. + pub fn ast_ty_to_ty_in_path(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { + self.ast_ty_to_ty_inner(ast_ty, false, true) } /// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait /// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors. #[tracing::instrument(level = "debug", skip(self))] - fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool) -> Ty<'tcx> { + fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool, in_path: bool) -> Ty<'tcx> { let tcx = self.tcx(); let result_ty = match ast_ty.kind { @@ -2306,7 +2291,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { hir::TyKind::Rptr(ref region, ref mt) => { let r = self.ast_region_to_region(region, None); debug!(?r); - let t = self.ast_ty_to_ty_inner(mt.ty, true); + let t = self.ast_ty_to_ty_inner(mt.ty, true, false); tcx.mk_ref(r, ty::TypeAndMut { ty: t, mutbl: mt.mutbl }) } hir::TyKind::Never => tcx.types.never, @@ -2325,6 +2310,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { )) } hir::TyKind::TraitObject(bounds, ref lifetime, _) => { + self.maybe_lint_bare_trait(ast_ty, in_path); self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed) } hir::TyKind::Path(hir::QPath::Resolved(ref maybe_qself, ref path)) => { @@ -2337,15 +2323,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let def_id = item_id.def_id.to_def_id(); match opaque_ty.kind { - hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => { - self.impl_trait_ty_to_ty(def_id, lifetimes, impl_trait_fn.is_some()) - } + hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => self + .impl_trait_ty_to_ty( + def_id, + lifetimes, + matches!( + origin, + hir::OpaqueTyOrigin::FnReturn(..) + | hir::OpaqueTyOrigin::AsyncFn(..) + ), + ), ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i), } } hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => { debug!(?qself, ?segment); - let ty = self.ast_ty_to_ty(qself); + let ty = self.ast_ty_to_ty_inner(qself, false, true); let res = if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = qself.kind { path.res @@ -2356,7 +2349,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .map(|(ty, _, _)| ty) .unwrap_or_else(|_| tcx.ty_error()) } - hir::TyKind::Path(hir::QPath::LangItem(lang_item, span)) => { + hir::TyKind::Path(hir::QPath::LangItem(lang_item, span, _)) => { let def_id = tcx.require_lang_item(lang_item, Some(span)); let (substs, _) = self.create_substs_for_ast_path( span, @@ -2370,8 +2363,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.normalize_ty(span, tcx.at(span).type_of(def_id).subst(tcx, substs)) } hir::TyKind::Array(ref ty, ref length) => { - let length_def_id = tcx.hir().local_def_id(length.hir_id); - let length = ty::Const::from_anon_const(tcx, length_def_id); + let length = match length { + &hir::ArrayLen::Infer(_, span) => self.ct_infer(tcx.types.usize, None, span), + hir::ArrayLen::Body(constant) => { + let length_def_id = tcx.hir().local_def_id(constant.hir_id); + ty::Const::from_anon_const(tcx, length_def_id) + } + }; + let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(ty), length)); self.normalize_ty(ast_ty.span, array_ty) } @@ -2602,4 +2601,62 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } Some(r) } + + fn maybe_lint_bare_trait(&self, self_ty: &hir::Ty<'_>, in_path: bool) { + let tcx = self.tcx(); + if let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = + self_ty.kind + { + let needs_bracket = in_path + && !tcx + .sess + .source_map() + .span_to_prev_source(self_ty.span) + .ok() + .map_or(false, |s| s.trim_end().ends_with('<')); + + let is_global = poly_trait_ref.trait_ref.path.is_global(); + let sugg = Vec::from_iter([ + ( + self_ty.span.shrink_to_lo(), + format!( + "{}dyn {}", + if needs_bracket { "<" } else { "" }, + if is_global { "(" } else { "" }, + ), + ), + ( + self_ty.span.shrink_to_hi(), + format!( + "{}{}", + if is_global { ")" } else { "" }, + if needs_bracket { ">" } else { "" }, + ), + ), + ]); + if self_ty.span.edition() >= Edition::Edition2021 { + let msg = "trait objects must include the `dyn` keyword"; + let label = "add `dyn` keyword before this trait"; + rustc_errors::struct_span_err!(tcx.sess, self_ty.span, E0782, "{}", msg) + .multipart_suggestion_verbose(label, sugg, Applicability::MachineApplicable) + .emit(); + } else { + let msg = "trait objects without an explicit `dyn` are deprecated"; + tcx.struct_span_lint_hir( + BARE_TRAIT_OBJECTS, + self_ty.hir_id, + self_ty.span, + |lint| { + lint.build(msg) + .multipart_suggestion_verbose( + "use `dyn`", + sugg, + Applicability::MachineApplicable, + ) + .emit() + }, + ); + } + } + } } diff --git a/compiler/rustc_typeck/src/bounds.rs b/compiler/rustc_typeck/src/bounds.rs index 24474e163b..8bc3a48e5b 100644 --- a/compiler/rustc_typeck/src/bounds.rs +++ b/compiler/rustc_typeck/src/bounds.rs @@ -1,7 +1,7 @@ //! Bounds are restrictions applied to some types after they've been converted into the //! `ty` form from the HIR. -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; use rustc_span::Span; /// Collects together a list of type bounds. These lists of bounds occur in many places diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs index a816031322..405e4e8594 100644 --- a/compiler/rustc_typeck/src/check/_match.rs +++ b/compiler/rustc_typeck/src/check/_match.rs @@ -557,7 +557,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } -fn arms_contain_ref_bindings(arms: &'tcx [hir::Arm<'tcx>]) -> Option { +fn arms_contain_ref_bindings<'tcx>(arms: &'tcx [hir::Arm<'tcx>]) -> Option { arms.iter().filter_map(|a| a.pat.contains_explicit_ref_binding()).max_by_key(|m| match *m { hir::Mutability::Mut => 1, hir::Mutability::Not => 0, diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs index 635ed93819..eea8f40635 100644 --- a/compiler/rustc_typeck/src/check/callee.rs +++ b/compiler/rustc_typeck/src/check/callee.rs @@ -496,7 +496,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_expr.span, call_expr, fn_sig.inputs(), - &expected_arg_tys[..], + expected_arg_tys, arg_exprs, fn_sig.c_variadic, TupleArgumentsFlag::DontTupleArguments, @@ -529,7 +529,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_expr.span, call_expr, fn_sig.inputs(), - &expected_arg_tys, + expected_arg_tys, arg_exprs, fn_sig.c_variadic, TupleArgumentsFlag::TupleArguments, diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index 511a2d7dda..a397ee771a 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -638,7 +638,11 @@ impl<'a, 'tcx> CastCheck<'tcx> { self.expr_ty = fcx.structurally_resolved_type(self.expr.span, self.expr_ty); self.cast_ty = fcx.structurally_resolved_type(self.cast_span, self.cast_ty); - if !fcx.type_is_known_to_be_sized_modulo_regions(self.cast_ty, self.span) { + debug!("check_cast({}, {:?} as {:?})", self.expr.hir_id, self.expr_ty, self.cast_ty); + + if !fcx.type_is_known_to_be_sized_modulo_regions(self.cast_ty, self.span) + && !self.cast_ty.has_infer_types() + { self.report_cast_to_unsized_type(fcx); } else if self.expr_ty.references_error() || self.cast_ty.references_error() { // No sense in giving duplicate error messages diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index bb1d9744e6..fd7b3a55df 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -453,12 +453,12 @@ pub(super) fn check_opaque<'tcx>( /// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result /// in "inheriting lifetimes". #[instrument(level = "debug", skip(tcx, span))] -pub(super) fn check_opaque_for_inheriting_lifetimes( +pub(super) fn check_opaque_for_inheriting_lifetimes<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span, ) { - let item = tcx.hir().expect_item(tcx.hir().local_def_id_to_hir_id(def_id)); + let item = tcx.hir().expect_item(def_id); debug!(?item, ?span); struct FoundParentLifetime; @@ -517,7 +517,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( } } - impl Visitor<'tcx> for ProhibitOpaqueVisitor<'tcx> { + impl<'tcx> Visitor<'tcx> for ProhibitOpaqueVisitor<'tcx> { type Map = rustc_middle::hir::map::Map<'tcx>; fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap { @@ -541,7 +541,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( } if let ItemKind::OpaqueTy(hir::OpaqueTy { - origin: hir::OpaqueTyOrigin::AsyncFn | hir::OpaqueTyOrigin::FnReturn, + origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..), .. }) = item.kind { @@ -567,7 +567,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( visitor.visit_item(&item); let is_async = match item.kind { ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => { - matches!(origin, hir::OpaqueTyOrigin::AsyncFn) + matches!(origin, hir::OpaqueTyOrigin::AsyncFn(..)) } _ => unreachable!(), }; @@ -604,7 +604,7 @@ pub(super) fn check_opaque_for_cycles<'tcx>( ) -> Result<(), ErrorReported> { if tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs).is_err() { match origin { - hir::OpaqueTyOrigin::AsyncFn => async_opaque_type_cycle_error(tcx, span), + hir::OpaqueTyOrigin::AsyncFn(..) => async_opaque_type_cycle_error(tcx, span), _ => opaque_type_cycle_error(tcx, def_id, span), } Err(ErrorReported) @@ -635,7 +635,7 @@ fn check_opaque_meets_bounds<'tcx>( ) { match origin { // Checked when type checking the function containing them. - hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => return, + hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => return, // Can have different predicates to their defining use hir::OpaqueTyOrigin::TyAlias => {} } @@ -730,7 +730,7 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) { let abi = sig.header.abi; fn_maybe_err(tcx, item.ident.span, abi); } - hir::TraitItemKind::Type(.., Some(_default)) => { + hir::TraitItemKind::Type(.., Some(default)) => { let assoc_item = tcx.associated_item(item.def_id); let trait_substs = InternalSubsts::identity_for_item(tcx, it.def_id.to_def_id()); @@ -738,7 +738,7 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) { tcx, assoc_item, assoc_item, - item.span, + default.span, ty::TraitRef { def_id: it.def_id.to_def_id(), substs: trait_substs }, ); } @@ -987,12 +987,12 @@ pub(super) fn check_impl_items_against_trait<'tcx>( opt_trait_span, ); } - hir::ImplItemKind::TyAlias(_) => { + hir::ImplItemKind::TyAlias(impl_ty) => { let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id); compare_ty_impl( tcx, &ty_impl_item, - impl_item.span, + impl_ty.span, &ty_trait_item, impl_trait_ref, opt_trait_span, @@ -1506,19 +1506,13 @@ pub(super) fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckItemTypesVisitor { tcx }); } -pub(super) fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { - wfcheck::check_item_well_formed(tcx, def_id); -} +pub(super) use wfcheck::check_item_well_formed; -pub(super) fn check_trait_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { - wfcheck::check_trait_item(tcx, def_id); -} +pub(super) use wfcheck::check_trait_item as check_trait_item_well_formed; -pub(super) fn check_impl_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { - wfcheck::check_impl_item(tcx, def_id); -} +pub(super) use wfcheck::check_impl_item as check_impl_item_well_formed; -fn async_opaque_type_cycle_error(tcx: TyCtxt<'tcx>, span: Span) { +fn async_opaque_type_cycle_error(tcx: TyCtxt<'_>, span: Span) { struct_span_err!(tcx.sess, span, E0733, "recursion in an `async fn` requires boxing") .span_label(span, "recursive `async fn`") .note("a recursive `async fn` must be rewritten to return a boxed `dyn Future`") @@ -1536,7 +1530,7 @@ fn async_opaque_type_cycle_error(tcx: TyCtxt<'tcx>, span: Span) { /// /// If all the return expressions evaluate to `!`, then we explain that the error will go away /// after changing it. This can happen when a user uses `panic!()` or similar as a placeholder. -fn opaque_type_cycle_error(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span) { +fn opaque_type_cycle_error(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) { let mut err = struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type"); let mut label = false; diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index 4a41552a5f..c87ab0d410 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -80,7 +80,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let generator_types = check_fn( self, - self.param_env, + self.param_env.without_const(), liberated_sig, decl, expr.hir_id, diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 77f7cccc04..6192c77d6c 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -102,7 +102,7 @@ fn identity(_: Ty<'_>) -> Vec> { vec![] } -fn simple(kind: Adjust<'tcx>) -> impl FnOnce(Ty<'tcx>) -> Vec> { +fn simple<'tcx>(kind: Adjust<'tcx>) -> impl FnOnce(Ty<'tcx>) -> Vec> { move |target| vec![Adjustment { kind, target }] } @@ -1126,8 +1126,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for expr in exprs { let expr = expr.as_coercion_site(); let noop = match self.typeck_results.borrow().expr_adjustments(expr) { - &[Adjustment { kind: Adjust::Deref(_), .. }, Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl_adj)), .. }] => - { + &[ + Adjustment { kind: Adjust::Deref(_), .. }, + Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl_adj)), .. }, + ] => { match *self.node_ty(expr.hir_id).kind() { ty::Ref(_, _, mt_orig) => { let mutbl_adj: hir::Mutability = mutbl_adj.into(); @@ -1442,7 +1444,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { let mut err; let mut unsized_return = false; - match cause.code { + match *cause.code() { ObligationCauseCode::ReturnNoExpression => { err = struct_span_err!( fcx.tcx.sess, @@ -1637,11 +1639,10 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { let ty = >::ast_ty_to_ty(fcx, ty); // Get the `impl Trait`'s `DefId`. if let ty::Opaque(def_id, _) = ty.kind() { - let hir_id = fcx.tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); // Get the `impl Trait`'s `Item` so that we can get its trait bounds and // get the `Trait`'s `DefId`. if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }) = - fcx.tcx.hir().expect_item(hir_id).kind + fcx.tcx.hir().expect_item(def_id.expect_local()).kind { // Are of this `impl Trait`'s traits object safe? is_object_safe = bounds.iter().all(|bound| { @@ -1693,7 +1694,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { err.help("you could instead create a new `enum` with a variant for each returned type"); } - fn is_return_ty_unsized(&self, fcx: &FnCtxt<'a, 'tcx>, blk_id: hir::HirId) -> bool { + fn is_return_ty_unsized<'a>(&self, fcx: &FnCtxt<'a, 'tcx>, blk_id: hir::HirId) -> bool { if let Some((fn_decl, _)) = fcx.get_fn_decl(blk_id) { if let hir::FnRetTy::Return(ty) = fn_decl.output { let ty = >::ast_ty_to_ty(fcx, ty); diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index fdc5d16acc..c942bafcf0 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -208,8 +208,11 @@ fn compare_predicate_entailment<'tcx>( // The key step here is to update the caller_bounds's predicates to be // the new hybrid bounds we computed. let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_hir_id); - let param_env = - ty::ParamEnv::new(tcx.intern_predicates(&hybrid_preds.predicates), Reveal::UserFacing); + let param_env = ty::ParamEnv::new( + tcx.intern_predicates(&hybrid_preds.predicates), + Reveal::UserFacing, + hir::Constness::NotConst, + ); let param_env = traits::normalize_param_env_or_error(tcx, impl_m.def_id, param_env, normalize_cause); @@ -229,7 +232,7 @@ fn compare_predicate_entailment<'tcx>( inh.register_predicates(obligations); let mut cause = cause.clone(); - cause.make_mut().span = span; + cause.span = span; inh.register_predicate(traits::Obligation::new(cause, param_env, predicate)); } @@ -290,7 +293,7 @@ fn compare_predicate_entailment<'tcx>( let (impl_err_span, trait_err_span) = extract_spans_for_error_reporting(&infcx, &terr, &cause, impl_m, trait_m); - cause.make_mut().span = impl_err_span; + cause.span = impl_err_span; let mut diag = struct_span_err!( tcx.sess, @@ -317,9 +320,7 @@ fn compare_predicate_entailment<'tcx>( // When the `impl` receiver is an arbitrary self type, like `self: Box`, the // span points only at the type `Box, but we want to cover the whole // argument pattern and type. - let impl_m_hir_id = - tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local()); - let span = match tcx.hir().expect_impl_item(impl_m_hir_id).kind { + let span = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind { ImplItemKind::Fn(ref sig, body) => tcx .hir() .body_param_names(body) @@ -341,9 +342,7 @@ fn compare_predicate_entailment<'tcx>( if trait_sig.inputs().len() == *i { // Suggestion to change output type. We do not suggest in `async` functions // to avoid complex logic or incorrect output. - let impl_m_hir_id = - tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local()); - match tcx.hir().expect_impl_item(impl_m_hir_id).kind { + match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind { ImplItemKind::Fn(ref sig, _) if sig.header.asyncness == hir::IsAsync::NotAsync => { @@ -383,6 +382,7 @@ fn compare_predicate_entailment<'tcx>( found: impl_fty, })), &terr, + false, ); diag.emit(); return Err(ErrorReported); @@ -462,22 +462,19 @@ fn extract_spans_for_error_reporting<'a, 'tcx>( trait_m: &ty::AssocItem, ) -> (Span, Option) { let tcx = infcx.tcx; - let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local()); - let mut impl_args = match tcx.hir().expect_impl_item(impl_m_hir_id).kind { + let mut impl_args = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind { ImplItemKind::Fn(ref sig, _) => { sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span())) } _ => bug!("{:?} is not a method", impl_m), }; - let trait_args = trait_m.def_id.as_local().map(|def_id| { - let trait_m_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - match tcx.hir().expect_trait_item(trait_m_hir_id).kind { + let trait_args = + trait_m.def_id.as_local().map(|def_id| match tcx.hir().expect_trait_item(def_id).kind { TraitItemKind::Fn(ref sig, _) => { sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span())) } _ => bug!("{:?} is not a TraitItemKind::Fn", trait_m), - } - }); + }); match *terr { TypeError::ArgumentMutability(i) => { @@ -595,8 +592,7 @@ fn compare_number_of_generics<'tcx>( err_occurred = true; let (trait_spans, impl_trait_spans) = if let Some(def_id) = trait_.def_id.as_local() { - let trait_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let trait_item = tcx.hir().expect_trait_item(trait_hir_id); + let trait_item = tcx.hir().expect_trait_item(def_id); if trait_item.generics.params.is_empty() { (Some(vec![trait_item.generics.span]), vec![]) } else { @@ -617,8 +613,7 @@ fn compare_number_of_generics<'tcx>( (trait_span.map(|s| vec![s]), vec![]) }; - let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_.def_id.expect_local()); - let impl_item = tcx.hir().expect_impl_item(impl_hir_id); + let impl_item = tcx.hir().expect_impl_item(impl_.def_id.expect_local()); let impl_item_impl_trait_spans: Vec = impl_item .generics .params @@ -706,8 +701,7 @@ fn compare_number_of_method_arguments<'tcx>( let impl_number_args = impl_m_fty.inputs().skip_binder().len(); if trait_number_args != impl_number_args { let trait_span = if let Some(def_id) = trait_m.def_id.as_local() { - let trait_id = tcx.hir().local_def_id_to_hir_id(def_id); - match tcx.hir().expect_trait_item(trait_id).kind { + match tcx.hir().expect_trait_item(def_id).kind { TraitItemKind::Fn(ref trait_m_sig, _) => { let pos = if trait_number_args > 0 { trait_number_args - 1 } else { 0 }; if let Some(arg) = trait_m_sig.decl.inputs.get(pos) { @@ -725,8 +719,7 @@ fn compare_number_of_method_arguments<'tcx>( } else { trait_item_span }; - let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local()); - let impl_span = match tcx.hir().expect_impl_item(impl_m_hir_id).kind { + let impl_span = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind { ImplItemKind::Fn(ref impl_m_sig, _) => { let pos = if impl_number_args > 0 { impl_number_args - 1 } else { 0 }; if let Some(arg) = impl_m_sig.decl.inputs.get(pos) { @@ -745,8 +738,7 @@ fn compare_number_of_method_arguments<'tcx>( tcx.sess, impl_span, E0050, - "method `{}` has {} but the declaration in \ - trait `{}` has {}", + "method `{}` has {} but the declaration in trait `{}` has {}", trait_m.ident, potentially_plural_count(impl_number_args, "parameter"), tcx.def_path_str(trait_m.def_id), @@ -1050,8 +1042,8 @@ crate fn compare_const_impl<'tcx>( ); // Locate the Span containing just the type of the offending impl - match tcx.hir().expect_impl_item(impl_c_hir_id).kind { - ImplItemKind::Const(ref ty, _) => cause.make_mut().span = ty.span, + match tcx.hir().expect_impl_item(impl_c.def_id.expect_local()).kind { + ImplItemKind::Const(ref ty, _) => cause.span = ty.span, _ => bug!("{:?} is not a impl const", impl_c), } @@ -1063,11 +1055,9 @@ crate fn compare_const_impl<'tcx>( trait_c.ident ); - let trait_c_hir_id = - trait_c.def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)); - let trait_c_span = trait_c_hir_id.map(|trait_c_hir_id| { + let trait_c_span = trait_c.def_id.as_local().map(|trait_c_def_id| { // Add a label to the Span containing just the type of the const - match tcx.hir().expect_trait_item(trait_c_hir_id).kind { + match tcx.hir().expect_trait_item(trait_c_def_id).kind { TraitItemKind::Const(ref ty, _) => ty.span, _ => bug!("{:?} is not a trait const", trait_c), } @@ -1082,6 +1072,7 @@ crate fn compare_const_impl<'tcx>( found: impl_ty, })), &terr, + false, ); diag.emit(); } @@ -1112,7 +1103,8 @@ crate fn compare_ty_impl<'tcx>( let _: Result<(), ErrorReported> = (|| { compare_number_of_generics(tcx, impl_ty, impl_ty_span, trait_ty, trait_item_span)?; - compare_type_predicate_entailment(tcx, impl_ty, impl_ty_span, trait_ty, impl_trait_ref)?; + let sp = tcx.def_span(impl_ty.def_id); + compare_type_predicate_entailment(tcx, impl_ty, sp, trait_ty, impl_trait_ref)?; check_type_bounds(tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref) })(); @@ -1178,8 +1170,11 @@ fn compare_type_predicate_entailment<'tcx>( debug!("compare_type_predicate_entailment: bounds={:?}", hybrid_preds); let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id); - let param_env = - ty::ParamEnv::new(tcx.intern_predicates(&hybrid_preds.predicates), Reveal::UserFacing); + let param_env = ty::ParamEnv::new( + tcx.intern_predicates(&hybrid_preds.predicates), + Reveal::UserFacing, + hir::Constness::NotConst, + ); let param_env = traits::normalize_param_env_or_error( tcx, impl_ty.def_id, @@ -1364,7 +1359,11 @@ pub fn check_type_bounds<'tcx>( .to_predicate(tcx), ), }; - ty::ParamEnv::new(tcx.intern_predicates(&predicates), Reveal::UserFacing) + ty::ParamEnv::new( + tcx.intern_predicates(&predicates), + Reveal::UserFacing, + param_env.constness(), + ) }; debug!(?normalize_param_env); @@ -1373,13 +1372,7 @@ pub fn check_type_bounds<'tcx>( impl_ty_substs.rebase_onto(tcx, impl_ty.container.id(), impl_trait_ref.substs); tcx.infer_ctxt().enter(move |infcx| { - let constness = impl_ty - .container - .impl_def_id() - .map(|did| tcx.impl_constness(did)) - .unwrap_or(hir::Constness::NotConst); - - let inh = Inherited::with_constness(infcx, impl_ty.def_id.expect_local(), constness); + let inh = Inherited::new(infcx, impl_ty.def_id.expect_local()); let infcx = &inh.infcx; let mut selcx = traits::SelectionContext::new(&infcx); @@ -1423,8 +1416,7 @@ pub fn check_type_bounds<'tcx>( // Check that all obligations are satisfied by the implementation's // version. - let errors = - inh.fulfillment_cx.borrow_mut().select_all_with_constness_or_error(&infcx, constness); + let errors = inh.fulfillment_cx.borrow_mut().select_all_or_error(&infcx); if !errors.is_empty() { infcx.report_fulfillment_errors(&errors, None, false); return Err(ErrorReported); diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 12cd7ad184..b7e276b696 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -1223,7 +1223,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Missing try_into implementation for `{integer}` to `{float}` err.multipart_suggestion_verbose( &format!( - "{}, producing the floating point representation of the integer, + "{}, producing the floating point representation of the integer, \ rounded if necessary", cast_msg, ), @@ -1264,6 +1264,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } true } + ( + &ty::Uint(ty::UintTy::U32 | ty::UintTy::U64 | ty::UintTy::U128) + | &ty::Int(ty::IntTy::I32 | ty::IntTy::I64 | ty::IntTy::I128), + &ty::Char, + ) => { + err.multipart_suggestion_verbose( + &format!("{}, since a `char` always occupies 4 bytes", cast_msg,), + cast_suggestion, + Applicability::MachineApplicable, + ); + true + } _ => false, } } diff --git a/compiler/rustc_typeck/src/check/dropck.rs b/compiler/rustc_typeck/src/check/dropck.rs index 4b4d29307f..3cc66aaf0d 100644 --- a/compiler/rustc_typeck/src/check/dropck.rs +++ b/compiler/rustc_typeck/src/check/dropck.rs @@ -302,7 +302,7 @@ impl<'tcx> SimpleEqRelation<'tcx> { } } -impl TypeRelation<'tcx> for SimpleEqRelation<'tcx> { +impl<'tcx> TypeRelation<'tcx> for SimpleEqRelation<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index eb997b014c..621938c9b7 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -36,8 +36,8 @@ use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::InferOk; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase}; +use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::error::TypeError::{FieldMisMatch, Sorts}; -use rustc_middle::ty::relate::expected_found_bool; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, AdtKind, Ty, TypeFoldable}; use rustc_session::parse::feature_err; @@ -46,6 +46,7 @@ use rustc_span::hygiene::DesugaringKind; use rustc_span::lev_distance::find_best_match_for_name; use rustc_span::source_map::Span; use rustc_span::symbol::{kw, sym, Ident, Symbol}; +use rustc_span::{BytePos, Pos}; use rustc_trait_selection::traits::{self, ObligationCauseCode}; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -276,8 +277,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ExprKind::AddrOf(kind, mutbl, oprnd) => { self.check_expr_addr_of(kind, mutbl, oprnd, expected, expr) } - ExprKind::Path(QPath::LangItem(lang_item, _)) => { - self.check_lang_item_path(lang_item, expr) + ExprKind::Path(QPath::LangItem(lang_item, _, hir_id)) => { + self.check_lang_item_path(lang_item, expr, hir_id) } ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, &[]), ExprKind::InlineAsm(asm) => self.check_expr_asm(asm), @@ -299,7 +300,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } ExprKind::Ret(ref expr_opt) => self.check_expr_return(expr_opt.as_deref(), expr), - ExprKind::Let(pat, let_expr, _) => self.check_expr_let(let_expr, pat), + ExprKind::Let(let_expr) => self.check_expr_let(let_expr), ExprKind::Loop(body, _, source, _) => { self.check_expr_loop(body, source, expected, expr) } @@ -497,8 +498,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, lang_item: hir::LangItem, expr: &'tcx hir::Expr<'tcx>, + hir_id: Option, ) -> Ty<'tcx> { - self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id).1 + self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id, hir_id).1 } pub(crate) fn check_expr_path( @@ -876,11 +878,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "let ".to_string(), Applicability::MachineApplicable, ); - if !self.sess().features_untracked().destructuring_assignment { - // We already emit an E0658 with a suggestion for `while let`, this is - // redundant output. - err.delay_as_bug(); - } break; } hir::Node::Item(_) @@ -1047,10 +1044,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn check_expr_let(&self, expr: &'tcx hir::Expr<'tcx>, pat: &'tcx hir::Pat<'tcx>) -> Ty<'tcx> { - self.warn_if_unreachable(expr.hir_id, expr.span, "block in `let` expression"); - let expr_ty = self.demand_scrutinee_type(expr, pat.contains_explicit_ref_binding(), false); - self.check_pat_top(pat, expr_ty, Some(expr.span), true); + fn check_expr_let(&self, let_expr: &'tcx hir::Let<'tcx>) -> Ty<'tcx> { + // for let statements, this is done in check_stmt + let init = let_expr.init; + self.warn_if_unreachable(init.hir_id, init.span, "block in `let` expression"); + // otherwise check exactly as a let statement + self.check_decl(let_expr.into()); + // but return a bool, for this is a boolean expression self.tcx.types.bool } @@ -1238,12 +1238,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_expr_repeat( &self, element: &'tcx hir::Expr<'tcx>, - count: &'tcx hir::AnonConst, + count: &'tcx hir::ArrayLen, expected: Expectation<'tcx>, _expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { let tcx = self.tcx; - let count = self.to_const(count); + let count = self.array_length_to_const(count); let uty = match expected { ExpectHasType(uty) => match *uty.kind() { @@ -1493,7 +1493,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self.misc(base_expr.span), adt_ty, base_ty, - Sorts(expected_found_bool(true, adt_ty, base_ty)), + Sorts(ExpectedFound::new(true, adt_ty, base_ty)), ) .emit(); } @@ -1508,7 +1508,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } else { self.check_expr_has_type_or_error(base_expr, adt_ty, |_| { - let base_ty = self.check_expr(base_expr); + let base_ty = self.typeck_results.borrow().node_type(base_expr.hir_id); let same_adt = match (adt_ty.kind(), base_ty.kind()) { (ty::Adt(adt, _), ty::Adt(base_adt, _)) if adt == base_adt => true, _ => false, @@ -2063,7 +2063,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(span), ); } else { - err.help("methods are immutable and cannot be assigned to"); + let mut found = false; + + if let ty::RawPtr(ty_and_mut) = expr_t.kind() { + if let ty::Adt(adt_def, _) = ty_and_mut.ty.kind() { + if adt_def.variants.len() == 1 + && adt_def + .variants + .iter() + .next() + .unwrap() + .fields + .iter() + .any(|f| f.ident == field) + { + if let Some(dot_loc) = expr_snippet.rfind('.') { + found = true; + err.span_suggestion( + expr.span.with_hi(expr.span.lo() + BytePos::from_usize(dot_loc)), + "to access the field, dereference first", + format!("(*{})", &expr_snippet[0..dot_loc]), + Applicability::MaybeIncorrect, + ); + } + } + } + } + + if !found { + err.help("methods are immutable and cannot be assigned to"); + } } err.emit(); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 142a0a8fc2..1aca291153 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -6,7 +6,6 @@ use crate::check::callee::{self, DeferredCallResolution}; use crate::check::method::{self, MethodCallee, SelfSource}; use crate::check::{BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy}; -use rustc_ast::TraitObjectSyntax; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, DiagnosticBuilder, ErrorReported}; @@ -14,7 +13,7 @@ use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; -use rustc_hir::{ExprKind, GenericArg, Node, QPath, TyKind}; +use rustc_hir::{ExprKind, GenericArg, Node, QPath}; use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc_infer::infer::{InferOk, InferResult}; @@ -28,8 +27,6 @@ use rustc_middle::ty::{ Ty, UserType, }; use rustc_session::lint; -use rustc_session::lint::builtin::BARE_TRAIT_OBJECTS; -use rustc_span::edition::Edition; use rustc_span::hygiene::DesugaringKind; use rustc_span::source_map::{original_sp, DUMMY_SP}; use rustc_span::symbol::{kw, sym, Ident}; @@ -304,20 +301,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // is a valid NeverToAny adjustment, because it can't // be reached. (&[Adjustment { kind: Adjust::NeverToAny, .. }], _) => return, - (&[ - Adjustment { kind: Adjust::Deref(_), .. }, - Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), .. }, - ], &[ - Adjustment { kind: Adjust::Deref(_), .. }, - .. // Any following adjustments are allowed. - ]) => { + ( + &[ + Adjustment { kind: Adjust::Deref(_), .. }, + Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), .. }, + ], + &[ + Adjustment { kind: Adjust::Deref(_), .. }, + .., // Any following adjustments are allowed. + ], + ) => { // A reborrow has no effect before a dereference. } // FIXME: currently we never try to compose autoderefs // and ReifyFnPointer/UnsafeFnPointer, but we could. - _ => - bug!("while adjusting {:?}, can't compose {:?} and {:?}", - expr, entry.get(), adj) + _ => bug!( + "while adjusting {:?}, can't compose {:?} and {:?}", + expr, + entry.get(), + adj + ), }; *entry.get_mut() = adj; } @@ -495,6 +498,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty } + pub fn array_length_to_const(&self, length: &hir::ArrayLen) -> &'tcx ty::Const<'tcx> { + match length { + &hir::ArrayLen::Infer(_, span) => self.ct_infer(self.tcx.types.usize, None, span), + hir::ArrayLen::Body(anon_const) => self.to_const(anon_const), + } + } + pub fn to_const(&self, ast_c: &hir::AnonConst) -> &'tcx ty::Const<'tcx> { let const_def_id = self.tcx.hir().local_def_id(ast_c.hir_id); let c = ty::Const::from_anon_const(self.tcx, const_def_id); @@ -610,10 +620,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { #[instrument(skip(self), level = "debug")] pub(in super::super) fn select_all_obligations_or_error(&self) { - let errors = self - .fulfillment_cx - .borrow_mut() - .select_all_with_constness_or_error(&self, self.inh.constness); + let errors = self.fulfillment_cx.borrow_mut().select_all_or_error(&self); if !errors.is_empty() { self.report_fulfillment_errors(&errors, self.inh.body_id, false); @@ -626,10 +633,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fallback_has_occurred: bool, mutate_fulfillment_errors: impl Fn(&mut Vec>), ) { - let mut result = self - .fulfillment_cx - .borrow_mut() - .select_with_constness_where_possible(self, self.inh.constness); + let mut result = self.fulfillment_cx.borrow_mut().select_where_possible(self); if !result.is_empty() { mutate_fulfillment_errors(&mut result); self.report_fulfillment_errors(&result, self.inh.body_id, fallback_has_occurred); @@ -791,6 +795,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { lang_item: hir::LangItem, span: Span, hir_id: hir::HirId, + expr_hir_id: Option, ) -> (Res, Ty<'tcx>) { let def_id = self.tcx.require_lang_item(lang_item, Some(span)); let def_kind = self.tcx.def_kind(def_id); @@ -804,7 +809,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = item_ty.subst(self.tcx, substs); self.write_resolution(hir_id, Ok((def_kind, def_id))); - self.add_required_obligations(span, def_id, &substs); + self.add_required_obligations_with_code( + span, + def_id, + &substs, + match lang_item { + hir::LangItem::IntoFutureIntoFuture => { + ObligationCauseCode::AwaitableExpr(expr_hir_id) + } + hir::LangItem::IteratorNext | hir::LangItem::IntoIterIntoIter => { + ObligationCauseCode::ForLoopIterator + } + hir::LangItem::TryTraitFromOutput + | hir::LangItem::TryTraitFromResidual + | hir::LangItem::TryTraitBranch => ObligationCauseCode::QuestionMark, + _ => traits::ItemObligation(def_id), + }, + ); (Res::Def(def_kind, def_id), ty) } @@ -838,7 +859,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // to be object-safe. // We manually call `register_wf_obligation` in the success path // below. - (>::ast_ty_to_ty(self, qself), qself, segment) + (>::ast_ty_to_ty_in_path(self, qself), qself, segment) } QPath::LangItem(..) => { bug!("`resolve_ty_and_res_fully_qualified_call` called on `LangItem`") @@ -884,7 +905,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); if result.is_ok() { - self.maybe_lint_bare_trait(qpath, hir_id, span); self.register_wf_obligation(ty.into(), qself.span, traits::WellFormed(None)); } @@ -897,56 +917,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) } - fn maybe_lint_bare_trait(&self, qpath: &QPath<'_>, hir_id: hir::HirId, span: Span) { - if let QPath::TypeRelative(self_ty, _) = qpath { - if let TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = - self_ty.kind - { - let msg = "trait objects without an explicit `dyn` are deprecated"; - let (sugg, app) = match self.tcx.sess.source_map().span_to_snippet(self_ty.span) { - Ok(s) if poly_trait_ref.trait_ref.path.is_global() => { - (format!("dyn ({})", s), Applicability::MachineApplicable) - } - Ok(s) => (format!("dyn {}", s), Applicability::MachineApplicable), - Err(_) => ("dyn ".to_string(), Applicability::HasPlaceholders), - }; - // Wrap in `<..>` if it isn't already. - let sugg = match self.tcx.sess.source_map().span_to_snippet(span) { - Ok(s) if s.starts_with('<') => sugg, - _ => format!("<{}>", sugg), - }; - let sugg_label = "use `dyn`"; - if self.sess().edition() >= Edition::Edition2021 { - let mut err = rustc_errors::struct_span_err!( - self.sess(), - self_ty.span, - E0782, - "{}", - msg, - ); - err.span_suggestion( - self_ty.span, - sugg_label, - sugg, - Applicability::MachineApplicable, - ) - .emit(); - } else { - self.tcx.struct_span_lint_hir( - BARE_TRAIT_OBJECTS, - hir_id, - self_ty.span, - |lint| { - let mut db = lint.build(msg); - db.span_suggestion(self_ty.span, sugg_label, sugg, app); - db.emit() - }, - ); - } - } - } - } - /// Given a function `Node`, return its `FnDecl` if it exists, or `None` otherwise. pub(in super::super) fn get_node_fn_decl( &self, @@ -1097,12 +1067,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (_, _) => return None, }; - let last_hir_id = self.tcx.hir().local_def_id_to_hir_id(last_local_id); - let exp_hir_id = self.tcx.hir().local_def_id_to_hir_id(exp_local_id); - match ( - &self.tcx.hir().expect_item(last_hir_id).kind, - &self.tcx.hir().expect_item(exp_hir_id).kind, + &self.tcx.hir().expect_item(last_local_id).kind, + &self.tcx.hir().expect_item(exp_local_id).kind, ) { ( hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: last_bounds, .. }), @@ -1433,7 +1400,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { >::create_substs_for_generic_args( tcx, def_id, - &[][..], + &[], has_self, self_ty, &arg_count, @@ -1489,12 +1456,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Add all the obligations that are required, substituting and normalized appropriately. - #[tracing::instrument(level = "debug", skip(self, span, def_id, substs))] crate fn add_required_obligations(&self, span: Span, def_id: DefId, substs: &SubstsRef<'tcx>) { + self.add_required_obligations_with_code( + span, + def_id, + substs, + traits::ItemObligation(def_id), + ) + } + + #[tracing::instrument(level = "debug", skip(self, span, def_id, substs))] + fn add_required_obligations_with_code( + &self, + span: Span, + def_id: DefId, + substs: &SubstsRef<'tcx>, + code: ObligationCauseCode<'tcx>, + ) { let (bounds, _) = self.instantiate_bounds(span, def_id, &substs); for obligation in traits::predicates_for_generics( - traits::ObligationCause::new(span, self.body_id, traits::ItemObligation(def_id)), + traits::ObligationCause::new(span, self.body_id, code), self.param_env, bounds, ) { diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index 74d7f0a80b..e796fe5817 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -1,5 +1,6 @@ use crate::astconv::AstConv; use crate::check::coercion::CoerceMany; +use crate::check::gather_locals::Declaration; use crate::check::method::MethodCallee; use crate::check::Expectation::*; use crate::check::TupleArgumentsFlag::*; @@ -54,14 +55,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let err_inputs = match tuple_arguments { DontTupleArguments => err_inputs, - TupleArguments => vec![self.tcx.intern_tup(&err_inputs[..])], + TupleArguments => vec![self.tcx.intern_tup(&err_inputs)], }; self.check_argument_types( sp, expr, - &err_inputs[..], - &[], + &err_inputs, + vec![], args_no_rcvr, false, tuple_arguments, @@ -72,7 +73,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let method = method.unwrap(); // HACK(eddyb) ignore self in the definition (see above). - let expected_arg_tys = self.expected_inputs_for_expected_output( + let expected_input_tys = self.expected_inputs_for_expected_output( sp, expected, method.sig.output(), @@ -82,7 +83,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sp, expr, &method.sig.inputs()[1..], - &expected_arg_tys[..], + expected_input_tys, args_no_rcvr, method.sig.c_variadic, tuple_arguments, @@ -95,34 +96,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// method calls and overloaded operators. pub(in super::super) fn check_argument_types( &self, - sp: Span, - expr: &'tcx hir::Expr<'tcx>, - fn_inputs: &[Ty<'tcx>], - expected_arg_tys: &[Ty<'tcx>], - args: &'tcx [hir::Expr<'tcx>], + // Span enclosing the call site + call_span: Span, + // Expression of the call site + call_expr: &'tcx hir::Expr<'tcx>, + // Types (as defined in the *signature* of the target function) + formal_input_tys: &[Ty<'tcx>], + // More specific expected types, after unifying with caller output types + expected_input_tys: Vec>, + // The expressions for each provided argument + provided_args: &'tcx [hir::Expr<'tcx>], + // Whether the function is variadic, for example when imported from C c_variadic: bool, + // Whether the arguments have been bundled in a tuple (ex: closures) tuple_arguments: TupleArgumentsFlag, - def_id: Option, + // The DefId for the function being called, for better error messages + fn_def_id: Option, ) { let tcx = self.tcx; // Grab the argument types, supplying fresh type variables // if the wrong number of arguments were supplied - let supplied_arg_count = if tuple_arguments == DontTupleArguments { args.len() } else { 1 }; + let supplied_arg_count = + if tuple_arguments == DontTupleArguments { provided_args.len() } else { 1 }; // All the input types from the fn signature must outlive the call // so as to validate implied bounds. - for (&fn_input_ty, arg_expr) in iter::zip(fn_inputs, args) { + for (&fn_input_ty, arg_expr) in iter::zip(formal_input_tys, provided_args) { self.register_wf_obligation(fn_input_ty.into(), arg_expr.span, traits::MiscObligation); } - let expected_arg_count = fn_inputs.len(); + let expected_arg_count = formal_input_tys.len(); let param_count_error = |expected_count: usize, arg_count: usize, error_code: &str, c_variadic: bool, sugg_unit: bool| { - let (span, start_span, args, ctor_of) = match &expr.kind { + let (span, start_span, args, ctor_of) = match &call_expr.kind { hir::ExprKind::Call( hir::Expr { span, @@ -155,14 +165,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &args[1..], // Skip the receiver. None, // methods are never ctors ), - k => span_bug!(sp, "checking argument types on a non-call: `{:?}`", k), + k => span_bug!(call_span, "checking argument types on a non-call: `{:?}`", k), }; - let arg_spans = if args.is_empty() { + let arg_spans = if provided_args.is_empty() { // foo() // ^^^-- supplied 0 arguments // | // expected 2 arguments - vec![tcx.sess.source_map().next_point(start_span).with_hi(sp.hi())] + vec![tcx.sess.source_map().next_point(start_span).with_hi(call_span.hi())] } else { // foo(1, 2, 3) // ^^^ - - - supplied 3 arguments @@ -195,7 +205,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - if let Some(def_id) = def_id { + if let Some(def_id) = fn_def_id { if let Some(def_span) = tcx.def_ident_span(def_id) { let mut spans: MultiSpan = def_span.into(); @@ -217,7 +227,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if sugg_unit { - let sugg_span = tcx.sess.source_map().end_point(expr.span); + let sugg_span = tcx.sess.source_map().end_point(call_expr.span); // remove closing `)` from the span let sugg_span = sugg_span.shrink_to_lo(); err.span_suggestion( @@ -239,110 +249,148 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.emit(); }; - let mut expected_arg_tys = expected_arg_tys.to_vec(); - - let formal_tys = if tuple_arguments == TupleArguments { - let tuple_type = self.structurally_resolved_type(sp, fn_inputs[0]); + let (formal_input_tys, expected_input_tys) = if tuple_arguments == TupleArguments { + let tuple_type = self.structurally_resolved_type(call_span, formal_input_tys[0]); match tuple_type.kind() { - ty::Tuple(arg_types) if arg_types.len() != args.len() => { - param_count_error(arg_types.len(), args.len(), "E0057", false, false); - expected_arg_tys = vec![]; - self.err_args(args.len()) + ty::Tuple(arg_types) if arg_types.len() != provided_args.len() => { + param_count_error(arg_types.len(), provided_args.len(), "E0057", false, false); + (self.err_args(provided_args.len()), vec![]) } ty::Tuple(arg_types) => { - expected_arg_tys = match expected_arg_tys.get(0) { + let expected_input_tys = match expected_input_tys.get(0) { Some(&ty) => match ty.kind() { ty::Tuple(ref tys) => tys.iter().map(|k| k.expect_ty()).collect(), _ => vec![], }, None => vec![], }; - arg_types.iter().map(|k| k.expect_ty()).collect() + (arg_types.iter().map(|k| k.expect_ty()).collect(), expected_input_tys) } _ => { struct_span_err!( tcx.sess, - sp, + call_span, E0059, "cannot use call notation; the first type parameter \ for the function trait is neither a tuple nor unit" ) .emit(); - expected_arg_tys = vec![]; - self.err_args(args.len()) + (self.err_args(provided_args.len()), vec![]) } } } else if expected_arg_count == supplied_arg_count { - fn_inputs.to_vec() + (formal_input_tys.to_vec(), expected_input_tys) } else if c_variadic { if supplied_arg_count >= expected_arg_count { - fn_inputs.to_vec() + (formal_input_tys.to_vec(), expected_input_tys) } else { param_count_error(expected_arg_count, supplied_arg_count, "E0060", true, false); - expected_arg_tys = vec![]; - self.err_args(supplied_arg_count) + (self.err_args(supplied_arg_count), vec![]) } } else { // is the missing argument of type `()`? - let sugg_unit = if expected_arg_tys.len() == 1 && supplied_arg_count == 0 { - self.resolve_vars_if_possible(expected_arg_tys[0]).is_unit() - } else if fn_inputs.len() == 1 && supplied_arg_count == 0 { - self.resolve_vars_if_possible(fn_inputs[0]).is_unit() + let sugg_unit = if expected_input_tys.len() == 1 && supplied_arg_count == 0 { + self.resolve_vars_if_possible(expected_input_tys[0]).is_unit() + } else if formal_input_tys.len() == 1 && supplied_arg_count == 0 { + self.resolve_vars_if_possible(formal_input_tys[0]).is_unit() } else { false }; param_count_error(expected_arg_count, supplied_arg_count, "E0061", false, sugg_unit); - expected_arg_tys = vec![]; - self.err_args(supplied_arg_count) + (self.err_args(supplied_arg_count), vec![]) }; debug!( - "check_argument_types: formal_tys={:?}", - formal_tys.iter().map(|t| self.ty_to_string(*t)).collect::>() + "check_argument_types: formal_input_tys={:?}", + formal_input_tys.iter().map(|t| self.ty_to_string(*t)).collect::>() ); - // If there is no expectation, expect formal_tys. - let expected_arg_tys = - if !expected_arg_tys.is_empty() { expected_arg_tys } else { formal_tys.clone() }; + // If there is no expectation, expect formal_input_tys. + let expected_input_tys = if !expected_input_tys.is_empty() { + expected_input_tys + } else { + formal_input_tys.clone() + }; + assert_eq!(expected_input_tys.len(), formal_input_tys.len()); + + // Keep track of the fully coerced argument types let mut final_arg_types: Vec<(usize, Ty<'_>, Ty<'_>)> = vec![]; + // We introduce a helper function to demand that a given argument satisfy a given input + // This is more complicated than just checking type equality, as arguments could be coerced + // This version writes those types back so further type checking uses the narrowed types + let demand_compatible = |idx, final_arg_types: &mut Vec<(usize, Ty<'tcx>, Ty<'tcx>)>| { + let formal_input_ty: Ty<'tcx> = formal_input_tys[idx]; + let expected_input_ty: Ty<'tcx> = expected_input_tys[idx]; + let provided_arg = &provided_args[idx]; + + debug!("checking argument {}: {:?} = {:?}", idx, provided_arg, formal_input_ty); + + // The special-cased logic below has three functions: + // 1. Provide as good of an expected type as possible. + let expectation = Expectation::rvalue_hint(self, expected_input_ty); + + let checked_ty = self.check_expr_with_expectation(provided_arg, expectation); + + // 2. Coerce to the most detailed type that could be coerced + // to, which is `expected_ty` if `rvalue_hint` returns an + // `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise. + let coerced_ty = expectation.only_has_type(self).unwrap_or(formal_input_ty); + + // Keep track of these for below + final_arg_types.push((idx, checked_ty, coerced_ty)); + + // Cause selection errors caused by resolving a single argument to point at the + // argument and not the call. This is otherwise redundant with the `demand_coerce` + // call immediately after, but it lets us customize the span pointed to in the + // fulfillment error to be more accurate. + let _ = + self.resolve_vars_with_obligations_and_mutate_fulfillment(coerced_ty, |errors| { + self.point_at_type_arg_instead_of_call_if_possible(errors, call_expr); + self.point_at_arg_instead_of_call_if_possible( + errors, + &final_arg_types, + call_expr, + call_span, + provided_args, + ); + }); + + // We're processing function arguments so we definitely want to use + // two-phase borrows. + self.demand_coerce(&provided_arg, checked_ty, coerced_ty, None, AllowTwoPhase::Yes); + + // 3. Relate the expected type and the formal one, + // if the expected type was used for the coercion. + self.demand_suptype(provided_arg.span, formal_input_ty, coerced_ty); + }; + // Check the arguments. // We do this in a pretty awful way: first we type-check any arguments // that are not closures, then we type-check the closures. This is so // that we have more information about the types of arguments when we // type-check the functions. This isn't really the right way to do this. for check_closures in [false, true] { - debug!("check_closures={}", check_closures); - // More awful hacks: before we check argument types, try to do // an "opportunistic" trait resolution of any trait bounds on // the call. This helps coercions. if check_closures { self.select_obligations_where_possible(false, |errors| { - self.point_at_type_arg_instead_of_call_if_possible(errors, expr); + self.point_at_type_arg_instead_of_call_if_possible(errors, call_expr); self.point_at_arg_instead_of_call_if_possible( errors, - &final_arg_types[..], - expr, - sp, - &args, + &final_arg_types, + call_expr, + call_span, + &provided_args, ); }) } - // For C-variadic functions, we don't have a declared type for all of - // the arguments hence we only do our usual type checking with - // the arguments who's types we do know. - let t = if c_variadic { - expected_arg_count - } else if tuple_arguments == TupleArguments { - args.len() - } else { - supplied_arg_count - }; - for (i, arg) in args.iter().take(t).enumerate() { + let minimum_input_count = formal_input_tys.len(); + for (idx, arg) in provided_args.iter().enumerate() { // Warn only for the first loop (the "no closures" one). // Closure arguments themselves can't be diverging, but // a previous argument can, e.g., `foo(panic!(), || {})`. @@ -350,53 +398,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.warn_if_unreachable(arg.hir_id, arg.span, "expression"); } - let is_closure = matches!(arg.kind, ExprKind::Closure(..)); + // For C-variadic functions, we don't have a declared type for all of + // the arguments hence we only do our usual type checking with + // the arguments who's types we do know. However, we *can* check + // for unreachable expressions (see above). + // FIXME: unreachable warning current isn't emitted + if idx >= minimum_input_count { + continue; + } + let is_closure = matches!(arg.kind, ExprKind::Closure(..)); if is_closure != check_closures { continue; } - let formal_ty = formal_tys[i]; - debug!("checking argument {}: {:?} = {:?}", i, arg, formal_ty); - - // The special-cased logic below has three functions: - // 1. Provide as good of an expected type as possible. - let expected = Expectation::rvalue_hint(self, expected_arg_tys[i]); - - let checked_ty = self.check_expr_with_expectation(&arg, expected); - - // 2. Coerce to the most detailed type that could be coerced - // to, which is `expected_ty` if `rvalue_hint` returns an - // `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise. - let coerce_ty = expected.only_has_type(self).unwrap_or(formal_ty); - - final_arg_types.push((i, checked_ty, coerce_ty)); - - // Cause selection errors caused by resolving a single argument to point at the - // argument and not the call. This is otherwise redundant with the `demand_coerce` - // call immediately after, but it lets us customize the span pointed to in the - // fulfillment error to be more accurate. - let _ = self.resolve_vars_with_obligations_and_mutate_fulfillment( - coerce_ty, - |errors| { - self.point_at_type_arg_instead_of_call_if_possible(errors, expr); - self.point_at_arg_instead_of_call_if_possible( - errors, - &final_arg_types, - expr, - sp, - args, - ); - }, - ); - - // We're processing function arguments so we definitely want to use - // two-phase borrows. - self.demand_coerce(&arg, checked_ty, coerce_ty, None, AllowTwoPhase::Yes); - - // 3. Relate the expected type and the formal one, - // if the expected type was used for the coercion. - self.demand_suptype(arg.span, formal_ty, coerce_ty); + demand_compatible(idx, &mut final_arg_types); } } @@ -409,7 +425,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit() } - for arg in args.iter().skip(expected_arg_count) { + for arg in provided_args.iter().skip(expected_arg_count) { let arg_ty = self.check_expr(&arg); // There are a few types which get autopromoted when passed via varargs @@ -538,16 +554,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn check_decl_initializer( &self, - local: &'tcx hir::Local<'tcx>, + hir_id: hir::HirId, + pat: &'tcx hir::Pat<'tcx>, init: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { // FIXME(tschottdorf): `contains_explicit_ref_binding()` must be removed // for #42640 (default match binding modes). // // See #44848. - let ref_bindings = local.pat.contains_explicit_ref_binding(); + let ref_bindings = pat.contains_explicit_ref_binding(); - let local_ty = self.local_ty(init.span, local.hir_id).revealed_ty; + let local_ty = self.local_ty(init.span, hir_id).revealed_ty; if let Some(m) = ref_bindings { // Somewhat subtle: if we have a `ref` binding in the pattern, // we want to avoid introducing coercions for the RHS. This is @@ -565,29 +582,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - /// Type check a `let` statement. - pub fn check_decl_local(&self, local: &'tcx hir::Local<'tcx>) { + pub(in super::super) fn check_decl(&self, decl: Declaration<'tcx>) { // Determine and write the type which we'll check the pattern against. - let ty = self.local_ty(local.span, local.hir_id).decl_ty; - self.write_ty(local.hir_id, ty); + let decl_ty = self.local_ty(decl.span, decl.hir_id).decl_ty; + self.write_ty(decl.hir_id, decl_ty); // Type check the initializer. - if let Some(ref init) = local.init { - let init_ty = self.check_decl_initializer(local, &init); - self.overwrite_local_ty_if_err(local, ty, init_ty); + if let Some(ref init) = decl.init { + let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, &init); + self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, decl_ty, init_ty); } // Does the expected pattern type originate from an expression and what is the span? - let (origin_expr, ty_span) = match (local.ty, local.init) { + let (origin_expr, ty_span) = match (decl.ty, decl.init) { (Some(ty), _) => (false, Some(ty.span)), // Bias towards the explicit user type. (_, Some(init)) => (true, Some(init.span)), // No explicit type; so use the scrutinee. _ => (false, None), // We have `let $pat;`, so the expected type is unconstrained. }; // Type check the pattern. Override if necessary to avoid knock-on errors. - self.check_pat_top(&local.pat, ty, ty_span, origin_expr); - let pat_ty = self.node_ty(local.pat.hir_id); - self.overwrite_local_ty_if_err(local, ty, pat_ty); + self.check_pat_top(&decl.pat, decl_ty, ty_span, origin_expr); + let pat_ty = self.node_ty(decl.pat.hir_id); + self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, decl_ty, pat_ty); + } + + /// Type check a `let` statement. + pub fn check_decl_local(&self, local: &'tcx hir::Local<'tcx>) { + self.check_decl(local.into()); } pub fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>, is_last: bool) { @@ -891,17 +912,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn overwrite_local_ty_if_err( &self, - local: &'tcx hir::Local<'tcx>, + hir_id: hir::HirId, + pat: &'tcx hir::Pat<'tcx>, decl_ty: Ty<'tcx>, ty: Ty<'tcx>, ) { if ty.references_error() { // Override the types everywhere with `err()` to avoid knock on errors. - self.write_ty(local.hir_id, ty); - self.write_ty(local.pat.hir_id, ty); + self.write_ty(hir_id, ty); + self.write_ty(pat.hir_id, ty); let local_ty = LocalTy { decl_ty, revealed_ty: ty }; - self.locals.borrow_mut().insert(local.hir_id, local_ty); - self.locals.borrow_mut().insert(local.pat.hir_id, local_ty); + self.locals.borrow_mut().insert(hir_id, local_ty); + self.locals.borrow_mut().insert(pat.hir_id, local_ty); } } @@ -938,8 +960,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty) } - QPath::LangItem(lang_item, span) => { - self.resolve_lang_item_path(lang_item, span, hir_id) + QPath::LangItem(lang_item, span, id) => { + self.resolve_lang_item_path(lang_item, span, hir_id, id) } } } @@ -990,7 +1012,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } result_code } - let self_: ty::subst::GenericArg<'_> = match &*unpeel_to_top(Lrc::new(error.obligation.cause.code.clone())) { + let self_: ty::subst::GenericArg<'_> = match &*unpeel_to_top(error.obligation.cause.clone_code()) { ObligationCauseCode::BuiltinDerivedObligation(code) | ObligationCauseCode::ImplDerivedObligation(code) | ObligationCauseCode::DerivedObligation(code) => { @@ -1033,18 +1055,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // We make sure that only *one* argument matches the obligation failure // and we assign the obligation's span to its expression's. - error.obligation.cause.make_mut().span = args[ref_in].span; - let code = error.obligation.cause.code.clone(); - error.obligation.cause.make_mut().code = + error.obligation.cause.span = args[ref_in].span; + let parent_code = error.obligation.cause.clone_code(); + *error.obligation.cause.make_mut_code() = ObligationCauseCode::FunctionArgumentObligation { arg_hir_id: args[ref_in].hir_id, call_hir_id: expr.hir_id, - parent_code: Lrc::new(code), + parent_code, }; - } else if error.obligation.cause.make_mut().span == call_sp { + } else if error.obligation.cause.span == call_sp { // Make function calls point at the callee, not the whole thing. if let hir::ExprKind::Call(callee, _) = expr.kind { - error.obligation.cause.make_mut().span = callee.span; + error.obligation.cause.span = callee.span; } } } @@ -1085,7 +1107,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = >::ast_ty_to_ty(self, hir_ty); let ty = self.resolve_vars_if_possible(ty); if ty == predicate.self_ty() { - error.obligation.cause.make_mut().span = hir_ty.span; + error.obligation.cause.span = hir_ty.span; } } } diff --git a/compiler/rustc_typeck/src/check/gather_locals.rs b/compiler/rustc_typeck/src/check/gather_locals.rs index 4ebfd7fd21..839bd56b39 100644 --- a/compiler/rustc_typeck/src/check/gather_locals.rs +++ b/compiler/rustc_typeck/src/check/gather_locals.rs @@ -7,6 +7,31 @@ use rustc_middle::ty::Ty; use rustc_span::Span; use rustc_trait_selection::traits; +/// A declaration is an abstraction of [hir::Local] and [hir::Let]. +/// +/// It must have a hir_id, as this is how we connect gather_locals to the check functions. +pub(super) struct Declaration<'a> { + pub hir_id: hir::HirId, + pub pat: &'a hir::Pat<'a>, + pub ty: Option<&'a hir::Ty<'a>>, + pub span: Span, + pub init: Option<&'a hir::Expr<'a>>, +} + +impl<'a> From<&'a hir::Local<'a>> for Declaration<'a> { + fn from(local: &'a hir::Local<'a>) -> Self { + let hir::Local { hir_id, pat, ty, span, init, .. } = *local; + Declaration { hir_id, pat, ty, span, init } + } +} + +impl<'a> From<&'a hir::Let<'a>> for Declaration<'a> { + fn from(let_expr: &'a hir::Let<'a>) -> Self { + let hir::Let { hir_id, pat, ty, span, init } = *let_expr; + Declaration { hir_id, pat, ty, span, init: Some(init) } + } +} + pub(super) struct GatherLocalsVisitor<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, // parameters are special cases of patterns, but we want to handle them as @@ -41,18 +66,12 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> { } } } -} -impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { - type Map = intravisit::ErasedMap<'tcx>; - - fn nested_visit_map(&mut self) -> NestedVisitorMap { - NestedVisitorMap::None - } - - // Add explicitly-declared locals. - fn visit_local(&mut self, local: &'tcx hir::Local<'tcx>) { - let local_ty = match local.ty { + /// Allocates a [LocalTy] for a declaration, which may have a type annotation. If it does have + /// a type annotation, then the LocalTy stored will be the resolved type. This may be found + /// again during type checking by querying [FnCtxt::local_ty] for the same hir_id. + fn declare(&mut self, decl: Declaration<'tcx>) { + let local_ty = match decl.ty { Some(ref ty) => { let o_ty = self.fcx.to_ty(&ty); @@ -68,16 +87,34 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { } None => None, }; - self.assign(local.span, local.hir_id, local_ty); + self.assign(decl.span, decl.hir_id, local_ty); debug!( "local variable {:?} is assigned type {}", - local.pat, - self.fcx.ty_to_string(&*self.fcx.locals.borrow().get(&local.hir_id).unwrap().decl_ty) + decl.pat, + self.fcx.ty_to_string(&*self.fcx.locals.borrow().get(&decl.hir_id).unwrap().decl_ty) ); + } +} + +impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { + type Map = intravisit::ErasedMap<'tcx>; + + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::None + } + + // Add explicitly-declared locals. + fn visit_local(&mut self, local: &'tcx hir::Local<'tcx>) { + self.declare(local.into()); intravisit::walk_local(self, local); } + fn visit_let_expr(&mut self, let_expr: &'tcx hir::Let<'tcx>) { + self.declare(let_expr.into()); + intravisit::walk_let_expr(self, let_expr); + } + fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { let old_outermost_fn_param_pat = self.outermost_fn_param_pat.replace(param.ty_span); intravisit::walk_param(self, param); diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs index 2910ce6de6..d54b1d62ee 100644 --- a/compiler/rustc_typeck/src/check/generator_interior.rs +++ b/compiler/rustc_typeck/src/check/generator_interior.rs @@ -536,22 +536,28 @@ pub fn check_must_not_suspend_ty<'tcx>( } has_emitted } - ty::Tuple(ref tys) => { + ty::Tuple(_) => { let mut has_emitted = false; - let spans = if let Some(hir::ExprKind::Tup(comps)) = data.expr.map(|e| &e.kind) { - debug_assert_eq!(comps.len(), tys.len()); - comps.iter().map(|e| e.span).collect() - } else { - vec![] + let comps = match data.expr.map(|e| &e.kind) { + Some(hir::ExprKind::Tup(comps)) => { + debug_assert_eq!(comps.len(), ty.tuple_fields().count()); + Some(comps) + } + _ => None, }; - for (i, ty) in tys.iter().map(|k| k.expect_ty()).enumerate() { + for (i, ty) in ty.tuple_fields().enumerate() { let descr_post = &format!(" in tuple element {}", i); - let span = *spans.get(i).unwrap_or(&data.source_span); + let span = comps.and_then(|c| c.get(i)).map(|e| e.span).unwrap_or(data.source_span); if check_must_not_suspend_ty( fcx, ty, hir_id, - SuspendCheckData { descr_post, source_span: span, ..data }, + SuspendCheckData { + descr_post, + expr: comps.and_then(|comps| comps.get(i)), + source_span: span, + ..data + }, ) { has_emitted = true; } @@ -603,7 +609,7 @@ fn check_must_not_suspend_def( // Add optional reason note if let Some(note) = attr.value_str() { // FIXME(guswynn): consider formatting this better - err.span_note(data.source_span, ¬e.as_str()); + err.span_note(data.source_span, note.as_str()); } // Add some quick suggestions on what to do diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs index f7552c1f4e..beb6b371b2 100644 --- a/compiler/rustc_typeck/src/check/inherited.rs +++ b/compiler/rustc_typeck/src/check/inherited.rs @@ -53,9 +53,6 @@ pub struct Inherited<'a, 'tcx> { pub(super) deferred_generator_interiors: RefCell, hir::GeneratorKind)>>, - /// Reports whether this is in a const context. - pub(super) constness: hir::Constness, - pub(super) body_id: Option, /// Whenever we introduce an adjustment from `!` into a type variable, @@ -79,7 +76,7 @@ pub struct InheritedBuilder<'tcx> { def_id: LocalDefId, } -impl Inherited<'_, 'tcx> { +impl<'tcx> Inherited<'_, 'tcx> { pub fn build(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> InheritedBuilder<'tcx> { let hir_owner = tcx.hir().local_def_id_to_hir_id(def_id).owner; @@ -100,18 +97,8 @@ impl<'tcx> InheritedBuilder<'tcx> { } } -impl Inherited<'a, 'tcx> { +impl<'a, 'tcx> Inherited<'a, 'tcx> { pub(super) fn new(infcx: InferCtxt<'a, 'tcx>, def_id: LocalDefId) -> Self { - let tcx = infcx.tcx; - let item_id = tcx.hir().local_def_id_to_hir_id(def_id); - Self::with_constness(infcx, def_id, tcx.hir().get(item_id).constness_for_typeck()) - } - - pub(super) fn with_constness( - infcx: InferCtxt<'a, 'tcx>, - def_id: LocalDefId, - constness: hir::Constness, - ) -> Self { let tcx = infcx.tcx; let item_id = tcx.hir().local_def_id_to_hir_id(def_id); let body_id = tcx.hir().maybe_body_owned_by(item_id); @@ -128,7 +115,6 @@ impl Inherited<'a, 'tcx> { deferred_cast_checks: RefCell::new(Vec::new()), deferred_generator_interiors: RefCell::new(Vec::new()), diverging_type_vars: RefCell::new(Default::default()), - constness, body_id, } } diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index dbc1d4ec19..f7f4c52c2a 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs @@ -7,7 +7,7 @@ mod prelude2021; pub mod probe; mod suggest; -pub use self::suggest::{SelfSource, TraitInfo}; +pub use self::suggest::SelfSource; pub use self::CandidateSource::*; pub use self::MethodError::*; @@ -22,7 +22,7 @@ use rustc_infer::infer::{self, InferOk}; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; use rustc_middle::ty::GenericParamDefKind; -use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable, WithConstness}; +use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable}; use rustc_span::symbol::Ident; use rustc_span::Span; use rustc_trait_selection::traits; @@ -31,7 +31,6 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use self::probe::{IsSuggestion, ProbeScope}; pub fn provide(providers: &mut ty::query::Providers) { - suggest::provide(providers); probe::provide(providers); } diff --git a/compiler/rustc_typeck/src/check/method/prelude2021.rs b/compiler/rustc_typeck/src/check/method/prelude2021.rs index 5c8056b244..bc2859719e 100644 --- a/compiler/rustc_typeck/src/check/method/prelude2021.rs +++ b/compiler/rustc_typeck/src/check/method/prelude2021.rs @@ -345,10 +345,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let import_items: Vec<_> = applicable_trait .import_ids .iter() - .map(|&import_id| { - let hir_id = self.tcx.hir().local_def_id_to_hir_id(import_id); - self.tcx.hir().expect_item(hir_id) - }) + .map(|&import_id| self.tcx.hir().expect_item(import_id)) .collect(); // Find an identifier with which this trait was imported (note that `_` doesn't count). diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index 9fd7e8c4da..5615a08369 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -21,7 +21,7 @@ use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; use rustc_middle::middle::stability; use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc_middle::ty::GenericParamDefKind; -use rustc_middle::ty::{self, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; +use rustc_middle::ty::{self, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc_session::lint; use rustc_span::def_id::LocalDefId; use rustc_span::lev_distance::{find_best_match_for_name, lev_distance}; @@ -1038,7 +1038,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { .collect(); // Sort them by the name so we have a stable result. - names.sort_by_cached_key(|n| n.as_str()); + names.sort_by(|a, b| a.as_str().partial_cmp(b.as_str()).unwrap()); names } @@ -1372,7 +1372,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { if applicable_candidates.len() > 1 { if let Some(pick) = - self.collapse_candidates_to_trait_pick(self_ty, &applicable_candidates[..]) + self.collapse_candidates_to_trait_pick(self_ty, &applicable_candidates) { return Some(Ok(pick)); } @@ -1908,7 +1908,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { .associated_items(def_id) .in_definition_order() .filter(|x| { - let dist = lev_distance(&*name.as_str(), &x.ident.as_str()); + let dist = lev_distance(name.as_str(), x.ident.as_str()); x.kind.namespace() == Namespace::ValueNS && dist > 0 && dist <= max_dist }) .copied() diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index ca174ed5e8..7f9c75c7fe 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -5,14 +5,14 @@ use crate::check::FnCtxt; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; -use rustc_hir::def::{DefKind, Namespace, Res}; -use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX}; +use rustc_hir::def::Namespace; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, Node, QPath}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_middle::ty::fast_reject::simplify_type; +use rustc_middle::ty::fast_reject::{simplify_type, SimplifyParams, StripReferences}; use rustc_middle::ty::print::with_crate_prefix; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; +use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc_span::lev_distance; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{source_map, FileName, MultiSpan, Span, Symbol}; @@ -67,6 +67,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool { + self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..))) + } + pub fn report_method_error( &self, mut span: Span, @@ -691,7 +695,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut restrict_type_params = false; let mut unsatisfied_bounds = false; - if !unsatisfied_predicates.is_empty() { + if item_name.name == sym::count && self.is_slice_ty(actual, span) { + let msg = "consider using `len` instead"; + if let SelfSource::MethodCall(_expr) = source { + err.span_suggestion_short( + span, + msg, + String::from("len"), + Applicability::MachineApplicable, + ); + } else { + err.span_label(span, msg); + } + if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) { + let iterator_trait = self.tcx.def_path_str(iterator_trait); + err.note(&format!("`count` is defined on `{iterator_trait}`, which `{actual}` does not implement")); + } + } else if !unsatisfied_predicates.is_empty() { let def_span = |def_id| { self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id)) }; @@ -812,7 +832,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for (data, p, parent_p) in unsatisfied_predicates .iter() .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c))) - .filter_map(|(p, parent, c)| match c.code { + .filter_map(|(p, parent, c)| match c.code() { ObligationCauseCode::ImplDerivedObligation(ref data) => { Some((data, p, parent)) } @@ -990,9 +1010,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - let mut fallback_span = true; - let msg = "remove this method call"; if item_name.name == sym::as_str && actual.peel_refs().is_str() { + let msg = "remove this method call"; + let mut fallback_span = true; if let SelfSource::MethodCall(expr) = source { let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)); @@ -1175,11 +1195,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn suggest_derive( &self, err: &mut DiagnosticBuilder<'_>, - unsatisfied_predicates: &Vec<( + unsatisfied_predicates: &[( ty::Predicate<'tcx>, Option>, Option>, - )>, + )], ) { let mut derives = Vec::<(String, Span, String)>::new(); let mut traits = Vec::::new(); @@ -1216,23 +1236,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { traits.push(self.tcx.def_span(trait_pred.def_id())); } } - derives.sort(); - let derives_grouped = derives.into_iter().fold( - Vec::<(String, Span, String)>::new(), - |mut acc, (self_name, self_span, trait_name)| { - if let Some((acc_self_name, _, ref mut traits)) = acc.last_mut() { - if acc_self_name == &self_name { - traits.push_str(format!(", {}", trait_name).as_str()); - return acc; - } - } - acc.push((self_name, self_span, trait_name)); - acc - }, - ); traits.sort(); traits.dedup(); + derives.sort(); + derives.dedup(); + + let mut derives_grouped = Vec::<(String, Span, String)>::new(); + for (self_name, self_span, trait_name) in derives.into_iter() { + if let Some((last_self_name, _, ref mut last_trait_names)) = derives_grouped.last_mut() + { + if last_self_name == &self_name { + last_trait_names.push_str(format!(", {}", trait_name).as_str()); + continue; + } + } + derives_grouped.push((self_name, self_span, trait_name)); + } + let len = traits.len(); if len > 0 { let span: MultiSpan = traits.into(); @@ -1290,25 +1311,66 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { mut msg: String, candidates: Vec, ) { + let parent_map = self.tcx.visible_parent_map(()); + + // Separate out candidates that must be imported with a glob, because they are named `_` + // and cannot be referred with their identifier. + let (candidates, globs): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|trait_did| { + if let Some(parent_did) = parent_map.get(trait_did) { + // If the item is re-exported as `_`, we should suggest a glob-import instead. + if Some(*parent_did) != self.tcx.parent(*trait_did) + && self + .tcx + .item_children(*parent_did) + .iter() + .filter(|child| child.res.opt_def_id() == Some(*trait_did)) + .all(|child| child.ident.name == kw::Underscore) + { + return false; + } + } + + true + }); + let module_did = self.tcx.parent_module(self.body_id); let (span, found_use) = find_use_placement(self.tcx, module_did); if let Some(span) = span { - let path_strings = candidates.iter().map(|did| { + let path_strings = candidates.iter().map(|trait_did| { // Produce an additional newline to separate the new use statement // from the directly following item. let additional_newline = if found_use { "" } else { "\n" }; format!( "use {};\n{}", - with_crate_prefix(|| self.tcx.def_path_str(*did)), + with_crate_prefix(|| self.tcx.def_path_str(*trait_did)), additional_newline ) }); - err.span_suggestions(span, &msg, path_strings, Applicability::MaybeIncorrect); + let glob_path_strings = globs.iter().map(|trait_did| { + let parent_did = parent_map.get(trait_did).unwrap(); + + // Produce an additional newline to separate the new use statement + // from the directly following item. + let additional_newline = if found_use { "" } else { "\n" }; + format!( + "use {}::*; // trait {}\n{}", + with_crate_prefix(|| self.tcx.def_path_str(*parent_did)), + self.tcx.item_name(*trait_did), + additional_newline + ) + }); + + err.span_suggestions( + span, + &msg, + path_strings.chain(glob_path_strings), + Applicability::MaybeIncorrect, + ); } else { - let limit = if candidates.len() == 5 { 5 } else { 4 }; + let limit = if candidates.len() + globs.len() == 5 { 5 } else { 4 }; for (i, trait_did) in candidates.iter().take(limit).enumerate() { - if candidates.len() > 1 { + if candidates.len() + globs.len() > 1 { msg.push_str(&format!( "\ncandidate #{}: `use {};`", i + 1, @@ -1321,10 +1383,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )); } } - if candidates.len() > limit { - msg.push_str(&format!("\nand {} others", candidates.len() - limit)); + for (i, trait_did) in + globs.iter().take(limit.saturating_sub(candidates.len())).enumerate() + { + let parent_did = parent_map.get(trait_did).unwrap(); + + if candidates.len() + globs.len() > 1 { + msg.push_str(&format!( + "\ncandidate #{}: `use {}::*; // trait {}`", + candidates.len() + i + 1, + with_crate_prefix(|| self.tcx.def_path_str(*parent_did)), + self.tcx.item_name(*trait_did), + )); + } else { + msg.push_str(&format!( + "\n`use {}::*; // trait {}`", + with_crate_prefix(|| self.tcx.def_path_str(*parent_did)), + self.tcx.item_name(*trait_did), + )); + } } - err.note(&msg[..]); + if candidates.len() > limit { + msg.push_str(&format!("\nand {} others", candidates.len() + globs.len() - limit)); + } + err.note(&msg); } } @@ -1683,7 +1765,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // FIXME: Even though negative bounds are not implemented, we could maybe handle // cases where a positive bound implies a negative impl. (candidates, Vec::new()) - } else if let Some(simp_rcvr_ty) = simplify_type(self.tcx, rcvr_ty, true) { + } else if let Some(simp_rcvr_ty) = + simplify_type(self.tcx, rcvr_ty, SimplifyParams::Yes, StripReferences::No) + { let mut potential_candidates = Vec::new(); let mut explicitly_negative = Vec::new(); for candidate in candidates { @@ -1696,7 +1780,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) .any(|imp_did| { let imp = self.tcx.impl_trait_ref(imp_did).unwrap(); - let imp_simp = simplify_type(self.tcx, imp.self_ty(), true); + let imp_simp = simplify_type( + self.tcx, + imp.self_ty(), + SimplifyParams::Yes, + StripReferences::No, + ); imp_simp.map_or(false, |s| s == simp_rcvr_ty) }) { @@ -1833,76 +1922,10 @@ impl Ord for TraitInfo { } } -/// Retrieves all traits in this crate and any dependent crates. +/// Retrieves all traits in this crate and any dependent crates, +/// and wraps them into `TraitInfo` for custom sorting. pub fn all_traits(tcx: TyCtxt<'_>) -> Vec { - tcx.all_traits(()).iter().map(|&def_id| TraitInfo { def_id }).collect() -} - -/// Computes all traits in this crate and any dependent crates. -fn compute_all_traits(tcx: TyCtxt<'_>, (): ()) -> &[DefId] { - use hir::itemlikevisit; - - let mut traits = vec![]; - - // Crate-local: - - struct Visitor<'a> { - traits: &'a mut Vec, - } - - impl<'v, 'a> itemlikevisit::ItemLikeVisitor<'v> for Visitor<'a> { - fn visit_item(&mut self, i: &'v hir::Item<'v>) { - match i.kind { - hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => { - self.traits.push(i.def_id.to_def_id()); - } - _ => (), - } - } - - fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {} - - fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {} - - fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {} - } - - tcx.hir().visit_all_item_likes(&mut Visitor { traits: &mut traits }); - - // Cross-crate: - - let mut external_mods = FxHashSet::default(); - fn handle_external_res( - tcx: TyCtxt<'_>, - traits: &mut Vec, - external_mods: &mut FxHashSet, - res: Res, - ) { - match res { - Res::Def(DefKind::Trait | DefKind::TraitAlias, def_id) => { - traits.push(def_id); - } - Res::Def(DefKind::Mod, def_id) => { - if !external_mods.insert(def_id) { - return; - } - for child in tcx.item_children(def_id).iter() { - handle_external_res(tcx, traits, external_mods, child.res) - } - } - _ => {} - } - } - for &cnum in tcx.crates(()).iter() { - let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX }; - handle_external_res(tcx, &mut traits, &mut external_mods, Res::Def(DefKind::Mod, def_id)); - } - - tcx.arena.alloc_from_iter(traits) -} - -pub fn provide(providers: &mut ty::query::Providers) { - providers.all_traits = compute_all_traits; + tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect() } fn find_use_placement<'tcx>(tcx: TyCtxt<'tcx>, target_module: LocalDefId) -> (Option, bool) { @@ -1948,7 +1971,7 @@ fn find_use_placement<'tcx>(tcx: TyCtxt<'tcx>, target_module: LocalDefId) -> (Op (span, found_use) } -fn print_disambiguation_help( +fn print_disambiguation_help<'tcx>( item_name: Ident, args: Option<&'tcx [hir::Expr<'tcx>]>, err: &mut DiagnosticBuilder<'_>, diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 7bfd3f0ee8..a9e6b1caff 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -508,7 +508,7 @@ struct GeneratorTypes<'tcx> { /// Given a `DefId` for an opaque type in return position, find its parent item's return /// expressions. -fn get_owner_return_paths( +fn get_owner_return_paths<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, ) -> Option<(hir::HirId, ReturnsVisitor<'tcx>)> { @@ -686,9 +686,8 @@ fn bounds_from_generic_predicates<'tcx>( }; let mut where_clauses = vec![]; for (ty, bounds) in types { - for bound in &bounds { - where_clauses.push(format!("{}: {}", ty, tcx.def_path_str(*bound))); - } + where_clauses + .extend(bounds.into_iter().map(|bound| format!("{}: {}", ty, tcx.def_path_str(bound)))); } for projection in &projections { let p = projection.skip_binder(); @@ -907,7 +906,7 @@ struct CheckItemTypesVisitor<'tcx> { tcx: TyCtxt<'tcx>, } -impl ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'tcx> { +impl<'tcx> ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'tcx> { fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) { check_item_type(self.tcx, i); } diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs index f83209f57a..8ebfcdd539 100644 --- a/compiler/rustc_typeck/src/check/op.rs +++ b/compiler/rustc_typeck/src/check/op.rs @@ -492,7 +492,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> bool /* did we suggest to call a function because of missing parentheses? */ { err.span_label(span, ty.to_string()); if let FnDef(def_id, _) = *ty.kind() { - let source_map = self.tcx.sess.source_map(); if !self.tcx.has_typeck_results(def_id) { return false; } @@ -517,20 +516,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .lookup_op_method(fn_sig.output(), &[other_ty], Op::Binary(op, is_assign)) .is_ok() { - if let Ok(snippet) = source_map.span_to_snippet(span) { - let (variable_snippet, applicability) = if !fn_sig.inputs().is_empty() { - (format!("{}( /* arguments */ )", snippet), Applicability::HasPlaceholders) - } else { - (format!("{}()", snippet), Applicability::MaybeIncorrect) - }; + let (variable_snippet, applicability) = if !fn_sig.inputs().is_empty() { + ("( /* arguments */ )".to_string(), Applicability::HasPlaceholders) + } else { + ("()".to_string(), Applicability::MaybeIncorrect) + }; - err.span_suggestion( - span, - "you might have forgotten to call this function", - variable_snippet, - applicability, - ); - } + err.span_suggestion_verbose( + span.shrink_to_hi(), + "you might have forgotten to call this function", + variable_snippet, + applicability, + ); return true; } } @@ -896,7 +893,7 @@ enum Op { } /// Dereferences a single level of immutable referencing. -fn deref_ty_if_possible(ty: Ty<'tcx>) -> Ty<'tcx> { +fn deref_ty_if_possible<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> { match ty.kind() { ty::Ref(_, ty, hir::Mutability::Not) => ty, _ => ty, @@ -1010,7 +1007,7 @@ impl<'tcx> TypeVisitor<'tcx> for TypeParamVisitor<'tcx> { struct TypeParamEraser<'a, 'tcx>(&'a FnCtxt<'a, 'tcx>, Span); -impl TypeFolder<'tcx> for TypeParamEraser<'_, 'tcx> { +impl<'tcx> TypeFolder<'tcx> for TypeParamEraser<'_, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.0.tcx } diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index cbf33cf1b7..ec06e0b112 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -740,7 +740,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn check_pat_path( + fn check_pat_path<'b>( &self, pat: &Pat<'_>, path_resolution: (Res, Option>, &'b [hir::PathSegment<'b>]), @@ -816,7 +816,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } - fn emit_bad_pat_path( + fn emit_bad_pat_path<'b>( &self, mut e: DiagnosticBuilder<'_>, pat_span: Span, diff --git a/compiler/rustc_typeck/src/check/place_op.rs b/compiler/rustc_typeck/src/check/place_op.rs index 5d9e6ebd50..d01e21bcb2 100644 --- a/compiler/rustc_typeck/src/check/place_op.rs +++ b/compiler/rustc_typeck/src/check/place_op.rs @@ -440,8 +440,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // If we have an autoref followed by unsizing at the end, fix the unsize target. - if let [.., Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), .. }, Adjustment { kind: Adjust::Pointer(PointerCast::Unsize), ref mut target }] = - adjustments[..] + if let [ + .., + Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), .. }, + Adjustment { kind: Adjust::Pointer(PointerCast::Unsize), ref mut target }, + ] = adjustments[..] { *target = method.sig.inputs()[0]; } diff --git a/compiler/rustc_typeck/src/check/regionck.rs b/compiler/rustc_typeck/src/check/regionck.rs index d2d8b14dd9..1b42edc83b 100644 --- a/compiler/rustc_typeck/src/check/regionck.rs +++ b/compiler/rustc_typeck/src/check/regionck.rs @@ -106,7 +106,7 @@ macro_rules! ignore_err { pub(crate) trait OutlivesEnvironmentExt<'tcx> { fn add_implied_bounds( &mut self, - infcx: &InferCtxt<'a, 'tcx>, + infcx: &InferCtxt<'_, 'tcx>, fn_sig_tys: FxHashSet>, body_id: hir::HirId, span: Span, @@ -130,7 +130,7 @@ impl<'tcx> OutlivesEnvironmentExt<'tcx> for OutlivesEnvironment<'tcx> { /// add those assumptions into the outlives-environment. /// /// Tests: `src/test/ui/regions/regions-free-region-ordering-*.rs` - fn add_implied_bounds( + fn add_implied_bounds<'a>( &mut self, infcx: &InferCtxt<'a, 'tcx>, fn_sig_tys: FxHashSet>, diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 5f5d308a33..ffd7d29bbb 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -687,15 +687,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { r ), ( - l - @ - (ProjectionKind::Index + l @ (ProjectionKind::Index | ProjectionKind::Subslice | ProjectionKind::Deref | ProjectionKind::Field(..)), - r - @ - (ProjectionKind::Index + r @ (ProjectionKind::Index | ProjectionKind::Subslice | ProjectionKind::Deref | ProjectionKind::Field(..)), @@ -908,10 +904,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> MigrationWarningReason { let mut reasons = MigrationWarningReason::default(); - for auto_trait in auto_trait_reasons { - reasons.auto_traits.push(auto_trait); - } - + reasons.auto_traits.extend(auto_trait_reasons); reasons.drop_order = drop_order; reasons @@ -1679,7 +1672,7 @@ fn restrict_repr_packed_field_ref_capture<'tcx>( } /// Returns a Ty that applies the specified capture kind on the provided capture Ty -fn apply_capture_kind_on_capture_ty( +fn apply_capture_kind_on_capture_ty<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, capture_kind: UpvarCapture<'tcx>, @@ -1692,7 +1685,7 @@ fn apply_capture_kind_on_capture_ty( } /// Returns the Span of where the value with the provided HirId would be dropped -fn drop_location_span(tcx: TyCtxt<'tcx>, hir_id: &hir::HirId) -> Span { +fn drop_location_span<'tcx>(tcx: TyCtxt<'tcx>, hir_id: &hir::HirId) -> Span { let owner_id = tcx.hir().get_enclosing_scope(*hir_id).unwrap(); let owner_node = tcx.hir().get(owner_id); @@ -2006,7 +1999,7 @@ fn restrict_precision_for_drop_types<'a, 'tcx>( /// - No projections are applied to raw pointers, since these require unsafe blocks. We capture /// them completely. /// - No projections are applied on top of Union ADTs, since these require unsafe blocks. -fn restrict_precision_for_unsafe( +fn restrict_precision_for_unsafe<'tcx>( mut place: Place<'tcx>, mut curr_mode: ty::UpvarCapture<'tcx>, ) -> (Place<'tcx>, ty::UpvarCapture<'tcx>) { @@ -2104,7 +2097,7 @@ fn adjust_for_non_move_closure<'tcx>( (place, kind) } -fn construct_place_string(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String { +fn construct_place_string<'tcx>(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String { let variable_name = match place.base { PlaceBase::Upvar(upvar_id) => var_name(tcx, upvar_id.var_path.hir_id).to_string(), _ => bug!("Capture_information should only contain upvars"), @@ -2127,7 +2120,7 @@ fn construct_place_string(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String { format!("{}[{}]", variable_name, projections_str) } -fn construct_capture_kind_reason_string( +fn construct_capture_kind_reason_string<'tcx>( tcx: TyCtxt<'_>, place: &Place<'tcx>, capture_info: &ty::CaptureInfo<'tcx>, @@ -2142,13 +2135,13 @@ fn construct_capture_kind_reason_string( format!("{} captured as {} here", place_str, capture_kind_str) } -fn construct_path_string(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String { +fn construct_path_string<'tcx>(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String { let place_str = construct_place_string(tcx, place); format!("{} used here", place_str) } -fn construct_capture_info_string( +fn construct_capture_info_string<'tcx>( tcx: TyCtxt<'_>, place: &Place<'tcx>, capture_info: &ty::CaptureInfo<'tcx>, @@ -2240,7 +2233,7 @@ fn migration_suggestion_for_2229( /// would've already handled `E1`, and have an existing capture_information for it. /// Calling `determine_capture_info(existing_info_e1, current_info_e2)` will return /// `existing_info_e1` in this case, allowing us to point to `E1` in case of diagnostics. -fn determine_capture_info( +fn determine_capture_info<'tcx>( capture_info_a: ty::CaptureInfo<'tcx>, capture_info_b: ty::CaptureInfo<'tcx>, ) -> ty::CaptureInfo<'tcx> { @@ -2299,7 +2292,7 @@ fn determine_capture_info( /// /// Note: Capture kind changes from `MutBorrow` to `UniqueImmBorrow` if the truncated part of the `place` /// contained `Deref` of `&mut`. -fn truncate_place_to_len_and_update_capture_kind( +fn truncate_place_to_len_and_update_capture_kind<'tcx>( place: &mut Place<'tcx>, curr_mode: &mut ty::UpvarCapture<'tcx>, len: usize, @@ -2337,7 +2330,7 @@ fn truncate_place_to_len_and_update_capture_kind( /// `PlaceAncestryRelation::Ancestor` implies Place A is ancestor of Place B /// `PlaceAncestryRelation::Descendant` implies Place A is descendant of Place B /// `PlaceAncestryRelation::Divergent` implies neither of them is the ancestor of the other. -fn determine_place_ancestry_relation( +fn determine_place_ancestry_relation<'tcx>( place_a: &Place<'tcx>, place_b: &Place<'tcx>, ) -> PlaceAncestryRelation { diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index e58faf9a89..7c4f5d16ab 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -21,7 +21,6 @@ use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst}; use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::{ self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitor, - WithConstness, }; use rustc_session::parse::feature_err; use rustc_span::symbol::{sym, Ident, Symbol}; @@ -84,8 +83,7 @@ impl<'tcx> CheckWfFcxBuilder<'tcx> { /// the types first. #[instrument(skip(tcx), level = "debug")] pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let item = tcx.hir().expect_item(hir_id); + let item = tcx.hir().expect_item(def_id); debug!( ?item.def_id, @@ -197,7 +195,7 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let trait_item = tcx.hir().expect_trait_item(hir_id); + let trait_item = tcx.hir().expect_trait_item(def_id); let (method_sig, span) = match trait_item.kind { hir::TraitItemKind::Fn(ref sig, _) => (Some(sig), trait_item.span), @@ -207,8 +205,8 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { check_object_unsafe_self_trait_by_name(tcx, trait_item); check_associated_item(tcx, trait_item.def_id, span, method_sig); - let encl_trait_hir_id = tcx.hir().get_parent_item(hir_id); - let encl_trait = tcx.hir().expect_item(encl_trait_hir_id); + let encl_trait_def_id = tcx.hir().get_parent_did(hir_id); + let encl_trait = tcx.hir().expect_item(encl_trait_def_id); let encl_trait_def_id = encl_trait.def_id.to_def_id(); let fn_lang_item_name = if Some(encl_trait_def_id) == tcx.lang_items().fn_trait() { Some("fn") @@ -428,22 +426,48 @@ fn check_gat_where_clauses( } } - // If there are any missing clauses, emit an error - let mut clauses = clauses.unwrap_or_default(); + // If there are any clauses that aren't provable, emit an error + let clauses = clauses.unwrap_or_default(); debug!(?clauses); if !clauses.is_empty() { - let written_predicates: ty::GenericPredicates<'_> = - tcx.explicit_predicates_of(trait_item.def_id); + let param_env = tcx.param_env(trait_item.def_id); + let mut clauses: Vec<_> = clauses - .drain_filter(|clause| !written_predicates.predicates.iter().any(|p| &p.0 == clause)) + .into_iter() + .filter(|clause| match clause.kind().skip_binder() { + ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => { + !region_known_to_outlive( + tcx, + trait_item.hir_id(), + param_env, + &FxHashSet::default(), + a, + b, + ) + } + ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => { + !ty_known_to_outlive( + tcx, + trait_item.hir_id(), + param_env, + &FxHashSet::default(), + a, + b, + ) + } + _ => bug!("Unexpected PredicateKind"), + }) .map(|clause| format!("{}", clause)) .collect(); + // We sort so that order is predictable clauses.sort(); + if !clauses.is_empty() { + let plural = if clauses.len() > 1 { "s" } else { "" }; let mut err = tcx.sess.struct_span_err( trait_item.span, - &format!("Missing required bounds on {}", trait_item.ident), + &format!("missing required bound{} on `{}`", plural, trait_item.ident), ); let suggestion = format!( @@ -457,11 +481,22 @@ fn check_gat_where_clauses( ); err.span_suggestion( trait_item.generics.where_clause.tail_span_for_suggestion(), - "add the required where clauses", + &format!("add the required where clause{}", plural), suggestion, Applicability::MachineApplicable, ); + let bound = if clauses.len() > 1 { "these bounds are" } else { "this bound is" }; + err.note(&format!( + "{} currently required to ensure that impls have maximum flexibility", + bound + )); + err.note( + "we are soliciting feedback, see issue #87479 \ + \ + for more information", + ); + err.emit() } } @@ -543,7 +578,8 @@ fn region_known_to_outlive<'tcx>( }); use rustc_infer::infer::outlives::obligations::TypeOutlivesDelegate; - (&infcx).push_sub_region_constraint(origin, region_a, region_b); + // `region_a: region_b` -> `region_b <= region_a` + (&infcx).push_sub_region_constraint(origin, region_b, region_a); let errors = infcx.resolve_regions( id.expect_owner().to_def_id(), @@ -680,12 +716,12 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem } pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let impl_item = tcx.hir().expect_impl_item(hir_id); + let impl_item = tcx.hir().expect_impl_item(def_id); let (method_sig, span) = match impl_item.kind { hir::ImplItemKind::Fn(ref sig, _) => (Some(sig), impl_item.span), - hir::ImplItemKind::TyAlias(ty) => (None, ty.span), + // Constrain binding and overflow error spans to `` in `type foo = `. + hir::ImplItemKind::TyAlias(ty) if ty.span != DUMMY_SP => (None, ty.span), _ => (None, impl_item.span), }; @@ -698,7 +734,6 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) { hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => (), // Const parameters are well formed if their type is structural match. - // FIXME(const_generics_defaults): we also need to check that the `default` is wf. hir::GenericParamKind::Const { ty: hir_ty, default: _ } => { let ty = tcx.type_of(tcx.hir().local_def_id(param.hir_id)); @@ -1060,6 +1095,20 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_fo ); } + // Ensure that the end result is `Sync` in a non-thread local `static`. + let should_check_for_sync = tcx.static_mutability(item_id.to_def_id()) + == Some(hir::Mutability::Not) + && !tcx.is_foreign_item(item_id.to_def_id()) + && !tcx.is_thread_local_static(item_id.to_def_id()); + + if should_check_for_sync { + fcx.register_bound( + item_ty, + tcx.require_lang_item(LangItem::Sync, Some(ty_span)), + traits::ObligationCause::new(ty_span, fcx.body_id, traits::SharedStatic), + ); + } + // No implied bounds in a const, etc. FxHashSet::default() }); @@ -1439,7 +1488,7 @@ fn check_method_receiver<'fcx, 'tcx>( } } -fn e0307(fcx: &FnCtxt<'fcx, 'tcx>, span: Span, receiver_ty: Ty<'_>) { +fn e0307<'tcx>(fcx: &FnCtxt<'_, 'tcx>, span: Span, receiver_ty: Ty<'_>) { struct_span_err!( fcx.tcx.sess.diagnostic(), span, @@ -1542,7 +1591,7 @@ fn receiver_is_valid<'fcx, 'tcx>( true } -fn receiver_is_implemented( +fn receiver_is_implemented<'tcx>( fcx: &FnCtxt<'_, 'tcx>, receiver_trait_def_id: DefId, cause: ObligationCause<'tcx>, @@ -1685,13 +1734,13 @@ pub struct CheckTypeWellFormedVisitor<'tcx> { tcx: TyCtxt<'tcx>, } -impl CheckTypeWellFormedVisitor<'tcx> { +impl<'tcx> CheckTypeWellFormedVisitor<'tcx> { pub fn new(tcx: TyCtxt<'tcx>) -> CheckTypeWellFormedVisitor<'tcx> { CheckTypeWellFormedVisitor { tcx } } } -impl ParItemLikeVisitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> { +impl<'tcx> ParItemLikeVisitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> { fn visit_item(&self, i: &'tcx hir::Item<'tcx>) { Visitor::visit_item(&mut self.clone(), i); } @@ -1709,7 +1758,7 @@ impl ParItemLikeVisitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> { } } -impl Visitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> { type Map = hir_map::Map<'tcx>; fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap { @@ -1810,7 +1859,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Inherent impl: take implied bounds from the `self` type. let self_ty = self.tcx.type_of(impl_def_id); let self_ty = self.normalize_associated_types_in(span, self_ty); - std::array::IntoIter::new([self_ty]).collect() + FxHashSet::from_iter([self_ty]) } } } diff --git a/compiler/rustc_typeck/src/check_unused.rs b/compiler/rustc_typeck/src/check_unused.rs index 89ce3700aa..f45cd3ed68 100644 --- a/compiler/rustc_typeck/src/check_unused.rs +++ b/compiler/rustc_typeck/src/check_unused.rs @@ -21,7 +21,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) { unused_crates_lint(tcx); } -impl ItemLikeVisitor<'v> for CheckVisitor<'tcx> { +impl<'tcx> ItemLikeVisitor<'_> for CheckVisitor<'tcx> { fn visit_item(&mut self, item: &hir::Item<'_>) { if item.vis.node.is_pub() || item.span.is_dummy() { return; @@ -43,7 +43,7 @@ struct CheckVisitor<'tcx> { used_trait_imports: FxHashSet, } -impl CheckVisitor<'tcx> { +impl<'tcx> CheckVisitor<'tcx> { fn check_import(&self, item_id: hir::ItemId, span: Span) { if !self.tcx.maybe_unused_trait_import(item_id.def_id) { return; @@ -119,13 +119,13 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) { for extern_crate in &crates_to_lint { let def_id = extern_crate.def_id.expect_local(); - let id = tcx.hir().local_def_id_to_hir_id(def_id); - let item = tcx.hir().expect_item(id); + let item = tcx.hir().expect_item(def_id); // If the crate is fully unused, we suggest removing it altogether. // We do this in any edition. if extern_crate.warn_if_unused { if let Some(&span) = unused_extern_crates.get(&def_id) { + let id = tcx.hir().local_def_id_to_hir_id(def_id); tcx.struct_span_lint_hir(lint, id, span, |lint| { // Removal suggestion span needs to include attributes (Issue #54400) let span_with_attrs = tcx @@ -173,6 +173,7 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) { if !tcx.get_attrs(extern_crate.def_id).is_empty() { continue; } + let id = tcx.hir().local_def_id_to_hir_id(def_id); tcx.struct_span_lint_hir(lint, id, extern_crate.span, |lint| { // Otherwise, we can convert it into a `use` of some kind. let base_replacement = match extern_crate.orig_name { diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs index 372e83592b..d5494c5a68 100644 --- a/compiler/rustc_typeck/src/coherence/builtin.rs +++ b/compiler/rustc_typeck/src/coherence/builtin.rs @@ -52,8 +52,7 @@ fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) { return; } - let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did); - let sp = match tcx.hir().expect_item(impl_hir_id).kind { + let sp = match tcx.hir().expect_item(impl_did).kind { ItemKind::Impl(ref impl_) => impl_.self_ty.span, _ => bug!("expected Drop impl item"), }; @@ -78,7 +77,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { match can_type_implement_copy(tcx, param_env, self_type) { Ok(()) => {} Err(CopyImplementationError::InfrigingFields(fields)) => { - let item = tcx.hir().expect_item(impl_hir_id); + let item = tcx.hir().expect_item(impl_did); let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(ref tr), .. }) = item.kind { tr.path.span } else { @@ -97,7 +96,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { err.emit() } Err(CopyImplementationError::NotAnAdt) => { - let item = tcx.hir().expect_item(impl_hir_id); + let item = tcx.hir().expect_item(impl_did); let span = if let ItemKind::Impl(ref impl_) = item.kind { impl_.self_ty.span } else { span }; @@ -109,7 +108,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { } } -fn visit_implementation_of_coerce_unsized(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) { +fn visit_implementation_of_coerce_unsized<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) { debug!("visit_implementation_of_coerce_unsized: impl_did={:?}", impl_did); // Just compute this for the side-effects, in particular reporting @@ -119,7 +118,7 @@ fn visit_implementation_of_coerce_unsized(tcx: TyCtxt<'tcx>, impl_did: LocalDefI tcx.at(span).coerce_unsized_info(impl_did); } -fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDefId) { +fn visit_implementation_of_dispatch_from_dyn<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) { debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did); let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did); @@ -288,12 +287,12 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef }) } -pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedInfo { +pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedInfo { debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did); // this provider should only get invoked for local def-ids - let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did.expect_local()); - let span = tcx.hir().span(impl_hir_id); + let impl_did = impl_did.expect_local(); + let span = tcx.def_span(impl_did); let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, Some(span)); @@ -315,6 +314,7 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (free)", source, target); tcx.infer_ctxt().enter(|infcx| { + let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did); let cause = ObligationCause::misc(span, impl_hir_id); let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>, mt_b: ty::TypeAndMut<'tcx>, @@ -452,13 +452,13 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI .emit(); return err_info; } else if diff_fields.len() > 1 { - let item = tcx.hir().expect_item(impl_hir_id); + let item = tcx.hir().expect_item(impl_did); let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(ref t), .. }) = item.kind { t.path.span } else { - tcx.hir().span(impl_hir_id) + tcx.def_span(impl_did) }; struct_span_err!( @@ -530,7 +530,11 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI // Finally, resolve all regions. let outlives_env = OutlivesEnvironment::new(param_env); - infcx.resolve_regions_and_report_errors(impl_did, &outlives_env, RegionckMode::default()); + infcx.resolve_regions_and_report_errors( + impl_did.to_def_id(), + &outlives_env, + RegionckMode::default(), + ); CoerceUnsizedInfo { custom_kind: kind } }) diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_typeck/src/coherence/inherent_impls.rs index 6a9ba9d491..f4e5cce012 100644 --- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs +++ b/compiler/rustc_typeck/src/coherence/inherent_impls.rs @@ -38,7 +38,7 @@ struct InherentCollect<'tcx> { impls_map: CrateInherentImpls, } -impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { +impl<'tcx> ItemLikeVisitor<'_> for InherentCollect<'tcx> { fn visit_item(&mut self, item: &hir::Item<'_>) { let (ty, assoc_items) = match item.kind { hir::ItemKind::Impl(hir::Impl { of_trait: None, ref self_ty, items, .. }) => { @@ -370,7 +370,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {} } -impl InherentCollect<'tcx> { +impl<'tcx> InherentCollect<'tcx> { fn check_def_id(&mut self, item: &hir::Item<'_>, def_id: DefId) { if let Some(def_id) = def_id.as_local() { // Add the implementation to the mapping from implementation to base diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs index beacf301ca..59f211bd2c 100644 --- a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs @@ -18,7 +18,7 @@ struct InherentOverlapChecker<'tcx> { tcx: TyCtxt<'tcx>, } -impl InherentOverlapChecker<'tcx> { +impl<'tcx> InherentOverlapChecker<'tcx> { /// Checks whether any associated items in impls 1 and 2 share the same identifier and /// namespace. fn impls_have_common_items( @@ -115,8 +115,8 @@ impl InherentOverlapChecker<'tcx> { } } -impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> { - fn visit_item(&mut self, item: &'v hir::Item<'v>) { +impl<'tcx> ItemLikeVisitor<'_> for InherentOverlapChecker<'tcx> { + fn visit_item(&mut self, item: &hir::Item<'_>) { match item.kind { hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) @@ -300,9 +300,9 @@ impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> { } } - fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'v>) {} + fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {} - fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'v>) {} + fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {} - fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'v>) {} + fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {} } diff --git a/compiler/rustc_typeck/src/coherence/orphan.rs b/compiler/rustc_typeck/src/coherence/orphan.rs index b450d3f6c0..e954b4cf51 100644 --- a/compiler/rustc_typeck/src/coherence/orphan.rs +++ b/compiler/rustc_typeck/src/coherence/orphan.rs @@ -143,7 +143,7 @@ fn orphan_check_impl(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorRep Ok(()) } -fn emit_orphan_check_error( +fn emit_orphan_check_error<'tcx>( tcx: TyCtxt<'tcx>, sp: Span, trait_span: Span, diff --git a/compiler/rustc_typeck/src/coherence/unsafety.rs b/compiler/rustc_typeck/src/coherence/unsafety.rs index e7b03fa3ac..f7aabf2406 100644 --- a/compiler/rustc_typeck/src/coherence/unsafety.rs +++ b/compiler/rustc_typeck/src/coherence/unsafety.rs @@ -16,10 +16,10 @@ struct UnsafetyChecker<'tcx> { tcx: TyCtxt<'tcx>, } -impl UnsafetyChecker<'tcx> { +impl<'tcx> UnsafetyChecker<'tcx> { fn check_unsafety_coherence( &mut self, - item: &'v hir::Item<'v>, + item: &hir::Item<'_>, impl_generics: Option<&hir::Generics<'_>>, unsafety: hir::Unsafety, polarity: hir::ImplPolarity, @@ -83,8 +83,8 @@ impl UnsafetyChecker<'tcx> { } } -impl ItemLikeVisitor<'v> for UnsafetyChecker<'tcx> { - fn visit_item(&mut self, item: &'v hir::Item<'v>) { +impl<'tcx> ItemLikeVisitor<'_> for UnsafetyChecker<'tcx> { + fn visit_item(&mut self, item: &hir::Item<'_>) { if let hir::ItemKind::Impl(ref impl_) = item.kind { self.check_unsafety_coherence( item, diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index b9db8a6be5..41c8a37a71 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -41,7 +41,7 @@ use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::util::Discr; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, Ty, TyCtxt}; -use rustc_middle::ty::{ReprOptions, ToPredicate, WithConstness}; +use rustc_middle::ty::{ReprOptions, ToPredicate, TypeFoldable}; use rustc_session::lint; use rustc_session::parse::feature_err; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -147,7 +147,7 @@ struct CollectItemTypesVisitor<'tcx> { /// If there are any placeholder types (`_`), emit an error explaining that this is not allowed /// and suggest adding type parameters in the appropriate place, taking into consideration any and /// all already existing generic type parameters to avoid suggesting a name that is already in use. -crate fn placeholder_type_error( +crate fn placeholder_type_error<'tcx>( tcx: TyCtxt<'tcx>, span: Option, generics: &[hir::GenericParam<'_>], @@ -177,14 +177,12 @@ crate fn placeholder_type_error( sugg.push((arg.span, (*type_name).to_string())); } else { let last = generics.iter().last().unwrap(); - sugg.push(( - // Account for bounds, we want `fn foo(_: K)` not `fn foo(_: K)`. - last.bounds_span().unwrap_or(last.span).shrink_to_hi(), - format!(", {}", type_name), - )); + // Account for bounds, we want `fn foo(_: K)` not `fn foo(_: K)`. + let span = last.bounds_span_for_suggestions().unwrap_or(last.span.shrink_to_hi()); + sugg.push((span, format!(", {}", type_name))); } - let mut err = bad_placeholder_type(tcx, placeholder_types, kind); + let mut err = bad_placeholder(tcx, "type", placeholder_types, kind); // Suggest, but only if it is not a function in const or static if suggest { @@ -225,7 +223,10 @@ crate fn placeholder_type_error( err.emit(); } -fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { +fn reject_placeholder_type_signatures_in_item<'tcx>( + tcx: TyCtxt<'tcx>, + item: &'tcx hir::Item<'tcx>, +) { let (generics, suggest) = match &item.kind { hir::ItemKind::Union(_, generics) | hir::ItemKind::Enum(_, generics) @@ -253,7 +254,7 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir ); } -impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { type Map = Map<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -294,7 +295,9 @@ impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { if let hir::ExprKind::Closure(..) = expr.kind { let def_id = self.tcx.hir().local_def_id(expr.hir_id); self.tcx.ensure().generics_of(def_id); - self.tcx.ensure().type_of(def_id); + // We do not call `type_of` for closures here as that + // depends on typecheck and would therefore hide + // any further errors in case one typeck fails. } intravisit::walk_expr(self, expr); } @@ -313,8 +316,9 @@ impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { /////////////////////////////////////////////////////////////////////////// // Utility types and common code for the above passes. -fn bad_placeholder_type( +fn bad_placeholder<'tcx>( tcx: TyCtxt<'tcx>, + placeholder_kind: &'static str, mut spans: Vec, kind: &'static str, ) -> rustc_errors::DiagnosticBuilder<'tcx> { @@ -325,7 +329,8 @@ fn bad_placeholder_type( tcx.sess, spans.clone(), E0121, - "the type placeholder `_` is not allowed within types on item signatures for {}", + "the {} placeholder `_` is not allowed within types on item signatures for {}", + placeholder_kind, kind ); for span in spans { @@ -334,7 +339,7 @@ fn bad_placeholder_type( err } -impl ItemCtxt<'tcx> { +impl<'tcx> ItemCtxt<'tcx> { pub fn new(tcx: TyCtxt<'tcx>, item_def_id: DefId) -> ItemCtxt<'tcx> { ItemCtxt { tcx, item_def_id } } @@ -352,7 +357,7 @@ impl ItemCtxt<'tcx> { } } -impl AstConv<'tcx> for ItemCtxt<'tcx> { +impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -392,7 +397,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { _: Option<&ty::GenericParamDef>, span: Span, ) -> &'tcx Const<'tcx> { - bad_placeholder_type(self.tcx(), vec![span], "generic").emit(); + bad_placeholder(self.tcx(), "const", vec![span], "generic").emit(); // Typeck doesn't expect erased regions to be returned from `type_of`. let ty = self.tcx.fold_regions(ty, &mut false, |r, _| match r { ty::ReErased => self.tcx.lifetimes.re_static, @@ -431,7 +436,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { match self.node() { hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => { let item = - self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(self.hir_id())); + self.tcx.hir().expect_item(self.tcx.hir().get_parent_did(self.hir_id())); match &item.kind { hir::ItemKind::Enum(_, generics) | hir::ItemKind::Struct(_, generics) @@ -596,7 +601,11 @@ fn type_param_predicates( ItemKind::Fn(.., ref generics, _) | ItemKind::Impl(hir::Impl { ref generics, .. }) | ItemKind::TyAlias(_, ref generics) - | ItemKind::OpaqueTy(OpaqueTy { ref generics, impl_trait_fn: None, .. }) + | ItemKind::OpaqueTy(OpaqueTy { + ref generics, + origin: hir::OpaqueTyOrigin::TyAlias, + .. + }) | ItemKind::Enum(_, ref generics) | ItemKind::Struct(_, ref generics) | ItemKind::Union(_, ref generics) => generics, @@ -641,7 +650,7 @@ fn type_param_predicates( result } -impl ItemCtxt<'tcx> { +impl<'tcx> ItemCtxt<'tcx> { /// Finds bounds from `hir::Generics`. This requires scanning through the /// AST. We do this to avoid having to convert *all* the bounds, which /// would create artificial cycles. Instead, we can only convert the @@ -666,7 +675,7 @@ impl ItemCtxt<'tcx> { Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name), None => true, }) - .flat_map(|b| predicates_from_bound(self, ty, b)); + .flat_map(|b| predicates_from_bound(self, ty, b, ty::List::empty())); let param_def_id = self.tcx.hir().local_def_id(param_id).to_def_id(); let from_where_clauses = ast_generics @@ -685,15 +694,17 @@ impl ItemCtxt<'tcx> { } else { None }; + let bvars = self.tcx.late_bound_vars(bp.bounded_ty.hir_id); + bp.bounds .iter() .filter(|b| match assoc_name { Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name), None => true, }) - .filter_map(move |b| bt.map(|bt| (bt, b))) + .filter_map(move |b| bt.map(|bt| (bt, b, bvars))) }) - .flat_map(|(bt, b)| predicates_from_bound(self, bt, b)); + .flat_map(|(bt, b, bvars)| predicates_from_bound(self, bt, b, bvars)); from_ty_params.chain(from_where_clauses).collect() } @@ -793,7 +804,10 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { } // Desugared from `impl Trait`, so visited by the function's return type. - hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: Some(_), .. }) => {} + hir::ItemKind::OpaqueTy(hir::OpaqueTy { + origin: hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..), + .. + }) => {} // Don't call `type_of` on opaque types, since that depends on type // checking function bodies. `check_item_type` ensures that it's called @@ -1182,8 +1196,7 @@ fn super_predicates_that_define_assoc_type( } fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - let item = tcx.hir().expect_item(hir_id); + let item = tcx.hir().expect_item(def_id.expect_local()); let (is_auto, unsafety) = match item.kind { hir::ItemKind::Trait(is_auto, unsafety, ..) => (is_auto == hir::IsAuto::Yes, unsafety), @@ -1233,7 +1246,7 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option, } - impl Visitor<'tcx> for LateBoundRegionsDetector<'tcx> { + impl<'tcx> Visitor<'tcx> for LateBoundRegionsDetector<'tcx> { type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { @@ -1473,7 +1486,11 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { // `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`), // as they shouldn't be able to cause query cycle errors. Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. }) - | Node::Variant(Variant { disr_expr: Some(ref constant), .. }) + if constant.hir_id() == hir_id => + { + Some(parent_def_id.to_def_id()) + } + Node::Variant(Variant { disr_expr: Some(ref constant), .. }) if constant.hir_id == hir_id => { Some(parent_def_id.to_def_id()) @@ -1489,15 +1506,18 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { Some(tcx.typeck_root_def_id(def_id)) } Node::Item(item) => match item.kind { - ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => { - impl_trait_fn.or_else(|| { - let parent_id = tcx.hir().get_parent_item(hir_id); - assert!(parent_id != hir_id && parent_id != CRATE_HIR_ID); - debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id); - // Opaque types are always nested within another item, and - // inherit the generics of the item. - Some(tcx.hir().local_def_id(parent_id).to_def_id()) - }) + ItemKind::OpaqueTy(hir::OpaqueTy { + origin: + hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id), + .. + }) => Some(fn_def_id.to_def_id()), + ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => { + let parent_id = tcx.hir().get_parent_item(hir_id); + assert!(parent_id != hir_id && parent_id != CRATE_HIR_ID); + debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id); + // Opaque types are always nested within another item, and + // inherit the generics of the item. + Some(tcx.hir().local_def_id(parent_id).to_def_id()) } _ => None, }, @@ -1737,7 +1757,7 @@ fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool { } } -pub fn get_infer_ret_ty(output: &'hir hir::FnRetTy<'hir>) -> Option<&'hir hir::Ty<'hir>> { +pub fn get_infer_ret_ty<'hir>(output: &'hir hir::FnRetTy<'hir>) -> Option<&'hir hir::Ty<'hir>> { if let hir::FnRetTy::Return(ty) = output { if is_suggestable_infer_ty(ty) { return Some(&*ty); @@ -1776,9 +1796,9 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_ty(ty); - let mut diag = bad_placeholder_type(tcx, visitor.0, "return type"); + let mut diag = bad_placeholder(tcx, "type", visitor.0, "return type"); let ret_ty = fn_sig.skip_binder().output(); - if ret_ty != tcx.ty_error() { + if !ret_ty.references_error() { if !ret_ty.is_closure() { let ret_ty_str = match ret_ty.kind() { // Suggest a function pointer return type instead of a unique function definition @@ -1878,9 +1898,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { let icx = ItemCtxt::new(tcx, def_id); - - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - match tcx.hir().expect_item(hir_id).kind { + match tcx.hir().expect_item(def_id.expect_local()).kind { hir::ItemKind::Impl(ref impl_) => impl_.of_trait.as_ref().map(|ast_trait_ref| { let selfty = tcx.type_of(def_id); >::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty) @@ -1890,9 +1908,8 @@ fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { } fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl); - let item = tcx.hir().expect_item(hir_id); + let item = tcx.hir().expect_item(def_id.expect_local()); match &item.kind { hir::ItemKind::Impl(hir::Impl { polarity: hir::ImplPolarity::Negative(span), @@ -2055,31 +2072,32 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP generics } ItemKind::OpaqueTy(OpaqueTy { - bounds: _, - impl_trait_fn, - ref generics, - origin: _, + origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..), + .. }) => { - if impl_trait_fn.is_some() { - // return-position impl trait - // - // We don't inherit predicates from the parent here: - // If we have, say `fn f<'a, T: 'a>() -> impl Sized {}` - // then the return type is `f::<'static, T>::{{opaque}}`. - // - // If we inherited the predicates of `f` then we would - // require that `T: 'static` to show that the return - // type is well-formed. - // - // The only way to have something with this opaque type - // is from the return type of the containing function, - // which will ensure that the function's predicates - // hold. - return ty::GenericPredicates { parent: None, predicates: &[] }; - } else { - // type-alias impl trait - generics - } + // return-position impl trait + // + // We don't inherit predicates from the parent here: + // If we have, say `fn f<'a, T: 'a>() -> impl Sized {}` + // then the return type is `f::<'static, T>::{{opaque}}`. + // + // If we inherited the predicates of `f` then we would + // require that `T: 'static` to show that the return + // type is well-formed. + // + // The only way to have something with this opaque type + // is from the return type of the containing function, + // which will ensure that the function's predicates + // hold. + return ty::GenericPredicates { parent: None, predicates: &[] }; + } + ItemKind::OpaqueTy(OpaqueTy { + ref generics, + origin: hir::OpaqueTyOrigin::TyAlias, + .. + }) => { + // type-alias impl trait + generics } _ => NO_GENERICS, @@ -2433,14 +2451,10 @@ fn predicates_from_bound<'tcx>( astconv: &dyn AstConv<'tcx>, param_ty: Ty<'tcx>, bound: &'tcx hir::GenericBound<'tcx>, + bound_vars: &'tcx ty::List, ) -> Vec<(ty::Predicate<'tcx>, Span)> { let mut bounds = Bounds::default(); - astconv.add_bounds( - param_ty, - std::array::IntoIter::new([bound]), - &mut bounds, - ty::List::empty(), - ); + astconv.add_bounds(param_ty, [bound].into_iter(), &mut bounds, bound_vars); bounds.predicates(astconv.tcx(), param_ty) } @@ -2843,7 +2857,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { ); } else if attr.has_name(sym::linkage) { if let Some(val) = attr.value_str() { - codegen_fn_attrs.linkage = Some(linkage_by_name(tcx, id, &val.as_str())); + codegen_fn_attrs.linkage = Some(linkage_by_name(tcx, id, val.as_str())); } } else if attr.has_name(sym::link_section) { if let Some(val) = attr.value_str() { @@ -2888,7 +2902,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { } } } else if attr.has_name(sym::instruction_set) { - codegen_fn_attrs.instruction_set = match attr.meta().map(|i| i.kind) { + codegen_fn_attrs.instruction_set = match attr.meta_kind() { Some(MetaItemKind::List(ref items)) => match items.as_slice() { [NestedMetaItem::MetaItem(set)] => { let segments = @@ -2993,7 +3007,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { if !attr.has_name(sym::inline) { return ia; } - match attr.meta().map(|i| i.kind) { + match attr.meta_kind() { Some(MetaItemKind::Word) => InlineAttr::Hint, Some(MetaItemKind::List(ref items)) => { inline_span = Some(attr.span); @@ -3006,9 +3020,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { ) .emit(); InlineAttr::None - } else if list_contains_name(&items[..], sym::always) { + } else if list_contains_name(&items, sym::always) { InlineAttr::Always - } else if list_contains_name(&items[..], sym::never) { + } else if list_contains_name(&items, sym::never) { InlineAttr::Never } else { struct_span_err!( @@ -3032,7 +3046,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { return ia; } let err = |sp, s| struct_span_err!(tcx.sess.diagnostic(), sp, E0722, "{}", s).emit(); - match attr.meta().map(|i| i.kind) { + match attr.meta_kind() { Some(MetaItemKind::Word) => { err(attr.span, "expected one argument"); ia @@ -3042,9 +3056,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { if items.len() != 1 { err(attr.span, "expected one argument"); OptimizeAttr::None - } else if list_contains_name(&items[..], sym::size) { + } else if list_contains_name(&items, sym::size) { OptimizeAttr::Size - } else if list_contains_name(&items[..], sym::speed) { + } else if list_contains_name(&items, sym::speed) { OptimizeAttr::Speed } else { err(items[0].span(), "invalid argument"); @@ -3227,7 +3241,7 @@ fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: let hir_id = tcx.hir().local_def_id_to_hir_id(id); let node = tcx.hir().get(hir_id); if let Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node { - let parent_id = tcx.hir().get_parent_item(hir_id); + let parent_id = tcx.hir().get_parent_did(hir_id); let parent_item = tcx.hir().expect_item(parent_id); if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = parent_item.kind { tcx.sess diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 04a68250ce..ae8d262fcf 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -13,7 +13,7 @@ use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; use super::ItemCtxt; -use super::{bad_placeholder_type, is_suggestable_infer_ty}; +use super::{bad_placeholder, is_suggestable_infer_ty}; /// Computes the relevant generic parameter for a potential generic const argument. /// @@ -172,7 +172,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< // We've encountered an `AnonConst` in some path, so we need to // figure out which generic parameter it corresponds to and return // the relevant type. - let (arg_index, segment) = path + let filtered = path .segments .iter() .filter_map(|seg| seg.args.map(|args| (args.args, seg))) @@ -181,10 +181,17 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< .filter(|arg| arg.is_const()) .position(|arg| arg.id() == hir_id) .map(|index| (index, seg)) - }) - .unwrap_or_else(|| { - bug!("no arg matching AnonConst in path"); }); + let (arg_index, segment) = match filtered { + None => { + tcx.sess.delay_span_bug( + tcx.def_span(def_id), + "no arg matching AnonConst in path", + ); + return None; + } + Some(inner) => inner, + }; // Try to use the segment resolution if it is valid, otherwise we // default to the path resolution. @@ -387,13 +394,13 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); tcx.mk_adt(def, substs) } - ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: None, .. }) => { + ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => { find_opaque_ty_constraints(tcx, def_id) } // Opaque types desugared from `impl Trait`. - ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: Some(owner), .. }) => { + ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), .. }) => { let concrete_ty = tcx - .mir_borrowck(owner.expect_local()) + .mir_borrowck(owner) .concrete_opaque_types .get_value_matching(|(key, _)| key.def_id == def_id.to_def_id()) .copied() @@ -406,7 +413,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { ), ); if let Some(ErrorReported) = - tcx.typeck(owner.expect_local()).tainted_by_errors + tcx.typeck(owner).tainted_by_errors { // Some error in the // owner fn prevented us from populating @@ -463,14 +470,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { Node::Field(field) => icx.to_ty(field.ty), - Node::Expr(&Expr { kind: ExprKind::Closure(.., gen), .. }) => { - let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id()); - if let Some(movability) = gen { - tcx.mk_generator(def_id.to_def_id(), substs, movability) - } else { - tcx.mk_closure(def_id.to_def_id(), substs) - } - } + Node::Expr(&Expr { kind: ExprKind::Closure(..), .. }) => tcx.typeck(def_id).node_type(hir_id), Node::AnonConst(_) if let Some(param) = tcx.opt_const_param_of(def_id) => { // We defer to `type_of` of the corresponding parameter @@ -483,7 +483,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { match parent_node { Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. }) | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. }) - if constant.hir_id == hir_id => + if constant.hir_id() == hir_id => { tcx.types.usize } @@ -724,7 +724,7 @@ fn infer_placeholder_type<'a>( } } - impl TypeFolder<'tcx> for MakeNameable<'tcx> { + impl<'tcx> TypeFolder<'tcx> for MakeNameable<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -781,7 +781,7 @@ fn infer_placeholder_type<'a>( err.emit(); } None => { - let mut diag = bad_placeholder_type(tcx, vec![span], kind); + let mut diag = bad_placeholder(tcx, "type", vec![span], kind); if !ty.references_error() { let mut mk_nameable = MakeNameable::new(tcx); diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index 7d0600b99e..1ae0ff3036 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -229,8 +229,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } } - hir::ExprKind::Let(pat, ref expr, _) => { - self.walk_local(expr, pat, |t| t.borrow_expr(expr, ty::ImmBorrow)); + hir::ExprKind::Let(hir::Let { pat, init, .. }) => { + self.walk_local(init, pat, |t| t.borrow_expr(init, ty::ImmBorrow)); } hir::ExprKind::Match(ref discr, arms, _) => { @@ -482,7 +482,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } } - fn walk_struct_expr( + fn walk_struct_expr<'hir>( &mut self, fields: &[hir::ExprField<'_>], opt_with: &Option<&'hir hir::Expr<'_>>, @@ -705,7 +705,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { /// - When reporting the Place back to the Delegate, ensure that the UpvarId uses the enclosing /// closure as the DefId. fn walk_captures(&mut self, closure_expr: &hir::Expr<'_>) { - fn upvar_is_local_variable( + fn upvar_is_local_variable<'tcx>( upvars: Option<&'tcx FxIndexMap>, upvar_id: &hir::HirId, body_owner_is_closure: bool, @@ -715,13 +715,14 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { debug!("walk_captures({:?})", closure_expr); - let closure_def_id = self.tcx().hir().local_def_id(closure_expr.hir_id).to_def_id(); - let upvars = self.tcx().upvars_mentioned(self.body_owner); + let tcx = self.tcx(); + let closure_def_id = tcx.hir().local_def_id(closure_expr.hir_id).to_def_id(); + let upvars = tcx.upvars_mentioned(self.body_owner); // For purposes of this function, generator and closures are equivalent. let body_owner_is_closure = matches!( - self.tcx().type_of(self.body_owner.to_def_id()).kind(), - ty::Closure(..) | ty::Generator(..) + tcx.hir().body_owner_kind(tcx.hir().local_def_id_to_hir_id(self.body_owner)), + hir::BodyOwnerKind::Closure, ); // If we have a nested closure, we want to include the fake reads present in the nested closure. @@ -846,7 +847,7 @@ fn delegate_consume<'a, 'tcx>( } } -fn is_multivariant_adt(ty: Ty<'tcx>) -> bool { +fn is_multivariant_adt(ty: Ty<'_>) -> bool { if let ty::Adt(def, _) = ty.kind() { // Note that if a non-exhaustive SingleVariant is defined in another crate, we need // to assume that more cases will be added to the variant in the future. This mean diff --git a/compiler/rustc_typeck/src/impl_wf_check.rs b/compiler/rustc_typeck/src/impl_wf_check.rs index 5d2f8fc424..ae6321de7f 100644 --- a/compiler/rustc_typeck/src/impl_wf_check.rs +++ b/compiler/rustc_typeck/src/impl_wf_check.rs @@ -76,7 +76,7 @@ struct ImplWfCheck<'tcx> { min_specialization: bool, } -impl ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> { +impl<'tcx> ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { if let hir::ItemKind::Impl(ref impl_) = item.kind { enforce_impl_params_are_constrained(self.tcx, item.def_id, impl_.items); diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index 0881cf0758..24e427f4bc 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -58,11 +58,8 @@ This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] -#![cfg_attr(bootstrap, feature(format_args_capture))] #![feature(if_let_guard)] -#![feature(in_band_lifetimes)] #![feature(is_sorted)] -#![feature(iter_zip)] #![feature(let_else)] #![feature(min_specialization)] #![feature(nll)] diff --git a/compiler/rustc_typeck/src/outlives/test.rs b/compiler/rustc_typeck/src/outlives/test.rs index ec4fa9cd4b..b3efd9f9ec 100644 --- a/compiler/rustc_typeck/src/outlives/test.rs +++ b/compiler/rustc_typeck/src/outlives/test.rs @@ -12,7 +12,7 @@ struct OutlivesTest<'tcx> { tcx: TyCtxt<'tcx>, } -impl ItemLikeVisitor<'tcx> for OutlivesTest<'tcx> { +impl<'tcx> ItemLikeVisitor<'tcx> for OutlivesTest<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { // For unit testing: check for a special "rustc_outlives" // attribute and report an error with various results if found. diff --git a/compiler/rustc_typeck/src/variance/test.rs b/compiler/rustc_typeck/src/variance/test.rs index 7be3c68e8f..d6959075d8 100644 --- a/compiler/rustc_typeck/src/variance/test.rs +++ b/compiler/rustc_typeck/src/variance/test.rs @@ -12,7 +12,7 @@ struct VarianceTest<'tcx> { tcx: TyCtxt<'tcx>, } -impl ItemLikeVisitor<'tcx> for VarianceTest<'tcx> { +impl<'tcx> ItemLikeVisitor<'tcx> for VarianceTest<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { // For unit testing: check for a special "rustc_variance" // attribute and report an error with various results if found. diff --git a/config.toml.example b/config.toml.example index 4dd953a495..f24f8e81a7 100644 --- a/config.toml.example +++ b/config.toml.example @@ -488,9 +488,12 @@ changelog-seen = 2 # FIXME(#75760): Some UI tests fail when this option is enabled. #parallel-compiler = false -# The default linker that will be hard-coded into the generated compiler for -# targets that don't specify linker explicitly in their target specifications. -# Note that this is not the linker used to link said compiler. +# The default linker that will be hard-coded into the generated +# compiler for targets that don't specify a default linker explicitly +# in their target specifications. Note that this is not the linker +# used to link said compiler. It can also be set per-target (via the +# `[target.]` block), which may be useful in a cross-compilation +# setting. # # See https://doc.rust-lang.org/rustc/codegen-options/index.html#linker for more information. #default-linker = (path) diff --git a/git-commit-hash b/git-commit-hash index 0150433bdf..9d9179cf7d 100644 --- a/git-commit-hash +++ b/git-commit-hash @@ -1 +1 @@ -db9d1b20bba1968c1ec1fc49616d4742c1725b4b \ No newline at end of file +9d1b2106e23b1abd32fce1f17267604a5102f57a \ No newline at end of file diff --git a/library/alloc/benches/vec.rs b/library/alloc/benches/vec.rs index 8e1d374b5d..0da4886278 100644 --- a/library/alloc/benches/vec.rs +++ b/library/alloc/benches/vec.rs @@ -733,11 +733,26 @@ fn bench_flat_map_collect(b: &mut Bencher) { b.iter(|| v.iter().flat_map(|color| color.rotate_left(8).to_be_bytes()).collect::>()); } +/// Reference benchmark that `retain` has to compete with. +#[bench] +fn bench_retain_iter_100000(b: &mut Bencher) { + let mut v = Vec::with_capacity(100000); + + b.iter(|| { + let mut tmp = std::mem::take(&mut v); + tmp.clear(); + tmp.extend(black_box(1..=100000)); + v = tmp.into_iter().filter(|x| x & 1 == 0).collect(); + }); +} + #[bench] fn bench_retain_100000(b: &mut Bencher) { - let v = (1..=100000).collect::>(); + let mut v = Vec::with_capacity(100000); + b.iter(|| { - let mut v = v.clone(); + v.clear(); + v.extend(black_box(1..=100000)); v.retain(|x| x & 1 == 0) }); } diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 66ef92558d..d075658f51 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -323,17 +323,21 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { #[cfg_attr(not(test), lang = "box_free")] #[inline] +#[rustc_const_unstable(feature = "const_box", issue = "92521")] // This signature has to be the same as `Box`, otherwise an ICE will happen. // When an additional parameter to `Box` is added (like `A: Allocator`), this has to be added here as // well. // For example if `Box` is changed to `struct Box(Unique, A)`, // this function has to be changed to `fn box_free(Unique, A)` as well. -pub(crate) unsafe fn box_free(ptr: Unique, alloc: A) { +pub(crate) const unsafe fn box_free( + ptr: Unique, + alloc: A, +) { unsafe { let size = size_of_val(ptr.as_ref()); let align = min_align_of_val(ptr.as_ref()); let layout = Layout::from_size_align_unchecked(size, align); - alloc.deallocate(ptr.cast().into(), layout) + alloc.deallocate(From::from(ptr.cast()), layout) } } @@ -361,13 +365,22 @@ extern "Rust" { /// [`set_alloc_error_hook`]: ../../std/alloc/fn.set_alloc_error_hook.html /// [`take_alloc_error_hook`]: ../../std/alloc/fn.take_alloc_error_hook.html #[stable(feature = "global_alloc", since = "1.28.0")] +#[rustc_const_unstable(feature = "const_alloc_error", issue = "92523")] #[cfg(all(not(no_global_oom_handling), not(test)))] #[rustc_allocator_nounwind] #[cold] -pub fn handle_alloc_error(layout: Layout) -> ! { - unsafe { - __rust_alloc_error_handler(layout.size(), layout.align()); +pub const fn handle_alloc_error(layout: Layout) -> ! { + const fn ct_error(_: Layout) -> ! { + panic!("allocation failed"); } + + fn rt_error(layout: Layout) -> ! { + unsafe { + __rust_alloc_error_handler(layout.size(), layout.align()); + } + } + + unsafe { core::intrinsics::const_eval_select((layout,), ct_error, rt_error) } } // For alloc test `std::alloc::handle_alloc_error` can be used directly. diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs index 9ecbf05823..63234ee91f 100644 --- a/library/alloc/src/borrow.rs +++ b/library/alloc/src/borrow.rs @@ -170,7 +170,7 @@ where /// clone_on_write.values.to_mut().push(3); /// println!("clone_on_write = {:?}", clone_on_write.values); /// -/// // The data was mutated. Let check it out. +/// // The data was mutated. Let's check it out. /// match clone_on_write { /// Items { values: Cow::Owned(_) } => println!("clone_on_write contains owned data"), /// _ => panic!("expect owned data"), diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index f6332b072c..aa7344ba40 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -346,9 +346,13 @@ impl Box { /// ``` #[cfg(not(no_global_oom_handling))] #[unstable(feature = "allocator_api", issue = "32838")] + #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[must_use] #[inline] - pub fn new_in(x: T, alloc: A) -> Self { + pub const fn new_in(x: T, alloc: A) -> Self + where + A: ~const Allocator + ~const Drop, + { let mut boxed = Self::new_uninit_in(alloc); unsafe { boxed.as_mut_ptr().write(x); @@ -372,8 +376,13 @@ impl Box { /// # Ok::<(), std::alloc::AllocError>(()) /// ``` #[unstable(feature = "allocator_api", issue = "32838")] + #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] - pub fn try_new_in(x: T, alloc: A) -> Result { + pub const fn try_new_in(x: T, alloc: A) -> Result + where + T: ~const Drop, + A: ~const Allocator + ~const Drop, + { let mut boxed = Self::try_new_uninit_in(alloc)?; unsafe { boxed.as_mut_ptr().write(x); @@ -402,10 +411,14 @@ impl Box { /// assert_eq!(*five, 5) /// ``` #[unstable(feature = "allocator_api", issue = "32838")] + #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[cfg(not(no_global_oom_handling))] #[must_use] // #[unstable(feature = "new_uninit", issue = "63291")] - pub fn new_uninit_in(alloc: A) -> Box, A> { + pub const fn new_uninit_in(alloc: A) -> Box, A> + where + A: ~const Allocator + ~const Drop, + { let layout = Layout::new::>(); // NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable. // That would make code size bigger. @@ -439,7 +452,11 @@ impl Box { /// ``` #[unstable(feature = "allocator_api", issue = "32838")] // #[unstable(feature = "new_uninit", issue = "63291")] - pub fn try_new_uninit_in(alloc: A) -> Result, A>, AllocError> { + #[rustc_const_unstable(feature = "const_box", issue = "92521")] + pub const fn try_new_uninit_in(alloc: A) -> Result, A>, AllocError> + where + A: ~const Allocator + ~const Drop, + { let layout = Layout::new::>(); let ptr = alloc.allocate(layout)?.cast(); unsafe { Ok(Box::from_raw_in(ptr.as_ptr(), alloc)) } @@ -466,10 +483,14 @@ impl Box { /// /// [zeroed]: mem::MaybeUninit::zeroed #[unstable(feature = "allocator_api", issue = "32838")] + #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[cfg(not(no_global_oom_handling))] // #[unstable(feature = "new_uninit", issue = "63291")] #[must_use] - pub fn new_zeroed_in(alloc: A) -> Box, A> { + pub const fn new_zeroed_in(alloc: A) -> Box, A> + where + A: ~const Allocator + ~const Drop, + { let layout = Layout::new::>(); // NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable. // That would make code size bigger. @@ -503,7 +524,11 @@ impl Box { /// [zeroed]: mem::MaybeUninit::zeroed #[unstable(feature = "allocator_api", issue = "32838")] // #[unstable(feature = "new_uninit", issue = "63291")] - pub fn try_new_zeroed_in(alloc: A) -> Result, A>, AllocError> { + #[rustc_const_unstable(feature = "const_box", issue = "92521")] + pub const fn try_new_zeroed_in(alloc: A) -> Result, A>, AllocError> + where + A: ~const Allocator + ~const Drop, + { let layout = Layout::new::>(); let ptr = alloc.allocate_zeroed(layout)?.cast(); unsafe { Ok(Box::from_raw_in(ptr.as_ptr(), alloc)) } @@ -513,20 +538,22 @@ impl Box { /// `x` will be pinned in memory and unable to be moved. #[cfg(not(no_global_oom_handling))] #[unstable(feature = "allocator_api", issue = "32838")] + #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[must_use] #[inline(always)] - pub fn pin_in(x: T, alloc: A) -> Pin + pub const fn pin_in(x: T, alloc: A) -> Pin where - A: 'static, + A: 'static + ~const Allocator + ~const Drop, { - Self::new_in(x, alloc).into() + Self::into_pin(Self::new_in(x, alloc)) } /// Converts a `Box` into a `Box<[T]>` /// /// This conversion does not allocate on the heap and happens in place. #[unstable(feature = "box_into_boxed_slice", issue = "71582")] - pub fn into_boxed_slice(boxed: Self) -> Box<[T], A> { + #[rustc_const_unstable(feature = "const_box", issue = "92521")] + pub const fn into_boxed_slice(boxed: Self) -> Box<[T], A> { let (raw, alloc) = Box::into_raw_with_allocator(boxed); unsafe { Box::from_raw_in(raw as *mut [T; 1], alloc) } } @@ -543,8 +570,12 @@ impl Box { /// assert_eq!(Box::into_inner(c), 5); /// ``` #[unstable(feature = "box_into_inner", issue = "80437")] + #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] - pub fn into_inner(boxed: Self) -> T { + pub const fn into_inner(boxed: Self) -> T + where + Self: ~const Drop, + { *boxed } } @@ -758,11 +789,49 @@ impl Box, A> { /// assert_eq!(*five, 5) /// ``` #[unstable(feature = "new_uninit", issue = "63291")] + #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] - pub unsafe fn assume_init(self) -> Box { + pub const unsafe fn assume_init(self) -> Box { let (raw, alloc) = Box::into_raw_with_allocator(self); unsafe { Box::from_raw_in(raw as *mut T, alloc) } } + + /// Writes the value and converts to `Box`. + /// + /// This method converts the box similarly to [`Box::assume_init`] but + /// writes `value` into it before conversion thus guaranteeing safety. + /// In some scenarios use of this method may improve performance because + /// the compiler may be able to optimize copying from stack. + /// + /// # Examples + /// + /// ``` + /// #![feature(new_uninit)] + /// + /// let big_box = Box::<[usize; 1024]>::new_uninit(); + /// + /// let mut array = [0; 1024]; + /// for (i, place) in array.iter_mut().enumerate() { + /// *place = i; + /// } + /// + /// // The optimizer may be able to elide this copy, so previous code writes + /// // to heap directly. + /// let big_box = Box::write(big_box, array); + /// + /// for (i, x) in big_box.iter().enumerate() { + /// assert_eq!(*x, i); + /// } + /// ``` + #[unstable(feature = "new_uninit", issue = "63291")] + #[rustc_const_unstable(feature = "const_box", issue = "92521")] + #[inline] + pub const fn write(mut boxed: Self, value: T) -> Box { + unsafe { + (*boxed).write(value); + boxed.assume_init() + } + } } impl Box<[mem::MaybeUninit], A> { @@ -902,8 +971,9 @@ impl Box { /// [memory layout]: self#memory-layout /// [`Layout`]: crate::Layout #[unstable(feature = "allocator_api", issue = "32838")] + #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] - pub unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self { + pub const unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self { Box(unsafe { Unique::new_unchecked(raw) }, alloc) } @@ -999,8 +1069,9 @@ impl Box { /// /// [memory layout]: self#memory-layout #[unstable(feature = "allocator_api", issue = "32838")] + #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] - pub fn into_raw_with_allocator(b: Self) -> (*mut T, A) { + pub const fn into_raw_with_allocator(b: Self) -> (*mut T, A) { let (leaked, alloc) = Box::into_unique(b); (leaked.as_ptr(), alloc) } @@ -1010,9 +1081,10 @@ impl Box { issue = "none", reason = "use `Box::leak(b).into()` or `Unique::from(Box::leak(b))` instead" )] + #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] #[doc(hidden)] - pub fn into_unique(b: Self) -> (Unique, A) { + pub const fn into_unique(b: Self) -> (Unique, A) { // Box is recognized as a "unique pointer" by Stacked Borrows, but internally it is a // raw pointer for the type system. Turning it directly into a raw pointer would not be // recognized as "releasing" the unique pointer to permit aliased raw accesses, @@ -1028,8 +1100,9 @@ impl Box { /// to call it as `Box::allocator(&b)` instead of `b.allocator()`. This /// is so that there is no conflict with a method on the inner type. #[unstable(feature = "allocator_api", issue = "32838")] + #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] - pub fn allocator(b: &Self) -> &A { + pub const fn allocator(b: &Self) -> &A { &b.1 } @@ -1069,8 +1142,9 @@ impl Box { /// assert_eq!(*static_ref, [4, 2, 3]); /// ``` #[stable(feature = "box_leak", since = "1.26.0")] + #[rustc_const_unstable(feature = "const_box", issue = "92521")] #[inline] - pub fn leak<'a>(b: Self) -> &'a mut T + pub const fn leak<'a>(b: Self) -> &'a mut T where A: 'a, { @@ -1083,7 +1157,8 @@ impl Box { /// /// This is also available via [`From`]. #[unstable(feature = "box_into_pin", issue = "62370")] - pub fn into_pin(boxed: Self) -> Pin + #[rustc_const_unstable(feature = "const_box", issue = "92521")] + pub const fn into_pin(boxed: Self) -> Pin where A: 'static, { @@ -1095,7 +1170,8 @@ impl Box { } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Box { +#[rustc_const_unstable(feature = "const_box", issue = "92521")] +unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> const Drop for Box { fn drop(&mut self) { // FIXME: Do nothing, drop is currently performed by compiler. } @@ -1305,7 +1381,8 @@ impl From for Box { } #[stable(feature = "pin", since = "1.33.0")] -impl From> for Pin> +#[rustc_const_unstable(feature = "const_box", issue = "92521")] +impl const From> for Pin> where A: 'static, { @@ -1482,8 +1559,6 @@ impl TryFrom> for Box<[T; N]> { } impl Box { - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] /// Attempt to downcast the box to a concrete type. /// /// # Examples @@ -1501,21 +1576,48 @@ impl Box { /// print_if_string(Box::new(my_string)); /// print_if_string(Box::new(0i8)); /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn downcast(self) -> Result, Self> { - if self.is::() { - unsafe { - let (raw, alloc): (*mut dyn Any, _) = Box::into_raw_with_allocator(self); - Ok(Box::from_raw_in(raw as *mut T, alloc)) - } - } else { - Err(self) + if self.is::() { unsafe { Ok(self.downcast_unchecked::()) } } else { Err(self) } + } + + /// Downcasts the box to a concrete type. + /// + /// For a safe alternative see [`downcast`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// + /// let x: Box = Box::new(1_usize); + /// + /// unsafe { + /// assert_eq!(*x.downcast_unchecked::(), 1); + /// } + /// ``` + /// + /// # Safety + /// + /// The contained value must be of type `T`. Calling this method + /// with the incorrect type is *undefined behavior*. + /// + /// [`downcast`]: Self::downcast + #[inline] + #[unstable(feature = "downcast_unchecked", issue = "90850")] + pub unsafe fn downcast_unchecked(self) -> Box { + debug_assert!(self.is::()); + unsafe { + let (raw, alloc): (*mut dyn Any, _) = Box::into_raw_with_allocator(self); + Box::from_raw_in(raw as *mut T, alloc) } } } impl Box { - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] /// Attempt to downcast the box to a concrete type. /// /// # Examples @@ -1533,21 +1635,48 @@ impl Box { /// print_if_string(Box::new(my_string)); /// print_if_string(Box::new(0i8)); /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] pub fn downcast(self) -> Result, Self> { - if self.is::() { - unsafe { - let (raw, alloc): (*mut (dyn Any + Send), _) = Box::into_raw_with_allocator(self); - Ok(Box::from_raw_in(raw as *mut T, alloc)) - } - } else { - Err(self) + if self.is::() { unsafe { Ok(self.downcast_unchecked::()) } } else { Err(self) } + } + + /// Downcasts the box to a concrete type. + /// + /// For a safe alternative see [`downcast`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// + /// let x: Box = Box::new(1_usize); + /// + /// unsafe { + /// assert_eq!(*x.downcast_unchecked::(), 1); + /// } + /// ``` + /// + /// # Safety + /// + /// The contained value must be of type `T`. Calling this method + /// with the incorrect type is *undefined behavior*. + /// + /// [`downcast`]: Self::downcast + #[inline] + #[unstable(feature = "downcast_unchecked", issue = "90850")] + pub unsafe fn downcast_unchecked(self) -> Box { + debug_assert!(self.is::()); + unsafe { + let (raw, alloc): (*mut (dyn Any + Send), _) = Box::into_raw_with_allocator(self); + Box::from_raw_in(raw as *mut T, alloc) } } } impl Box { - #[inline] - #[stable(feature = "box_send_sync_any_downcast", since = "1.51.0")] /// Attempt to downcast the box to a concrete type. /// /// # Examples @@ -1565,15 +1694,44 @@ impl Box { /// print_if_string(Box::new(my_string)); /// print_if_string(Box::new(0i8)); /// ``` + #[inline] + #[stable(feature = "box_send_sync_any_downcast", since = "1.51.0")] pub fn downcast(self) -> Result, Self> { - if self.is::() { - unsafe { - let (raw, alloc): (*mut (dyn Any + Send + Sync), _) = - Box::into_raw_with_allocator(self); - Ok(Box::from_raw_in(raw as *mut T, alloc)) - } - } else { - Err(self) + if self.is::() { unsafe { Ok(self.downcast_unchecked::()) } } else { Err(self) } + } + + /// Downcasts the box to a concrete type. + /// + /// For a safe alternative see [`downcast`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// + /// let x: Box = Box::new(1_usize); + /// + /// unsafe { + /// assert_eq!(*x.downcast_unchecked::(), 1); + /// } + /// ``` + /// + /// # Safety + /// + /// The contained value must be of type `T`. Calling this method + /// with the incorrect type is *undefined behavior*. + /// + /// [`downcast`]: Self::downcast + #[inline] + #[unstable(feature = "downcast_unchecked", issue = "90850")] + pub unsafe fn downcast_unchecked(self) -> Box { + debug_assert!(self.is::()); + unsafe { + let (raw, alloc): (*mut (dyn Any + Send + Sync), _) = + Box::into_raw_with_allocator(self); + Box::from_raw_in(raw as *mut T, alloc) } } } @@ -1603,7 +1761,8 @@ impl fmt::Pointer for Box { } #[stable(feature = "rust1", since = "1.0.0")] -impl Deref for Box { +#[rustc_const_unstable(feature = "const_box", issue = "92521")] +impl const Deref for Box { type Target = T; fn deref(&self) -> &T { @@ -1612,7 +1771,8 @@ impl Deref for Box { } #[stable(feature = "rust1", since = "1.0.0")] -impl DerefMut for Box { +#[rustc_const_unstable(feature = "const_box", issue = "92521")] +impl const DerefMut for Box { fn deref_mut(&mut self) -> &mut T { &mut **self } @@ -1791,7 +1951,8 @@ impl AsMut for Box { * could have a method to project a Pin from it. */ #[stable(feature = "pin", since = "1.33.0")] -impl Unpin for Box where A: 'static {} +#[rustc_const_unstable(feature = "const_box", issue = "92521")] +impl const Unpin for Box where A: 'static {} #[unstable(feature = "generator_trait", issue = "43122")] impl + Unpin, R, A: Allocator> Generator for Box diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs index 7d87974b47..6fc6002d55 100644 --- a/library/alloc/src/collections/binary_heap.rs +++ b/library/alloc/src/collections/binary_heap.rs @@ -149,6 +149,7 @@ use core::mem::{self, swap, ManuallyDrop}; use core::ops::{Deref, DerefMut}; use core::ptr; +use crate::collections::TryReserveError; use crate::slice; use crate::vec::{self, AsIntoIter, Vec}; @@ -953,6 +954,84 @@ impl BinaryHeap { self.data.reserve(additional); } + /// Tries to reserve the minimum capacity for exactly `additional` + /// elements to be inserted in the given `BinaryHeap`. After calling + /// `try_reserve_exact`, capacity will be greater than or equal to + /// `self.len() + additional` if it returns `Ok(())`. + /// Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the collection more space than it + /// requests. Therefore, capacity can not be relied upon to be precisely + /// minimal. Prefer [`try_reserve`] if future insertions are expected. + /// + /// [`try_reserve`]: BinaryHeap::try_reserve + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_reserve_2)] + /// use std::collections::BinaryHeap; + /// use std::collections::TryReserveError; + /// + /// fn find_max_slow(data: &[u32]) -> Result, TryReserveError> { + /// let mut heap = BinaryHeap::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// heap.try_reserve_exact(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// heap.extend(data.iter()); + /// + /// Ok(heap.pop()) + /// } + /// # find_max_slow(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); + /// ``` + #[unstable(feature = "try_reserve_2", issue = "91789")] + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.data.try_reserve_exact(additional) + } + + /// Tries to reserve capacity for at least `additional` more elements to be inserted + /// in the given `BinaryHeap`. The collection may reserve more space to avoid + /// frequent reallocations. After calling `try_reserve`, capacity will be + /// greater than or equal to `self.len() + additional`. Does nothing if + /// capacity is already sufficient. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_reserve_2)] + /// use std::collections::BinaryHeap; + /// use std::collections::TryReserveError; + /// + /// fn find_max_slow(data: &[u32]) -> Result, TryReserveError> { + /// let mut heap = BinaryHeap::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// heap.try_reserve(data.len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// heap.extend(data.iter()); + /// + /// Ok(heap.pop()) + /// } + /// # find_max_slow(&[1, 2, 3]).expect("why is the test harness OOMing on 12 bytes?"); + /// ``` + #[unstable(feature = "try_reserve_2", issue = "91789")] + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.data.try_reserve(additional) + } + /// Discards as much additional capacity as possible. /// /// # Examples @@ -1500,7 +1579,7 @@ impl From<[T; N]> for BinaryHeap { /// } /// ``` fn from(arr: [T; N]) -> Self { - core::array::IntoIter::new(arr).collect() + Self::from_iter(arr) } } diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 2ff7b0fbb7..199c05dc5d 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -1305,11 +1305,11 @@ impl BTreeMap { pub(crate) fn bulk_build_from_sorted_iter(iter: I) -> Self where K: Ord, - I: Iterator, + I: IntoIterator, { let mut root = Root::new(); let mut length = 0; - root.bulk_push(DedupSortedIter::new(iter), &mut length); + root.bulk_push(DedupSortedIter::new(iter.into_iter()), &mut length); BTreeMap { root: Some(root), length } } } @@ -1944,7 +1944,7 @@ impl FromIterator<(K, V)> for BTreeMap { // use stable sort to preserve the insertion order. inputs.sort_by(|a, b| a.0.cmp(&b.0)); - BTreeMap::bulk_build_from_sorted_iter(inputs.into_iter()) + BTreeMap::bulk_build_from_sorted_iter(inputs) } } @@ -2061,7 +2061,7 @@ impl From<[(K, V); N]> for BTreeMap { // use stable sort to preserve the insertion order. arr.sort_by(|a, b| a.0.cmp(&b.0)); - BTreeMap::bulk_build_from_sorted_iter(core::array::IntoIter::new(arr)) + BTreeMap::bulk_build_from_sorted_iter(arr) } } @@ -2107,10 +2107,11 @@ impl BTreeMap { /// ``` /// use std::collections::BTreeMap; /// - /// let mut map = BTreeMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); + /// let mut map = BTreeMap::from([ + /// ("a", 1), + /// ("b", 2), + /// ("c", 3), + /// ]); /// /// // add 10 to the value if the key isn't "a" /// for (key, value) in map.iter_mut() { diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs index 17389657af..c95aeeaa60 100644 --- a/library/alloc/src/collections/btree/map/tests.rs +++ b/library/alloc/src/collections/btree/map/tests.rs @@ -1556,7 +1556,7 @@ fn test_clone_from() { } #[allow(dead_code)] -fn test_variance() { +fn assert_covariance() { fn map_key<'new>(v: BTreeMap<&'static str, ()>) -> BTreeMap<&'new str, ()> { v } @@ -1615,7 +1615,7 @@ fn test_variance() { } #[allow(dead_code)] -fn test_sync() { +fn assert_sync() { fn map(v: &BTreeMap) -> impl Sync + '_ { v } @@ -1684,7 +1684,7 @@ fn test_sync() { } #[allow(dead_code)] -fn test_send() { +fn assert_send() { fn map(v: BTreeMap) -> impl Send { v } diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 0322cabccd..394c21bf51 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -155,7 +155,7 @@ enum DifferenceInner<'a, T: 'a> { self_iter: Iter<'a, T>, other_set: &'a BTreeSet, }, - Iterate(Iter<'a, T>), // simply produce all values in `self` + Iterate(Iter<'a, T>), // simply produce all elements in `self` } #[stable(feature = "collection_debug", since = "1.17.0")] @@ -207,7 +207,7 @@ enum IntersectionInner<'a, T: 'a> { small_iter: Iter<'a, T>, large_set: &'a BTreeSet, }, - Answer(Option<&'a T>), // return a specific value or emptiness + Answer(Option<&'a T>), // return a specific element or emptiness } #[stable(feature = "collection_debug", since = "1.17.0")] @@ -295,8 +295,8 @@ impl BTreeSet { Range { iter: self.map.range(range) } } - /// Visits the values representing the difference, - /// i.e., the values that are in `self` but not in `other`, + /// Visits the elements representing the difference, + /// i.e., the elements that are in `self` but not in `other`, /// in ascending order. /// /// # Examples @@ -356,8 +356,8 @@ impl BTreeSet { } } - /// Visits the values representing the symmetric difference, - /// i.e., the values that are in `self` or in `other` but not in both, + /// Visits the elements representing the symmetric difference, + /// i.e., the elements that are in `self` or in `other` but not in both, /// in ascending order. /// /// # Examples @@ -384,8 +384,8 @@ impl BTreeSet { SymmetricDifference(MergeIterInner::new(self.iter(), other.iter())) } - /// Visits the values representing the intersection, - /// i.e., the values that are both in `self` and `other`, + /// Visits the elements representing the intersection, + /// i.e., the elements that are both in `self` and `other`, /// in ascending order. /// /// # Examples @@ -437,8 +437,8 @@ impl BTreeSet { } } - /// Visits the values representing the union, - /// i.e., all the values in `self` or `other`, without duplicates, + /// Visits the elements representing the union, + /// i.e., all the elements in `self` or `other`, without duplicates, /// in ascending order. /// /// # Examples @@ -463,7 +463,7 @@ impl BTreeSet { Union(MergeIterInner::new(self.iter(), other.iter())) } - /// Clears the set, removing all values. + /// Clears the set, removing all elements. /// /// # Examples /// @@ -480,18 +480,18 @@ impl BTreeSet { self.map.clear() } - /// Returns `true` if the set contains a value. + /// Returns `true` if the set contains an element equal to the value. /// - /// The value may be any borrowed form of the set's value type, + /// The value may be any borrowed form of the set's element type, /// but the ordering on the borrowed form *must* match the - /// ordering on the value type. + /// ordering on the element type. /// /// # Examples /// /// ``` /// use std::collections::BTreeSet; /// - /// let set: BTreeSet<_> = [1, 2, 3].iter().cloned().collect(); + /// let set = BTreeSet::from([1, 2, 3]); /// assert_eq!(set.contains(&1), true); /// assert_eq!(set.contains(&4), false); /// ``` @@ -504,18 +504,19 @@ impl BTreeSet { self.map.contains_key(value) } - /// Returns a reference to the value in the set, if any, that is equal to the given value. + /// Returns a reference to the element in the set, if any, that is equal to + /// the value. /// - /// The value may be any borrowed form of the set's value type, + /// The value may be any borrowed form of the set's element type, /// but the ordering on the borrowed form *must* match the - /// ordering on the value type. + /// ordering on the element type. /// /// # Examples /// /// ``` /// use std::collections::BTreeSet; /// - /// let set: BTreeSet<_> = [1, 2, 3].iter().cloned().collect(); + /// let set = BTreeSet::from([1, 2, 3]); /// assert_eq!(set.get(&2), Some(&2)); /// assert_eq!(set.get(&4), None); /// ``` @@ -536,7 +537,7 @@ impl BTreeSet { /// ``` /// use std::collections::BTreeSet; /// - /// let a: BTreeSet<_> = [1, 2, 3].iter().cloned().collect(); + /// let a = BTreeSet::from([1, 2, 3]); /// let mut b = BTreeSet::new(); /// /// assert_eq!(a.is_disjoint(&b), true); @@ -555,14 +556,14 @@ impl BTreeSet { } /// Returns `true` if the set is a subset of another, - /// i.e., `other` contains at least all the values in `self`. + /// i.e., `other` contains at least all the elements in `self`. /// /// # Examples /// /// ``` /// use std::collections::BTreeSet; /// - /// let sup: BTreeSet<_> = [1, 2, 3].iter().cloned().collect(); + /// let sup = BTreeSet::from([1, 2, 3]); /// let mut set = BTreeSet::new(); /// /// assert_eq!(set.is_subset(&sup), true); @@ -632,14 +633,14 @@ impl BTreeSet { } /// Returns `true` if the set is a superset of another, - /// i.e., `self` contains at least all the values in `other`. + /// i.e., `self` contains at least all the elements in `other`. /// /// # Examples /// /// ``` /// use std::collections::BTreeSet; /// - /// let sub: BTreeSet<_> = [1, 2].iter().cloned().collect(); + /// let sub = BTreeSet::from([1, 2]); /// let mut set = BTreeSet::new(); /// /// assert_eq!(set.is_superset(&sub), false); @@ -660,8 +661,8 @@ impl BTreeSet { other.is_subset(self) } - /// Returns a reference to the first value in the set, if any. - /// This value is always the minimum of all values in the set. + /// Returns a reference to the first element in the set, if any. + /// This element is always the minimum of all elements in the set. /// /// # Examples /// @@ -687,8 +688,8 @@ impl BTreeSet { self.map.first_key_value().map(|(k, _)| k) } - /// Returns a reference to the last value in the set, if any. - /// This value is always the maximum of all values in the set. + /// Returns a reference to the last element in the set, if any. + /// This element is always the maximum of all elements in the set. /// /// # Examples /// @@ -714,8 +715,8 @@ impl BTreeSet { self.map.last_key_value().map(|(k, _)| k) } - /// Removes the first value from the set and returns it, if any. - /// The first value is always the minimum value in the set. + /// Removes the first element from the set and returns it, if any. + /// The first element is always the minimum element in the set. /// /// # Examples /// @@ -739,8 +740,8 @@ impl BTreeSet { self.map.pop_first().map(|kv| kv.0) } - /// Removes the last value from the set and returns it, if any. - /// The last value is always the maximum value in the set. + /// Removes the last element from the set and returns it, if any. + /// The last element is always the maximum element in the set. /// /// # Examples /// @@ -766,10 +767,10 @@ impl BTreeSet { /// Adds a value to the set. /// - /// If the set did not have this value present, `true` is returned. + /// If the set did not have an equal element present, `true` is returned. /// - /// If the set did have this value present, `false` is returned, and the - /// entry is not updated. See the [module-level documentation] for more. + /// If the set did have an equal element present, `false` is returned, and + /// the entry is not updated. See the [module-level documentation] for more. /// /// [module-level documentation]: index.html#insert-and-complex-keys /// @@ -792,8 +793,8 @@ impl BTreeSet { self.map.insert(value, ()).is_none() } - /// Adds a value to the set, replacing the existing value, if any, that is equal to the given - /// one. Returns the replaced value. + /// Adds a value to the set, replacing the existing element, if any, that is + /// equal to the value. Returns the replaced element. /// /// # Examples /// @@ -815,12 +816,12 @@ impl BTreeSet { Recover::replace(&mut self.map, value) } - /// Removes a value from the set. Returns whether the value was - /// present in the set. + /// If the set contains an element equal to the value, removes it from the + /// set and drops it. Returns whether such an element was present. /// - /// The value may be any borrowed form of the set's value type, + /// The value may be any borrowed form of the set's element type, /// but the ordering on the borrowed form *must* match the - /// ordering on the value type. + /// ordering on the element type. /// /// # Examples /// @@ -842,18 +843,19 @@ impl BTreeSet { self.map.remove(value).is_some() } - /// Removes and returns the value in the set, if any, that is equal to the given one. + /// Removes and returns the element in the set, if any, that is equal to + /// the value. /// - /// The value may be any borrowed form of the set's value type, + /// The value may be any borrowed form of the set's element type, /// but the ordering on the borrowed form *must* match the - /// ordering on the value type. + /// ordering on the element type. /// /// # Examples /// /// ``` /// use std::collections::BTreeSet; /// - /// let mut set: BTreeSet<_> = [1, 2, 3].iter().cloned().collect(); + /// let mut set = BTreeSet::from([1, 2, 3]); /// assert_eq!(set.take(&2), Some(2)); /// assert_eq!(set.take(&2), None); /// ``` @@ -876,8 +878,7 @@ impl BTreeSet { /// ``` /// use std::collections::BTreeSet; /// - /// let xs = [1, 2, 3, 4, 5, 6]; - /// let mut set: BTreeSet = xs.iter().cloned().collect(); + /// let mut set = BTreeSet::from([1, 2, 3, 4, 5, 6]); /// // Keep only the even numbers. /// set.retain(|&k| k % 2 == 0); /// assert!(set.iter().eq([2, 4, 6].iter())); @@ -927,8 +928,8 @@ impl BTreeSet { self.map.append(&mut other.map); } - /// Splits the collection into two at the given value. Returns everything after the given value, - /// including the value. + /// Splits the collection into two at the value. Returns a new collection + /// with all elements greater than or equal to the value. /// /// # Examples /// @@ -964,20 +965,20 @@ impl BTreeSet { BTreeSet { map: self.map.split_off(value) } } - /// Creates an iterator that visits all values in ascending order and uses a closure - /// to determine if a value should be removed. + /// Creates an iterator that visits all elements in ascending order and + /// uses a closure to determine if an element should be removed. /// - /// If the closure returns `true`, the value is removed from the set and yielded. If - /// the closure returns `false`, or panics, the value remains in the set and will - /// not be yielded. + /// If the closure returns `true`, the element is removed from the set and + /// yielded. If the closure returns `false`, or panics, the element remains + /// in the set and will not be yielded. /// - /// If the iterator is only partially consumed or not consumed at all, each of the - /// remaining values is still subjected to the closure and removed and dropped if it - /// returns `true`. + /// If the iterator is only partially consumed or not consumed at all, each + /// of the remaining elements is still subjected to the closure and removed + /// and dropped if it returns `true`. /// - /// It is unspecified how many more values will be subjected to the closure if a - /// panic occurs in the closure, or if a panic occurs while dropping a value, or if - /// the `DrainFilter` itself is leaked. + /// It is unspecified how many more elements will be subjected to the + /// closure if a panic occurs in the closure, or if a panic occurs while + /// dropping an element, or if the `DrainFilter` itself is leaked. /// /// # Examples /// @@ -1002,14 +1003,15 @@ impl BTreeSet { DrainFilter { pred, inner: self.map.drain_filter_inner() } } - /// Gets an iterator that visits the values in the `BTreeSet` in ascending order. + /// Gets an iterator that visits the elements in the `BTreeSet` in ascending + /// order. /// /// # Examples /// /// ``` /// use std::collections::BTreeSet; /// - /// let set: BTreeSet = [1, 2, 3].iter().cloned().collect(); + /// let set = BTreeSet::from([1, 2, 3]); /// let mut set_iter = set.iter(); /// assert_eq!(set_iter.next(), Some(&1)); /// assert_eq!(set_iter.next(), Some(&2)); @@ -1022,7 +1024,7 @@ impl BTreeSet { /// ``` /// use std::collections::BTreeSet; /// - /// let set: BTreeSet = [3, 1, 2].iter().cloned().collect(); + /// let set = BTreeSet::from([3, 1, 2]); /// let mut set_iter = set.iter(); /// assert_eq!(set_iter.next(), Some(&1)); /// assert_eq!(set_iter.next(), Some(&2)); @@ -1106,7 +1108,7 @@ impl From<[T; N]> for BTreeSet { // use stable sort to preserve the insertion order. arr.sort(); - let iter = core::array::IntoIter::new(arr).map(|k| (k, ())); + let iter = IntoIterator::into_iter(arr).map(|k| (k, ())); let map = BTreeMap::bulk_build_from_sorted_iter(iter); BTreeSet { map } } @@ -1124,7 +1126,7 @@ impl IntoIterator for BTreeSet { /// ``` /// use std::collections::BTreeSet; /// - /// let set: BTreeSet = [1, 2, 3, 4].iter().cloned().collect(); + /// let set = BTreeSet::from([1, 2, 3, 4]); /// /// let v: Vec<_> = set.into_iter().collect(); /// assert_eq!(v, [1, 2, 3, 4]); @@ -1243,8 +1245,8 @@ impl Sub<&BTreeSet> for &BTreeSet { /// ``` /// use std::collections::BTreeSet; /// - /// let a: BTreeSet<_> = vec![1, 2, 3].into_iter().collect(); - /// let b: BTreeSet<_> = vec![3, 4, 5].into_iter().collect(); + /// let a = BTreeSet::from([1, 2, 3]); + /// let b = BTreeSet::from([3, 4, 5]); /// /// let result = &a - &b; /// let result_vec: Vec<_> = result.into_iter().collect(); @@ -1266,8 +1268,8 @@ impl BitXor<&BTreeSet> for &BTreeSet { /// ``` /// use std::collections::BTreeSet; /// - /// let a: BTreeSet<_> = vec![1, 2, 3].into_iter().collect(); - /// let b: BTreeSet<_> = vec![2, 3, 4].into_iter().collect(); + /// let a = BTreeSet::from([1, 2, 3]); + /// let b = BTreeSet::from([2, 3, 4]); /// /// let result = &a ^ &b; /// let result_vec: Vec<_> = result.into_iter().collect(); @@ -1289,8 +1291,8 @@ impl BitAnd<&BTreeSet> for &BTreeSet { /// ``` /// use std::collections::BTreeSet; /// - /// let a: BTreeSet<_> = vec![1, 2, 3].into_iter().collect(); - /// let b: BTreeSet<_> = vec![2, 3, 4].into_iter().collect(); + /// let a = BTreeSet::from([1, 2, 3]); + /// let b = BTreeSet::from([2, 3, 4]); /// /// let result = &a & &b; /// let result_vec: Vec<_> = result.into_iter().collect(); @@ -1312,8 +1314,8 @@ impl BitOr<&BTreeSet> for &BTreeSet { /// ``` /// use std::collections::BTreeSet; /// - /// let a: BTreeSet<_> = vec![1, 2, 3].into_iter().collect(); - /// let b: BTreeSet<_> = vec![3, 4, 5].into_iter().collect(); + /// let a = BTreeSet::from([1, 2, 3]); + /// let b = BTreeSet::from([3, 4, 5]); /// /// let result = &a | &b; /// let result_vec: Vec<_> = result.into_iter().collect(); diff --git a/library/alloc/src/collections/btree/set/tests.rs b/library/alloc/src/collections/btree/set/tests.rs index 2fc17a7c86..7390ff5a59 100644 --- a/library/alloc/src/collections/btree/set/tests.rs +++ b/library/alloc/src/collections/btree/set/tests.rs @@ -3,6 +3,7 @@ use super::super::testing::rng::DeterministicRng; use super::*; use crate::vec::Vec; use std::cmp::Ordering; +use std::hash::{Hash, Hasher}; use std::iter::FromIterator; use std::panic::{catch_unwind, AssertUnwindSafe}; @@ -513,7 +514,7 @@ fn test_recovery() { } #[allow(dead_code)] -fn test_variance() { +fn assert_covariance() { fn set<'new>(v: BTreeSet<&'static str>) -> BTreeSet<&'new str> { v } @@ -530,7 +531,7 @@ fn test_variance() { } #[allow(dead_code)] -fn test_sync() { +fn assert_sync() { fn set(v: &BTreeSet) -> impl Sync + '_ { v } @@ -569,7 +570,7 @@ fn test_sync() { } #[allow(dead_code)] -fn test_send() { +fn assert_send() { fn set(v: BTreeSet) -> impl Send { v } @@ -607,6 +608,37 @@ fn test_send() { } } +#[allow(dead_code)] +// Check that the member-like functions conditionally provided by #[derive()] +// are not overriden by genuine member functions with a different signature. +fn assert_derives() { + fn hash(v: BTreeSet, state: &mut H) { + v.hash(state); + // Tested much more thoroughly outside the crate in btree_set_hash.rs + } + fn eq(v: BTreeSet) { + let _ = v.eq(&v); + } + fn ne(v: BTreeSet) { + let _ = v.ne(&v); + } + fn cmp(v: BTreeSet) { + let _ = v.cmp(&v); + } + fn min(v: BTreeSet, w: BTreeSet) { + let _ = v.min(w); + } + fn max(v: BTreeSet, w: BTreeSet) { + let _ = v.max(w); + } + fn clamp(v: BTreeSet, w: BTreeSet, x: BTreeSet) { + let _ = v.clamp(w, x); + } + fn partial_cmp(v: &BTreeSet) { + let _ = v.partial_cmp(&v); + } +} + #[test] fn test_ord_absence() { fn set(mut set: BTreeSet) { diff --git a/library/alloc/src/collections/btree/testing/crash_test.rs b/library/alloc/src/collections/btree/testing/crash_test.rs index 488eaa07a9..bcf5f5f725 100644 --- a/library/alloc/src/collections/btree/testing/crash_test.rs +++ b/library/alloc/src/collections/btree/testing/crash_test.rs @@ -1,3 +1,4 @@ +// We avoid relying on anything else in the crate, apart from the `Debug` trait. use crate::fmt::Debug; use std::cmp::Ordering; use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; @@ -7,8 +8,7 @@ use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; /// Events are `clone`, `drop` or some anonymous `query`. /// /// Crash test dummies are identified and ordered by an id, so they can be used -/// as keys in a BTreeMap. The implementation intentionally uses does not rely -/// on anything defined in the crate, apart from the `Debug` trait. +/// as keys in a BTreeMap. #[derive(Debug)] pub struct CrashTestDummy { pub id: usize, diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index e4913b16ad..4a07d5d4be 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -417,7 +417,7 @@ impl LinkedList { /// let list: LinkedList = LinkedList::new(); /// ``` #[inline] - #[rustc_const_stable(feature = "const_linked_list_new", since = "1.32.0")] + #[rustc_const_stable(feature = "const_linked_list_new", since = "1.39.0")] #[stable(feature = "rust1", since = "1.0.0")] #[must_use] pub const fn new() -> Self { @@ -1961,7 +1961,7 @@ impl From<[T; N]> for LinkedList { /// assert_eq!(list1, list2); /// ``` fn from(arr: [T; N]) -> Self { - core::array::IntoIter::new(arr).collect() + Self::from_iter(arr) } } diff --git a/library/alloc/src/collections/vec_deque/iter_mut.rs b/library/alloc/src/collections/vec_deque/iter_mut.rs index 31e6e3b06a..ee2df0d516 100644 --- a/library/alloc/src/collections/vec_deque/iter_mut.rs +++ b/library/alloc/src/collections/vec_deque/iter_mut.rs @@ -12,7 +12,7 @@ use super::{count, wrap_index, RingSlices}; /// [`iter_mut`]: super::VecDeque::iter_mut #[stable(feature = "rust1", since = "1.0.0")] pub struct IterMut<'a, T: 'a> { - // Internal safety invariant: the entire slice is dereferencable. + // Internal safety invariant: the entire slice is dereferenceable. ring: *mut [T], tail: usize, head: usize, @@ -42,7 +42,7 @@ impl fmt::Debug for IterMut<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); // SAFETY: these are the elements we have not handed out yet, so aliasing is fine. - // The `IterMut` invariant also ensures everything is dereferencable. + // The `IterMut` invariant also ensures everything is dereferenceable. let (front, back) = unsafe { (&*front, &*back) }; f.debug_tuple("IterMut").field(&front).field(&back).finish() } @@ -78,7 +78,7 @@ impl<'a, T> Iterator for IterMut<'a, T> { { let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); // SAFETY: these are the elements we have not handed out yet, so aliasing is fine. - // The `IterMut` invariant also ensures everything is dereferencable. + // The `IterMut` invariant also ensures everything is dereferenceable. let (front, back) = unsafe { (&mut *front, &mut *back) }; accum = front.iter_mut().fold(accum, &mut f); back.iter_mut().fold(accum, &mut f) @@ -132,7 +132,7 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { { let (front, back) = RingSlices::ring_slices(self.ring, self.head, self.tail); // SAFETY: these are the elements we have not handed out yet, so aliasing is fine. - // The `IterMut` invariant also ensures everything is dereferencable. + // The `IterMut` invariant also ensures everything is dereferenceable. let (front, back) = unsafe { (&mut *front, &mut *back) }; accum = back.iter_mut().rfold(accum, &mut f); front.iter_mut().rfold(accum, &mut f) diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index de607c8fda..075becfb7d 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -720,9 +720,9 @@ impl VecDeque { /// /// Note that the allocator may give the collection more space than it /// requests. Therefore, capacity can not be relied upon to be precisely - /// minimal. Prefer [`reserve`] if future insertions are expected. + /// minimal. Prefer [`try_reserve`] if future insertions are expected. /// - /// [`reserve`]: VecDeque::reserve + /// [`try_reserve`]: VecDeque::try_reserve /// /// # Errors /// @@ -1020,7 +1020,7 @@ impl VecDeque { #[stable(feature = "rust1", since = "1.0.0")] pub fn iter_mut(&mut self) -> IterMut<'_, T> { // SAFETY: The internal `IterMut` safety invariant is established because the - // `ring` we create is a dereferencable slice for lifetime '_. + // `ring` we create is a dereferenceable slice for lifetime '_. let ring = ptr::slice_from_raw_parts_mut(self.ptr(), self.cap()); unsafe { IterMut::new(ring, self.tail, self.head, PhantomData) } @@ -1209,7 +1209,7 @@ impl VecDeque { let (tail, head) = self.range_tail_head(range); // SAFETY: The internal `IterMut` safety invariant is established because the - // `ring` we create is a dereferencable slice for lifetime '_. + // `ring` we create is a dereferenceable slice for lifetime '_. let ring = ptr::slice_from_raw_parts_mut(self.ptr(), self.cap()); unsafe { IterMut::new(ring, tail, head, PhantomData) } @@ -2148,6 +2148,37 @@ impl VecDeque { pub fn retain(&mut self, mut f: F) where F: FnMut(&T) -> bool, + { + self.retain_mut(|elem| f(elem)); + } + + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all elements `e` such that `f(&e)` returns false. + /// This method operates in place, visiting each element exactly once in the + /// original order, and preserves the order of the retained elements. + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_retain_mut)] + /// + /// use std::collections::VecDeque; + /// + /// let mut buf = VecDeque::new(); + /// buf.extend(1..5); + /// buf.retain_mut(|x| if *x % 2 == 0 { + /// *x += 1; + /// true + /// } else { + /// false + /// }); + /// assert_eq!(buf, [3, 5]); + /// ``` + #[unstable(feature = "vec_retain_mut", issue = "90829")] + pub fn retain_mut(&mut self, mut f: F) + where + F: FnMut(&mut T) -> bool, { let len = self.len(); let mut idx = 0; @@ -2155,7 +2186,7 @@ impl VecDeque { // Stage 1: All values are retained. while cur < len { - if !f(&self[cur]) { + if !f(&mut self[cur]) { cur += 1; break; } @@ -2164,7 +2195,7 @@ impl VecDeque { } // Stage 2: Swap retained value into current idx. while cur < len { - if !f(&self[cur]) { + if !f(&mut self[cur]) { cur += 1; continue; } @@ -2173,25 +2204,27 @@ impl VecDeque { cur += 1; idx += 1; } - // Stage 3: Trancate all values after idx. + // Stage 3: Truncate all values after idx. if cur != idx { self.truncate(idx); } } + // Double the buffer size. This method is inline(never), so we expect it to only + // be called in cold paths. // This may panic or abort #[inline(never)] fn grow(&mut self) { - if self.is_full() { - let old_cap = self.cap(); - // Double the buffer size. - self.buf.reserve_exact(old_cap, old_cap); - assert!(self.cap() == old_cap * 2); - unsafe { - self.handle_capacity_increase(old_cap); - } - debug_assert!(!self.is_full()); + // Extend or possibly remove this assertion when valid use-cases for growing the + // buffer without it being full emerge + debug_assert!(self.is_full()); + let old_cap = self.cap(); + self.buf.reserve_exact(old_cap, old_cap); + assert!(self.cap() == old_cap * 2); + unsafe { + self.handle_capacity_increase(old_cap); } + debug_assert!(!self.is_full()); } /// Modifies the `VecDeque` in-place so that `len()` is equal to `new_len`, diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 4a66c3f6b2..7e663fab16 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -96,19 +96,28 @@ #![feature(array_windows)] #![feature(async_stream)] #![feature(coerce_unsized)] +#![cfg_attr(not(no_global_oom_handling), feature(const_alloc_error))] +#![feature(const_box)] #![cfg_attr(not(no_global_oom_handling), feature(const_btree_new))] #![feature(const_cow_is_borrowed)] +#![feature(const_convert)] +#![feature(const_size_of_val)] +#![feature(const_align_of_val)] +#![feature(const_ptr_read)] +#![feature(const_maybe_uninit_write)] +#![feature(const_maybe_uninit_as_mut_ptr)] +#![feature(const_refs_to_cell)] #![feature(core_intrinsics)] +#![feature(const_eval_select)] +#![feature(const_pin)] #![feature(dispatch_from_dyn)] #![feature(exact_size_is_empty)] #![feature(extend_one)] #![feature(fmt_internals)] #![feature(fn_traits)] #![feature(inherent_ascii_escape)] -#![cfg_attr(bootstrap, feature(format_args_capture))] #![feature(inplace_iteration)] #![feature(iter_advance_by)] -#![feature(iter_zip)] #![feature(layout_for_ptr)] #![feature(maybe_uninit_extra)] #![feature(maybe_uninit_slice)] @@ -136,9 +145,14 @@ #![feature(box_syntax)] #![feature(cfg_sanitize)] #![feature(cfg_target_has_atomic)] +#![feature(const_deref)] #![feature(const_fn_trait_bound)] +#![feature(const_mut_refs)] +#![feature(const_ptr_write)] +#![feature(const_precise_live_drops)] #![feature(const_trait_impl)] -#![feature(destructuring_assignment)] +#![feature(const_try)] +#![cfg_attr(bootstrap, feature(destructuring_assignment))] #![feature(dropck_eyepatch)] #![feature(exclusive_range_pattern)] #![feature(fundamental)] diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 4ab38c802a..3806bc546e 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -190,9 +190,12 @@ impl RawVec { Err(_) => handle_alloc_error(layout), }; + // Allocators currently return a `NonNull<[u8]>` whose length + // matches the size requested. If that ever changes, the capacity + // here should change to `ptr.len() / mem::size_of::()`. Self { ptr: unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) }, - cap: Self::capacity_from_bytes(ptr.len()), + cap: capacity, alloc, } } @@ -289,6 +292,14 @@ impl RawVec { } } + /// A specialized version of `reserve()` used only by the hot and + /// oft-instantiated `Vec::push()`, which does its own capacity check. + #[cfg(not(no_global_oom_handling))] + #[inline(never)] + pub fn reserve_for_push(&mut self, len: usize) { + handle_reserve(self.grow_amortized(len, 1)); + } + /// The same as `reserve`, but returns on errors instead of panicking or aborting. pub fn try_reserve(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> { if self.needs_to_grow(len, additional) { @@ -329,7 +340,7 @@ impl RawVec { if self.needs_to_grow(len, additional) { self.grow_exact(len, additional) } else { Ok(()) } } - /// Shrinks the allocation down to the specified amount. If the given amount + /// Shrinks the buffer down to the specified capacity. If the given amount /// is 0, actually completely deallocates. /// /// # Panics @@ -340,8 +351,8 @@ impl RawVec { /// /// Aborts on OOM. #[cfg(not(no_global_oom_handling))] - pub fn shrink_to_fit(&mut self, amount: usize) { - handle_reserve(self.shrink(amount)); + pub fn shrink_to_fit(&mut self, cap: usize) { + handle_reserve(self.shrink(cap)); } } @@ -352,14 +363,12 @@ impl RawVec { additional > self.capacity().wrapping_sub(len) } - fn capacity_from_bytes(excess: usize) -> usize { - debug_assert_ne!(mem::size_of::(), 0); - excess / mem::size_of::() - } - - fn set_ptr(&mut self, ptr: NonNull<[u8]>) { + fn set_ptr_and_cap(&mut self, ptr: NonNull<[u8]>, cap: usize) { + // Allocators currently return a `NonNull<[u8]>` whose length matches + // the size requested. If that ever changes, the capacity here should + // change to `ptr.len() / mem::size_of::()`. self.ptr = unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) }; - self.cap = Self::capacity_from_bytes(ptr.len()); + self.cap = cap; } // This method is usually instantiated many times. So we want it to be as @@ -391,7 +400,7 @@ impl RawVec { // `finish_grow` is non-generic over `T`. let ptr = finish_grow(new_layout, self.current_memory(), &mut self.alloc)?; - self.set_ptr(ptr); + self.set_ptr_and_cap(ptr, cap); Ok(()) } @@ -410,15 +419,15 @@ impl RawVec { // `finish_grow` is non-generic over `T`. let ptr = finish_grow(new_layout, self.current_memory(), &mut self.alloc)?; - self.set_ptr(ptr); + self.set_ptr_and_cap(ptr, cap); Ok(()) } - fn shrink(&mut self, amount: usize) -> Result<(), TryReserveError> { - assert!(amount <= self.capacity(), "Tried to shrink to a larger capacity"); + fn shrink(&mut self, cap: usize) -> Result<(), TryReserveError> { + assert!(cap <= self.capacity(), "Tried to shrink to a larger capacity"); let (ptr, layout) = if let Some(mem) = self.current_memory() { mem } else { return Ok(()) }; - let new_size = amount * mem::size_of::(); + let new_size = cap * mem::size_of::(); let ptr = unsafe { let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); @@ -426,7 +435,7 @@ impl RawVec { .shrink(ptr, layout, new_layout) .map_err(|_| AllocError { layout: new_layout, non_exhaustive: () })? }; - self.set_ptr(ptr); + self.set_ptr_and_cap(ptr, cap); Ok(()) } } diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index c4e5e44fec..33bee4324f 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -2121,7 +2121,7 @@ impl Weak { // a valid payload address, as the payload is at least as aligned as RcBox (usize). ptr as *const T } else { - // SAFETY: if is_dangling returns false, then the pointer is dereferencable. + // SAFETY: if is_dangling returns false, then the pointer is dereferenceable. // The payload may be dropped at this point, and we have to maintain provenance, // so use raw pointer manipulation. unsafe { ptr::addr_of_mut!((*ptr).value) } diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index ae730be0d2..8853577371 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -892,7 +892,7 @@ where // performance than with the 2nd method. // // All methods were benchmarked, and the 3rd showed best results. So we chose that one. - let mut tmp = mem::ManuallyDrop::new(ptr::read(&v[0])); + let tmp = mem::ManuallyDrop::new(ptr::read(&v[0])); // Intermediate state of the insertion process is always tracked by `hole`, which // serves two purposes: @@ -904,7 +904,7 @@ where // If `is_less` panics at any point during the process, `hole` will get dropped and // fill the hole in `v` with `tmp`, thus ensuring that `v` still holds every object it // initially held exactly once. - let mut hole = InsertionHole { src: &mut *tmp, dest: &mut v[1] }; + let mut hole = InsertionHole { src: &*tmp, dest: &mut v[1] }; ptr::copy_nonoverlapping(&v[1], &mut v[0], 1); for i in 2..v.len() { @@ -920,7 +920,7 @@ where // When dropped, copies from `src` into `dest`. struct InsertionHole { - src: *mut T, + src: *const T, dest: *mut T, } diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index 104f555656..69495f31c3 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -178,12 +178,20 @@ where unsafe { let pos = result.len(); - let target = result.get_unchecked_mut(pos..reserved_len); + let target = result.spare_capacity_mut().get_unchecked_mut(..reserved_len - pos); + + // Convert the separator and slices to slices of MaybeUninit + // to simplify implementation in specialize_for_lengths + let sep_uninit = core::slice::from_raw_parts(sep.as_ptr().cast(), sep.len()); + let iter_uninit = iter.map(|it| { + let it = it.borrow().as_ref(); + core::slice::from_raw_parts(it.as_ptr().cast(), it.len()) + }); // copy separator and slices over without bounds checks // generate loops with hardcoded offsets for small separators // massive improvements possible (~ x2) - let remain = specialize_for_lengths!(sep, target, iter; 0, 1, 2, 3, 4); + let remain = specialize_for_lengths!(sep_uninit, target, iter_uninit; 0, 1, 2, 3, 4); // A weird borrow implementation may return different // slices for the length calculation and the actual copy. diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 906b0187f7..7c0faf0659 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -558,13 +558,13 @@ impl String { pub fn from_utf8_lossy(v: &[u8]) -> Cow<'_, str> { let mut iter = lossy::Utf8Lossy::from_bytes(v).chunks(); - let (first_valid, first_broken) = if let Some(chunk) = iter.next() { + let first_valid = if let Some(chunk) = iter.next() { let lossy::Utf8LossyChunk { valid, broken } = chunk; - if valid.len() == v.len() { - debug_assert!(broken.is_empty()); + if broken.is_empty() { + debug_assert_eq!(valid.len(), v.len()); return Cow::Borrowed(valid); } - (valid, broken) + valid } else { return Cow::Borrowed(""); }; @@ -573,9 +573,7 @@ impl String { let mut res = String::with_capacity(v.len()); res.push_str(first_valid); - if !first_broken.is_empty() { - res.push_str(REPLACEMENT); - } + res.push_str(REPLACEMENT); for lossy::Utf8LossyChunk { valid, broken } in iter { res.push_str(valid); @@ -1046,9 +1044,9 @@ impl String { /// /// Note that the allocator may give the collection more space than it /// requests. Therefore, capacity can not be relied upon to be precisely - /// minimal. Prefer [`reserve`] if future insertions are expected. + /// minimal. Prefer [`try_reserve`] if future insertions are expected. /// - /// [`reserve`]: String::reserve + /// [`try_reserve`]: String::try_reserve /// /// # Errors /// @@ -1064,7 +1062,7 @@ impl String { /// let mut output = String::new(); /// /// // Pre-reserve the memory, exiting if we can't - /// output.try_reserve(data.len())?; + /// output.try_reserve_exact(data.len())?; /// /// // Now we know this can't OOM in the middle of our complex work /// output.push_str(data); diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 733a898b28..7c065f37d1 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1743,7 +1743,7 @@ impl Weak { // a valid payload address, as the payload is at least as aligned as ArcInner (usize). ptr as *const T } else { - // SAFETY: if is_dangling returns false, then the pointer is dereferencable. + // SAFETY: if is_dangling returns false, then the pointer is dereferenceable. // The payload may be dropped at this point, and we have to maintain provenance, // so use raw pointer manipulation. unsafe { ptr::addr_of_mut!((*ptr).data) } diff --git a/library/alloc/src/vec/drain.rs b/library/alloc/src/vec/drain.rs index ff98091a0d..1bff19d05c 100644 --- a/library/alloc/src/vec/drain.rs +++ b/library/alloc/src/vec/drain.rs @@ -1,7 +1,7 @@ use crate::alloc::{Allocator, Global}; use core::fmt; use core::iter::{FusedIterator, TrustedLen}; -use core::mem::{self}; +use core::mem; use core::ptr::{self, NonNull}; use core::slice::{self}; @@ -104,16 +104,11 @@ impl DoubleEndedIterator for Drain<'_, T, A> { #[stable(feature = "drain", since = "1.6.0")] impl Drop for Drain<'_, T, A> { fn drop(&mut self) { - /// Continues dropping the remaining elements in the `Drain`, then moves back the - /// un-`Drain`ed elements to restore the original `Vec`. + /// Moves back the un-`Drain`ed elements to restore the original `Vec`. struct DropGuard<'r, 'a, T, A: Allocator>(&'r mut Drain<'a, T, A>); impl<'r, 'a, T, A: Allocator> Drop for DropGuard<'r, 'a, T, A> { fn drop(&mut self) { - // Continue the same loop we have below. If the loop already finished, this does - // nothing. - self.0.for_each(drop); - if self.0.tail_len > 0 { unsafe { let source_vec = self.0.vec.as_mut(); @@ -131,15 +126,47 @@ impl Drop for Drain<'_, T, A> { } } - // exhaust self first - while let Some(item) = self.next() { - let guard = DropGuard(self); - drop(item); - mem::forget(guard); + let iter = mem::replace(&mut self.iter, (&mut []).iter()); + let drop_len = iter.len(); + + let mut vec = self.vec; + + if mem::size_of::() == 0 { + // ZSTs have no identity, so we don't need to move them around, we only need to drop the correct amount. + // this can be achieved by manipulating the Vec length instead of moving values out from `iter`. + unsafe { + let vec = vec.as_mut(); + let old_len = vec.len(); + vec.set_len(old_len + drop_len + self.tail_len); + vec.truncate(old_len + self.tail_len); + } + + return; } - // Drop a `DropGuard` to move back the non-drained tail of `self`. - DropGuard(self); + // ensure elements are moved back into their appropriate places, even when drop_in_place panics + let _guard = DropGuard(self); + + if drop_len == 0 { + return; + } + + // as_slice() must only be called when iter.len() is > 0 because + // vec::Splice modifies vec::Drain fields and may grow the vec which would invalidate + // the iterator's internal pointers. Creating a reference to deallocated memory + // is invalid even when it is zero-length + let drop_ptr = iter.as_slice().as_ptr(); + + unsafe { + // drop_ptr comes from a slice::Iter which only gives us a &[T] but for drop_in_place + // a pointer with mutable provenance is necessary. Therefore we must reconstruct + // it from the original vec but also avoid creating a &mut to the front since that could + // invalidate raw pointers to it which some unsafe code might rely on. + let vec_ptr = vec.as_mut().as_mut_ptr(); + let drop_offset = drop_ptr.offset_from(vec_ptr) as usize; + let to_drop = ptr::slice_from_raw_parts_mut(vec_ptr.add(drop_offset), drop_len); + ptr::drop_in_place(to_drop); + } } } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 8575991776..3ad48a1d28 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -148,7 +148,7 @@ use self::spec_extend::SpecExtend; #[cfg(not(no_global_oom_handling))] mod spec_extend; -/// A contiguous growable array type, written as `Vec` and pronounced 'vector'. +/// A contiguous growable array type, written as `Vec`, short for 'vector'. /// /// # Examples /// @@ -822,7 +822,7 @@ impl Vec { /// /// # Panics /// - /// Panics if the new capacity overflows `usize`. + /// Panics if the new capacity exceeds `isize::MAX` bytes. /// /// # Examples /// @@ -881,9 +881,9 @@ impl Vec { /// /// Note that the allocator may give the collection more space than it /// requests. Therefore, capacity can not be relied upon to be precisely - /// minimal. Prefer [`reserve`] if future insertions are expected. + /// minimal. Prefer [`try_reserve`] if future insertions are expected. /// - /// [`reserve`]: Vec::reserve + /// [`try_reserve`]: Vec::try_reserve /// /// # Errors /// @@ -1520,49 +1520,46 @@ impl Vec { let mut g = BackshiftOnDrop { v: self, processed_len: 0, deleted_cnt: 0, original_len }; - // process_one return a bool indicates whether the processing element should be retained. - #[inline(always)] - fn process_one( + fn process_loop( + original_len: usize, f: &mut F, g: &mut BackshiftOnDrop<'_, T, A>, - ) -> bool - where + ) where F: FnMut(&mut T) -> bool, { - // SAFETY: Unchecked element must be valid. - let cur = unsafe { &mut *g.v.as_mut_ptr().add(g.processed_len) }; - if !f(cur) { - // Advance early to avoid double drop if `drop_in_place` panicked. - g.processed_len += 1; - g.deleted_cnt += 1; - // SAFETY: We never touch this element again after dropped. - unsafe { ptr::drop_in_place(cur) }; - // We already advanced the counter. - return false; - } - if DELETED { - // SAFETY: `deleted_cnt` > 0, so the hole slot must not overlap with current element. - // We use copy for move, and never touch this element again. - unsafe { - let hole_slot = g.v.as_mut_ptr().add(g.processed_len - g.deleted_cnt); - ptr::copy_nonoverlapping(cur, hole_slot, 1); + while g.processed_len != original_len { + // SAFETY: Unchecked element must be valid. + let cur = unsafe { &mut *g.v.as_mut_ptr().add(g.processed_len) }; + if !f(cur) { + // Advance early to avoid double drop if `drop_in_place` panicked. + g.processed_len += 1; + g.deleted_cnt += 1; + // SAFETY: We never touch this element again after dropped. + unsafe { ptr::drop_in_place(cur) }; + // We already advanced the counter. + if DELETED { + continue; + } else { + break; + } } + if DELETED { + // SAFETY: `deleted_cnt` > 0, so the hole slot must not overlap with current element. + // We use copy for move, and never touch this element again. + unsafe { + let hole_slot = g.v.as_mut_ptr().add(g.processed_len - g.deleted_cnt); + ptr::copy_nonoverlapping(cur, hole_slot, 1); + } + } + g.processed_len += 1; } - g.processed_len += 1; - return true; } // Stage 1: Nothing was deleted. - while g.processed_len != original_len { - if !process_one::(&mut f, &mut g) { - break; - } - } + process_loop::(original_len, &mut f, &mut g); // Stage 2: Some elements were deleted. - while g.processed_len != original_len { - process_one::(&mut f, &mut g); - } + process_loop::(original_len, &mut f, &mut g); // All item are processed. This can be optimized to `set_len` by LLVM. drop(g); @@ -1644,7 +1641,7 @@ impl Vec { let ptr = self.vec.as_mut_ptr(); let len = self.vec.len(); - /* How many items were left when `same_bucket` paniced. + /* How many items were left when `same_bucket` panicked. * Basically vec[read..].len() */ let items_left = len.wrapping_sub(self.read); @@ -1726,7 +1723,7 @@ impl Vec { // This will panic or abort if we would allocate > isize::MAX bytes // or if the length increment would overflow for zero-sized types. if self.len == self.buf.capacity() { - self.reserve(1); + self.buf.reserve_for_push(self.len); } unsafe { let end = self.as_mut_ptr().add(self.len); @@ -2046,7 +2043,7 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(vec_spare_capacity, maybe_uninit_extra)] + /// #![feature(vec_spare_capacity)] /// /// // Allocate vector big enough for 10 elements. /// let mut v = Vec::with_capacity(10); @@ -2105,7 +2102,7 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(vec_split_at_spare, maybe_uninit_extra)] + /// #![feature(vec_split_at_spare)] /// /// let mut v = vec![1, 1, 2]; /// @@ -2144,12 +2141,17 @@ impl Vec { unsafe fn split_at_spare_mut_with_len( &mut self, ) -> (&mut [T], &mut [MaybeUninit], &mut usize) { - let Range { start: ptr, end: spare_ptr } = self.as_mut_ptr_range(); + let ptr = self.as_mut_ptr(); + // SAFETY: + // - `ptr` is guaranteed to be valid for `self.len` elements + // - but the allocation extends out to `self.buf.capacity()` elements, possibly + // uninitialized + let spare_ptr = unsafe { ptr.add(self.len) }; let spare_ptr = spare_ptr.cast::>(); let spare_len = self.buf.capacity() - self.len; // SAFETY: - // - `ptr` is guaranteed to be valid for `len` elements + // - `ptr` is guaranteed to be valid for `self.len` elements // - `spare_ptr` is pointing one element past the buffer, so it doesn't overlap with `initialized` unsafe { let initialized = slice::from_raw_parts_mut(ptr, self.len); @@ -2199,7 +2201,7 @@ impl Vec { /// Clones and appends all elements in a slice to the `Vec`. /// /// Iterates over the slice `other`, clones each element, and then appends - /// it to this `Vec`. The `other` vector is traversed in-order. + /// it to this `Vec`. The `other` slice is traversed in-order. /// /// Note that this function is same as [`extend`] except that it is /// specialized to work with slices instead. If and when Rust gets @@ -2275,16 +2277,6 @@ impl ExtendWith for ExtendElement { } } -struct ExtendDefault; -impl ExtendWith for ExtendDefault { - fn next(&mut self) -> T { - Default::default() - } - fn last(self) -> T { - Default::default() - } -} - struct ExtendFunc(F); impl T> ExtendWith for ExtendFunc { fn next(&mut self) -> T { @@ -2686,11 +2678,11 @@ impl Vec { /// # Examples /// /// ``` - /// let mut v = vec![1, 2, 3]; - /// let new = [7, 8]; - /// let u: Vec<_> = v.splice(..2, new).collect(); - /// assert_eq!(v, &[7, 8, 3]); - /// assert_eq!(u, &[1, 2]); + /// let mut v = vec![1, 2, 3, 4]; + /// let new = [7, 8, 9]; + /// let u: Vec<_> = v.splice(1..3, new).collect(); + /// assert_eq!(v, &[1, 7, 8, 9, 4]); + /// assert_eq!(u, &[2, 3]); /// ``` #[cfg(not(no_global_oom_handling))] #[inline] diff --git a/library/alloc/tests/boxed.rs b/library/alloc/tests/boxed.rs index a38b5c471b..0d7acfed8c 100644 --- a/library/alloc/tests/boxed.rs +++ b/library/alloc/tests/boxed.rs @@ -1,9 +1,10 @@ -use std::cell::Cell; -use std::mem::MaybeUninit; -use std::ptr::NonNull; +use core::alloc::{AllocError, Allocator, Layout}; +use core::cell::Cell; +use core::mem::MaybeUninit; +use core::ptr::NonNull; #[test] -fn unitialized_zero_size_box() { +fn uninitialized_zero_size_box() { assert_eq!( &*Box::<()>::new_uninit() as *const _, NonNull::>::dangling().as_ptr(), @@ -57,3 +58,110 @@ fn box_deref_lval() { x.set(1000); assert_eq!(x.get(), 1000); } + +pub struct ConstAllocator; + +unsafe impl const Allocator for ConstAllocator { + fn allocate(&self, layout: Layout) -> Result, AllocError> { + match layout.size() { + 0 => Ok(NonNull::slice_from_raw_parts(layout.dangling(), 0)), + _ => unsafe { + let ptr = core::intrinsics::const_allocate(layout.size(), layout.align()); + Ok(NonNull::new_unchecked(ptr as *mut [u8; 0] as *mut [u8])) + }, + } + } + + unsafe fn deallocate(&self, _ptr: NonNull, layout: Layout) { + match layout.size() { + 0 => { /* do nothing */ } + _ => { /* do nothing too */ } + } + } + + fn allocate_zeroed(&self, layout: Layout) -> Result, AllocError> { + let ptr = self.allocate(layout)?; + if layout.size() > 0 { + unsafe { + ptr.as_mut_ptr().write_bytes(0, layout.size()); + } + } + Ok(ptr) + } + + unsafe fn grow( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + debug_assert!( + new_layout.size() >= old_layout.size(), + "`new_layout.size()` must be greater than or equal to `old_layout.size()`" + ); + + let new_ptr = self.allocate(new_layout)?; + if new_layout.size() > 0 { + new_ptr.as_mut_ptr().copy_from_nonoverlapping(ptr.as_ptr(), old_layout.size()); + self.deallocate(ptr, old_layout); + } + Ok(new_ptr) + } + + unsafe fn grow_zeroed( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + let new_ptr = self.grow(ptr, old_layout, new_layout)?; + if new_layout.size() > 0 { + let old_size = old_layout.size(); + let new_size = new_layout.size(); + let raw_ptr = new_ptr.as_mut_ptr(); + raw_ptr.add(old_size).write_bytes(0, new_size - old_size); + } + Ok(new_ptr) + } + + unsafe fn shrink( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + debug_assert!( + new_layout.size() <= old_layout.size(), + "`new_layout.size()` must be smaller than or equal to `old_layout.size()`" + ); + + let new_ptr = self.allocate(new_layout)?; + if new_layout.size() > 0 { + new_ptr.as_mut_ptr().copy_from_nonoverlapping(ptr.as_ptr(), new_layout.size()); + self.deallocate(ptr, old_layout); + } + Ok(new_ptr) + } + + fn by_ref(&self) -> &Self + where + Self: Sized, + { + self + } +} + +#[test] +fn const_box() { + const VALUE: u32 = { + let mut boxed = Box::new_in(1u32, ConstAllocator); + assert!(*boxed == 1); + + *boxed = 42; + assert!(*boxed == 42); + + *boxed + }; + + assert!(VALUE == 42); +} diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 68e48348b0..eec24a5c3f 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -1,8 +1,19 @@ #![feature(allocator_api)] +#![feature(alloc_layout_extra)] #![feature(assert_matches)] #![feature(box_syntax)] #![feature(cow_is_borrowed)] +#![feature(const_box)] +#![feature(const_convert)] #![feature(const_cow_is_borrowed)] +#![feature(const_heap)] +#![feature(const_intrinsic_copy)] +#![feature(const_mut_refs)] +#![feature(const_nonnull_slice_from_raw_parts)] +#![feature(const_ptr_offset)] +#![feature(const_ptr_write)] +#![feature(const_try)] +#![feature(core_intrinsics)] #![feature(drain_filter)] #![feature(exact_size_is_empty)] #![feature(new_uninit)] @@ -26,6 +37,7 @@ #![feature(const_default_impls)] #![feature(const_trait_impl)] #![feature(const_str_from_utf8)] +#![feature(nonnull_slice_from_raw_parts)] use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; diff --git a/library/alloc/tests/slice.rs b/library/alloc/tests/slice.rs index 13b8c059e3..18ea6a2141 100644 --- a/library/alloc/tests/slice.rs +++ b/library/alloc/tests/slice.rs @@ -863,7 +863,7 @@ fn test_splitator_inclusive() { assert_eq!(xs.split_inclusive(|_| true).collect::>(), splits); let xs: &[i32] = &[]; - let splits: &[&[i32]] = &[&[]]; + let splits: &[&[i32]] = &[]; assert_eq!(xs.split_inclusive(|x| *x == 5).collect::>(), splits); } @@ -883,7 +883,7 @@ fn test_splitator_inclusive_reverse() { assert_eq!(xs.split_inclusive(|_| true).rev().collect::>(), splits); let xs: &[i32] = &[]; - let splits: &[&[i32]] = &[&[]]; + let splits: &[&[i32]] = &[]; assert_eq!(xs.split_inclusive(|x| *x == 5).rev().collect::>(), splits); } @@ -903,7 +903,7 @@ fn test_splitator_mut_inclusive() { assert_eq!(xs.split_inclusive_mut(|_| true).collect::>(), splits); let xs: &mut [i32] = &mut []; - let splits: &[&[i32]] = &[&[]]; + let splits: &[&[i32]] = &[]; assert_eq!(xs.split_inclusive_mut(|x| *x == 5).collect::>(), splits); } @@ -923,7 +923,7 @@ fn test_splitator_mut_inclusive_reverse() { assert_eq!(xs.split_inclusive_mut(|_| true).rev().collect::>(), splits); let xs: &mut [i32] = &mut []; - let splits: &[&[i32]] = &[&[]]; + let splits: &[&[i32]] = &[]; assert_eq!(xs.split_inclusive_mut(|x| *x == 5).rev().collect::>(), splits); } diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs index 1b741f174f..e92881b104 100644 --- a/library/alloc/tests/str.rs +++ b/library/alloc/tests/str.rs @@ -162,7 +162,7 @@ fn test_join_for_different_lengths_with_long_separator() { } #[test] -fn test_join_isue_80335() { +fn test_join_issue_80335() { use core::{borrow::Borrow, cell::Cell}; struct WeirdBorrow { @@ -1183,6 +1183,37 @@ fn test_rev_iterator() { assert_eq!(pos, v.len()); } +#[test] +fn test_to_lowercase_rev_iterator() { + let s = "AÖßÜ💩ΣΤΙΓΜΑΣDžfiİ"; + let v = ['\u{307}', 'i', 'fi', 'dž', 'σ', 'α', 'μ', 'γ', 'ι', 'τ', 'σ', '💩', 'ü', 'ß', 'ö', 'a']; + + let mut pos = 0; + let it = s.chars().flat_map(|c| c.to_lowercase()).rev(); + + for c in it { + assert_eq!(c, v[pos]); + pos += 1; + } + assert_eq!(pos, v.len()); +} + +#[test] +fn test_to_uppercase_rev_iterator() { + let s = "aößü💩στιγμαςDžfiᾀ"; + let v = + ['Ι', 'Ἀ', 'I', 'F', 'DŽ', 'Σ', 'Α', 'Μ', 'Γ', 'Ι', 'Τ', 'Σ', '💩', 'Ü', 'S', 'S', 'Ö', 'A']; + + let mut pos = 0; + let it = s.chars().flat_map(|c| c.to_uppercase()).rev(); + + for c in it { + assert_eq!(c, v[pos]); + pos += 1; + } + assert_eq!(pos, v.len()); +} + #[test] #[cfg_attr(miri, ignore)] // Miri is too slow fn test_chars_decoding() { diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 00a878c079..7731428253 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -985,6 +985,9 @@ fn test_into_iter_advance_by() { assert_eq!(i.advance_by(usize::MAX), Err(0)); + i.advance_by(0).unwrap(); + i.advance_back_by(0).unwrap(); + assert_eq!(i.len(), 0); } diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index 9df0b5c551..ea63926865 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -157,11 +157,11 @@ impl Layout { /// /// - If `T` is `Sized`, this function is always safe to call. /// - If the unsized tail of `T` is: - /// - a [slice], then the length of the slice tail must be an intialized + /// - a [slice], then the length of the slice tail must be an initialized /// integer, and the size of the *entire value* /// (dynamic tail length + statically sized prefix) must fit in `isize`. /// - a [trait object], then the vtable part of the pointer must point - /// to a valid vtable for the type `T` acquired by an unsizing coersion, + /// to a valid vtable for the type `T` acquired by an unsizing coercion, /// and the size of the *entire value* /// (dynamic tail length + statically sized prefix) must fit in `isize`. /// - an (unstable) [extern type], then this function is always safe to diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 1fd5aa27fc..7252818570 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -164,7 +164,7 @@ impl fmt::Debug for dyn Any + Send + Sync { } impl dyn Any { - /// Returns `true` if the boxed type is the same as `T`. + /// Returns `true` if the inner type is the same as `T`. /// /// # Examples /// @@ -195,7 +195,7 @@ impl dyn Any { t == concrete } - /// Returns some reference to the boxed value if it is of type `T`, or + /// Returns some reference to the inner value if it is of type `T`, or /// `None` if it isn't. /// /// # Examples @@ -221,13 +221,13 @@ impl dyn Any { // SAFETY: just checked whether we are pointing to the correct type, and we can rely on // that check for memory safety because we have implemented Any for all types; no other // impls can exist as they would conflict with our impl. - unsafe { Some(&*(self as *const dyn Any as *const T)) } + unsafe { Some(self.downcast_ref_unchecked()) } } else { None } } - /// Returns some mutable reference to the boxed value if it is of type `T`, or + /// Returns some mutable reference to the inner value if it is of type `T`, or /// `None` if it isn't. /// /// # Examples @@ -257,15 +257,73 @@ impl dyn Any { // SAFETY: just checked whether we are pointing to the correct type, and we can rely on // that check for memory safety because we have implemented Any for all types; no other // impls can exist as they would conflict with our impl. - unsafe { Some(&mut *(self as *mut dyn Any as *mut T)) } + unsafe { Some(self.downcast_mut_unchecked()) } } else { None } } + + /// Returns a reference to the inner value as type `dyn T`. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// + /// let x: Box = Box::new(1_usize); + /// + /// unsafe { + /// assert_eq!(*x.downcast_ref_unchecked::(), 1); + /// } + /// ``` + /// + /// # Safety + /// + /// The contained value must be of type `T`. Calling this method + /// with the incorrect type is *undefined behavior*. + #[unstable(feature = "downcast_unchecked", issue = "90850")] + #[inline] + pub unsafe fn downcast_ref_unchecked(&self) -> &T { + debug_assert!(self.is::()); + // SAFETY: caller guarantees that T is the correct type + unsafe { &*(self as *const dyn Any as *const T) } + } + + /// Returns a mutable reference to the inner value as type `dyn T`. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// + /// let mut x: Box = Box::new(1_usize); + /// + /// unsafe { + /// *x.downcast_mut_unchecked::() += 1; + /// } + /// + /// assert_eq!(*x.downcast_ref::().unwrap(), 2); + /// ``` + /// + /// # Safety + /// + /// The contained value must be of type `T`. Calling this method + /// with the incorrect type is *undefined behavior*. + #[unstable(feature = "downcast_unchecked", issue = "90850")] + #[inline] + pub unsafe fn downcast_mut_unchecked(&mut self) -> &mut T { + debug_assert!(self.is::()); + // SAFETY: caller guarantees that T is the correct type + unsafe { &mut *(self as *mut dyn Any as *mut T) } + } } impl dyn Any + Send { - /// Forwards to the method defined on the type `Any`. + /// Forwards to the method defined on the type `dyn Any`. /// /// # Examples /// @@ -289,7 +347,7 @@ impl dyn Any + Send { ::is::(self) } - /// Forwards to the method defined on the type `Any`. + /// Forwards to the method defined on the type `dyn Any`. /// /// # Examples /// @@ -313,7 +371,7 @@ impl dyn Any + Send { ::downcast_ref::(self) } - /// Forwards to the method defined on the type `Any`. + /// Forwards to the method defined on the type `dyn Any`. /// /// # Examples /// @@ -340,6 +398,60 @@ impl dyn Any + Send { pub fn downcast_mut(&mut self) -> Option<&mut T> { ::downcast_mut::(self) } + + /// Forwards to the method defined on the type `dyn Any`. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// + /// let x: Box = Box::new(1_usize); + /// + /// unsafe { + /// assert_eq!(*x.downcast_ref_unchecked::(), 1); + /// } + /// ``` + /// + /// # Safety + /// + /// Same as the method on the type `dyn Any`. + #[unstable(feature = "downcast_unchecked", issue = "90850")] + #[inline] + pub unsafe fn downcast_ref_unchecked(&self) -> &T { + // SAFETY: guaranteed by caller + unsafe { ::downcast_ref_unchecked::(self) } + } + + /// Forwards to the method defined on the type `dyn Any`. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// + /// let mut x: Box = Box::new(1_usize); + /// + /// unsafe { + /// *x.downcast_mut_unchecked::() += 1; + /// } + /// + /// assert_eq!(*x.downcast_ref::().unwrap(), 2); + /// ``` + /// + /// # Safety + /// + /// Same as the method on the type `dyn Any`. + #[unstable(feature = "downcast_unchecked", issue = "90850")] + #[inline] + pub unsafe fn downcast_mut_unchecked(&mut self) -> &mut T { + // SAFETY: guaranteed by caller + unsafe { ::downcast_mut_unchecked::(self) } + } } impl dyn Any + Send + Sync { @@ -418,6 +530,52 @@ impl dyn Any + Send + Sync { pub fn downcast_mut(&mut self) -> Option<&mut T> { ::downcast_mut::(self) } + + /// Forwards to the method defined on the type `Any`. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// + /// let x: Box = Box::new(1_usize); + /// + /// unsafe { + /// assert_eq!(*x.downcast_ref_unchecked::(), 1); + /// } + /// ``` + #[unstable(feature = "downcast_unchecked", issue = "90850")] + #[inline] + pub unsafe fn downcast_ref_unchecked(&self) -> &T { + // SAFETY: guaranteed by caller + unsafe { ::downcast_ref_unchecked::(self) } + } + + /// Forwards to the method defined on the type `Any`. + /// + /// # Examples + /// + /// ``` + /// #![feature(downcast_unchecked)] + /// + /// use std::any::Any; + /// + /// let mut x: Box = Box::new(1_usize); + /// + /// unsafe { + /// *x.downcast_mut_unchecked::() += 1; + /// } + /// + /// assert_eq!(*x.downcast_ref::().unwrap(), 2); + /// ``` + #[unstable(feature = "downcast_unchecked", issue = "90850")] + #[inline] + pub unsafe fn downcast_mut_unchecked(&mut self) -> &mut T { + // SAFETY: guaranteed by caller + unsafe { ::downcast_mut_unchecked::(self) } + } } /////////////////////////////////////////////////////////////////////////////// diff --git a/library/core/src/array/equality.rs b/library/core/src/array/equality.rs index a882d18b15..33f7f494e9 100644 --- a/library/core/src/array/equality.rs +++ b/library/core/src/array/equality.rs @@ -1,3 +1,7 @@ +use crate::convert::TryInto; +use crate::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize}; +use crate::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize}; + #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq<[B; N]> for [A; N] where @@ -20,11 +24,19 @@ where { #[inline] fn eq(&self, other: &[B]) -> bool { - self[..] == other[..] + let b: Result<&[B; N], _> = other.try_into(); + match b { + Ok(b) => *self == *b, + Err(_) => false, + } } #[inline] fn ne(&self, other: &[B]) -> bool { - self[..] != other[..] + let b: Result<&[B; N], _> = other.try_into(); + match b { + Ok(b) => *self != *b, + Err(_) => true, + } } } @@ -35,11 +47,19 @@ where { #[inline] fn eq(&self, other: &[A; N]) -> bool { - self[..] == other[..] + let b: Result<&[B; N], _> = self.try_into(); + match b { + Ok(b) => *b == *other, + Err(_) => false, + } } #[inline] fn ne(&self, other: &[A; N]) -> bool { - self[..] != other[..] + let b: Result<&[B; N], _> = self.try_into(); + match b { + Ok(b) => *b != *other, + Err(_) => true, + } } } @@ -50,11 +70,11 @@ where { #[inline] fn eq(&self, other: &&[B]) -> bool { - self[..] == other[..] + *self == **other } #[inline] fn ne(&self, other: &&[B]) -> bool { - self[..] != other[..] + *self != **other } } @@ -65,11 +85,11 @@ where { #[inline] fn eq(&self, other: &[A; N]) -> bool { - self[..] == other[..] + **self == *other } #[inline] fn ne(&self, other: &[A; N]) -> bool { - self[..] != other[..] + **self != *other } } @@ -80,11 +100,11 @@ where { #[inline] fn eq(&self, other: &&mut [B]) -> bool { - self[..] == other[..] + *self == **other } #[inline] fn ne(&self, other: &&mut [B]) -> bool { - self[..] != other[..] + *self != **other } } @@ -95,11 +115,11 @@ where { #[inline] fn eq(&self, other: &[A; N]) -> bool { - self[..] == other[..] + **self == *other } #[inline] fn ne(&self, other: &[A; N]) -> bool { - self[..] != other[..] + **self != *other } } @@ -124,7 +144,7 @@ impl, Other, const N: usize> SpecArrayEq for T { } } -impl + IsRawEqComparable, U, const N: usize> SpecArrayEq for T { +impl, U, const N: usize> SpecArrayEq for T { fn spec_eq(a: &[T; N], b: &[U; N]) -> bool { // SAFETY: This is why `IsRawEqComparable` is an `unsafe trait`. unsafe { @@ -145,11 +165,52 @@ impl + IsRawEqComparable, U, const N: usize> SpecArrayEq` is byte-wise (this means no floats, among other things) #[rustc_specialization_trait] -unsafe trait IsRawEqComparable {} +unsafe trait IsRawEqComparable: PartialEq {} -macro_rules! is_raw_comparable { - ($($t:ty),+) => {$( +macro_rules! is_raw_eq_comparable { + ($($t:ty),+ $(,)?) => {$( unsafe impl IsRawEqComparable<$t> for $t {} )+}; } -is_raw_comparable!(bool, char, u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); + +// SAFETY: All the ordinary integer types allow all bit patterns as distinct values +is_raw_eq_comparable!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize); + +// SAFETY: bool and char have *niches*, but no *padding*, so this is sound +is_raw_eq_comparable!(bool, char); + +// SAFETY: Similarly, the non-zero types have a niche, but no undef, +// and they compare like their underlying numeric type. +is_raw_eq_comparable!( + NonZeroU8, + NonZeroU16, + NonZeroU32, + NonZeroU64, + NonZeroU128, + NonZeroUsize, + NonZeroI8, + NonZeroI16, + NonZeroI32, + NonZeroI64, + NonZeroI128, + NonZeroIsize, +); + +// SAFETY: The NonZero types have the "null" optimization guaranteed, and thus +// are also safe to equality-compare bitwise inside an `Option`. +// The way `PartialOrd` is defined for `Option` means that this wouldn't work +// for `<` or `>` on the signed types, but since we only do `==` it's fine. +is_raw_eq_comparable!( + Option, + Option, + Option, + Option, + Option, + Option, + Option, + Option, + Option, + Option, + Option, + Option, +); diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs index 5d63cf03fc..72a634443e 100644 --- a/library/core/src/array/iter.rs +++ b/library/core/src/array/iter.rs @@ -1,7 +1,7 @@ //! Defines the `IntoIter` owned iterator for arrays. use crate::{ - fmt, + cmp, fmt, iter::{self, ExactSizeIterator, FusedIterator, TrustedLen}, mem::{self, MaybeUninit}, ops::Range, @@ -34,30 +34,23 @@ pub struct IntoIter { alive: Range, } -impl IntoIter { - /// Creates a new iterator over the given `array`. +// Note: the `#[rustc_skip_array_during_method_dispatch]` on `trait IntoIterator` +// hides this implementation from explicit `.into_iter()` calls on editions < 2021, +// so those calls will still resolve to the slice implementation, by reference. +#[stable(feature = "array_into_iter_impl", since = "1.53.0")] +impl IntoIterator for [T; N] { + type Item = T; + type IntoIter = IntoIter; + + /// Creates a consuming iterator, that is, one that moves each value out of + /// the array (from start to end). The array cannot be used after calling + /// this unless `T` implements `Copy`, so the whole array is copied. /// - /// *Note*: this method might be deprecated in the future, - /// since [`IntoIterator`] is now implemented for arrays. + /// Arrays have special behavior when calling `.into_iter()` prior to the + /// 2021 edition -- see the [array] Editions section for more information. /// - /// # Examples - /// - /// ``` - /// use std::array; - /// - /// for value in array::IntoIter::new([1, 2, 3, 4, 5]) { - /// // The type of `value` is an `i32` here, instead of `&i32` - /// let _: i32 = value; - /// } - /// - /// // Since Rust 1.53, arrays implement IntoIterator directly: - /// for value in [1, 2, 3, 4, 5] { - /// // The type of `value` is an `i32` here, instead of `&i32` - /// let _: i32 = value; - /// } - /// ``` - #[stable(feature = "array_value_iter", since = "1.51.0")] - pub fn new(array: [T; N]) -> Self { + /// [array]: prim@array + fn into_iter(self) -> Self::IntoIter { // SAFETY: The transmute here is actually safe. The docs of `MaybeUninit` // promise: // @@ -76,11 +69,149 @@ impl IntoIter { // Until then, we can use `mem::transmute_copy` to create a bitwise copy // as a different type, then forget `array` so that it is not dropped. unsafe { - let iter = Self { data: mem::transmute_copy(&array), alive: 0..N }; - mem::forget(array); + let iter = IntoIter { data: mem::transmute_copy(&self), alive: 0..N }; + mem::forget(self); iter } } +} + +impl IntoIter { + /// Creates a new iterator over the given `array`. + #[stable(feature = "array_value_iter", since = "1.51.0")] + #[rustc_deprecated(since = "1.59.0", reason = "use `IntoIterator::into_iter` instead")] + pub fn new(array: [T; N]) -> Self { + IntoIterator::into_iter(array) + } + + /// Creates an iterator over the elements in a partially-initialized buffer. + /// + /// If you have a fully-initialized array, then use [`IntoIterator`]. + /// But this is useful for returning partial results from unsafe code. + /// + /// # Safety + /// + /// - The `buffer[initialized]` elements must all be initialized. + /// - The range must be canonical, with `initialized.start <= initialized.end`. + /// - The range must in in-bounds for the buffer, with `initialized.end <= N`. + /// (Like how indexing `[0][100..100]` fails despite the range being empty.) + /// + /// It's sound to have more elements initialized than mentioned, though that + /// will most likely result in them being leaked. + /// + /// # Examples + /// + /// ``` + /// #![feature(array_into_iter_constructors)] + /// + /// #![feature(maybe_uninit_array_assume_init)] + /// #![feature(maybe_uninit_uninit_array)] + /// use std::array::IntoIter; + /// use std::mem::MaybeUninit; + /// + /// # // Hi! Thanks for reading the code. This is restricted to `Copy` because + /// # // otherwise it could leak. A fully-general version this would need a drop + /// # // guard to handle panics from the iterator, but this works for an example. + /// fn next_chunk( + /// it: &mut impl Iterator, + /// ) -> Result<[T; N], IntoIter> { + /// let mut buffer = MaybeUninit::uninit_array(); + /// let mut i = 0; + /// while i < N { + /// match it.next() { + /// Some(x) => { + /// buffer[i].write(x); + /// i += 1; + /// } + /// None => { + /// // SAFETY: We've initialized the first `i` items + /// unsafe { + /// return Err(IntoIter::new_unchecked(buffer, 0..i)); + /// } + /// } + /// } + /// } + /// + /// // SAFETY: We've initialized all N items + /// unsafe { Ok(MaybeUninit::array_assume_init(buffer)) } + /// } + /// + /// let r: [_; 4] = next_chunk(&mut (10..16)).unwrap(); + /// assert_eq!(r, [10, 11, 12, 13]); + /// let r: IntoIter<_, 40> = next_chunk(&mut (10..16)).unwrap_err(); + /// assert_eq!(r.collect::>(), vec![10, 11, 12, 13, 14, 15]); + /// ``` + #[unstable(feature = "array_into_iter_constructors", issue = "91583")] + #[rustc_const_unstable(feature = "const_array_into_iter_constructors", issue = "91583")] + pub const unsafe fn new_unchecked( + buffer: [MaybeUninit; N], + initialized: Range, + ) -> Self { + Self { data: buffer, alive: initialized } + } + + /// Creates an iterator over `T` which returns no elements. + /// + /// If you just need an empty iterator, then use + /// [`iter::empty()`](crate::iter::empty) instead. + /// And if you need an empty array, use `[]`. + /// + /// But this is useful when you need an `array::IntoIter` *specifically*. + /// + /// # Examples + /// + /// ``` + /// #![feature(array_into_iter_constructors)] + /// use std::array::IntoIter; + /// + /// let empty = IntoIter::::empty(); + /// assert_eq!(empty.len(), 0); + /// assert_eq!(empty.as_slice(), &[]); + /// + /// let empty = IntoIter::::empty(); + /// assert_eq!(empty.len(), 0); + /// ``` + /// + /// `[1, 2].into_iter()` and `[].into_iter()` have different types + /// ```should_fail,edition2021 + /// #![feature(array_into_iter_constructors)] + /// use std::array::IntoIter; + /// + /// pub fn get_bytes(b: bool) -> IntoIter { + /// if b { + /// [1, 2, 3, 4].into_iter() + /// } else { + /// [].into_iter() // error[E0308]: mismatched types + /// } + /// } + /// ``` + /// + /// But using this method you can get an empty iterator of appropriate size: + /// ```edition2021 + /// #![feature(array_into_iter_constructors)] + /// use std::array::IntoIter; + /// + /// pub fn get_bytes(b: bool) -> IntoIter { + /// if b { + /// [1, 2, 3, 4].into_iter() + /// } else { + /// IntoIter::empty() + /// } + /// } + /// + /// assert_eq!(get_bytes(true).collect::>(), vec![1, 2, 3, 4]); + /// assert_eq!(get_bytes(false).collect::>(), vec![]); + /// ``` + #[unstable(feature = "array_into_iter_constructors", issue = "91583")] + #[rustc_const_unstable(feature = "const_array_into_iter_constructors", issue = "91583")] + pub const fn empty() -> Self { + let buffer = MaybeUninit::uninit_array(); + let initialized = 0..0; + + // SAFETY: We're telling it that none of the elements are initialized, + // which is trivially true. And ∀N: usize, 0 <= N. + unsafe { Self::new_unchecked(buffer, initialized) } + } /// Returns an immutable slice of all elements that have not been yielded /// yet. @@ -150,6 +281,27 @@ impl Iterator for IntoIter { fn last(mut self) -> Option { self.next_back() } + + fn advance_by(&mut self, n: usize) -> Result<(), usize> { + let len = self.len(); + + // The number of elements to drop. Always in-bounds by construction. + let delta = cmp::min(n, len); + + let range_to_drop = self.alive.start..(self.alive.start + delta); + + // Moving the start marks them as conceptually "dropped", so if anything + // goes bad then our drop impl won't double-free them. + self.alive.start += delta; + + // SAFETY: These elements are currently initialized, so it's fine to drop them. + unsafe { + let slice = self.data.get_unchecked_mut(range_to_drop); + ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(slice)); + } + + if n > len { Err(len) } else { Ok(()) } + } } #[stable(feature = "array_value_iter_impls", since = "1.40.0")] @@ -170,6 +322,27 @@ impl DoubleEndedIterator for IntoIter { unsafe { self.data.get_unchecked(idx).assume_init_read() } }) } + + fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { + let len = self.len(); + + // The number of elements to drop. Always in-bounds by construction. + let delta = cmp::min(n, len); + + let range_to_drop = (self.alive.end - delta)..self.alive.end; + + // Moving the end marks them as conceptually "dropped", so if anything + // goes bad then our drop impl won't double-free them. + self.alive.end -= delta; + + // SAFETY: These elements are currently initialized, so it's fine to drop them. + unsafe { + let slice = self.data.get_unchecked_mut(range_to_drop); + ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(slice)); + } + + if n > len { Err(len) } else { Ok(()) } + } } #[stable(feature = "array_value_iter_impls", since = "1.40.0")] diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 09bb451917..37292bf8e2 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -11,7 +11,9 @@ use crate::fmt; use crate::hash::{self, Hash}; use crate::iter::TrustedLen; use crate::mem::{self, MaybeUninit}; -use crate::ops::{Index, IndexMut}; +use crate::ops::{ + ChangeOutputType, ControlFlow, FromResidual, Index, IndexMut, NeverShortCircuit, Residual, Try, +}; use crate::slice::{Iter, IterMut}; mod equality; @@ -49,9 +51,13 @@ where } /// Creates an array `[T; N]` where each fallible array element `T` is returned by the `cb` call. -/// Unlike `core::array::from_fn`, where the element creation can't fail, this version will return an error +/// Unlike [`from_fn`], where the element creation can't fail, this version will return an error /// if any element creation was unsuccessful. /// +/// The return type of this function depends on the return type of the closure. +/// If you return `Result` from the closure, you'll get a `Result<[T; N]; E>`. +/// If you return `Option` from the closure, you'll get an `Option<[T; N]>`. +/// /// # Arguments /// /// * `cb`: Callback where the passed argument is the current array index. @@ -60,27 +66,32 @@ where /// /// ```rust /// #![feature(array_from_fn)] +/// # // Apparently these doc tests are still on edition2018 +/// # use std::convert::TryInto; /// -/// #[derive(Debug, PartialEq)] -/// enum SomeError { -/// Foo, -/// } -/// -/// let array = core::array::try_from_fn(|i| Ok::<_, SomeError>(i)); +/// let array: Result<[u8; 5], _> = std::array::try_from_fn(|i| i.try_into()); /// assert_eq!(array, Ok([0, 1, 2, 3, 4])); /// -/// let another_array = core::array::try_from_fn::(|_| Err(SomeError::Foo)); -/// assert_eq!(another_array, Err(SomeError::Foo)); +/// let array: Result<[i8; 200], _> = std::array::try_from_fn(|i| i.try_into()); +/// assert!(array.is_err()); +/// +/// let array: Option<[_; 4]> = std::array::try_from_fn(|i| i.checked_add(100)); +/// assert_eq!(array, Some([100, 101, 102, 103])); +/// +/// let array: Option<[_; 4]> = std::array::try_from_fn(|i| i.checked_sub(100)); +/// assert_eq!(array, None); /// ``` #[inline] #[unstable(feature = "array_from_fn", issue = "89379")] -pub fn try_from_fn(cb: F) -> Result<[T; N], E> +pub fn try_from_fn(cb: F) -> ChangeOutputType where - F: FnMut(usize) -> Result, + F: FnMut(usize) -> R, + R: Try, + R::Residual: Residual<[R::Output; N]>, { // SAFETY: we know for certain that this iterator will yield exactly `N` // items. - unsafe { collect_into_array_rslt_unchecked(&mut (0..N).map(cb)) } + unsafe { try_collect_into_array_unchecked(&mut (0..N).map(cb)) } } /// Converts a reference to `T` into a reference to an array of length 1 (without copying). @@ -151,14 +162,16 @@ impl AsMut<[T]> for [T; N] { } #[stable(feature = "array_borrow", since = "1.4.0")] -impl Borrow<[T]> for [T; N] { +#[rustc_const_unstable(feature = "const_borrow", issue = "91522")] +impl const Borrow<[T]> for [T; N] { fn borrow(&self) -> &[T] { self } } #[stable(feature = "array_borrow", since = "1.4.0")] -impl BorrowMut<[T]> for [T; N] { +#[rustc_const_unstable(feature = "const_borrow", issue = "91522")] +impl const BorrowMut<[T]> for [T; N] { fn borrow_mut(&mut self) -> &mut [T] { self } @@ -176,6 +189,18 @@ where } } +#[stable(feature = "try_from_mut_slice_to_array", since = "1.59.0")] +impl TryFrom<&mut [T]> for [T; N] +where + T: Copy, +{ + type Error = TryFromSliceError; + + fn try_from(slice: &mut [T]) -> Result<[T; N], TryFromSliceError> { + ::try_from(&*slice) + } +} + #[stable(feature = "try_from", since = "1.34.0")] impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] { type Error = TryFromSliceError; @@ -232,27 +257,6 @@ impl fmt::Debug for [T; N] { } } -// Note: the `#[rustc_skip_array_during_method_dispatch]` on `trait IntoIterator` -// hides this implementation from explicit `.into_iter()` calls on editions < 2021, -// so those calls will still resolve to the slice implementation, by reference. -#[stable(feature = "array_into_iter_impl", since = "1.53.0")] -impl IntoIterator for [T; N] { - type Item = T; - type IntoIter = IntoIter; - - /// Creates a consuming iterator, that is, one that moves each value out of - /// the array (from start to end). The array cannot be used after calling - /// this unless `T` implements `Copy`, so the whole array is copied. - /// - /// Arrays have special behavior when calling `.into_iter()` prior to the - /// 2021 edition -- see the [array] Editions section for more information. - /// - /// [array]: prim@array - fn into_iter(self) -> Self::IntoIter { - IntoIter::new(self) - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T, const N: usize> IntoIterator for &'a [T; N] { type Item = &'a T; @@ -330,11 +334,9 @@ impl Ord for [T; N] { } } -#[cfg(not(bootstrap))] #[stable(feature = "copy_clone_array_lib", since = "1.58.0")] impl Copy for [T; N] {} -#[cfg(not(bootstrap))] #[stable(feature = "copy_clone_array_lib", since = "1.58.0")] impl Clone for [T; N] { #[inline] @@ -348,12 +350,10 @@ impl Clone for [T; N] { } } -#[cfg(not(bootstrap))] trait SpecArrayClone: Clone { fn clone(array: &[Self; N]) -> [Self; N]; } -#[cfg(not(bootstrap))] impl SpecArrayClone for T { #[inline] default fn clone(array: &[T; N]) -> [T; N] { @@ -363,7 +363,6 @@ impl SpecArrayClone for T { } } -#[cfg(not(bootstrap))] impl SpecArrayClone for T { #[inline] fn clone(array: &[T; N]) -> [T; N] { @@ -449,6 +448,45 @@ impl [T; N] { unsafe { collect_into_array_unchecked(&mut IntoIterator::into_iter(self).map(f)) } } + /// A fallible function `f` applied to each element on array `self` in order to + /// return an array the same size as `self` or the first error encountered. + /// + /// The return type of this function depends on the return type of the closure. + /// If you return `Result` from the closure, you'll get a `Result<[T; N]; E>`. + /// If you return `Option` from the closure, you'll get an `Option<[T; N]>`. + /// + /// # Examples + /// + /// ``` + /// #![feature(array_try_map)] + /// let a = ["1", "2", "3"]; + /// let b = a.try_map(|v| v.parse::()).unwrap().map(|v| v + 1); + /// assert_eq!(b, [2, 3, 4]); + /// + /// let a = ["1", "2a", "3"]; + /// let b = a.try_map(|v| v.parse::()); + /// assert!(b.is_err()); + /// + /// use std::num::NonZeroU32; + /// let z = [1, 2, 0, 3, 4]; + /// assert_eq!(z.try_map(NonZeroU32::new), None); + /// let a = [1, 2, 3]; + /// let b = a.try_map(NonZeroU32::new); + /// let c = b.map(|x| x.map(NonZeroU32::get)); + /// assert_eq!(c, Some(a)); + /// ``` + #[unstable(feature = "array_try_map", issue = "79711")] + pub fn try_map(self, f: F) -> ChangeOutputType + where + F: FnMut(T) -> R, + R: Try, + R::Residual: Residual<[R::Output; N]>, + { + // SAFETY: we know for certain that this iterator will yield exactly `N` + // items. + unsafe { try_collect_into_array_unchecked(&mut IntoIterator::into_iter(self).map(f)) } + } + /// 'Zips up' two arrays into a single array of pairs. /// /// `zip()` returns a new array where every element is a tuple where the @@ -621,47 +659,125 @@ impl [T; N] { pub fn split_array_mut(&mut self) -> (&mut [T; M], &mut [T]) { (&mut self[..]).split_array_mut::() } + + /// Divides one array reference into two at an index from the end. + /// + /// The first will contain all indices from `[0, N - M)` (excluding + /// the index `N - M` itself) and the second will contain all + /// indices from `[N - M, N)` (excluding the index `N` itself). + /// + /// # Panics + /// + /// Panics if `M > N`. + /// + /// # Examples + /// + /// ``` + /// #![feature(split_array)] + /// + /// let v = [1, 2, 3, 4, 5, 6]; + /// + /// { + /// let (left, right) = v.rsplit_array_ref::<0>(); + /// assert_eq!(left, &[1, 2, 3, 4, 5, 6]); + /// assert_eq!(right, &[]); + /// } + /// + /// { + /// let (left, right) = v.rsplit_array_ref::<2>(); + /// assert_eq!(left, &[1, 2, 3, 4]); + /// assert_eq!(right, &[5, 6]); + /// } + /// + /// { + /// let (left, right) = v.rsplit_array_ref::<6>(); + /// assert_eq!(left, &[]); + /// assert_eq!(right, &[1, 2, 3, 4, 5, 6]); + /// } + /// ``` + #[unstable( + feature = "split_array", + reason = "return type should have array as 2nd element", + issue = "90091" + )] + #[inline] + pub fn rsplit_array_ref(&self) -> (&[T], &[T; M]) { + (&self[..]).rsplit_array_ref::() + } + + /// Divides one mutable array reference into two at an index from the end. + /// + /// The first will contain all indices from `[0, N - M)` (excluding + /// the index `N - M` itself) and the second will contain all + /// indices from `[N - M, N)` (excluding the index `N` itself). + /// + /// # Panics + /// + /// Panics if `M > N`. + /// + /// # Examples + /// + /// ``` + /// #![feature(split_array)] + /// + /// let mut v = [1, 0, 3, 0, 5, 6]; + /// let (left, right) = v.rsplit_array_mut::<4>(); + /// assert_eq!(left, &mut [1, 0]); + /// assert_eq!(right, &mut [3, 0, 5, 6][..]); + /// left[1] = 2; + /// right[1] = 4; + /// assert_eq!(v, [1, 2, 3, 4, 5, 6]); + /// ``` + #[unstable( + feature = "split_array", + reason = "return type should have array as 2nd element", + issue = "90091" + )] + #[inline] + pub fn rsplit_array_mut(&mut self) -> (&mut [T], &mut [T; M]) { + (&mut self[..]).rsplit_array_mut::() + } } /// Pulls `N` items from `iter` and returns them as an array. If the iterator /// yields fewer than `N` items, this function exhibits undefined behavior. /// -/// See [`collect_into_array`] for more information. +/// See [`try_collect_into_array`] for more information. /// /// /// # Safety /// /// It is up to the caller to guarantee that `iter` yields at least `N` items. /// Violating this condition causes undefined behavior. -unsafe fn collect_into_array_rslt_unchecked( - iter: &mut I, -) -> Result<[T; N], E> +unsafe fn try_collect_into_array_unchecked(iter: &mut I) -> R::TryType where // Note: `TrustedLen` here is somewhat of an experiment. This is just an // internal function, so feel free to remove if this bound turns out to be a // bad idea. In that case, remember to also remove the lower bound // `debug_assert!` below! - I: Iterator> + TrustedLen, + I: Iterator + TrustedLen, + I::Item: Try, + R: Residual<[T; N]>, { debug_assert!(N <= iter.size_hint().1.unwrap_or(usize::MAX)); debug_assert!(N <= iter.size_hint().0); // SAFETY: covered by the function contract. - unsafe { collect_into_array(iter).unwrap_unchecked() } + unsafe { try_collect_into_array(iter).unwrap_unchecked() } } -// Infallible version of `collect_into_array_rslt_unchecked`. +// Infallible version of `try_collect_into_array_unchecked`. unsafe fn collect_into_array_unchecked(iter: &mut I) -> [I::Item; N] where I: Iterator + TrustedLen, { - let mut map = iter.map(Ok::<_, Infallible>); + let mut map = iter.map(NeverShortCircuit); // SAFETY: The same safety considerations w.r.t. the iterator length - // apply for `collect_into_array_rslt_unchecked` as for + // apply for `try_collect_into_array_unchecked` as for // `collect_into_array_unchecked` - match unsafe { collect_into_array_rslt_unchecked(&mut map) } { - Ok(array) => array, + match unsafe { try_collect_into_array_unchecked(&mut map) } { + NeverShortCircuit(array) => array, } } @@ -675,13 +791,15 @@ where /// /// If `iter.next()` panicks, all items already yielded by the iterator are /// dropped. -fn collect_into_array(iter: &mut I) -> Option> +fn try_collect_into_array(iter: &mut I) -> Option where - I: Iterator>, + I: Iterator, + I::Item: Try, + R: Residual<[T; N]>, { if N == 0 { // SAFETY: An empty array is always inhabited and has no validity invariants. - return unsafe { Some(Ok(mem::zeroed())) }; + return unsafe { Some(Try::from_output(mem::zeroed())) }; } struct Guard<'a, T, const N: usize> { @@ -706,11 +824,11 @@ where let mut guard = Guard { array_mut: &mut array, initialized: 0 }; while let Some(item_rslt) = iter.next() { - let item = match item_rslt { - Err(err) => { - return Some(Err(err)); + let item = match item_rslt.branch() { + ControlFlow::Break(r) => { + return Some(FromResidual::from_residual(r)); } - Ok(elem) => elem, + ControlFlow::Continue(elem) => elem, }; // SAFETY: `guard.initialized` starts at 0, is increased by one in the @@ -728,7 +846,7 @@ where // SAFETY: the condition above asserts that all elements are // initialized. let out = unsafe { MaybeUninit::array_assume_init(array) }; - return Some(Ok(out)); + return Some(Try::from_output(out)); } } diff --git a/library/core/src/bool.rs b/library/core/src/bool.rs index f14c2a4641..d5119d0b7c 100644 --- a/library/core/src/bool.rs +++ b/library/core/src/bool.rs @@ -14,8 +14,12 @@ impl bool { /// assert_eq!(true.then_some(0), Some(0)); /// ``` #[unstable(feature = "bool_to_option", issue = "80967")] + #[rustc_const_unstable(feature = "const_bool_to_option", issue = "91917")] #[inline] - pub fn then_some(self, t: T) -> Option { + pub const fn then_some(self, t: T) -> Option + where + T: ~const Drop, + { if self { Some(t) } else { None } } @@ -29,8 +33,13 @@ impl bool { /// assert_eq!(true.then(|| 0), Some(0)); /// ``` #[stable(feature = "lazy_bool_to_option", since = "1.50.0")] + #[rustc_const_unstable(feature = "const_bool_to_option", issue = "91917")] #[inline] - pub fn then T>(self, f: F) -> Option { + pub const fn then(self, f: F) -> Option + where + F: ~const FnOnce() -> T, + F: ~const Drop, + { if self { Some(f()) } else { None } } } diff --git a/library/core/src/borrow.rs b/library/core/src/borrow.rs index f28be20aaa..58eabecf3f 100644 --- a/library/core/src/borrow.rs +++ b/library/core/src/borrow.rs @@ -205,7 +205,8 @@ pub trait BorrowMut: Borrow { } #[stable(feature = "rust1", since = "1.0.0")] -impl Borrow for T { +#[rustc_const_unstable(feature = "const_borrow", issue = "91522")] +impl const Borrow for T { #[rustc_diagnostic_item = "noop_method_borrow"] fn borrow(&self) -> &T { self @@ -213,28 +214,32 @@ impl Borrow for T { } #[stable(feature = "rust1", since = "1.0.0")] -impl BorrowMut for T { +#[rustc_const_unstable(feature = "const_borrow", issue = "91522")] +impl const BorrowMut for T { fn borrow_mut(&mut self) -> &mut T { self } } #[stable(feature = "rust1", since = "1.0.0")] -impl Borrow for &T { +#[rustc_const_unstable(feature = "const_borrow", issue = "91522")] +impl const Borrow for &T { fn borrow(&self) -> &T { &**self } } #[stable(feature = "rust1", since = "1.0.0")] -impl Borrow for &mut T { +#[rustc_const_unstable(feature = "const_borrow", issue = "91522")] +impl const Borrow for &mut T { fn borrow(&self) -> &T { &**self } } #[stable(feature = "rust1", since = "1.0.0")] -impl BorrowMut for &mut T { +#[rustc_const_unstable(feature = "const_borrow", issue = "91522")] +impl const BorrowMut for &mut T { fn borrow_mut(&mut self) -> &mut T { &mut **self } diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 06dc5ecf2f..bc3f7167fa 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -898,7 +898,7 @@ impl RefCell { Ok(Ref { value: unsafe { &*self.value.get() }, borrow: b }) } None => Err(BorrowError { - // If a borrow occured, then we must already have an outstanding borrow, + // If a borrow occurred, then we must already have an outstanding borrow, // so `borrowed_at` will be `Some` #[cfg(feature = "debug_refcell")] location: self.borrowed_at.get().unwrap(), @@ -983,7 +983,7 @@ impl RefCell { Ok(RefMut { value: unsafe { &mut *self.value.get() }, borrow: b }) } None => Err(BorrowMutError { - // If a borrow occured, then we must already have an outstanding borrow, + // If a borrow occurred, then we must already have an outstanding borrow, // so `borrowed_at` will be `Some` #[cfg(feature = "debug_refcell")] location: self.borrowed_at.get().unwrap(), @@ -1104,7 +1104,7 @@ impl RefCell { Ok(unsafe { &*self.value.get() }) } else { Err(BorrowError { - // If a borrow occured, then we must already have an outstanding borrow, + // If a borrow occurred, then we must already have an outstanding borrow, // so `borrowed_at` will be `Some` #[cfg(feature = "debug_refcell")] location: self.borrowed_at.get().unwrap(), diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs index c4046d7496..1774ddd7cb 100644 --- a/library/core/src/char/convert.rs +++ b/library/core/src/char/convert.rs @@ -1,5 +1,6 @@ //! Character conversions. +use crate::char::TryFromCharError; use crate::convert::TryFrom; use crate::fmt; use crate::mem::transmute; @@ -166,6 +167,20 @@ impl const From for u128 { } } +/// Map `char` with code point in U+0000..=U+00FF to byte in 0x00..=0xFF with same value, failing +/// if the code point is greater than U+00FF. +/// +/// See [`impl From for char`](char#impl-From) for details on the encoding. +#[stable(feature = "u8_from_char", since = "1.59.0")] +impl TryFrom for u8 { + type Error = TryFromCharError; + + #[inline] + fn try_from(c: char) -> Result { + u8::try_from(u32::from(c)).map_err(|_| TryFromCharError(())) + } +} + /// Maps a byte in 0x00..=0xFF to a `char` whose code point has the same value, in U+0000..=U+00FF. /// /// Unicode is designed such that this effectively decodes bytes diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs index 0728523d0a..f65f84e93a 100644 --- a/library/core/src/char/mod.rs +++ b/library/core/src/char/mod.rs @@ -393,6 +393,13 @@ impl Iterator for ToLowercase { } } +#[stable(feature = "case_mapping_double_ended", since = "1.59.0")] +impl DoubleEndedIterator for ToLowercase { + fn next_back(&mut self) -> Option { + self.0.next_back() + } +} + #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for ToLowercase {} @@ -420,6 +427,13 @@ impl Iterator for ToUppercase { } } +#[stable(feature = "case_mapping_double_ended", since = "1.59.0")] +impl DoubleEndedIterator for ToUppercase { + fn next_back(&mut self) -> Option { + self.0.next_back() + } +} + #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for ToUppercase {} @@ -479,6 +493,26 @@ impl Iterator for CaseMappingIter { } } +impl DoubleEndedIterator for CaseMappingIter { + fn next_back(&mut self) -> Option { + match *self { + CaseMappingIter::Three(a, b, c) => { + *self = CaseMappingIter::Two(a, b); + Some(c) + } + CaseMappingIter::Two(b, c) => { + *self = CaseMappingIter::One(b); + Some(c) + } + CaseMappingIter::One(c) => { + *self = CaseMappingIter::Zero; + Some(c) + } + CaseMappingIter::Zero => None, + } + } +} + impl fmt::Display for CaseMappingIter { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { @@ -510,3 +544,15 @@ impl fmt::Display for ToUppercase { fmt::Display::fmt(&self.0, f) } } + +/// The error type returned when a checked char conversion fails. +#[stable(feature = "u8_from_char", since = "1.59.0")] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub struct TryFromCharError(pub(crate) ()); + +#[stable(feature = "u8_from_char", since = "1.59.0")] +impl fmt::Display for TryFromCharError { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + "unicode code point out of range".fmt(fmt) + } +} diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 7456f886ea..deed9901cc 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -215,6 +215,7 @@ pub trait PartialEq { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] + #[default_method_body_is_const] fn ne(&self, other: &Rhs) -> bool { !self.eq(other) } @@ -1031,6 +1032,7 @@ pub trait PartialOrd: PartialEq { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] + #[default_method_body_is_const] fn lt(&self, other: &Rhs) -> bool { matches!(self.partial_cmp(other), Some(Less)) } @@ -1050,6 +1052,7 @@ pub trait PartialOrd: PartialEq { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] + #[default_method_body_is_const] fn le(&self, other: &Rhs) -> bool { // Pattern `Some(Less | Eq)` optimizes worse than negating `None | Some(Greater)`. // FIXME: The root cause was fixed upstream in LLVM with: @@ -1072,6 +1075,7 @@ pub trait PartialOrd: PartialEq { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] + #[default_method_body_is_const] fn gt(&self, other: &Rhs) -> bool { matches!(self.partial_cmp(other), Some(Greater)) } @@ -1091,6 +1095,7 @@ pub trait PartialOrd: PartialEq { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] + #[default_method_body_is_const] fn ge(&self, other: &Rhs) -> bool { matches!(self.partial_cmp(other), Some(Greater | Equal)) } diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 5aa53deee3..1c2e673d60 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -534,9 +534,10 @@ where // From implies Into #[stable(feature = "rust1", since = "1.0.0")] -impl Into for T +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl const Into for T where - U: From, + U: ~const From, { fn into(self) -> U { U::from(self) diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 80d3270d73..8a2a64f8dc 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -570,11 +570,30 @@ impl Display for Arguments<'_> { /// There are a number of helper methods on the [`Formatter`] struct to help you with manual /// implementations, such as [`debug_struct`]. /// +/// [`debug_struct`]: Formatter::debug_struct +/// +/// Types that do not wish to use the standard suite of debug representations +/// provided by the `Formatter` trait (`debug_struct`, `debug_tuple`, +/// `debut_list`, `debug_set`, `debug_map`) can do something totally custom by +/// manually writing an arbitrary representation to the `Formatter`. +/// +/// ``` +/// # use std::fmt; +/// # struct Point { +/// # x: i32, +/// # y: i32, +/// # } +/// # +/// impl fmt::Debug for Point { +/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +/// write!(f, "Point [{} {}]", self.x, self.y) +/// } +/// } +/// ``` +/// /// `Debug` implementations using either `derive` or the debug builder API /// on [`Formatter`] support pretty-printing using the alternate flag: `{:#?}`. /// -/// [`debug_struct`]: Formatter::debug_struct -/// /// Pretty-printing with `#?`: /// /// ``` @@ -2186,28 +2205,34 @@ impl Display for char { #[stable(feature = "rust1", since = "1.0.0")] impl Pointer for *const T { fn fmt(&self, f: &mut Formatter<'_>) -> Result { - let old_width = f.width; - let old_flags = f.flags; + /// Since the formatting will be identical for all pointer types, use a non-monomorphized + /// implementation for the actual formatting to reduce the amount of codegen work needed + fn inner(ptr: *const (), f: &mut Formatter<'_>) -> Result { + let old_width = f.width; + let old_flags = f.flags; - // The alternate flag is already treated by LowerHex as being special- - // it denotes whether to prefix with 0x. We use it to work out whether - // or not to zero extend, and then unconditionally set it to get the - // prefix. - if f.alternate() { - f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32); + // The alternate flag is already treated by LowerHex as being special- + // it denotes whether to prefix with 0x. We use it to work out whether + // or not to zero extend, and then unconditionally set it to get the + // prefix. + if f.alternate() { + f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32); - if f.width.is_none() { - f.width = Some((usize::BITS / 4) as usize + 2); + if f.width.is_none() { + f.width = Some((usize::BITS / 4) as usize + 2); + } } + f.flags |= 1 << (FlagV1::Alternate as u32); + + let ret = LowerHex::fmt(&(ptr as usize), f); + + f.width = old_width; + f.flags = old_flags; + + ret } - f.flags |= 1 << (FlagV1::Alternate as u32); - let ret = LowerHex::fmt(&(*self as *const () as usize), f); - - f.width = old_width; - f.flags = old_flags; - - ret + inner(*self as *const (), f) } } diff --git a/library/core/src/future/future.rs b/library/core/src/future/future.rs index 09d8a2aac2..6b62236b32 100644 --- a/library/core/src/future/future.rs +++ b/library/core/src/future/future.rs @@ -28,7 +28,11 @@ use crate::task::{Context, Poll}; #[must_use = "futures do nothing unless you `.await` or poll them"] #[stable(feature = "futures_api", since = "1.36.0")] #[lang = "future_trait"] -#[rustc_on_unimplemented(label = "`{Self}` is not a future", message = "`{Self}` is not a future")] +#[rustc_on_unimplemented( + label = "`{Self}` is not a future", + message = "`{Self}` is not a future", + note = "{Self} must be a future or must implement `IntoFuture` to be awaited" +)] pub trait Future { /// The type of value produced on completion. #[stable(feature = "futures_api", since = "1.36.0")] diff --git a/library/core/src/future/into_future.rs b/library/core/src/future/into_future.rs index 4020c25444..cac1866188 100644 --- a/library/core/src/future/into_future.rs +++ b/library/core/src/future/into_future.rs @@ -13,6 +13,7 @@ pub trait IntoFuture { /// Creates a future from a value. #[unstable(feature = "into_future", issue = "67644")] + #[cfg_attr(not(bootstrap), lang = "into_future")] fn into_future(self) -> Self::Future; } diff --git a/library/core/src/future/join.rs b/library/core/src/future/join.rs new file mode 100644 index 0000000000..a6ffbe07d9 --- /dev/null +++ b/library/core/src/future/join.rs @@ -0,0 +1,193 @@ +#![allow(unused_imports, unused_macros)] // items are used by the macro + +use crate::cell::UnsafeCell; +use crate::future::{poll_fn, Future}; +use crate::mem; +use crate::pin::Pin; +use crate::task::{Context, Poll}; + +/// Polls multiple futures simultaneously, returning a tuple +/// of all results once complete. +/// +/// While `join!(a, b)` is similar to `(a.await, b.await)`, +/// `join!` polls both futures concurrently and is therefore more efficient. +/// +/// # Examples +/// +/// ``` +/// #![feature(future_join, future_poll_fn)] +/// +/// use std::future::join; +/// +/// async fn one() -> usize { 1 } +/// async fn two() -> usize { 2 } +/// +/// # let _ = async { +/// let x = join!(one(), two()).await; +/// assert_eq!(x, (1, 2)); +/// # }; +/// ``` +/// +/// `join!` is variadic, so you can pass any number of futures: +/// +/// ``` +/// #![feature(future_join, future_poll_fn)] +/// +/// use std::future::join; +/// +/// async fn one() -> usize { 1 } +/// async fn two() -> usize { 2 } +/// async fn three() -> usize { 3 } +/// +/// # let _ = async { +/// let x = join!(one(), two(), three()).await; +/// assert_eq!(x, (1, 2, 3)); +/// # }; +/// ``` +#[unstable(feature = "future_join", issue = "91642")] +pub macro join( $($fut:expr),+ $(,)? ) { + // Funnel through an internal macro not to leak implementation details. + join_internal! { + current_position: [] + futures_and_positions: [] + munching: [ $($fut)+ ] + } +} + +// FIXME(danielhenrymantilla): a private macro should need no stability guarantee. +#[unstable(feature = "future_join", issue = "91642")] +/// To be able to *name* the i-th future in the tuple (say we want the .4-th), +/// the following trick will be used: `let (_, _, _, _, it, ..) = tuple;` +/// In order to do that, we need to generate a `i`-long repetition of `_`, +/// for each i-th fut. Hence the recursive muncher approach. +macro join_internal { + // Recursion step: map each future with its "position" (underscore count). + ( + // Accumulate a token for each future that has been expanded: "_ _ _". + current_position: [ + $($underscores:tt)* + ] + // Accumulate Futures and their positions in the tuple: `_0th () _1st ( _ ) …`. + futures_and_positions: [ + $($acc:tt)* + ] + // Munch one future. + munching: [ + $current:tt + $($rest:tt)* + ] + ) => ( + join_internal! { + current_position: [ + $($underscores)* + _ + ] + futures_and_positions: [ + $($acc)* + $current ( $($underscores)* ) + ] + munching: [ + $($rest)* + ] + } + ), + + // End of recursion: generate the output future. + ( + current_position: $_:tt + futures_and_positions: [ + $( + $fut_expr:tt ( $($pos:tt)* ) + )* + ] + // Nothing left to munch. + munching: [] + ) => ( + match ( $( MaybeDone::Future($fut_expr), )* ) { futures => async { + let mut futures = futures; + // SAFETY: this is `pin_mut!`. + let mut futures = unsafe { Pin::new_unchecked(&mut futures) }; + poll_fn(move |cx| { + let mut done = true; + // For each `fut`, pin-project to it, and poll it. + $( + // SAFETY: pinning projection + let fut = unsafe { + futures.as_mut().map_unchecked_mut(|it| { + let ( $($pos,)* fut, .. ) = it; + fut + }) + }; + // Despite how tempting it may be to `let () = fut.poll(cx).ready()?;` + // doing so would defeat the point of `join!`: to start polling eagerly all + // of the futures, to allow parallelizing the waits. + done &= fut.poll(cx).is_ready(); + )* + if !done { + return Poll::Pending; + } + // All ready; time to extract all the outputs. + + // SAFETY: `.take_output()` does not break the `Pin` invariants for that `fut`. + let futures = unsafe { + futures.as_mut().get_unchecked_mut() + }; + Poll::Ready( + ($( + { + let ( $($pos,)* fut, .. ) = &mut *futures; + fut.take_output().unwrap() + } + ),*) // <- no trailing comma since we don't want 1-tuples. + ) + }).await + }} + ), +} + +/// Future used by `join!` that stores it's output to +/// be later taken and doesn't panic when polled after ready. +/// +/// This type is public in a private module for use by the macro. +#[allow(missing_debug_implementations)] +#[unstable(feature = "future_join", issue = "91642")] +pub enum MaybeDone { + Future(F), + Done(F::Output), + Taken, +} + +#[unstable(feature = "future_join", issue = "91642")] +impl MaybeDone { + pub fn take_output(&mut self) -> Option { + match *self { + MaybeDone::Done(_) => match mem::replace(self, Self::Taken) { + MaybeDone::Done(val) => Some(val), + _ => unreachable!(), + }, + _ => None, + } + } +} + +#[unstable(feature = "future_join", issue = "91642")] +impl Future for MaybeDone { + type Output = (); + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + // SAFETY: pinning in structural for `f` + unsafe { + // Do not mix match ergonomics with unsafe. + match *self.as_mut().get_unchecked_mut() { + MaybeDone::Future(ref mut f) => { + let val = Pin::new_unchecked(f).poll(cx).ready()?; + self.set(Self::Done(val)); + } + MaybeDone::Done(_) => {} + MaybeDone::Taken => unreachable!(), + } + } + + Poll::Ready(()) + } +} diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs index 7a3af70d6d..88db584aef 100644 --- a/library/core/src/future/mod.rs +++ b/library/core/src/future/mod.rs @@ -11,6 +11,7 @@ use crate::{ mod future; mod into_future; +mod join; mod pending; mod poll_fn; mod ready; @@ -18,6 +19,9 @@ mod ready; #[stable(feature = "futures_api", since = "1.36.0")] pub use self::future::Future; +#[unstable(feature = "future_join", issue = "91642")] +pub use self::join::join; + #[unstable(feature = "into_future", issue = "67644")] pub use into_future::IntoFuture; diff --git a/library/core/src/future/ready.rs b/library/core/src/future/ready.rs index cc905d288f..48f20f90a3 100644 --- a/library/core/src/future/ready.rs +++ b/library/core/src/future/ready.rs @@ -2,7 +2,7 @@ use crate::future::Future; use crate::pin::Pin; use crate::task::{Context, Poll}; -/// Creates a future that is immediately ready with a value. +/// A future that is immediately ready with a value. /// /// This `struct` is created by [`ready()`]. See its /// documentation for more. diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index 540160bc4c..3ff84cc967 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -164,6 +164,19 @@ mod sip; /// `0xFF` byte to the `Hasher` so that the values `("ab", "c")` and `("a", /// "bc")` hash differently. /// +/// ## Portability +/// +/// Due to differences in endianness and type sizes, data fed by `Hash` to a `Hasher` +/// should not be considered portable across platforms. Additionally the data passed by most +/// standard library types should not be considered stable between compiler versions. +/// +/// This means tests shouldn't probe hard-coded hash values or data fed to a `Hasher` and +/// instead should check consistency with `Eq`. +/// +/// Serialization formats intended to be portable between platforms or compiler versions should +/// either avoid encoding hashes or only rely on `Hash` and `Hasher` implementations that +/// provide additional guarantees. +/// /// [`HashMap`]: ../../std/collections/struct.HashMap.html /// [`HashSet`]: ../../std/collections/struct.HashSet.html /// [`hash`]: Hash::hash diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 9579887915..330c43d294 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -123,6 +123,21 @@ pub fn spin_loop() { } } + // RISC-V platform spin loop hint implementation + { + // RISC-V RV32 and RV64 share the same PAUSE instruction, but they are located in different + // modules in `core::arch`. + // In this case, here we call `pause` function in each core arch module. + #[cfg(target_arch = "riscv32")] + { + crate::arch::riscv32::pause(); + } + #[cfg(target_arch = "riscv64")] + { + crate::arch::riscv64::pause(); + } + } + #[cfg(any(target_arch = "aarch64", all(target_arch = "arm", target_feature = "v6")))] { #[cfg(target_arch = "aarch64")] @@ -154,6 +169,7 @@ pub fn spin_loop() { /// [`std::convert::identity`]: crate::convert::identity #[inline] #[unstable(feature = "bench_black_box", issue = "64102")] -pub fn black_box(dummy: T) -> T { +#[rustc_const_unstable(feature = "const_black_box", issue = "none")] +pub const fn black_box(dummy: T) -> T { crate::intrinsics::black_box(dummy) } diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 0f57fb5b14..4ecc3b0c7f 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -811,7 +811,8 @@ extern "rust-intrinsic" { /// The preferred alignment of a type. /// /// This intrinsic does not have a stable counterpart. - #[rustc_const_unstable(feature = "const_pref_align_of", issue = "none")] + /// It's "tracking issue" is [#91971](https://github.com/rust-lang/rust/issues/91971). + #[rustc_const_unstable(feature = "const_pref_align_of", issue = "91971")] pub fn pref_align_of() -> usize; /// The size of the referenced value in bytes. @@ -853,19 +854,21 @@ extern "rust-intrinsic" { /// This will statically either panic, or do nothing. /// /// This intrinsic does not have a stable counterpart. - #[rustc_const_unstable(feature = "const_assert_type", issue = "none")] + #[rustc_const_stable(feature = "const_assert_type", since = "1.59.0")] pub fn assert_inhabited(); /// A guard for unsafe functions that cannot ever be executed if `T` does not permit /// zero-initialization: This will statically either panic, or do nothing. /// /// This intrinsic does not have a stable counterpart. + #[rustc_const_unstable(feature = "const_assert_type2", issue = "none")] pub fn assert_zero_valid(); /// A guard for unsafe functions that cannot ever be executed if `T` has invalid /// bit patterns: This will statically either panic, or do nothing. /// /// This intrinsic does not have a stable counterpart. + #[rustc_const_unstable(feature = "const_assert_type2", issue = "none")] pub fn assert_uninit_valid(); /// Gets a reference to a static `Location` indicating where it was called. @@ -1917,7 +1920,7 @@ extern "rust-intrinsic" { /// Determines whether the raw bytes of the two values are equal. /// - /// The is particularly handy for arrays, since it allows things like just + /// This is particularly handy for arrays, since it allows things like just /// comparing `i96`s instead of forcing `alloca`s for `[6 x i16]`. /// /// Above some backend-decided threshold this will emit calls to `memcmp`, @@ -1937,6 +1940,7 @@ extern "rust-intrinsic" { /// See documentation of [`std::hint::black_box`] for details. /// /// [`std::hint::black_box`]: crate::hint::black_box + #[rustc_const_unstable(feature = "const_black_box", issue = "none")] pub fn black_box(dummy: T) -> T; } @@ -2068,8 +2072,8 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us #[cfg(debug_assertions)] const fn compiletime_check(_src: *const T, _dst: *mut T, _count: usize) {} #[cfg(debug_assertions)] - // SAFETY: runtime debug-assertions are a best-effort basis; it's fine to - // not do them during compile time + // SAFETY: As per our safety precondition, we may assume that the `abort` above is never reached. + // Therefore, compiletime_check and runtime_check are observably equivalent. unsafe { const_eval_select((src, dst, count), compiletime_check, runtime_check); } @@ -2159,8 +2163,8 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { #[cfg(debug_assertions)] const fn compiletime_check(_src: *const T, _dst: *mut T) {} #[cfg(debug_assertions)] - // SAFETY: runtime debug-assertions are a best-effort basis; it's fine to - // not do them during compile time + // SAFETY: As per our safety precondition, we may assume that the `abort` above is never reached. + // Therefore, compiletime_check and runtime_check are observably equivalent. unsafe { const_eval_select((src, dst), compiletime_check, runtime_check); } @@ -2242,13 +2246,29 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { /// assert_eq!(*v, 42); /// ``` #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] #[inline] -pub unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { +pub const unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { extern "rust-intrinsic" { + #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] fn write_bytes(dst: *mut T, val: u8, count: usize); } - debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer"); + #[cfg(debug_assertions)] + fn runtime_check(ptr: *mut T) { + debug_assert!( + is_aligned_and_not_null(ptr), + "attempt to write to unaligned or null pointer" + ); + } + #[cfg(debug_assertions)] + const fn compiletime_check(_ptr: *mut T) {} + #[cfg(debug_assertions)] + // SAFETY: runtime debug-assertions are a best-effort basis; it's fine to + // not do them during compile time + unsafe { + const_eval_select((dst,), compiletime_check, runtime_check); + } // SAFETY: the safety contract for `write_bytes` must be upheld by the caller. unsafe { write_bytes(dst, val, count) } @@ -2271,19 +2291,40 @@ pub unsafe fn write_bytes(dst: *mut T, val: u8, count: usize) { /// /// # Safety /// -/// This intrinsic allows breaking [referential transparency] in `const fn` -/// and is therefore `unsafe`. +/// The two functions must behave observably equivalent. Safe code in other +/// crates may assume that calling a `const fn` at compile-time and at run-time +/// produces the same result. A function that produces a different result when +/// evaluated at run-time, or has any other observable side-effects, is +/// *unsound*. /// -/// Code that uses this intrinsic must be extremely careful to ensure that -/// `const fn`s remain referentially-transparent independently of when they -/// are evaluated. +/// Here is an example of how this could cause a problem: +/// ```no_run +/// #![feature(const_eval_select)] +/// use std::hint::unreachable_unchecked; +/// use std::intrinsics::const_eval_select; /// -/// The Rust compiler assumes that it is sound to replace a call to a `const -/// fn` with the result produced by evaluating it at compile-time. If -/// evaluating the function at run-time were to produce a different result, -/// or have any other observable side-effects, the behavior is undefined. +/// // Crate A +/// pub const fn inconsistent() -> i32 { +/// fn runtime() -> i32 { 1 } +/// const fn compiletime() -> i32 { 2 } /// -/// [referential transparency]: https://en.wikipedia.org/wiki/Referential_transparency +/// unsafe { +// // ⚠ This code violates the required equivalence of `compiletime` +/// // and `runtime`. +/// const_eval_select((), compiletime, runtime) +/// } +/// } +/// +/// // Crate B +/// const X: i32 = inconsistent(); +/// let x = inconsistent(); +/// if x != X { unsafe { unreachable_unchecked(); }} +/// ``` +/// +/// This code causes Undefined Behavior when being run, since the +/// `unreachable_unchecked` is actually being reached. The bug is in *crate A*, +/// which violates the principle that a `const fn` must behave the same at +/// compile-time and at run-time. The unsafe code in crate B is fine. #[unstable( feature = "const_eval_select", issue = "none", diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index 9e1f4e425f..b1b917775c 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -54,7 +54,7 @@ pub use self::zip::TrustedRandomAccess; #[unstable(feature = "trusted_random_access", issue = "none")] pub use self::zip::TrustedRandomAccessNoCoerce; -#[unstable(feature = "iter_zip", issue = "83574")] +#[stable(feature = "iter_zip", since = "1.59.0")] pub use self::zip::zip; /// This trait provides transitive access to source-stage in an iterator-adapter pipeline diff --git a/library/core/src/iter/adapters/skip.rs b/library/core/src/iter/adapters/skip.rs index 565fc224f5..ea1da8ba43 100644 --- a/library/core/src/iter/adapters/skip.rs +++ b/library/core/src/iter/adapters/skip.rs @@ -119,8 +119,8 @@ where #[rustc_inherit_overflow_checks] fn advance_by(&mut self, n: usize) -> Result<(), usize> { let mut rem = n; - let step_one = self.n.saturating_add(rem); + match self.iter.advance_by(step_one) { Ok(_) => { rem -= step_one - self.n; @@ -129,7 +129,7 @@ where Err(advanced) => { let advanced_without_skip = advanced.saturating_sub(self.n); self.n = self.n.saturating_sub(advanced); - return Err(advanced_without_skip); + return if n == 0 { Ok(()) } else { Err(advanced_without_skip) }; } } diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs index 81f6c294fa..2962e0104d 100644 --- a/library/core/src/iter/adapters/take.rs +++ b/library/core/src/iter/adapters/take.rs @@ -215,21 +215,22 @@ where } #[inline] + #[rustc_inherit_overflow_checks] fn advance_back_by(&mut self, n: usize) -> Result<(), usize> { - let inner_len = self.iter.len(); - let len = self.n; - let remainder = len.saturating_sub(n); - let to_advance = inner_len - remainder; - match self.iter.advance_back_by(to_advance) { - Ok(_) => { - self.n = remainder; - if n > len { - return Err(len); - } - return Ok(()); - } - _ => panic!("ExactSizeIterator contract violation"), - } + // The amount by which the inner iterator needs to be shortened for it to be + // at most as long as the take() amount. + let trim_inner = self.iter.len().saturating_sub(self.n); + // The amount we need to advance inner to fulfill the caller's request. + // take(), advance_by() and len() all can be at most usize, so we don't have to worry + // about having to advance more than usize::MAX here. + let advance_by = trim_inner.saturating_add(n); + + let advanced = match self.iter.advance_back_by(advance_by) { + Ok(_) => advance_by - trim_inner, + Err(advanced) => advanced - trim_inner, + }; + self.n -= advanced; + return if advanced < n { Err(advanced) } else { Ok(()) }; } } diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs index 4b89bc3632..f50e71da20 100644 --- a/library/core/src/iter/adapters/zip.rs +++ b/library/core/src/iter/adapters/zip.rs @@ -40,22 +40,29 @@ impl Zip { /// # Examples /// /// ``` -/// #![feature(iter_zip)] /// use std::iter::zip; /// /// let xs = [1, 2, 3]; /// let ys = [4, 5, 6]; -/// for (x, y) in zip(&xs, &ys) { -/// println!("x:{}, y:{}", x, y); -/// } +/// +/// let mut iter = zip(xs, ys); +/// +/// assert_eq!(iter.next().unwrap(), (1, 4)); +/// assert_eq!(iter.next().unwrap(), (2, 5)); +/// assert_eq!(iter.next().unwrap(), (3, 6)); +/// assert!(iter.next().is_none()); /// /// // Nested zips are also possible: /// let zs = [7, 8, 9]; -/// for ((x, y), z) in zip(zip(&xs, &ys), &zs) { -/// println!("x:{}, y:{}, z:{}", x, y, z); -/// } +/// +/// let mut iter = zip(zip(xs, ys), zs); +/// +/// assert_eq!(iter.next().unwrap(), ((1, 4), 7)); +/// assert_eq!(iter.next().unwrap(), ((2, 5), 8)); +/// assert_eq!(iter.next().unwrap(), ((3, 6), 9)); +/// assert!(iter.next().is_none()); /// ``` -#[unstable(feature = "iter_zip", issue = "83574")] +#[stable(feature = "iter_zip", since = "1.59.0")] pub fn zip(a: A, b: B) -> Zip where A: IntoIterator, @@ -509,7 +516,7 @@ impl(self, predicate: P) -> SkipWhile where @@ -2216,6 +2216,86 @@ pub trait Iterator { Some(self.fold(first, f)) } + /// Reduces the elements to a single one by repeatedly applying a reducing operation. If the + /// closure returns a failure, the failure is propagated back to the caller immediately. + /// + /// The return type of this method depends on the return type of the closure. If the closure + /// returns `Result`, then this function will return `Result, + /// E>`. If the closure returns `Option`, then this function will return + /// `Option>`. + /// + /// When called on an empty iterator, this function will return either `Some(None)` or + /// `Ok(None)` depending on the type of the provided closure. + /// + /// For iterators with at least one element, this is essentially the same as calling + /// [`try_fold()`] with the first element of the iterator as the initial accumulator value. + /// + /// [`try_fold()`]: Iterator::try_fold + /// + /// # Examples + /// + /// Safely calculate the sum of a series of numbers: + /// + /// ``` + /// #![feature(iterator_try_reduce)] + /// + /// let numbers: Vec = vec![10, 20, 5, 23, 0]; + /// let sum = numbers.into_iter().try_reduce(|x, y| x.checked_add(y)); + /// assert_eq!(sum, Some(Some(58))); + /// ``` + /// + /// Determine when a reduction short circuited: + /// + /// ``` + /// #![feature(iterator_try_reduce)] + /// + /// let numbers = vec![1, 2, 3, usize::MAX, 4, 5]; + /// let sum = numbers.into_iter().try_reduce(|x, y| x.checked_add(y)); + /// assert_eq!(sum, None); + /// ``` + /// + /// Determine when a reduction was not performed because there are no elements: + /// + /// ``` + /// #![feature(iterator_try_reduce)] + /// + /// let numbers: Vec = Vec::new(); + /// let sum = numbers.into_iter().try_reduce(|x, y| x.checked_add(y)); + /// assert_eq!(sum, Some(None)); + /// ``` + /// + /// Use a [`Result`] instead of an [`Option`]: + /// + /// ``` + /// #![feature(iterator_try_reduce)] + /// + /// let numbers = vec!["1", "2", "3", "4", "5"]; + /// let max: Result, ::Err> = + /// numbers.into_iter().try_reduce(|x, y| { + /// if x.parse::()? > y.parse::()? { Ok(x) } else { Ok(y) } + /// }); + /// assert_eq!(max, Ok(Some("5"))); + /// ``` + #[inline] + #[unstable(feature = "iterator_try_reduce", reason = "new API", issue = "87053")] + fn try_reduce(&mut self, f: F) -> ChangeOutputType> + where + Self: Sized, + F: FnMut(Self::Item, Self::Item) -> R, + R: Try, + R::Residual: Residual>, + { + let first = match self.next() { + Some(i) => i, + None => return Try::from_output(None), + }; + + match self.try_fold(first, f).branch() { + ControlFlow::Break(r) => FromResidual::from_residual(r), + ControlFlow::Continue(i) => Try::from_output(Some(i)), + } + } + /// Tests if every element of the iterator matches a predicate. /// /// `all()` takes a closure that returns `true` or `false`. It applies @@ -2418,6 +2498,10 @@ pub trait Iterator { /// Applies function to the elements of iterator and returns /// the first true result or the first error. /// + /// The return type of this method depends on the return type of the closure. + /// If you return `Result` from the closure, you'll get a `Result; E>`. + /// If you return `Option` from the closure, you'll get an `Option>`. + /// /// # Examples /// /// ``` @@ -2435,32 +2519,48 @@ pub trait Iterator { /// let result = a.iter().try_find(|&&s| is_my_num(s, 5)); /// assert!(result.is_err()); /// ``` + /// + /// This also supports other types which implement `Try`, not just `Result`. + /// ``` + /// #![feature(try_find)] + /// + /// use std::num::NonZeroU32; + /// let a = [3, 5, 7, 4, 9, 0, 11]; + /// let result = a.iter().try_find(|&&x| NonZeroU32::new(x).map(|y| y.is_power_of_two())); + /// assert_eq!(result, Some(Some(&4))); + /// let result = a.iter().take(3).try_find(|&&x| NonZeroU32::new(x).map(|y| y.is_power_of_two())); + /// assert_eq!(result, Some(None)); + /// let result = a.iter().rev().try_find(|&&x| NonZeroU32::new(x).map(|y| y.is_power_of_two())); + /// assert_eq!(result, None); + /// ``` #[inline] #[unstable(feature = "try_find", reason = "new API", issue = "63178")] - fn try_find(&mut self, f: F) -> Result, E> + fn try_find(&mut self, f: F) -> ChangeOutputType> where Self: Sized, F: FnMut(&Self::Item) -> R, R: Try, - // FIXME: This bound is rather strange, but means minimal breakage on nightly. - // See #85115 for the issue tracking a holistic solution for this and try_map. - R: Try>, + R::Residual: Residual>, { #[inline] - fn check(mut f: F) -> impl FnMut((), T) -> ControlFlow> + fn check( + mut f: impl FnMut(&I) -> V, + ) -> impl FnMut((), I) -> ControlFlow where - F: FnMut(&T) -> R, - R: Try, - R: Try>, + V: Try, + R: Residual>, { move |(), x| match f(&x).branch() { ControlFlow::Continue(false) => ControlFlow::CONTINUE, - ControlFlow::Continue(true) => ControlFlow::Break(Ok(x)), - ControlFlow::Break(Err(x)) => ControlFlow::Break(Err(x)), + ControlFlow::Continue(true) => ControlFlow::Break(Try::from_output(Some(x))), + ControlFlow::Break(r) => ControlFlow::Break(FromResidual::from_residual(r)), } } - self.try_fold((), check(f)).break_value().transpose() + match self.try_fold((), check(f)) { + ControlFlow::Break(x) => x, + ControlFlow::Continue(()) => Try::from_output(None), + } } /// Searches for an element in an iterator, returning its index. @@ -2928,7 +3028,8 @@ pub trait Iterator { /// /// Instead of stopping at [`None`], the iterator will instead start again, /// from the beginning. After iterating again, it will start at the - /// beginning again. And again. And again. Forever. + /// beginning again. And again. And again. Forever. Note that in case the + /// original iterator is empty, the resulting iterator will also be empty. /// /// # Examples /// diff --git a/library/core/src/lazy.rs b/library/core/src/lazy.rs index 2b8a5f3cbf..788f0cce01 100644 --- a/library/core/src/lazy.rs +++ b/library/core/src/lazy.rs @@ -102,8 +102,7 @@ impl OnceCell { /// Returns `None` if the cell is empty. #[unstable(feature = "once_cell", issue = "74465")] pub fn get_mut(&mut self) -> Option<&mut T> { - // SAFETY: Safe because we have unique access - unsafe { &mut *self.inner.get() }.as_mut() + self.inner.get_mut().as_mut() } /// Sets the contents of the cell to `value`. diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index cb2854bc5f..d61800dcbb 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -101,8 +101,9 @@ #![feature(const_align_of_val)] #![feature(const_alloc_layout)] #![feature(const_arguments_as_str)] -#![feature(const_assert_type)] +#![feature(const_array_into_iter_constructors)] #![feature(const_bigint_helper_methods)] +#![feature(const_black_box)] #![feature(const_caller_location)] #![feature(const_cell_into_inner)] #![feature(const_char_convert)] @@ -112,18 +113,21 @@ #![feature(const_float_classify)] #![feature(const_fmt_arguments_new)] #![feature(const_heap)] +#![feature(const_convert)] #![feature(const_inherent_unchecked_arith)] #![feature(const_int_unchecked_arith)] #![feature(const_intrinsic_copy)] #![feature(const_intrinsic_forget)] #![feature(const_likely)] -#![feature(const_maybe_uninit_as_ptr)] +#![feature(const_maybe_uninit_as_mut_ptr)] #![feature(const_maybe_uninit_assume_init)] #![feature(const_num_from_num)] #![feature(const_ops)] #![feature(const_option)] +#![feature(const_option_ext)] #![feature(const_pin)] #![feature(const_replace)] +#![feature(const_ptr_is_null)] #![feature(const_ptr_offset)] #![feature(const_ptr_offset_from)] #![feature(const_ptr_read)] @@ -138,7 +142,9 @@ #![feature(const_type_id)] #![feature(const_type_name)] #![feature(const_default_impls)] +#![feature(core_panic)] #![feature(duration_consts_float)] +#![feature(maybe_uninit_uninit_array)] #![feature(ptr_metadata)] #![feature(slice_ptr_get)] #![feature(str_internals)] @@ -150,7 +156,6 @@ #![feature(abi_unadjusted)] #![feature(allow_internal_unsafe)] #![feature(allow_internal_unstable)] -#![feature(asm)] #![feature(associated_type_bounds)] #![feature(auto_traits)] #![feature(cfg_target_has_atomic)] @@ -160,14 +165,12 @@ #![feature(const_impl_trait)] #![feature(const_mut_refs)] #![feature(const_precise_live_drops)] -#![cfg_attr(bootstrap, feature(const_raw_ptr_deref))] #![feature(const_refs_to_cell)] #![feature(decl_macro)] #![feature(derive_default_enum)] #![feature(doc_cfg)] #![feature(doc_notable_trait)] -#![cfg_attr(bootstrap, feature(doc_primitive))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![feature(rustdoc_internals)] #![feature(exhaustive_patterns)] #![feature(doc_cfg_hide)] #![feature(extern_types)] @@ -199,7 +202,7 @@ #![feature(try_blocks)] #![feature(unboxed_closures)] #![feature(unsized_fn_params)] -#![cfg_attr(not(bootstrap), feature(asm_const))] +#![feature(asm_const)] // // Target features: #![feature(aarch64_target_feature)] @@ -373,29 +376,50 @@ pub mod arch { /// Inline assembly. /// - /// Read the [unstable book] for the usage. + /// Refer to [rust by example] for a usage guide and the [reference] for + /// detailed information about the syntax and available options. /// - /// [unstable book]: ../../unstable-book/library-features/asm.html - #[unstable( - feature = "asm", - issue = "72016", - reason = "inline assembly is not stable enough for use and is subject to change" - )] + /// [rust by example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html + /// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html + #[stable(feature = "asm", since = "1.59.0")] #[rustc_builtin_macro] pub macro asm("assembly template", $(operands,)* $(options($(option),*))?) { /* compiler built-in */ } /// Module-level inline assembly. - #[unstable( - feature = "global_asm", - issue = "35119", - reason = "`global_asm!` is not stable enough for use and is subject to change" - )] + /// + /// Refer to [rust by example] for a usage guide and the [reference] for + /// detailed information about the syntax and available options. + /// + /// [rust by example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html + /// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html + #[stable(feature = "global_asm", since = "1.59.0")] #[rustc_builtin_macro] pub macro global_asm("assembly template", $(operands,)* $(options($(option),*))?) { /* compiler built-in */ } } +// Pull in the `core_simd` crate directly into libcore. The contents of +// `core_simd` are in a different repository: rust-lang/portable-simd. +// +// `core_simd` depends on libcore, but the contents of this module are +// set up in such a way that directly pulling it here works such that the +// crate uses this crate as its libcore. +#[path = "../../portable-simd/crates/core_simd/src/mod.rs"] +#[allow(missing_debug_implementations, dead_code, unsafe_op_in_unsafe_fn, unused_unsafe)] +#[allow(rustdoc::bare_urls)] +#[unstable(feature = "portable_simd", issue = "86656")] +#[cfg(not(all(miri, doctest)))] // Miri does not support all SIMD intrinsics +mod core_simd; + +#[doc = include_str!("../../portable-simd/crates/core_simd/src/core_simd_docs.md")] +#[unstable(feature = "portable_simd", issue = "86656")] +#[cfg(not(all(miri, doctest)))] // Miri does not support all SIMD intrinsics +pub mod simd { + #[unstable(feature = "portable_simd", issue = "86656")] + pub use crate::core_simd::simd::*; +} + include!("primitive_docs.rs"); diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 993ae72322..cd2b01e7fc 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -587,11 +587,28 @@ macro_rules! writeln { /// unreachable!("The loop should always return"); /// } /// ``` +#[cfg(not(bootstrap))] +#[macro_export] +#[rustc_builtin_macro(unreachable)] +#[allow_internal_unstable(edition_panic)] +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "unreachable_macro")] +macro_rules! unreachable { + // Expands to either `$crate::panic::unreachable_2015` or `$crate::panic::unreachable_2021` + // depending on the edition of the caller. + ($($arg:tt)*) => { + /* compiler built-in */ + }; +} + +/// unreachable!() macro +#[cfg(bootstrap)] #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] +#[allow_internal_unstable(core_panic)] macro_rules! unreachable { () => ({ - $crate::panic!("internal error: entered unreachable code") + $crate::panicking::panic("internal error: entered unreachable code") }); ($msg:expr $(,)?) => ({ $crate::unreachable!("{}", $msg) @@ -674,8 +691,9 @@ macro_rules! unreachable { /// ``` #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] +#[allow_internal_unstable(core_panic)] macro_rules! unimplemented { - () => ($crate::panic!("not implemented")); + () => ($crate::panicking::panic("not implemented")); ($($arg:tt)+) => ($crate::panic!("not implemented: {}", $crate::format_args!($($arg)+))); } @@ -735,8 +753,9 @@ macro_rules! unimplemented { /// ``` #[macro_export] #[stable(feature = "todo_macro", since = "1.40.0")] +#[allow_internal_unstable(core_panic)] macro_rules! todo { - () => ($crate::panic!("not yet implemented")); + () => ($crate::panicking::panic("not yet implemented")); ($($arg:tt)+) => ($crate::panic!("not yet implemented: {}", $crate::format_args!($($arg)+))); } @@ -863,7 +882,6 @@ pub(crate) mod builtin { language use and is subject to change" )] #[allow_internal_unstable(fmt_internals)] - #[doc(hidden)] #[rustc_builtin_macro] #[macro_export] macro_rules! format_args_nl { @@ -967,6 +985,34 @@ pub(crate) mod builtin { ($($e:ident),+ $(,)?) => {{ /* compiler built-in */ }}; } + /// Concatenates literals into a byte slice. + /// + /// This macro takes any number of comma-separated literals, and concatenates them all into + /// one, yielding an expression of type `&[u8, _]`, which represents all of the literals + /// concatenated left-to-right. The literals passed can be any combination of: + /// + /// - byte literals (`b'r'`) + /// - byte strings (`b"Rust"`) + /// - arrays of bytes/numbers (`[b'A', 66, b'C']`) + /// + /// # Examples + /// + /// ``` + /// #![feature(concat_bytes)] + /// + /// # fn main() { + /// let s: &[u8; 6] = concat_bytes!(b'A', b"BC", [68, b'E', 70]); + /// assert_eq!(s, b"ABCDEF"); + /// # } + /// ``` + #[cfg(not(bootstrap))] + #[unstable(feature = "concat_bytes", issue = "87555")] + #[rustc_builtin_macro] + #[macro_export] + macro_rules! concat_bytes { + ($($e:literal),+ $(,)?) => {{ /* compiler built-in */ }}; + } + /// Concatenates literals into a static string slice. /// /// This macro takes any number of comma-separated literals, yielding an @@ -1034,6 +1080,18 @@ pub(crate) mod builtin { /// let current_col = column!(); /// println!("defined on column: {}", current_col); /// ``` + /// + /// `column!` counts Unicode code points, not bytes or graphemes. As a result, the first two + /// invocations return the same value, but the third does not. + /// + /// ``` + /// let a = ("foobar", column!()).1; + /// let b = ("人之初性本善", column!()).1; + /// let c = ("f̅o̅o̅b̅a̅r̅", column!()).1; // Uses combining overline (U+0305) + /// + /// assert_eq!(a, b); + /// assert_ne!(b, c); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] #[macro_export] @@ -1385,6 +1443,10 @@ pub(crate) mod builtin { } /// Attribute macro used to apply derive macros. + /// + /// See [the reference] for more info. + /// + /// [the reference]: ../../../reference/attributes/derive.html #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] pub macro derive($item:item) { @@ -1392,6 +1454,10 @@ pub(crate) mod builtin { } /// Attribute macro applied to a function to turn it into a unit test. + /// + /// See [the reference] for more info. + /// + /// [the reference]: ../../../reference/attributes/testing.html#the-test-attribute #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(test, rustc_attrs)] #[rustc_builtin_macro] @@ -1426,7 +1492,7 @@ pub(crate) mod builtin { /// Attribute macro applied to a static to register it as a global allocator. /// - /// See also [`std::alloc::GlobalAlloc`](../std/alloc/trait.GlobalAlloc.html). + /// See also [`std::alloc::GlobalAlloc`](../../../std/alloc/trait.GlobalAlloc.html). #[stable(feature = "global_allocator", since = "1.28.0")] #[allow_internal_unstable(rustc_attrs)] #[rustc_builtin_macro] @@ -1464,6 +1530,7 @@ pub(crate) mod builtin { since = "1.52.0", reason = "rustc-serialize is deprecated and no longer supported" )] + #[doc(hidden)] // While technically stable, using it is unstable, and deprecated. Hide it. pub macro RustcDecodable($item:item) { /* compiler built-in */ } @@ -1476,6 +1543,7 @@ pub(crate) mod builtin { since = "1.52.0", reason = "rustc-serialize is deprecated and no longer supported" )] + #[doc(hidden)] // While technically stable, using it is unstable, and deprecated. Hide it. pub macro RustcEncodable($item:item) { /* compiler built-in */ } diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index 20b6453990..f577f102e8 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -64,7 +64,7 @@ impl ManuallyDrop { /// ``` #[must_use = "if you don't need the wrapper, you can use `mem::forget` instead"] #[stable(feature = "manually_drop", since = "1.20.0")] - #[rustc_const_stable(feature = "const_manually_drop", since = "1.36.0")] + #[rustc_const_stable(feature = "const_manually_drop", since = "1.32.0")] #[inline(always)] pub const fn new(value: T) -> ManuallyDrop { ManuallyDrop { value } @@ -82,7 +82,7 @@ impl ManuallyDrop { /// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`. /// ``` #[stable(feature = "manually_drop", since = "1.20.0")] - #[rustc_const_stable(feature = "const_manually_drop", since = "1.36.0")] + #[rustc_const_stable(feature = "const_manually_drop", since = "1.32.0")] #[inline(always)] pub const fn into_inner(slot: ManuallyDrop) -> T { slot.value diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 624e879550..3b0e4a31db 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -394,10 +394,11 @@ impl MaybeUninit { /// // This is undefined behavior. ⚠️ /// ``` #[stable(feature = "maybe_uninit", since = "1.36.0")] + #[rustc_const_unstable(feature = "const_maybe_uninit_zeroed", issue = "91850")] #[must_use] #[inline] #[rustc_diagnostic_item = "maybe_uninit_zeroed"] - pub fn zeroed() -> MaybeUninit { + pub const fn zeroed() -> MaybeUninit { let mut u = MaybeUninit::::uninit(); // SAFETY: `u.as_mut_ptr()` points to allocated memory. unsafe { @@ -528,7 +529,7 @@ impl MaybeUninit { /// (Notice that the rules around references to uninitialized data are not finalized yet, but /// until they are, it is advisable to avoid them.) #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[rustc_const_unstable(feature = "const_maybe_uninit_as_ptr", issue = "75251")] + #[rustc_const_stable(feature = "const_maybe_uninit_as_ptr", since = "1.59.0")] #[inline(always)] pub const fn as_ptr(&self) -> *const T { // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer. @@ -567,7 +568,7 @@ impl MaybeUninit { /// (Notice that the rules around references to uninitialized data are not finalized yet, but /// until they are, it is advisable to avoid them.) #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[rustc_const_unstable(feature = "const_maybe_uninit_as_ptr", issue = "75251")] + #[rustc_const_unstable(feature = "const_maybe_uninit_as_mut_ptr", issue = "75251")] #[inline(always)] pub const fn as_mut_ptr(&mut self) -> *mut T { // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer. @@ -620,7 +621,7 @@ impl MaybeUninit { /// // `x` had not been initialized yet, so this last line caused undefined behavior. ⚠️ /// ``` #[stable(feature = "maybe_uninit", since = "1.36.0")] - #[rustc_const_unstable(feature = "const_maybe_uninit_assume_init", issue = "none")] + #[rustc_const_stable(feature = "const_maybe_uninit_assume_init", since = "1.59.0")] #[inline(always)] #[rustc_diagnostic_item = "assume_init"] #[track_caller] @@ -788,7 +789,7 @@ impl MaybeUninit { /// } /// ``` #[stable(feature = "maybe_uninit_ref", since = "1.55.0")] - #[rustc_const_unstable(feature = "const_maybe_uninit_assume_init", issue = "none")] + #[rustc_const_stable(feature = "const_maybe_uninit_assume_init", since = "1.59.0")] #[inline(always)] pub const unsafe fn assume_init_ref(&self) -> &T { // SAFETY: the caller must guarantee that `self` is initialized. @@ -968,11 +969,11 @@ impl MaybeUninit { /// /// [`assume_init_ref`]: MaybeUninit::assume_init_ref #[unstable(feature = "maybe_uninit_slice", issue = "63569")] - #[rustc_const_unstable(feature = "const_maybe_uninit_assume_init", issue = "none")] + #[rustc_const_unstable(feature = "maybe_uninit_slice", issue = "63569")] #[inline(always)] pub const unsafe fn slice_assume_init_ref(slice: &[Self]) -> &[T] { - // SAFETY: casting slice to a `*const [T]` is safe since the caller guarantees that - // `slice` is initialized, and`MaybeUninit` is guaranteed to have the same layout as `T`. + // SAFETY: casting `slice` to a `*const [T]` is safe since the caller guarantees that + // `slice` is initialized, and `MaybeUninit` is guaranteed to have the same layout as `T`. // The pointer obtained is valid since it refers to memory owned by `slice` which is a // reference and thus guaranteed to be valid for reads. unsafe { &*(slice as *const [Self] as *const [T]) } diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 7d005666a7..989ec0639c 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1045,6 +1045,10 @@ pub const fn discriminant(v: &T) -> Discriminant { /// return value is unspecified. Equally, if `T` is an enum with more variants than `usize::MAX` /// the return value is unspecified. Uninhabited variants will be counted. /// +/// Note that an enum may be expanded with additional variants in the future +/// as a non-breaking change, for example if it is marked `#[non_exhaustive]`, +/// which will change the result of this function. +/// /// # Examples /// /// ``` diff --git a/library/core/src/num/dec2flt/fpu.rs b/library/core/src/num/dec2flt/fpu.rs index 24492d9a1d..ec5fa45fda 100644 --- a/library/core/src/num/dec2flt/fpu.rs +++ b/library/core/src/num/dec2flt/fpu.rs @@ -10,6 +10,7 @@ pub use fpu_precision::set_precision; // computations are performed in the desired precision. #[cfg(all(target_arch = "x86", not(target_feature = "sse2")))] mod fpu_precision { + use core::arch::asm; use core::mem::size_of; /// A structure used to preserve the original value of the FPU control word, so that it can be diff --git a/library/core/src/num/dec2flt/number.rs b/library/core/src/num/dec2flt/number.rs index 36432718af..405f7e7b61 100644 --- a/library/core/src/num/dec2flt/number.rs +++ b/library/core/src/num/dec2flt/number.rs @@ -40,7 +40,7 @@ impl Number { && !self.many_digits } - /// The fast path algorithmn using machine-sized integers and floats. + /// The fast path algorithm using machine-sized integers and floats. /// /// This is extracted into a separate function so that it can be attempted before constructing /// a Decimal. This only works if both the mantissa and the exponent diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index c4a232ef36..85ceede5b9 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -628,6 +628,7 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + #[must_use = "this returns the result of the operation, without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn recip(self) -> f32 { @@ -684,6 +685,7 @@ impl f32 { /// ``` /// /// If one of the arguments is NaN, then the other argument is returned. + #[must_use = "this returns the result of the comparison, without modifying either input"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn max(self, other: f32) -> f32 { @@ -703,6 +705,7 @@ impl f32 { /// ``` /// /// If one of the arguments is NaN, then the other argument is returned. + #[must_use = "this returns the result of the comparison, without modifying either input"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn min(self, other: f32) -> f32 { @@ -726,6 +729,7 @@ impl f32 { /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the greater /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0. /// Note that this follows the semantics specified in IEEE 754-2019. + #[must_use = "this returns the result of the comparison, without modifying either input"] #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] pub fn maximum(self, other: f32) -> f32 { @@ -757,6 +761,7 @@ impl f32 { /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the lesser /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0. /// Note that this follows the semantics specified in IEEE 754-2019. + #[must_use = "this returns the result of the comparison, without modifying either input"] #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] pub fn minimum(self, other: f32) -> f32 { diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 85ee6aa2cb..4049c95b13 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -643,6 +643,7 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + #[must_use = "this returns the result of the operation, without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn recip(self) -> f64 { @@ -700,6 +701,7 @@ impl f64 { /// ``` /// /// If one of the arguments is NaN, then the other argument is returned. + #[must_use = "this returns the result of the comparison, without modifying either input"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn max(self, other: f64) -> f64 { @@ -719,6 +721,7 @@ impl f64 { /// ``` /// /// If one of the arguments is NaN, then the other argument is returned. + #[must_use = "this returns the result of the comparison, without modifying either input"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn min(self, other: f64) -> f64 { @@ -742,6 +745,7 @@ impl f64 { /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the greater /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0. /// Note that this follows the semantics specified in IEEE 754-2019. + #[must_use = "this returns the result of the comparison, without modifying either input"] #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] pub fn maximum(self, other: f64) -> f64 { @@ -773,6 +777,7 @@ impl f64 { /// If one of the arguments is NaN, then NaN is returned. Otherwise this returns the lesser /// of the two numbers. For this operation, -0.0 is considered to be less than +0.0. /// Note that this follows the semantics specified in IEEE 754-2019. + #[must_use = "this returns the result of the comparison, without modifying either input"] #[unstable(feature = "float_minimum_maximum", issue = "91079")] #[inline] pub fn minimum(self, other: f64) -> f64 { diff --git a/library/core/src/num/fmt.rs b/library/core/src/num/fmt.rs index 578288bda2..ed61197157 100644 --- a/library/core/src/num/fmt.rs +++ b/library/core/src/num/fmt.rs @@ -1,4 +1,4 @@ -//! Shared utilties used by both float and integer formatting. +//! Shared utilities used by both float and integer formatting. #![doc(hidden)] #![unstable( feature = "numfmt", diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 9a668d34b6..e6ae4afd7c 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -2025,17 +2025,17 @@ macro_rules! int_impl { #[doc = concat!("let a: ", stringify!($SelfT)," = 8;")] /// let b = 3; /// - /// assert_eq!(a.unstable_div_floor(b), 2); - /// assert_eq!(a.unstable_div_floor(-b), -3); - /// assert_eq!((-a).unstable_div_floor(b), -3); - /// assert_eq!((-a).unstable_div_floor(-b), 2); + /// assert_eq!(a.div_floor(b), 2); + /// assert_eq!(a.div_floor(-b), -3); + /// assert_eq!((-a).div_floor(b), -3); + /// assert_eq!((-a).div_floor(-b), 2); /// ``` #[unstable(feature = "int_roundings", issue = "88581")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] - pub const fn unstable_div_floor(self, rhs: Self) -> Self { + pub const fn div_floor(self, rhs: Self) -> Self { let d = self / rhs; let r = self % rhs; if (r > 0 && rhs < 0) || (r < 0 && rhs > 0) { @@ -2060,17 +2060,17 @@ macro_rules! int_impl { #[doc = concat!("let a: ", stringify!($SelfT)," = 8;")] /// let b = 3; /// - /// assert_eq!(a.unstable_div_ceil(b), 3); - /// assert_eq!(a.unstable_div_ceil(-b), -2); - /// assert_eq!((-a).unstable_div_ceil(b), -2); - /// assert_eq!((-a).unstable_div_ceil(-b), 3); + /// assert_eq!(a.div_ceil(b), 3); + /// assert_eq!(a.div_ceil(-b), -2); + /// assert_eq!((-a).div_ceil(b), -2); + /// assert_eq!((-a).div_ceil(-b), 3); /// ``` #[unstable(feature = "int_roundings", issue = "88581")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] - pub const fn unstable_div_ceil(self, rhs: Self) -> Self { + pub const fn div_ceil(self, rhs: Self) -> Self { let d = self / rhs; let r = self % rhs; if (r > 0 && rhs > 0) || (r < 0 && rhs < 0) { @@ -2095,21 +2095,21 @@ macro_rules! int_impl { /// /// ``` /// #![feature(int_roundings)] - #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".unstable_next_multiple_of(8), 16);")] - #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".unstable_next_multiple_of(8), 24);")] - #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".unstable_next_multiple_of(-8), 16);")] - #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".unstable_next_multiple_of(-8), 16);")] - #[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").unstable_next_multiple_of(8), -16);")] - #[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").unstable_next_multiple_of(8), -16);")] - #[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").unstable_next_multiple_of(-8), -16);")] - #[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").unstable_next_multiple_of(-8), -24);")] + #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".next_multiple_of(8), 16);")] + #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".next_multiple_of(8), 24);")] + #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".next_multiple_of(-8), 16);")] + #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".next_multiple_of(-8), 16);")] + #[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").next_multiple_of(8), -16);")] + #[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").next_multiple_of(8), -16);")] + #[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").next_multiple_of(-8), -16);")] + #[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").next_multiple_of(-8), -24);")] /// ``` #[unstable(feature = "int_roundings", issue = "88581")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] - pub const fn unstable_next_multiple_of(self, rhs: Self) -> Self { + pub const fn next_multiple_of(self, rhs: Self) -> Self { // This would otherwise fail when calculating `r` when self == T::MIN. if rhs == -1 { return self; diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 7708094e1f..8f895c33a6 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -915,15 +915,13 @@ macro_rules! nonzero_unsigned_is_power_of_two { /// Basic usage: /// /// ``` - /// #![feature(nonzero_is_power_of_two)] - /// #[doc = concat!("let eight = std::num::", stringify!($Ty), "::new(8).unwrap();")] /// assert!(eight.is_power_of_two()); #[doc = concat!("let ten = std::num::", stringify!($Ty), "::new(10).unwrap();")] /// assert!(!ten.is_power_of_two()); /// ``` #[must_use] - #[unstable(feature = "nonzero_is_power_of_two", issue = "81106")] + #[stable(feature = "nonzero_is_power_of_two", since = "1.59.0")] #[inline] pub const fn is_power_of_two(self) -> bool { // LLVM 11 normalizes `unchecked_sub(x, 1) & x == 0` to the implementation seen here. diff --git a/library/core/src/num/saturating.rs b/library/core/src/num/saturating.rs index ba81f3f9fd..d9b14c82e9 100644 --- a/library/core/src/num/saturating.rs +++ b/library/core/src/num/saturating.rs @@ -628,7 +628,7 @@ macro_rules! saturating_int_impl { /// ``` #[inline] #[unstable(feature = "saturating_int_impl", issue = "87920")] - #[rustc_const_stable(feature = "const_reverse_bits", since = "1.37.0")] + #[rustc_const_unstable(feature = "saturating_int_impl", issue = "87920")] #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn reverse_bits(self) -> Self { diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index a15eabf796..3cc454baf3 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2024,14 +2024,14 @@ macro_rules! uint_impl { /// /// ``` /// #![feature(int_roundings)] - #[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".unstable_div_floor(4), 1);")] + #[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".div_floor(4), 1);")] /// ``` #[unstable(feature = "int_roundings", issue = "88581")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] #[rustc_inherit_overflow_checks] - pub const fn unstable_div_floor(self, rhs: Self) -> Self { + pub const fn div_floor(self, rhs: Self) -> Self { self / rhs } @@ -2047,14 +2047,14 @@ macro_rules! uint_impl { /// /// ``` /// #![feature(int_roundings)] - #[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".unstable_div_ceil(4), 2);")] + #[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".div_ceil(4), 2);")] /// ``` #[unstable(feature = "int_roundings", issue = "88581")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] - pub const fn unstable_div_ceil(self, rhs: Self) -> Self { + pub const fn div_ceil(self, rhs: Self) -> Self { let d = self / rhs; let r = self % rhs; if r > 0 && rhs > 0 { @@ -2077,15 +2077,15 @@ macro_rules! uint_impl { /// /// ``` /// #![feature(int_roundings)] - #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".unstable_next_multiple_of(8), 16);")] - #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".unstable_next_multiple_of(8), 24);")] + #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".next_multiple_of(8), 16);")] + #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".next_multiple_of(8), 24);")] /// ``` #[unstable(feature = "int_roundings", issue = "88581")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] - pub const fn unstable_next_multiple_of(self, rhs: Self) -> Self { + pub const fn next_multiple_of(self, rhs: Self) -> Self { match self % rhs { 0 => self, r => self + (rhs - r) @@ -2223,7 +2223,7 @@ macro_rules! uint_impl { /// ``` #[unstable(feature = "wrapping_next_power_of_two", issue = "32463", reason = "needs decision on wrapping behaviour")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[rustc_const_unstable(feature = "wrapping_next_power_of_two", issue = "32463")] #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn wrapping_next_power_of_two(self) -> Self { diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index b0c15898a1..10a24a545d 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -123,6 +123,11 @@ impl ops::FromResidual for ControlFlow { } } +#[unstable(feature = "try_trait_v2_residual", issue = "91285")] +impl ops::Residual for ControlFlow { + type TryType = ControlFlow; +} + impl ControlFlow { /// Returns `true` if this is a `Break` variant. /// @@ -136,7 +141,7 @@ impl ControlFlow { /// assert!(!ControlFlow::::Continue(3).is_break()); /// ``` #[inline] - #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] + #[stable(feature = "control_flow_enum_is", since = "1.59.0")] pub fn is_break(&self) -> bool { matches!(*self, ControlFlow::Break(_)) } @@ -153,7 +158,7 @@ impl ControlFlow { /// assert!(ControlFlow::::Continue(3).is_continue()); /// ``` #[inline] - #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] + #[stable(feature = "control_flow_enum_is", since = "1.59.0")] pub fn is_continue(&self) -> bool { matches!(*self, ControlFlow::Continue(_)) } diff --git a/library/core/src/ops/generator.rs b/library/core/src/ops/generator.rs index b527c4b04a..52a2e464e3 100644 --- a/library/core/src/ops/generator.rs +++ b/library/core/src/ops/generator.rs @@ -82,7 +82,7 @@ pub trait Generator { /// `return` statement or implicitly as the last expression of a generator /// literal. For example futures would use this as `Result` as it /// represents a completed future. - #[cfg_attr(not(bootstrap), lang = "generator_return")] + #[lang = "generator_return"] type Return; /// Resumes the execution of this generator. diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index bd7feb8b18..9d1e7e81b0 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -181,9 +181,17 @@ pub use self::range::{Range, RangeFrom, RangeFull, RangeTo}; #[stable(feature = "inclusive_range", since = "1.26.0")] pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive}; +#[unstable(feature = "one_sided_range", issue = "69780")] +pub use self::range::OneSidedRange; + #[unstable(feature = "try_trait_v2", issue = "84277")] pub use self::try_trait::{FromResidual, Try}; +#[unstable(feature = "try_trait_v2_residual", issue = "91285")] +pub use self::try_trait::Residual; + +pub(crate) use self::try_trait::{ChangeOutputType, NeverShortCircuit}; + #[unstable(feature = "generator_trait", issue = "43122")] pub use self::generator::{Generator, GeneratorState}; diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index b74ba92c76..1136722067 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -971,3 +971,21 @@ impl RangeBounds for RangeToInclusive<&T> { Included(self.end) } } + +/// `OneSidedRange` is implemented for built-in range types that are unbounded +/// on one side. For example, `a..`, `..b` and `..=c` implement `OneSidedRange`, +/// but `..`, `d..e`, and `f..=g` do not. +/// +/// Types that implement `OneSidedRange` must return `Bound::Unbounded` +/// from one of `RangeBounds::start_bound` or `RangeBounds::end_bound`. +#[unstable(feature = "one_sided_range", issue = "69780")] +pub trait OneSidedRange: RangeBounds {} + +#[unstable(feature = "one_sided_range", issue = "69780")] +impl OneSidedRange for RangeTo where Self: RangeBounds {} + +#[unstable(feature = "one_sided_range", issue = "69780")] +impl OneSidedRange for RangeFrom where Self: RangeBounds {} + +#[unstable(feature = "one_sided_range", issue = "69780")] +impl OneSidedRange for RangeToInclusive where Self: RangeBounds {} diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs index 6bdcda775e..6a414ae8c4 100644 --- a/library/core/src/ops/try_trait.rs +++ b/library/core/src/ops/try_trait.rs @@ -115,15 +115,14 @@ use crate::ops::ControlFlow; #[unstable(feature = "try_trait_v2", issue = "84277")] #[rustc_on_unimplemented( on( - all(from_method = "from_output", from_desugaring = "TryBlock"), + all(from_desugaring = "TryBlock"), message = "a `try` block must return `Result` or `Option` \ (or another type that implements `{Try}`)", label = "could not wrap the final value of the block as `{Self}` doesn't implement `Try`", ), on( - all(from_method = "branch", from_desugaring = "QuestionMark"), - message = "the `?` operator can only be applied to values \ - that implement `{Try}`", + all(from_desugaring = "QuestionMark"), + message = "the `?` operator can only be applied to values that implement `{Try}`", label = "the `?` operator cannot be applied to type `{Self}`" ) )] @@ -226,7 +225,6 @@ pub trait Try: FromResidual { #[rustc_on_unimplemented( on( all( - from_method = "from_residual", from_desugaring = "QuestionMark", _Self = "std::result::Result", R = "std::option::Option" @@ -238,7 +236,6 @@ pub trait Try: FromResidual { ), on( all( - from_method = "from_residual", from_desugaring = "QuestionMark", _Self = "std::result::Result", ), @@ -252,7 +249,6 @@ pub trait Try: FromResidual { ), on( all( - from_method = "from_residual", from_desugaring = "QuestionMark", _Self = "std::option::Option", R = "std::result::Result", @@ -264,7 +260,6 @@ pub trait Try: FromResidual { ), on( all( - from_method = "from_residual", from_desugaring = "QuestionMark", _Self = "std::option::Option", ), @@ -277,7 +272,6 @@ pub trait Try: FromResidual { ), on( all( - from_method = "from_residual", from_desugaring = "QuestionMark", _Self = "std::ops::ControlFlow", R = "std::ops::ControlFlow", @@ -290,7 +284,6 @@ pub trait Try: FromResidual { ), on( all( - from_method = "from_residual", from_desugaring = "QuestionMark", _Self = "std::ops::ControlFlow", // `R` is not a `ControlFlow`, as that case was matched previously @@ -301,10 +294,7 @@ pub trait Try: FromResidual { enclosing_scope = "this function returns a `ControlFlow`", ), on( - all( - from_method = "from_residual", - from_desugaring = "QuestionMark" - ), + all(from_desugaring = "QuestionMark"), message = "the `?` operator can only be used in {ItemContext} \ that returns `Result` or `Option` \ (or another type that implements `{FromResidual}`)", @@ -338,3 +328,61 @@ pub trait FromResidual::Residual> { #[unstable(feature = "try_trait_v2", issue = "84277")] fn from_residual(residual: R) -> Self; } + +/// Allows retrieving the canonical type implementing [`Try`] that has this type +/// as its residual and allows it to hold an `O` as its output. +/// +/// If you think of the `Try` trait as splitting a type into its [`Try::Output`] +/// and [`Try::Residual`] components, this allows putting them back together. +/// +/// For example, +/// `Result: Try>`, +/// and in the other direction, +/// ` as Residual>::TryType = Result`. +#[unstable(feature = "try_trait_v2_residual", issue = "91285")] +pub trait Residual { + /// The "return" type of this meta-function. + #[unstable(feature = "try_trait_v2_residual", issue = "91285")] + type TryType: Try; +} + +#[unstable(feature = "pub_crate_should_not_need_unstable_attr", issue = "none")] +pub(crate) type ChangeOutputType = <::Residual as Residual>::TryType; + +/// An adapter for implementing non-try methods via the `Try` implementation. +/// +/// Conceptually the same as `Result`, but requiring less work in trait +/// solving and inhabited-ness checking and such, by being an obvious newtype +/// and not having `From` bounds lying around. +/// +/// Not currently planned to be exposed publicly, so just `pub(crate)`. +#[repr(transparent)] +pub(crate) struct NeverShortCircuit(pub T); + +pub(crate) enum NeverShortCircuitResidual {} + +impl Try for NeverShortCircuit { + type Output = T; + type Residual = NeverShortCircuitResidual; + + #[inline] + fn branch(self) -> ControlFlow { + ControlFlow::Continue(self.0) + } + + #[inline] + fn from_output(x: T) -> Self { + NeverShortCircuit(x) + } +} + +impl FromResidual for NeverShortCircuit { + #[inline] + fn from_residual(never: NeverShortCircuitResidual) -> Self { + match never {} + } +} + +impl Residual for NeverShortCircuitResidual { + type TryType = NeverShortCircuit; +} diff --git a/library/core/src/ops/unsize.rs b/library/core/src/ops/unsize.rs index 483362023b..a920b9165c 100644 --- a/library/core/src/ops/unsize.rs +++ b/library/core/src/ops/unsize.rs @@ -68,7 +68,38 @@ impl, U: ?Sized> CoerceUnsized<*const U> for *mut T {} #[unstable(feature = "coerce_unsized", issue = "27732")] impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} -/// This is used for object safety, to check that a method's receiver type can be dispatched on. +/// `DispatchFromDyn` is used in the implementation of object safety checks (specifically allowing +/// arbitrary self types), to guarantee that a method's receiver type can be dispatched on. +/// +/// Note: `DispatchFromDyn` was briefly named `CoerceSized` (and had a slightly different +/// interpretation). +/// +/// Imagine we have a trait object `t` with type `&dyn Tr`, where `Tr` is some trait with a method +/// `m` defined as `fn m(&self);`. When calling `t.m()`, the receiver `t` is a wide pointer, but an +/// implementation of `m` will expect a narrow pointer as `&self` (a reference to the concrete +/// type). The compiler must generate an implicit conversion from the trait object/wide pointer to +/// the concrete reference/narrow pointer. Implementing `DispatchFromDyn` indicates that that +/// conversion is allowed and thus that the type implementing `DispatchFromDyn` is safe to use as +/// the self type in an object-safe method. (in the above example, the compiler will require +/// `DispatchFromDyn` is implemented for `&'a U`). +/// +/// `DispatchFromDyn` does not specify the conversion from wide pointer to narrow pointer; the +/// conversion is hard-wired into the compiler. For the conversion to work, the following +/// properties must hold (i.e., it is only safe to implement `DispatchFromDyn` for types which have +/// these properties, these are also checked by the compiler): +/// +/// * EITHER `Self` and `T` are either both references or both raw pointers; in either case, with +/// the same mutability. +/// * OR, all of the following hold +/// - `Self` and `T` must have the same type constructor, and only vary in a single type parameter +/// formal (the *coerced type*, e.g., `impl DispatchFromDyn> for Rc` is ok and the +/// single type parameter (instantiated with `T` or `U`) is the coerced type, +/// `impl DispatchFromDyn> for Rc` is not ok). +/// - The definition for `Self` must be a struct. +/// - The definition for `Self` must not be `#[repr(packed)]` or `#[repr(C)]`. +/// - Other than one-aligned, zero-sized fields, the definition for `Self` must have exactly one +/// field and that field's type must be the coerced type. Furthermore, `Self`'s field type must +/// implement `DispatchFromDyn` where `F` is the type of `T`'s field type. /// /// An example implementation of the trait: /// diff --git a/library/core/src/option.rs b/library/core/src/option.rs index baf9948857..1ec119a71e 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -501,6 +501,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::iter::{FromIterator, FusedIterator, TrustedLen}; +use crate::panicking::{panic, panic_str}; use crate::pin::Pin; use crate::{ convert, hint, mem, @@ -512,11 +513,11 @@ use crate::{ #[rustc_diagnostic_item = "Option"] #[stable(feature = "rust1", since = "1.0.0")] pub enum Option { - /// No value + /// No value. #[lang = "None"] #[stable(feature = "rust1", since = "1.0.0")] None, - /// Some value `T` + /// Some value of type `T`. #[lang = "Some"] #[stable(feature = "rust1", since = "1.0.0")] Some(#[stable(feature = "rust1", since = "1.0.0")] T), @@ -570,35 +571,6 @@ impl Option { !self.is_some() } - /// Returns `true` if the option is a [`Some`] value containing the given value. - /// - /// # Examples - /// - /// ``` - /// #![feature(option_result_contains)] - /// - /// let x: Option = Some(2); - /// assert_eq!(x.contains(&2), true); - /// - /// let x: Option = Some(3); - /// assert_eq!(x.contains(&2), false); - /// - /// let x: Option = None; - /// assert_eq!(x.contains(&2), false); - /// ``` - #[must_use] - #[inline] - #[unstable(feature = "option_result_contains", issue = "62358")] - pub fn contains(&self, x: &U) -> bool - where - U: PartialEq, - { - match self { - Some(y) => x == y, - None => false, - } - } - ///////////////////////////////////////////////////////////////////////// // Adapter for working with references ///////////////////////////////////////////////////////////////////////// @@ -660,10 +632,14 @@ impl Option { #[inline] #[must_use] #[stable(feature = "pin", since = "1.33.0")] - pub fn as_pin_ref(self: Pin<&Self>) -> Option> { - // SAFETY: `x` is guaranteed to be pinned because it comes from `self` - // which is pinned. - unsafe { Pin::get_ref(self).as_ref().map(|x| Pin::new_unchecked(x)) } + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn as_pin_ref(self: Pin<&Self>) -> Option> { + match Pin::get_ref(self).as_ref() { + // SAFETY: `x` is guaranteed to be pinned because it comes from `self` + // which is pinned. + Some(x) => unsafe { Some(Pin::new_unchecked(x)) }, + None => None, + } } /// Converts from [Pin]<[&mut] Option\> to Option<[Pin]<[&mut] T>>. @@ -672,10 +648,16 @@ impl Option { #[inline] #[must_use] #[stable(feature = "pin", since = "1.33.0")] - pub fn as_pin_mut(self: Pin<&mut Self>) -> Option> { + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn as_pin_mut(self: Pin<&mut Self>) -> Option> { // SAFETY: `get_unchecked_mut` is never used to move the `Option` inside `self`. // `x` is guaranteed to be pinned because it comes from `self` which is pinned. - unsafe { Pin::get_unchecked_mut(self).as_mut().map(|x| Pin::new_unchecked(x)) } + unsafe { + match Pin::get_unchecked_mut(self).as_mut() { + Some(x) => Some(Pin::new_unchecked(x)), + None => None, + } + } } ///////////////////////////////////////////////////////////////////////// @@ -703,7 +685,8 @@ impl Option { #[inline] #[track_caller] #[stable(feature = "rust1", since = "1.0.0")] - pub fn expect(self, msg: &str) -> T { + #[rustc_const_unstable(feature = "const_option", issue = "67441")] + pub const fn expect(self, msg: &str) -> T { match self { Some(val) => val, None => expect_failed(msg), @@ -743,7 +726,7 @@ impl Option { pub const fn unwrap(self) -> T { match self { Some(val) => val, - None => panic!("called `Option::unwrap()` on a `None` value"), + None => panic("called `Option::unwrap()` on a `None` value"), } } @@ -763,7 +746,11 @@ impl Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn unwrap_or(self, default: T) -> T { + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn unwrap_or(self, default: T) -> T + where + T: ~const Drop, + { match self { Some(x) => x, None => default, @@ -781,13 +768,57 @@ impl Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn unwrap_or_else T>(self, f: F) -> T { + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn unwrap_or_else(self, f: F) -> T + where + F: ~const FnOnce() -> T, + F: ~const Drop, + { match self { Some(x) => x, None => f(), } } + /// Returns the contained [`Some`] value or a default. + /// + /// Consumes the `self` argument then, if [`Some`], returns the contained + /// value, otherwise if [`None`], returns the [default value] for that + /// type. + /// + /// # Examples + /// + /// Converts a string to an integer, turning poorly-formed strings + /// into 0 (the default value for integers). [`parse`] converts + /// a string to any other type that implements [`FromStr`], returning + /// [`None`] on error. + /// + /// ``` + /// let good_year_from_input = "1909"; + /// let bad_year_from_input = "190blarg"; + /// let good_year = good_year_from_input.parse().ok().unwrap_or_default(); + /// let bad_year = bad_year_from_input.parse().ok().unwrap_or_default(); + /// + /// assert_eq!(1909, good_year); + /// assert_eq!(0, bad_year); + /// ``` + /// + /// [default value]: Default::default + /// [`parse`]: str::parse + /// [`FromStr`]: crate::str::FromStr + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn unwrap_or_default(self) -> T + where + T: ~const Default, + { + match self { + Some(x) => x, + None => Default::default(), + } + } + /// Returns the contained [`Some`] value, consuming the `self` value, /// without checking that the value is not [`None`]. /// @@ -811,7 +842,8 @@ impl Option { #[inline] #[track_caller] #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")] - pub unsafe fn unwrap_unchecked(self) -> T { + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const unsafe fn unwrap_unchecked(self) -> T { debug_assert!(self.is_some()); match self { Some(val) => val, @@ -841,13 +873,48 @@ impl Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn map U>(self, f: F) -> Option { + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn map(self, f: F) -> Option + where + F: ~const FnOnce(T) -> U, + F: ~const Drop, + { match self { Some(x) => Some(f(x)), None => None, } } + /// Calls the provided closure with a reference to the contained value (if [`Some`]). + /// + /// # Examples + /// + /// ``` + /// #![feature(result_option_inspect)] + /// + /// let v = vec![1, 2, 3, 4, 5]; + /// + /// // prints "got: 4" + /// let x: Option<&usize> = v.get(3).inspect(|x| println!("got: {}", x)); + /// + /// // prints nothing + /// let x: Option<&usize> = v.get(5).inspect(|x| println!("got: {}", x)); + /// ``` + #[inline] + #[unstable(feature = "result_option_inspect", issue = "91345")] + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn inspect(self, f: F) -> Self + where + F: ~const FnOnce(&T), + F: ~const Drop, + { + if let Some(ref x) = self { + f(x); + } + + self + } + /// Returns the provided default result (if none), /// or applies a function to the contained value (if any). /// @@ -868,7 +935,13 @@ impl Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn map_or U>(self, default: U, f: F) -> U { + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn map_or(self, default: U, f: F) -> U + where + F: ~const FnOnce(T) -> U, + F: ~const Drop, + U: ~const Drop, + { match self { Some(t) => f(t), None => default, @@ -891,7 +964,14 @@ impl Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn map_or_else U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U { + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn map_or_else(self, default: D, f: F) -> U + where + D: ~const FnOnce() -> U, + D: ~const Drop, + F: ~const FnOnce(T) -> U, + F: ~const Drop, + { match self { Some(t) => f(t), None => default(), @@ -921,7 +1001,11 @@ impl Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn ok_or(self, err: E) -> Result { + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn ok_or(self, err: E) -> Result + where + E: ~const Drop, + { match self { Some(v) => Ok(v), None => Err(err), @@ -946,13 +1030,70 @@ impl Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn ok_or_else E>(self, err: F) -> Result { + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn ok_or_else(self, err: F) -> Result + where + F: ~const FnOnce() -> E, + F: ~const Drop, + { match self { Some(v) => Ok(v), None => Err(err()), } } + /// Converts from `Option` (or `&Option`) to `Option<&T::Target>`. + /// + /// Leaves the original Option in-place, creating a new one with a reference + /// to the original one, additionally coercing the contents via [`Deref`]. + /// + /// # Examples + /// + /// ``` + /// let x: Option = Some("hey".to_owned()); + /// assert_eq!(x.as_deref(), Some("hey")); + /// + /// let x: Option = None; + /// assert_eq!(x.as_deref(), None); + /// ``` + #[stable(feature = "option_deref", since = "1.40.0")] + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn as_deref(&self) -> Option<&T::Target> + where + T: ~const Deref, + { + match self.as_ref() { + Some(t) => Some(t.deref()), + None => None, + } + } + + /// Converts from `Option` (or `&mut Option`) to `Option<&mut T::Target>`. + /// + /// Leaves the original `Option` in-place, creating a new one containing a mutable reference to + /// the inner type's [`Deref::Target`] type. + /// + /// # Examples + /// + /// ``` + /// let mut x: Option = Some("hey".to_owned()); + /// assert_eq!(x.as_deref_mut().map(|x| { + /// x.make_ascii_uppercase(); + /// x + /// }), Some("HEY".to_owned().as_mut_str())); + /// ``` + #[stable(feature = "option_deref", since = "1.40.0")] + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn as_deref_mut(&mut self) -> Option<&mut T::Target> + where + T: ~const DerefMut, + { + match self.as_mut() { + Some(t) => Some(t.deref_mut()), + None => None, + } + } + ///////////////////////////////////////////////////////////////////////// // Iterator constructors ///////////////////////////////////////////////////////////////////////// @@ -1023,7 +1164,12 @@ impl Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn and(self, optb: Option) -> Option { + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn and(self, optb: Option) -> Option + where + T: ~const Drop, + U: ~const Drop, + { match self { Some(_) => optb, None => None, @@ -1048,7 +1194,12 @@ impl Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn and_then Option>(self, f: F) -> Option { + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn and_then(self, f: F) -> Option + where + F: ~const FnOnce(T) -> Option, + F: ~const Drop, + { match self { Some(x) => f(x), None => None, @@ -1081,7 +1232,13 @@ impl Option { /// [`Some(t)`]: Some #[inline] #[stable(feature = "option_filter", since = "1.27.0")] - pub fn filter bool>(self, predicate: P) -> Self { + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn filter

(self, predicate: P) -> Self + where + T: ~const Drop, + P: ~const FnOnce(&T) -> bool, + P: ~const Drop, + { if let Some(x) = self { if predicate(&x) { return Some(x); @@ -1119,9 +1276,13 @@ impl Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn or(self, optb: Option) -> Option { + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn or(self, optb: Option) -> Option + where + T: ~const Drop, + { match self { - Some(_) => self, + Some(x) => Some(x), None => optb, } } @@ -1141,9 +1302,14 @@ impl Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn or_else Option>(self, f: F) -> Option { + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn or_else(self, f: F) -> Option + where + F: ~const FnOnce() -> Option, + F: ~const Drop, + { match self { - Some(_) => self, + Some(x) => Some(x), None => f(), } } @@ -1171,7 +1337,11 @@ impl Option { /// ``` #[inline] #[stable(feature = "option_xor", since = "1.37.0")] - pub fn xor(self, optb: Option) -> Option { + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn xor(self, optb: Option) -> Option + where + T: ~const Drop, + { match (self, optb) { (Some(a), None) => Some(a), (None, Some(b)) => Some(b), @@ -1205,7 +1375,11 @@ impl Option { #[must_use = "if you intended to set a value, consider assignment instead"] #[inline] #[stable(feature = "option_insert", since = "1.53.0")] - pub fn insert(&mut self, value: T) -> &mut T { + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn insert(&mut self, value: T) -> &mut T + where + T: ~const Drop, + { *self = Some(value); // SAFETY: the code above just filled the option @@ -1234,8 +1408,18 @@ impl Option { /// ``` #[inline] #[stable(feature = "option_entry", since = "1.20.0")] - pub fn get_or_insert(&mut self, value: T) -> &mut T { - self.get_or_insert_with(|| value) + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn get_or_insert(&mut self, value: T) -> &mut T + where + T: ~const Drop, + { + if let None = *self { + *self = Some(value); + } + + // SAFETY: a `None` variant for `self` would have been replaced by a `Some` + // variant in the code above. + unsafe { self.as_mut().unwrap_unchecked() } } /// Inserts the default value into the option if it is [`None`], then @@ -1259,11 +1443,17 @@ impl Option { /// ``` #[inline] #[unstable(feature = "option_get_or_insert_default", issue = "82901")] - pub fn get_or_insert_default(&mut self) -> &mut T + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn get_or_insert_default(&mut self) -> &mut T where - T: Default, + T: ~const Default, { - self.get_or_insert_with(Default::default) + #[rustc_allow_const_fn_unstable(const_fn_trait_bound)] + const fn default() -> T { + T::default() + } + + self.get_or_insert_with(default) } /// Inserts a value computed from `f` into the option if it is [`None`], @@ -1285,17 +1475,21 @@ impl Option { /// ``` #[inline] #[stable(feature = "option_entry", since = "1.20.0")] - pub fn get_or_insert_with T>(&mut self, f: F) -> &mut T { + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn get_or_insert_with(&mut self, f: F) -> &mut T + where + F: ~const FnOnce() -> T, + F: ~const Drop, + { if let None = *self { - *self = Some(f()); + // the compiler isn't smart enough to know that we are not dropping a `T` + // here and wants us to ensure `T` can be dropped at compile time. + mem::forget(mem::replace(self, Some(f()))) } - match self { - Some(v) => v, - // SAFETY: a `None` variant for `self` would have been replaced by a `Some` - // variant in the code above. - None => unsafe { hint::unreachable_unchecked() }, - } + // SAFETY: a `None` variant for `self` would have been replaced by a `Some` + // variant in the code above. + unsafe { self.as_mut().unwrap_unchecked() } } ///////////////////////////////////////////////////////////////////////// @@ -1349,6 +1543,36 @@ impl Option { mem::replace(self, Some(value)) } + /// Returns `true` if the option is a [`Some`] value containing the given value. + /// + /// # Examples + /// + /// ``` + /// #![feature(option_result_contains)] + /// + /// let x: Option = Some(2); + /// assert_eq!(x.contains(&2), true); + /// + /// let x: Option = Some(3); + /// assert_eq!(x.contains(&2), false); + /// + /// let x: Option = None; + /// assert_eq!(x.contains(&2), false); + /// ``` + #[must_use] + #[inline] + #[unstable(feature = "option_result_contains", issue = "62358")] + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn contains(&self, x: &U) -> bool + where + U: ~const PartialEq, + { + match self { + Some(y) => x.eq(y), + None => false, + } + } + /// Zips `self` with another `Option`. /// /// If `self` is `Some(s)` and `other` is `Some(o)`, this method returns `Some((s, o))`. @@ -1365,7 +1589,12 @@ impl Option { /// assert_eq!(x.zip(z), None); /// ``` #[stable(feature = "option_zip_option", since = "1.46.0")] - pub fn zip(self, other: Option) -> Option<(T, U)> { + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn zip(self, other: Option) -> Option<(T, U)> + where + T: ~const Drop, + U: ~const Drop, + { match (self, other) { (Some(a), Some(b)) => Some((a, b)), _ => None, @@ -1401,11 +1630,18 @@ impl Option { /// assert_eq!(x.zip_with(None, Point::new), None); /// ``` #[unstable(feature = "option_zip", issue = "70086")] - pub fn zip_with(self, other: Option, f: F) -> Option + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn zip_with(self, other: Option, f: F) -> Option where - F: FnOnce(T, U) -> R, + F: ~const FnOnce(T, U) -> R, + F: ~const Drop, + T: ~const Drop, + U: ~const Drop, { - Some(f(self?, other?)) + match (self, other) { + (Some(a), Some(b)) => Some(f(a, b)), + _ => None, + } } } @@ -1436,7 +1672,7 @@ impl Option<(T, U)> { } } -impl Option<&T> { +impl Option<&T> { /// Maps an `Option<&T>` to an `Option` by copying the contents of the /// option. /// @@ -1452,7 +1688,10 @@ impl Option<&T> { #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "copied", since = "1.35.0")] #[rustc_const_unstable(feature = "const_option", issue = "67441")] - pub const fn copied(self) -> Option { + pub const fn copied(self) -> Option + where + T: Copy, + { // FIXME: this implementation, which sidesteps using `Option::map` since it's not const // ready yet, should be reverted when possible to avoid code repetition match self { @@ -1460,29 +1699,7 @@ impl Option<&T> { None => None, } } -} -impl Option<&mut T> { - /// Maps an `Option<&mut T>` to an `Option` by copying the contents of the - /// option. - /// - /// # Examples - /// - /// ``` - /// let mut x = 12; - /// let opt_x = Some(&mut x); - /// assert_eq!(opt_x, Some(&mut 12)); - /// let copied = opt_x.copied(); - /// assert_eq!(copied, Some(12)); - /// ``` - #[must_use = "`self` will be dropped if the result is not used"] - #[stable(feature = "copied", since = "1.35.0")] - pub fn copied(self) -> Option { - self.map(|&mut t| t) - } -} - -impl Option<&T> { /// Maps an `Option<&T>` to an `Option` by cloning the contents of the /// option. /// @@ -1497,12 +1714,44 @@ impl Option<&T> { /// ``` #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "rust1", since = "1.0.0")] - pub fn cloned(self) -> Option { - self.map(|t| t.clone()) + #[rustc_const_unstable(feature = "const_option_cloned", issue = "91582")] + pub const fn cloned(self) -> Option + where + T: ~const Clone, + { + match self { + Some(t) => Some(t.clone()), + None => None, + } } } -impl Option<&mut T> { +impl Option<&mut T> { + /// Maps an `Option<&mut T>` to an `Option` by copying the contents of the + /// option. + /// + /// # Examples + /// + /// ``` + /// let mut x = 12; + /// let opt_x = Some(&mut x); + /// assert_eq!(opt_x, Some(&mut 12)); + /// let copied = opt_x.copied(); + /// assert_eq!(copied, Some(12)); + /// ``` + #[must_use = "`self` will be dropped if the result is not used"] + #[stable(feature = "copied", since = "1.35.0")] + #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] + pub const fn copied(self) -> Option + where + T: Copy, + { + match self { + Some(&mut t) => Some(t), + None => None, + } + } + /// Maps an `Option<&mut T>` to an `Option` by cloning the contents of the /// option. /// @@ -1515,91 +1764,20 @@ impl Option<&mut T> { /// let cloned = opt_x.cloned(); /// assert_eq!(cloned, Some(12)); /// ``` + #[must_use = "`self` will be dropped if the result is not used"] #[stable(since = "1.26.0", feature = "option_ref_mut_cloned")] - pub fn cloned(self) -> Option { - self.map(|t| t.clone()) - } -} - -impl Option { - /// Returns the contained [`Some`] value or a default. - /// - /// Consumes the `self` argument then, if [`Some`], returns the contained - /// value, otherwise if [`None`], returns the [default value] for that - /// type. - /// - /// # Examples - /// - /// Converts a string to an integer, turning poorly-formed strings - /// into 0 (the default value for integers). [`parse`] converts - /// a string to any other type that implements [`FromStr`], returning - /// [`None`] on error. - /// - /// ``` - /// let good_year_from_input = "1909"; - /// let bad_year_from_input = "190blarg"; - /// let good_year = good_year_from_input.parse().ok().unwrap_or_default(); - /// let bad_year = bad_year_from_input.parse().ok().unwrap_or_default(); - /// - /// assert_eq!(1909, good_year); - /// assert_eq!(0, bad_year); - /// ``` - /// - /// [default value]: Default::default - /// [`parse`]: str::parse - /// [`FromStr`]: crate::str::FromStr - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn unwrap_or_default(self) -> T { + #[rustc_const_unstable(feature = "const_option_cloned", issue = "91582")] + pub const fn cloned(self) -> Option + where + T: ~const Clone, + { match self { - Some(x) => x, - None => Default::default(), + Some(t) => Some(t.clone()), + None => None, } } } -impl Option { - /// Converts from `Option` (or `&Option`) to `Option<&T::Target>`. - /// - /// Leaves the original Option in-place, creating a new one with a reference - /// to the original one, additionally coercing the contents via [`Deref`]. - /// - /// # Examples - /// - /// ``` - /// let x: Option = Some("hey".to_owned()); - /// assert_eq!(x.as_deref(), Some("hey")); - /// - /// let x: Option = None; - /// assert_eq!(x.as_deref(), None); - /// ``` - #[stable(feature = "option_deref", since = "1.40.0")] - pub fn as_deref(&self) -> Option<&T::Target> { - self.as_ref().map(|t| t.deref()) - } -} - -impl Option { - /// Converts from `Option` (or `&mut Option`) to `Option<&mut T::Target>`. - /// - /// Leaves the original `Option` in-place, creating a new one containing a mutable reference to - /// the inner type's [`Deref::Target`] type. - /// - /// # Examples - /// - /// ``` - /// let mut x: Option = Some("hey".to_owned()); - /// assert_eq!(x.as_deref_mut().map(|x| { - /// x.make_ascii_uppercase(); - /// x - /// }), Some("HEY".to_owned().as_mut_str())); - /// ``` - #[stable(feature = "option_deref", since = "1.40.0")] - pub fn as_deref_mut(&mut self) -> Option<&mut T::Target> { - self.as_mut().map(|t| t.deref_mut()) - } -} - impl Option> { /// Transposes an `Option` of a [`Result`] into a [`Result`] of an `Option`. /// @@ -1630,11 +1808,13 @@ impl Option> { } // This is a separate function to reduce the code size of .expect() itself. -#[inline(never)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] -fn expect_failed(msg: &str) -> ! { - panic!("{}", msg) +#[rustc_const_unstable(feature = "const_option", issue = "67441")] +const fn expect_failed(msg: &str) -> ! { + panic_str(msg) } ///////////////////////////////////////////////////////////////////////////// @@ -2035,7 +2215,8 @@ impl> FromIterator> for Option { } #[unstable(feature = "try_trait_v2", issue = "84277")] -impl ops::Try for Option { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl const ops::Try for Option { type Output = T; type Residual = Option; @@ -2054,6 +2235,7 @@ impl ops::Try for Option { } #[unstable(feature = "try_trait_v2", issue = "84277")] +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] impl const ops::FromResidual for Option { #[inline] fn from_residual(residual: Option) -> Self { @@ -2063,6 +2245,11 @@ impl const ops::FromResidual for Option { } } +#[unstable(feature = "try_trait_v2_residual", issue = "91285")] +impl ops::Residual for Option { + type TryType = Option; +} + impl Option> { /// Converts from `Option>` to `Option`. /// diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs index 7a8b04d6f3..0be3f06ff6 100644 --- a/library/core/src/panic.rs +++ b/library/core/src/panic.rs @@ -58,6 +58,39 @@ pub macro panic_2021 { ), } +#[doc(hidden)] +#[unstable(feature = "edition_panic", issue = "none", reason = "use unreachable!() instead")] +#[allow_internal_unstable(core_panic)] +#[rustc_diagnostic_item = "unreachable_2015_macro"] +#[rustc_macro_transparency = "semitransparent"] +pub macro unreachable_2015 { + () => ( + $crate::panicking::panic("internal error: entered unreachable code") + ), + // Use of `unreachable_display` for non_fmt_panic lint. + // NOTE: the message ("internal error ...") is embeded directly in unreachable_display + ($msg:expr $(,)?) => ( + $crate::panicking::unreachable_display(&$msg) + ), + ($fmt:expr, $($arg:tt)*) => ( + $crate::panic!($crate::concat!("internal error: entered unreachable code: ", $fmt), $($arg)*) + ), +} + +#[doc(hidden)] +#[unstable(feature = "edition_panic", issue = "none", reason = "use unreachable!() instead")] +#[allow_internal_unstable(core_panic)] +#[rustc_diagnostic_item = "unreachable_2021_macro"] +#[rustc_macro_transparency = "semitransparent"] +pub macro unreachable_2021 { + () => ( + $crate::panicking::panic("internal error: entered unreachable code") + ), + ($($t:tt)+) => ( + $crate::panic!("internal error: entered unreachable code: {}", $crate::format_args!($($t)+)) + ), +} + /// An internal trait used by libstd to pass data from libstd to `panic_unwind` /// and other panic runtimes. Not intended to be stabilized any time soon, do /// not use. diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index eedea6562b..422f0e187d 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -50,11 +50,20 @@ pub const fn panic(expr: &'static str) -> ! { #[inline] #[track_caller] -#[lang = "panic_str"] // needed for `non-fmt-panics` lint +#[rustc_diagnostic_item = "panic_str"] +#[rustc_const_unstable(feature = "core_panic", issue = "none")] pub const fn panic_str(expr: &str) -> ! { panic_display(&expr); } +#[cfg(not(bootstrap))] +#[inline] +#[track_caller] +#[rustc_diagnostic_item = "unreachable_display"] // needed for `non-fmt-panics` lint +pub fn unreachable_display(x: &T) -> ! { + panic_fmt(format_args!("internal error: entered unreachable code: {}", *x)); +} + #[inline] #[track_caller] #[lang = "panic_display"] // needed for const-evaluated panics diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs index 6b51ef5b01..0fb8846288 100644 --- a/library/core/src/prelude/v1.rs +++ b/library/core/src/prelude/v1.rs @@ -61,38 +61,29 @@ pub use crate::{ }; #[unstable( - feature = "asm", - issue = "72016", - reason = "inline assembly is not stable enough for use and is subject to change" + feature = "concat_bytes", + issue = "87555", + reason = "`concat_bytes` is not stable enough for use and is subject to change" )] +#[cfg(not(bootstrap))] #[doc(no_inline)] -pub use crate::arch::asm; - -#[unstable( - feature = "global_asm", - issue = "35119", - reason = "`global_asm!` is not stable enough for use and is subject to change" -)] -#[doc(no_inline)] -pub use crate::arch::global_asm; +pub use crate::concat_bytes; +// Do not `doc(inline)` these `doc(hidden)` items. #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] -#[allow(deprecated, deprecated_in_future)] -#[doc(no_inline)] -pub use crate::macros::builtin::{ - bench, global_allocator, test, test_case, RustcDecodable, RustcEncodable, -}; +#[allow(deprecated)] +pub use crate::macros::builtin::{RustcDecodable, RustcEncodable}; +// Do not `doc(no_inline)` so that they become doc items on their own +// (no public module for them to be re-exported from). #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] -#[doc(no_inline)] -pub use crate::macros::builtin::derive; +pub use crate::macros::builtin::{bench, derive, global_allocator, test, test_case}; #[unstable( feature = "cfg_accessible", issue = "64797", reason = "`cfg_accessible` is not fully implemented" )] -#[doc(no_inline)] pub use crate::macros::builtin::cfg_accessible; #[unstable( @@ -100,5 +91,4 @@ pub use crate::macros::builtin::cfg_accessible; issue = "82679", reason = "`cfg_eval` is a recently implemented feature" )] -#[doc(no_inline)] pub use crate::macros::builtin::cfg_eval; diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index f47a30c9b5..8fcd8cdeb1 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -606,8 +606,7 @@ mod prim_pointer {} /// println!("array[{}] = {}", i, x); /// } /// -/// // You can explicitly iterate an array by value using -/// // `IntoIterator::into_iter` or `std::array::IntoIter::new`: +/// // You can explicitly iterate an array by value using `IntoIterator::into_iter` /// for item in IntoIterator::into_iter(array).enumerate() { /// let (i, x): (usize, i32) = item; /// println!("array[{}] = {}", i, x); diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 344b483662..a93327a013 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -48,6 +48,54 @@ impl *const T { self as _ } + /// Casts a pointer to its raw bits. + /// + /// This is equivalent to `as usize`, but is more specific to enhance readability. + /// The inverse method is [`from_bits`](#method.from_bits). + /// + /// In particular, `*p as usize` and `p as usize` will both compile for + /// pointers to numeric types but do very different things, so using this + /// helps emphasize that reading the bits was intentional. + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_to_from_bits)] + /// let array = [13, 42]; + /// let p0: *const i32 = &array[0]; + /// assert_eq!(<*const _>::from_bits(p0.to_bits()), p0); + /// let p1: *const i32 = &array[1]; + /// assert_eq!(p1.to_bits() - p0.to_bits(), 4); + /// ``` + #[unstable(feature = "ptr_to_from_bits", issue = "91126")] + pub fn to_bits(self) -> usize + where + T: Sized, + { + self as usize + } + + /// Creates a pointer from its raw bits. + /// + /// This is equivalent to `as *const T`, but is more specific to enhance readability. + /// The inverse method is [`to_bits`](#method.to_bits). + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_to_from_bits)] + /// use std::ptr::NonNull; + /// let dangling: *const u8 = NonNull::dangling().as_ptr(); + /// assert_eq!(<*const u8>::from_bits(1), dangling); + /// ``` + #[unstable(feature = "ptr_to_from_bits", issue = "91126")] + pub fn from_bits(bits: usize) -> Self + where + T: Sized, + { + bits as Self + } + /// Decompose a (possibly wide) pointer into its address and metadata components. /// /// The pointer can be later reconstructed with [`from_raw_parts`]. @@ -71,7 +119,7 @@ impl *const T { /// /// * The pointer must be properly aligned. /// - /// * It must be "dereferencable" in the sense defined in [the module documentation]. + /// * It must be "dereferenceable" in the sense defined in [the module documentation]. /// /// * The pointer must point to an initialized instance of `T`. /// @@ -115,8 +163,9 @@ impl *const T { /// } /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] + #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] #[inline] - pub unsafe fn as_ref<'a>(self) -> Option<&'a T> { + pub const unsafe fn as_ref<'a>(self) -> Option<&'a T> { // SAFETY: the caller must guarantee that `self` is valid // for a reference if it isn't null. if self.is_null() { None } else { unsafe { Some(&*self) } } @@ -135,7 +184,7 @@ impl *const T { /// /// * The pointer must be properly aligned. /// - /// * It must be "dereferencable" in the sense defined in [the module documentation]. + /// * It must be "dereferenceable" in the sense defined in [the module documentation]. /// /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. @@ -163,7 +212,8 @@ impl *const T { /// ``` #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit> + #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + pub const unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit> where T: Sized, { @@ -955,7 +1005,7 @@ impl *const [T] { /// Returns a raw pointer to an element or subslice, without doing bounds /// checking. /// - /// Calling this method with an out-of-bounds index or when `self` is not dereferencable + /// Calling this method with an out-of-bounds index or when `self` is not dereferenceable /// is *[undefined behavior]* even if the resulting pointer is not used. /// /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html @@ -977,7 +1027,7 @@ impl *const [T] { where I: SliceIndex<[T]>, { - // SAFETY: the caller ensures that `self` is dereferencable and `index` in-bounds. + // SAFETY: the caller ensures that `self` is dereferenceable and `index` in-bounds. unsafe { index.get_unchecked(self) } } @@ -1020,7 +1070,8 @@ impl *const [T] { /// [allocated object]: crate::ptr#allocated-object #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - pub unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit]> { + #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + pub const unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit]> { if self.is_null() { None } else { diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index f3b2bdfefe..5fd3b2ebc6 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -47,6 +47,55 @@ impl *mut T { self as _ } + /// Casts a pointer to its raw bits. + /// + /// This is equivalent to `as usize`, but is more specific to enhance readability. + /// The inverse method is [`from_bits`](#method.from_bits-1). + /// + /// In particular, `*p as usize` and `p as usize` will both compile for + /// pointers to numeric types but do very different things, so using this + /// helps emphasize that reading the bits was intentional. + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_to_from_bits)] + /// let mut array = [13, 42]; + /// let mut it = array.iter_mut(); + /// let p0: *mut i32 = it.next().unwrap(); + /// assert_eq!(<*mut _>::from_bits(p0.to_bits()), p0); + /// let p1: *mut i32 = it.next().unwrap(); + /// assert_eq!(p1.to_bits() - p0.to_bits(), 4); + /// ``` + #[unstable(feature = "ptr_to_from_bits", issue = "91126")] + pub fn to_bits(self) -> usize + where + T: Sized, + { + self as usize + } + + /// Creates a pointer from its raw bits. + /// + /// This is equivalent to `as *mut T`, but is more specific to enhance readability. + /// The inverse method is [`to_bits`](#method.to_bits-1). + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_to_from_bits)] + /// use std::ptr::NonNull; + /// let dangling: *mut u8 = NonNull::dangling().as_ptr(); + /// assert_eq!(<*mut u8>::from_bits(1), dangling); + /// ``` + #[unstable(feature = "ptr_to_from_bits", issue = "91126")] + pub fn from_bits(bits: usize) -> Self + where + T: Sized, + { + bits as Self + } + /// Decompose a (possibly wide) pointer into its address and metadata components. /// /// The pointer can be later reconstructed with [`from_raw_parts_mut`]. @@ -73,7 +122,7 @@ impl *mut T { /// /// * The pointer must be properly aligned. /// - /// * It must be "dereferencable" in the sense defined in [the module documentation]. + /// * It must be "dereferenceable" in the sense defined in [the module documentation]. /// /// * The pointer must point to an initialized instance of `T`. /// @@ -117,8 +166,9 @@ impl *mut T { /// } /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] + #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] #[inline] - pub unsafe fn as_ref<'a>(self) -> Option<&'a T> { + pub const unsafe fn as_ref<'a>(self) -> Option<&'a T> { // SAFETY: the caller must guarantee that `self` is valid for a // reference if it isn't null. if self.is_null() { None } else { unsafe { Some(&*self) } } @@ -140,7 +190,7 @@ impl *mut T { /// /// * The pointer must be properly aligned. /// - /// * It must be "dereferencable" in the sense defined in [the module documentation]. + /// * It must be "dereferenceable" in the sense defined in [the module documentation]. /// /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. @@ -168,7 +218,8 @@ impl *mut T { /// ``` #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit> + #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + pub const unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit> where T: Sized, { @@ -319,7 +370,7 @@ impl *mut T { /// /// * The pointer must be properly aligned. /// - /// * It must be "dereferencable" in the sense defined in [the module documentation]. + /// * It must be "dereferenceable" in the sense defined in [the module documentation]. /// /// * The pointer must point to an initialized instance of `T`. /// @@ -362,8 +413,9 @@ impl *mut T { /// println!("{:?}", s); // It'll print: "[4, 2, 3]". /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] + #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] #[inline] - pub unsafe fn as_mut<'a>(self) -> Option<&'a mut T> { + pub const unsafe fn as_mut<'a>(self) -> Option<&'a mut T> { // SAFETY: the caller must guarantee that `self` is be valid for // a mutable reference if it isn't null. if self.is_null() { None } else { unsafe { Some(&mut *self) } } @@ -385,7 +437,7 @@ impl *mut T { /// /// * The pointer must be properly aligned. /// - /// * It must be "dereferencable" in the sense defined in [the module documentation]. + /// * It must be "dereferenceable" in the sense defined in [the module documentation]. /// /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. @@ -397,7 +449,8 @@ impl *mut T { /// [the module documentation]: crate::ptr#safety #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - pub unsafe fn as_uninit_mut<'a>(self) -> Option<&'a mut MaybeUninit> + #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + pub const unsafe fn as_uninit_mut<'a>(self) -> Option<&'a mut MaybeUninit> where T: Sized, { @@ -1020,8 +1073,9 @@ impl *mut T { /// /// [`ptr::write_bytes`]: crate::ptr::write_bytes() #[stable(feature = "pointer_methods", since = "1.26.0")] + #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")] #[inline(always)] - pub unsafe fn write_bytes(self, val: u8, count: usize) + pub const unsafe fn write_bytes(self, val: u8, count: usize) where T: Sized, { @@ -1217,7 +1271,7 @@ impl *mut [T] { /// Returns a raw pointer to an element or subslice, without doing bounds /// checking. /// - /// Calling this method with an out-of-bounds index or when `self` is not dereferencable + /// Calling this method with an out-of-bounds index or when `self` is not dereferenceable /// is *[undefined behavior]* even if the resulting pointer is not used. /// /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html @@ -1239,7 +1293,7 @@ impl *mut [T] { where I: SliceIndex<[T]>, { - // SAFETY: the caller ensures that `self` is dereferencable and `index` in-bounds. + // SAFETY: the caller ensures that `self` is dereferenceable and `index` in-bounds. unsafe { index.get_unchecked_mut(self) } } @@ -1285,7 +1339,8 @@ impl *mut [T] { /// [allocated object]: crate::ptr#allocated-object #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - pub unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit]> { + #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + pub const unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit]> { if self.is_null() { None } else { @@ -1336,7 +1391,8 @@ impl *mut [T] { /// [allocated object]: crate::ptr#allocated-object #[inline] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - pub unsafe fn as_uninit_slice_mut<'a>(self) -> Option<&'a mut [MaybeUninit]> { + #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + pub const unsafe fn as_uninit_slice_mut<'a>(self) -> Option<&'a mut [MaybeUninit]> { if self.is_null() { None } else { diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 58110b0680..3a7e99facc 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -109,7 +109,7 @@ impl NonNull { /// /// * The pointer must be properly aligned. /// - /// * It must be "dereferencable" in the sense defined in [the module documentation]. + /// * It must be "dereferenceable" in the sense defined in [the module documentation]. /// /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. @@ -122,7 +122,8 @@ impl NonNull { #[inline] #[must_use] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - pub unsafe fn as_uninit_ref<'a>(&self) -> &'a MaybeUninit { + #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + pub const unsafe fn as_uninit_ref<'a>(&self) -> &'a MaybeUninit { // SAFETY: the caller must guarantee that `self` meets all the // requirements for a reference. unsafe { &*self.cast().as_ptr() } @@ -142,7 +143,7 @@ impl NonNull { /// /// * The pointer must be properly aligned. /// - /// * It must be "dereferencable" in the sense defined in [the module documentation]. + /// * It must be "dereferenceable" in the sense defined in [the module documentation]. /// /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. @@ -155,7 +156,8 @@ impl NonNull { #[inline] #[must_use] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - pub unsafe fn as_uninit_mut<'a>(&mut self) -> &'a mut MaybeUninit { + #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + pub const unsafe fn as_uninit_mut<'a>(&mut self) -> &'a mut MaybeUninit { // SAFETY: the caller must guarantee that `self` meets all the // requirements for a reference. unsafe { &mut *self.cast().as_ptr() } @@ -289,7 +291,7 @@ impl NonNull { /// /// * The pointer must be properly aligned. /// - /// * It must be "dereferencable" in the sense defined in [the module documentation]. + /// * It must be "dereferenceable" in the sense defined in [the module documentation]. /// /// * The pointer must point to an initialized instance of `T`. /// @@ -316,9 +318,10 @@ impl NonNull { /// /// [the module documentation]: crate::ptr#safety #[stable(feature = "nonnull", since = "1.25.0")] + #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] #[must_use] #[inline] - pub unsafe fn as_ref<'a>(&self) -> &'a T { + pub const unsafe fn as_ref<'a>(&self) -> &'a T { // SAFETY: the caller must guarantee that `self` meets all the // requirements for a reference. unsafe { &*self.as_ptr() } @@ -338,7 +341,7 @@ impl NonNull { /// /// * The pointer must be properly aligned. /// - /// * It must be "dereferencable" in the sense defined in [the module documentation]. + /// * It must be "dereferenceable" in the sense defined in [the module documentation]. /// /// * The pointer must point to an initialized instance of `T`. /// @@ -366,9 +369,10 @@ impl NonNull { /// /// [the module documentation]: crate::ptr#safety #[stable(feature = "nonnull", since = "1.25.0")] + #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] #[must_use] #[inline] - pub unsafe fn as_mut<'a>(&mut self) -> &'a mut T { + pub const unsafe fn as_mut<'a>(&mut self) -> &'a mut T { // SAFETY: the caller must guarantee that `self` meets all the // requirements for a mutable reference. unsafe { &mut *self.as_ptr() } @@ -534,7 +538,8 @@ impl NonNull<[T]> { #[inline] #[must_use] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - pub unsafe fn as_uninit_slice<'a>(&self) -> &'a [MaybeUninit] { + #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + pub const unsafe fn as_uninit_slice<'a>(&self) -> &'a [MaybeUninit] { // SAFETY: the caller must uphold the safety contract for `as_uninit_slice`. unsafe { slice::from_raw_parts(self.cast().as_ptr(), self.len()) } } @@ -596,7 +601,8 @@ impl NonNull<[T]> { #[inline] #[must_use] #[unstable(feature = "ptr_as_uninit", issue = "75402")] - pub unsafe fn as_uninit_slice_mut<'a>(&self) -> &'a mut [MaybeUninit] { + #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")] + pub const unsafe fn as_uninit_slice_mut<'a>(&self) -> &'a mut [MaybeUninit] { // SAFETY: the caller must uphold the safety contract for `as_uninit_slice_mut`. unsafe { slice::from_raw_parts_mut(self.cast().as_ptr(), self.len()) } } @@ -604,7 +610,7 @@ impl NonNull<[T]> { /// Returns a raw pointer to an element or subslice, without doing bounds /// checking. /// - /// Calling this method with an out-of-bounds index or when `self` is not dereferencable + /// Calling this method with an out-of-bounds index or when `self` is not dereferenceable /// is *[undefined behavior]* even if the resulting pointer is not used. /// /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html @@ -628,7 +634,7 @@ impl NonNull<[T]> { where I: SliceIndex<[T]>, { - // SAFETY: the caller ensures that `self` is dereferencable and `index` in-bounds. + // SAFETY: the caller ensures that `self` is dereferenceable and `index` in-bounds. // As a consequence, the resulting pointer cannot be null. unsafe { NonNull::new_unchecked(self.as_ptr().get_unchecked_mut(index)) } } diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index d650a6f974..f5c624c225 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -92,7 +92,7 @@ impl Unique { /// Creates a new `Unique` if `ptr` is non-null. #[inline] - pub fn new(ptr: *mut T) -> Option { + pub const fn new(ptr: *mut T) -> Option { if !ptr.is_null() { // SAFETY: The pointer has already been checked and is not null. Some(unsafe { Unique { pointer: ptr as _, _marker: PhantomData } }) @@ -115,7 +115,7 @@ impl Unique { /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`. #[must_use] #[inline] - pub unsafe fn as_ref(&self) -> &T { + pub const unsafe fn as_ref(&self) -> &T { // SAFETY: the caller must guarantee that `self` meets all the // requirements for a reference. unsafe { &*self.as_ptr() } @@ -128,7 +128,7 @@ impl Unique { /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`. #[must_use] #[inline] - pub unsafe fn as_mut(&mut self) -> &mut T { + pub const unsafe fn as_mut(&mut self) -> &mut T { // SAFETY: the caller must guarantee that `self` meets all the // requirements for a mutable reference. unsafe { &mut *self.as_ptr() } diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 8fec2e928a..575fd2b42d 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -563,64 +563,6 @@ impl Result { !self.is_ok() } - /// Returns `true` if the result is an [`Ok`] value containing the given value. - /// - /// # Examples - /// - /// ``` - /// #![feature(option_result_contains)] - /// - /// let x: Result = Ok(2); - /// assert_eq!(x.contains(&2), true); - /// - /// let x: Result = Ok(3); - /// assert_eq!(x.contains(&2), false); - /// - /// let x: Result = Err("Some error message"); - /// assert_eq!(x.contains(&2), false); - /// ``` - #[must_use] - #[inline] - #[unstable(feature = "option_result_contains", issue = "62358")] - pub fn contains(&self, x: &U) -> bool - where - U: PartialEq, - { - match self { - Ok(y) => x == y, - Err(_) => false, - } - } - - /// Returns `true` if the result is an [`Err`] value containing the given value. - /// - /// # Examples - /// - /// ``` - /// #![feature(result_contains_err)] - /// - /// let x: Result = Ok(2); - /// assert_eq!(x.contains_err(&"Some error message"), false); - /// - /// let x: Result = Err("Some error message"); - /// assert_eq!(x.contains_err(&"Some error message"), true); - /// - /// let x: Result = Err("Some other error message"); - /// assert_eq!(x.contains_err(&"Some error message"), false); - /// ``` - #[must_use] - #[inline] - #[unstable(feature = "result_contains_err", issue = "62358")] - pub fn contains_err(&self, f: &F) -> bool - where - F: PartialEq, - { - match self { - Ok(_) => false, - Err(e) => f == e, - } - } - ///////////////////////////////////////////////////////////////////////// // Adapter for each variant ///////////////////////////////////////////////////////////////////////// @@ -854,6 +796,103 @@ impl Result { } } + /// Calls the provided closure with a reference to the contained value (if [`Ok`]). + /// + /// # Examples + /// + /// ``` + /// #![feature(result_option_inspect)] + /// + /// let x: u8 = "4" + /// .parse::() + /// .inspect(|x| println!("original: {}", x)) + /// .map(|x| x.pow(3)) + /// .expect("failed to parse number"); + /// ``` + #[inline] + #[unstable(feature = "result_option_inspect", issue = "91345")] + pub fn inspect(self, f: F) -> Self { + if let Ok(ref t) = self { + f(t); + } + + self + } + + /// Calls the provided closure with a reference to the contained error (if [`Err`]). + /// + /// # Examples + /// + /// ``` + /// #![feature(result_option_inspect)] + /// + /// use std::{fs, io}; + /// + /// fn read() -> io::Result { + /// fs::read_to_string("address.txt") + /// .inspect_err(|e| eprintln!("failed to read file: {}", e)) + /// } + /// ``` + #[inline] + #[unstable(feature = "result_option_inspect", issue = "91345")] + pub fn inspect_err(self, f: F) -> Self { + if let Err(ref e) = self { + f(e); + } + + self + } + + /// Converts from `Result` (or `&Result`) to `Result<&::Target, &E>`. + /// + /// Coerces the [`Ok`] variant of the original [`Result`] via [`Deref`](crate::ops::Deref) + /// and returns the new [`Result`]. + /// + /// # Examples + /// + /// ``` + /// let x: Result = Ok("hello".to_string()); + /// let y: Result<&str, &u32> = Ok("hello"); + /// assert_eq!(x.as_deref(), y); + /// + /// let x: Result = Err(42); + /// let y: Result<&str, &u32> = Err(&42); + /// assert_eq!(x.as_deref(), y); + /// ``` + #[stable(feature = "inner_deref", since = "1.47.0")] + pub fn as_deref(&self) -> Result<&T::Target, &E> + where + T: Deref, + { + self.as_ref().map(|t| t.deref()) + } + + /// Converts from `Result` (or `&mut Result`) to `Result<&mut ::Target, &mut E>`. + /// + /// Coerces the [`Ok`] variant of the original [`Result`] via [`DerefMut`](crate::ops::DerefMut) + /// and returns the new [`Result`]. + /// + /// # Examples + /// + /// ``` + /// let mut s = "HELLO".to_string(); + /// let mut x: Result = Ok("hello".to_string()); + /// let y: Result<&mut str, &mut u32> = Ok(&mut s); + /// assert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y); + /// + /// let mut i = 42; + /// let mut x: Result = Err(42); + /// let y: Result<&mut str, &mut u32> = Err(&mut i); + /// assert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y); + /// ``` + #[stable(feature = "inner_deref", since = "1.47.0")] + pub fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E> + where + T: DerefMut, + { + self.as_mut().map(|t| t.deref_mut()) + } + ///////////////////////////////////////////////////////////////////////// // Iterator constructors ///////////////////////////////////////////////////////////////////////// @@ -904,6 +943,253 @@ impl Result { IterMut { inner: self.as_mut().ok() } } + ///////////////////////////////////////////////////////////////////////// + // Extract a value + ///////////////////////////////////////////////////////////////////////// + + /// Returns the contained [`Ok`] value, consuming the `self` value. + /// + /// # Panics + /// + /// Panics if the value is an [`Err`], with a panic message including the + /// passed message, and the content of the [`Err`]. + /// + /// + /// # Examples + /// + /// Basic usage: + /// + /// ```should_panic + /// let x: Result = Err("emergency failure"); + /// x.expect("Testing expect"); // panics with `Testing expect: emergency failure` + /// ``` + #[inline] + #[track_caller] + #[stable(feature = "result_expect", since = "1.4.0")] + pub fn expect(self, msg: &str) -> T + where + E: fmt::Debug, + { + match self { + Ok(t) => t, + Err(e) => unwrap_failed(msg, &e), + } + } + + /// Returns the contained [`Ok`] value, consuming the `self` value. + /// + /// Because this function may panic, its use is generally discouraged. + /// Instead, prefer to use pattern matching and handle the [`Err`] + /// case explicitly, or call [`unwrap_or`], [`unwrap_or_else`], or + /// [`unwrap_or_default`]. + /// + /// [`unwrap_or`]: Result::unwrap_or + /// [`unwrap_or_else`]: Result::unwrap_or_else + /// [`unwrap_or_default`]: Result::unwrap_or_default + /// + /// # Panics + /// + /// Panics if the value is an [`Err`], with a panic message provided by the + /// [`Err`]'s value. + /// + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let x: Result = Ok(2); + /// assert_eq!(x.unwrap(), 2); + /// ``` + /// + /// ```should_panic + /// let x: Result = Err("emergency failure"); + /// x.unwrap(); // panics with `emergency failure` + /// ``` + #[inline] + #[track_caller] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn unwrap(self) -> T + where + E: fmt::Debug, + { + match self { + Ok(t) => t, + Err(e) => unwrap_failed("called `Result::unwrap()` on an `Err` value", &e), + } + } + + /// Returns the contained [`Ok`] value or a default + /// + /// Consumes the `self` argument then, if [`Ok`], returns the contained + /// value, otherwise if [`Err`], returns the default value for that + /// type. + /// + /// # Examples + /// + /// Converts a string to an integer, turning poorly-formed strings + /// into 0 (the default value for integers). [`parse`] converts + /// a string to any other type that implements [`FromStr`], returning an + /// [`Err`] on error. + /// + /// ``` + /// let good_year_from_input = "1909"; + /// let bad_year_from_input = "190blarg"; + /// let good_year = good_year_from_input.parse().unwrap_or_default(); + /// let bad_year = bad_year_from_input.parse().unwrap_or_default(); + /// + /// assert_eq!(1909, good_year); + /// assert_eq!(0, bad_year); + /// ``` + /// + /// [`parse`]: str::parse + /// [`FromStr`]: crate::str::FromStr + #[inline] + #[stable(feature = "result_unwrap_or_default", since = "1.16.0")] + pub fn unwrap_or_default(self) -> T + where + T: Default, + { + match self { + Ok(x) => x, + Err(_) => Default::default(), + } + } + + /// Returns the contained [`Err`] value, consuming the `self` value. + /// + /// # Panics + /// + /// Panics if the value is an [`Ok`], with a panic message including the + /// passed message, and the content of the [`Ok`]. + /// + /// + /// # Examples + /// + /// Basic usage: + /// + /// ```should_panic + /// let x: Result = Ok(10); + /// x.expect_err("Testing expect_err"); // panics with `Testing expect_err: 10` + /// ``` + #[inline] + #[track_caller] + #[stable(feature = "result_expect_err", since = "1.17.0")] + pub fn expect_err(self, msg: &str) -> E + where + T: fmt::Debug, + { + match self { + Ok(t) => unwrap_failed(msg, &t), + Err(e) => e, + } + } + + /// Returns the contained [`Err`] value, consuming the `self` value. + /// + /// # Panics + /// + /// Panics if the value is an [`Ok`], with a custom panic message provided + /// by the [`Ok`]'s value. + /// + /// # Examples + /// + /// ```should_panic + /// let x: Result = Ok(2); + /// x.unwrap_err(); // panics with `2` + /// ``` + /// + /// ``` + /// let x: Result = Err("emergency failure"); + /// assert_eq!(x.unwrap_err(), "emergency failure"); + /// ``` + #[inline] + #[track_caller] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn unwrap_err(self) -> E + where + T: fmt::Debug, + { + match self { + Ok(t) => unwrap_failed("called `Result::unwrap_err()` on an `Ok` value", &t), + Err(e) => e, + } + } + + /// Returns the contained [`Ok`] value, but never panics. + /// + /// Unlike [`unwrap`], this method is known to never panic on the + /// result types it is implemented for. Therefore, it can be used + /// instead of `unwrap` as a maintainability safeguard that will fail + /// to compile if the error type of the `Result` is later changed + /// to an error that can actually occur. + /// + /// [`unwrap`]: Result::unwrap + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(never_type)] + /// # #![feature(unwrap_infallible)] + /// + /// fn only_good_news() -> Result { + /// Ok("this is fine".into()) + /// } + /// + /// let s: String = only_good_news().into_ok(); + /// println!("{}", s); + /// ``` + #[unstable(feature = "unwrap_infallible", reason = "newly added", issue = "61695")] + #[inline] + pub fn into_ok(self) -> T + where + E: Into, + { + match self { + Ok(x) => x, + Err(e) => e.into(), + } + } + + /// Returns the contained [`Err`] value, but never panics. + /// + /// Unlike [`unwrap_err`], this method is known to never panic on the + /// result types it is implemented for. Therefore, it can be used + /// instead of `unwrap_err` as a maintainability safeguard that will fail + /// to compile if the ok type of the `Result` is later changed + /// to a type that can actually occur. + /// + /// [`unwrap_err`]: Result::unwrap_err + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(never_type)] + /// # #![feature(unwrap_infallible)] + /// + /// fn only_bad_news() -> Result { + /// Err("Oops, it failed".into()) + /// } + /// + /// let error: String = only_bad_news().into_err(); + /// println!("{}", error); + /// ``` + #[unstable(feature = "unwrap_infallible", reason = "newly added", issue = "61695")] + #[inline] + pub fn into_err(self) -> E + where + T: Into, + { + match self { + Ok(x) => x.into(), + Err(e) => e, + } + } + //////////////////////////////////////////////////////////////////////// // Boolean operations on the values, eager and lazy ///////////////////////////////////////////////////////////////////////// @@ -1147,368 +1433,158 @@ impl Result { Err(e) => e, } } + + ///////////////////////////////////////////////////////////////////////// + // Misc or niche + ///////////////////////////////////////////////////////////////////////// + + /// Returns `true` if the result is an [`Ok`] value containing the given value. + /// + /// # Examples + /// + /// ``` + /// #![feature(option_result_contains)] + /// + /// let x: Result = Ok(2); + /// assert_eq!(x.contains(&2), true); + /// + /// let x: Result = Ok(3); + /// assert_eq!(x.contains(&2), false); + /// + /// let x: Result = Err("Some error message"); + /// assert_eq!(x.contains(&2), false); + /// ``` + #[must_use] + #[inline] + #[unstable(feature = "option_result_contains", issue = "62358")] + pub fn contains(&self, x: &U) -> bool + where + U: PartialEq, + { + match self { + Ok(y) => x == y, + Err(_) => false, + } + } + + /// Returns `true` if the result is an [`Err`] value containing the given value. + /// + /// # Examples + /// + /// ``` + /// #![feature(result_contains_err)] + /// + /// let x: Result = Ok(2); + /// assert_eq!(x.contains_err(&"Some error message"), false); + /// + /// let x: Result = Err("Some error message"); + /// assert_eq!(x.contains_err(&"Some error message"), true); + /// + /// let x: Result = Err("Some other error message"); + /// assert_eq!(x.contains_err(&"Some error message"), false); + /// ``` + #[must_use] + #[inline] + #[unstable(feature = "result_contains_err", issue = "62358")] + pub fn contains_err(&self, f: &F) -> bool + where + F: PartialEq, + { + match self { + Ok(_) => false, + Err(e) => f == e, + } + } } -impl Result<&T, E> { +impl Result<&T, E> { /// Maps a `Result<&T, E>` to a `Result` by copying the contents of the /// `Ok` part. /// /// # Examples /// /// ``` - /// #![feature(result_copied)] /// let val = 12; /// let x: Result<&i32, i32> = Ok(&val); /// assert_eq!(x, Ok(&12)); /// let copied = x.copied(); /// assert_eq!(copied, Ok(12)); /// ``` - #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] - pub fn copied(self) -> Result { + #[inline] + #[stable(feature = "result_copied", since = "1.59.0")] + pub fn copied(self) -> Result + where + T: Copy, + { self.map(|&t| t) } -} -impl Result<&mut T, E> { - /// Maps a `Result<&mut T, E>` to a `Result` by copying the contents of the - /// `Ok` part. - /// - /// # Examples - /// - /// ``` - /// #![feature(result_copied)] - /// let mut val = 12; - /// let x: Result<&mut i32, i32> = Ok(&mut val); - /// assert_eq!(x, Ok(&mut 12)); - /// let copied = x.copied(); - /// assert_eq!(copied, Ok(12)); - /// ``` - #[unstable(feature = "result_copied", reason = "newly added", issue = "63168")] - pub fn copied(self) -> Result { - self.map(|&mut t| t) - } -} - -impl Result<&T, E> { /// Maps a `Result<&T, E>` to a `Result` by cloning the contents of the /// `Ok` part. /// /// # Examples /// /// ``` - /// #![feature(result_cloned)] /// let val = 12; /// let x: Result<&i32, i32> = Ok(&val); /// assert_eq!(x, Ok(&12)); /// let cloned = x.cloned(); /// assert_eq!(cloned, Ok(12)); /// ``` - #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] - pub fn cloned(self) -> Result { + #[inline] + #[stable(feature = "result_cloned", since = "1.59.0")] + pub fn cloned(self) -> Result + where + T: Clone, + { self.map(|t| t.clone()) } } -impl Result<&mut T, E> { +impl Result<&mut T, E> { + /// Maps a `Result<&mut T, E>` to a `Result` by copying the contents of the + /// `Ok` part. + /// + /// # Examples + /// + /// ``` + /// let mut val = 12; + /// let x: Result<&mut i32, i32> = Ok(&mut val); + /// assert_eq!(x, Ok(&mut 12)); + /// let copied = x.copied(); + /// assert_eq!(copied, Ok(12)); + /// ``` + #[inline] + #[stable(feature = "result_copied", since = "1.59.0")] + pub fn copied(self) -> Result + where + T: Copy, + { + self.map(|&mut t| t) + } + /// Maps a `Result<&mut T, E>` to a `Result` by cloning the contents of the /// `Ok` part. /// /// # Examples /// /// ``` - /// #![feature(result_cloned)] /// let mut val = 12; /// let x: Result<&mut i32, i32> = Ok(&mut val); /// assert_eq!(x, Ok(&mut 12)); /// let cloned = x.cloned(); /// assert_eq!(cloned, Ok(12)); /// ``` - #[unstable(feature = "result_cloned", reason = "newly added", issue = "63168")] - pub fn cloned(self) -> Result { + #[inline] + #[stable(feature = "result_cloned", since = "1.59.0")] + pub fn cloned(self) -> Result + where + T: Clone, + { self.map(|t| t.clone()) } } -impl Result { - /// Returns the contained [`Ok`] value, consuming the `self` value. - /// - /// # Panics - /// - /// Panics if the value is an [`Err`], with a panic message including the - /// passed message, and the content of the [`Err`]. - /// - /// - /// # Examples - /// - /// Basic usage: - /// - /// ```should_panic - /// let x: Result = Err("emergency failure"); - /// x.expect("Testing expect"); // panics with `Testing expect: emergency failure` - /// ``` - #[inline] - #[track_caller] - #[stable(feature = "result_expect", since = "1.4.0")] - pub fn expect(self, msg: &str) -> T { - match self { - Ok(t) => t, - Err(e) => unwrap_failed(msg, &e), - } - } - - /// Returns the contained [`Ok`] value, consuming the `self` value. - /// - /// Because this function may panic, its use is generally discouraged. - /// Instead, prefer to use pattern matching and handle the [`Err`] - /// case explicitly, or call [`unwrap_or`], [`unwrap_or_else`], or - /// [`unwrap_or_default`]. - /// - /// [`unwrap_or`]: Result::unwrap_or - /// [`unwrap_or_else`]: Result::unwrap_or_else - /// [`unwrap_or_default`]: Result::unwrap_or_default - /// - /// # Panics - /// - /// Panics if the value is an [`Err`], with a panic message provided by the - /// [`Err`]'s value. - /// - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// let x: Result = Ok(2); - /// assert_eq!(x.unwrap(), 2); - /// ``` - /// - /// ```should_panic - /// let x: Result = Err("emergency failure"); - /// x.unwrap(); // panics with `emergency failure` - /// ``` - #[inline] - #[track_caller] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn unwrap(self) -> T { - match self { - Ok(t) => t, - Err(e) => unwrap_failed("called `Result::unwrap()` on an `Err` value", &e), - } - } -} - -impl Result { - /// Returns the contained [`Err`] value, consuming the `self` value. - /// - /// # Panics - /// - /// Panics if the value is an [`Ok`], with a panic message including the - /// passed message, and the content of the [`Ok`]. - /// - /// - /// # Examples - /// - /// Basic usage: - /// - /// ```should_panic - /// let x: Result = Ok(10); - /// x.expect_err("Testing expect_err"); // panics with `Testing expect_err: 10` - /// ``` - #[inline] - #[track_caller] - #[stable(feature = "result_expect_err", since = "1.17.0")] - pub fn expect_err(self, msg: &str) -> E { - match self { - Ok(t) => unwrap_failed(msg, &t), - Err(e) => e, - } - } - - /// Returns the contained [`Err`] value, consuming the `self` value. - /// - /// # Panics - /// - /// Panics if the value is an [`Ok`], with a custom panic message provided - /// by the [`Ok`]'s value. - /// - /// # Examples - /// - /// ```should_panic - /// let x: Result = Ok(2); - /// x.unwrap_err(); // panics with `2` - /// ``` - /// - /// ``` - /// let x: Result = Err("emergency failure"); - /// assert_eq!(x.unwrap_err(), "emergency failure"); - /// ``` - #[inline] - #[track_caller] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn unwrap_err(self) -> E { - match self { - Ok(t) => unwrap_failed("called `Result::unwrap_err()` on an `Ok` value", &t), - Err(e) => e, - } - } -} - -impl Result { - /// Returns the contained [`Ok`] value or a default - /// - /// Consumes the `self` argument then, if [`Ok`], returns the contained - /// value, otherwise if [`Err`], returns the default value for that - /// type. - /// - /// # Examples - /// - /// Converts a string to an integer, turning poorly-formed strings - /// into 0 (the default value for integers). [`parse`] converts - /// a string to any other type that implements [`FromStr`], returning an - /// [`Err`] on error. - /// - /// ``` - /// let good_year_from_input = "1909"; - /// let bad_year_from_input = "190blarg"; - /// let good_year = good_year_from_input.parse().unwrap_or_default(); - /// let bad_year = bad_year_from_input.parse().unwrap_or_default(); - /// - /// assert_eq!(1909, good_year); - /// assert_eq!(0, bad_year); - /// ``` - /// - /// [`parse`]: str::parse - /// [`FromStr`]: crate::str::FromStr - #[inline] - #[stable(feature = "result_unwrap_or_default", since = "1.16.0")] - pub fn unwrap_or_default(self) -> T { - match self { - Ok(x) => x, - Err(_) => Default::default(), - } - } -} - -#[unstable(feature = "unwrap_infallible", reason = "newly added", issue = "61695")] -impl> Result { - /// Returns the contained [`Ok`] value, but never panics. - /// - /// Unlike [`unwrap`], this method is known to never panic on the - /// result types it is implemented for. Therefore, it can be used - /// instead of `unwrap` as a maintainability safeguard that will fail - /// to compile if the error type of the `Result` is later changed - /// to an error that can actually occur. - /// - /// [`unwrap`]: Result::unwrap - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # #![feature(never_type)] - /// # #![feature(unwrap_infallible)] - /// - /// fn only_good_news() -> Result { - /// Ok("this is fine".into()) - /// } - /// - /// let s: String = only_good_news().into_ok(); - /// println!("{}", s); - /// ``` - #[inline] - pub fn into_ok(self) -> T { - match self { - Ok(x) => x, - Err(e) => e.into(), - } - } -} - -#[unstable(feature = "unwrap_infallible", reason = "newly added", issue = "61695")] -impl, E> Result { - /// Returns the contained [`Err`] value, but never panics. - /// - /// Unlike [`unwrap_err`], this method is known to never panic on the - /// result types it is implemented for. Therefore, it can be used - /// instead of `unwrap_err` as a maintainability safeguard that will fail - /// to compile if the ok type of the `Result` is later changed - /// to a type that can actually occur. - /// - /// [`unwrap_err`]: Result::unwrap_err - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # #![feature(never_type)] - /// # #![feature(unwrap_infallible)] - /// - /// fn only_bad_news() -> Result { - /// Err("Oops, it failed".into()) - /// } - /// - /// let error: String = only_bad_news().into_err(); - /// println!("{}", error); - /// ``` - #[inline] - pub fn into_err(self) -> E { - match self { - Ok(x) => x.into(), - Err(e) => e, - } - } -} - -impl Result { - /// Converts from `Result` (or `&Result`) to `Result<&::Target, &E>`. - /// - /// Coerces the [`Ok`] variant of the original [`Result`] via [`Deref`](crate::ops::Deref) - /// and returns the new [`Result`]. - /// - /// # Examples - /// - /// ``` - /// let x: Result = Ok("hello".to_string()); - /// let y: Result<&str, &u32> = Ok("hello"); - /// assert_eq!(x.as_deref(), y); - /// - /// let x: Result = Err(42); - /// let y: Result<&str, &u32> = Err(&42); - /// assert_eq!(x.as_deref(), y); - /// ``` - #[stable(feature = "inner_deref", since = "1.47.0")] - pub fn as_deref(&self) -> Result<&T::Target, &E> { - self.as_ref().map(|t| t.deref()) - } -} - -impl Result { - /// Converts from `Result` (or `&mut Result`) to `Result<&mut ::Target, &mut E>`. - /// - /// Coerces the [`Ok`] variant of the original [`Result`] via [`DerefMut`](crate::ops::DerefMut) - /// and returns the new [`Result`]. - /// - /// # Examples - /// - /// ``` - /// let mut s = "HELLO".to_string(); - /// let mut x: Result = Ok("hello".to_string()); - /// let y: Result<&mut str, &mut u32> = Ok(&mut s); - /// assert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y); - /// - /// let mut i = 42; - /// let mut x: Result = Err(42); - /// let y: Result<&mut str, &mut u32> = Err(&mut i); - /// assert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y); - /// ``` - #[stable(feature = "inner_deref", since = "1.47.0")] - pub fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E> { - self.as_mut().map(|t| t.deref_mut()) - } -} - impl Result, E> { /// Transposes a `Result` of an `Option` into an `Option` of a `Result`. /// @@ -1606,6 +1682,7 @@ impl Result { } // This is a separate function to reduce the code size of the methods +#[cfg(not(feature = "panic_immediate_abort"))] #[inline(never)] #[cold] #[track_caller] @@ -1613,6 +1690,18 @@ fn unwrap_failed(msg: &str, error: &dyn fmt::Debug) -> ! { panic!("{}: {:?}", msg, error) } +// This is a separate function to avoid constructing a `dyn Debug` +// that gets immediately thrown away, since vtables don't get cleaned up +// by dead code elimination if a trait object is constructed even if it goes +// unused +#[cfg(feature = "panic_immediate_abort")] +#[inline] +#[cold] +#[track_caller] +fn unwrap_failed(_msg: &str, _error: &T) -> ! { + panic!() +} + ///////////////////////////////////////////////////////////////////////////// // Trait implementations ///////////////////////////////////////////////////////////////////////////// @@ -1885,7 +1974,8 @@ impl> FromIterator> for Result { } #[unstable(feature = "try_trait_v2", issue = "84277")] -impl ops::Try for Result { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl const ops::Try for Result { type Output = T; type Residual = Result; @@ -1904,11 +1994,20 @@ impl ops::Try for Result { } #[unstable(feature = "try_trait_v2", issue = "84277")] -impl> ops::FromResidual> for Result { +#[rustc_const_unstable(feature = "const_convert", issue = "88674")] +impl> const ops::FromResidual> + for Result +{ #[inline] + #[track_caller] fn from_residual(residual: Result) -> Self { match residual { Err(e) => Err(From::from(e)), } } } + +#[unstable(feature = "try_trait_v2_residual", issue = "91285")] +impl ops::Residual for Result { + type TryType = Result; +} diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index f722430354..0298bba8d3 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -27,35 +27,40 @@ where } } -#[inline(never)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] fn slice_start_index_len_fail(index: usize, len: usize) -> ! { panic!("range start index {} out of range for slice of length {}", index, len); } -#[inline(never)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] fn slice_end_index_len_fail(index: usize, len: usize) -> ! { panic!("range end index {} out of range for slice of length {}", index, len); } -#[inline(never)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] fn slice_index_order_fail(index: usize, end: usize) -> ! { panic!("slice index starts at {} but ends at {}", index, end); } -#[inline(never)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] fn slice_start_index_overflow_fail() -> ! { panic!("attempted to index slice from after maximum usize"); } -#[inline(never)] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[cfg_attr(feature = "panic_immediate_abort", inline)] #[cold] #[track_caller] fn slice_end_index_overflow_fail() -> ! { diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index ad1d6b8b84..176820efe3 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -221,7 +221,7 @@ impl<'a, T> IterMut<'a, T> { // the length, to also allows for the fast `ptr == end` check. // // See the `next_unchecked!` and `is_empty!` macros as well as the - // `post_inc_start` method for more informations. + // `post_inc_start` method for more information. unsafe { assume(!ptr.is_null()); @@ -481,7 +481,8 @@ where impl<'a, T: 'a, P: FnMut(&T) -> bool> SplitInclusive<'a, T, P> { #[inline] pub(super) fn new(slice: &'a [T], pred: P) -> Self { - Self { v: slice, pred, finished: false } + let finished = slice.is_empty(); + Self { v: slice, pred, finished } } } @@ -729,7 +730,8 @@ where impl<'a, T: 'a, P: FnMut(&T) -> bool> SplitInclusiveMut<'a, T, P> { #[inline] pub(super) fn new(slice: &'a mut [T], pred: P) -> Self { - Self { v: slice, pred, finished: false } + let finished = slice.is_empty(); + Self { v: slice, pred, finished } } } diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 34754cffae..0599f27401 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -10,12 +10,14 @@ use crate::cmp::Ordering::{self, Greater, Less}; use crate::marker::Copy; use crate::mem; use crate::num::NonZeroUsize; -use crate::ops::{FnMut, Range, RangeBounds}; +use crate::ops::{Bound, FnMut, OneSidedRange, Range, RangeBounds}; use crate::option::Option; use crate::option::Option::{None, Some}; use crate::ptr; use crate::result::Result; use crate::result::Result::{Err, Ok}; +#[cfg(not(miri))] // Miri does not support all SIMD intrinsics +use crate::simd::{self, Simd}; use crate::slice; #[unstable( @@ -82,6 +84,29 @@ pub use index::range; #[unstable(feature = "inherent_ascii_escape", issue = "77174")] pub use ascii::EscapeAscii; +/// Calculates the direction and split point of a one-sided range. +/// +/// This is a helper function for `take` and `take_mut` that returns +/// the direction of the split (front or back) as well as the index at +/// which to split. Returns `None` if the split index would overflow. +#[inline] +fn split_point_of(range: impl OneSidedRange) -> Option<(Direction, usize)> { + use Bound::*; + + Some(match (range.start_bound(), range.end_bound()) { + (Unbounded, Excluded(i)) => (Direction::Front, *i), + (Unbounded, Included(i)) => (Direction::Front, i.checked_add(1)?), + (Excluded(i), Unbounded) => (Direction::Back, i.checked_add(1)?), + (Included(i), Unbounded) => (Direction::Back, *i), + _ => unreachable!(), + }) +} + +enum Direction { + Front, + Back, +} + #[lang = "slice"] #[cfg(not(test))] impl [T] { @@ -357,7 +382,7 @@ impl [T] { I: SliceIndex, { // SAFETY: the caller must uphold most of the safety requirements for `get_unchecked`; - // the slice is dereferencable because `self` is a safe reference. + // the slice is dereferenceable because `self` is a safe reference. // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is. unsafe { &*index.get_unchecked(self) } } @@ -393,7 +418,7 @@ impl [T] { I: SliceIndex, { // SAFETY: the caller must uphold the safety requirements for `get_unchecked_mut`; - // the slice is dereferencable because `self` is a safe reference. + // the slice is dereferenceable because `self` is a safe reference. // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is. unsafe { &mut *index.get_unchecked_mut(self) } } @@ -560,6 +585,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_swap", issue = "83163")] #[inline] + #[track_caller] pub const fn swap(&mut self, a: usize, b: usize) { let _ = &self[a]; let _ = &self[b]; @@ -1476,6 +1502,7 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] + #[track_caller] pub fn split_at(&self, mid: usize) -> (&[T], &[T]) { assert!(mid <= self.len()); // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which @@ -1506,6 +1533,7 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] + #[track_caller] pub fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) { assert!(mid <= self.len()); // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which @@ -1645,6 +1673,7 @@ impl [T] { /// ``` #[unstable(feature = "split_array", reason = "new API", issue = "90091")] #[inline] + #[track_caller] pub fn split_array_ref(&self) -> (&[T; N], &[T]) { let (a, b) = self.split_at(N); // SAFETY: a points to [T; N]? Yes it's [T] of length N (checked by split_at) @@ -1676,12 +1705,91 @@ impl [T] { /// ``` #[unstable(feature = "split_array", reason = "new API", issue = "90091")] #[inline] + #[track_caller] pub fn split_array_mut(&mut self) -> (&mut [T; N], &mut [T]) { let (a, b) = self.split_at_mut(N); // SAFETY: a points to [T; N]? Yes it's [T] of length N (checked by split_at_mut) unsafe { (&mut *(a.as_mut_ptr() as *mut [T; N]), b) } } + /// Divides one slice into an array and a remainder slice at an index from + /// the end. + /// + /// The slice will contain all indices from `[0, len - N)` (excluding + /// the index `len - N` itself) and the array will contain all + /// indices from `[len - N, len)` (excluding the index `len` itself). + /// + /// # Panics + /// + /// Panics if `N > len`. + /// + /// # Examples + /// + /// ``` + /// #![feature(split_array)] + /// + /// let v = &[1, 2, 3, 4, 5, 6][..]; + /// + /// { + /// let (left, right) = v.rsplit_array_ref::<0>(); + /// assert_eq!(left, [1, 2, 3, 4, 5, 6]); + /// assert_eq!(right, &[]); + /// } + /// + /// { + /// let (left, right) = v.rsplit_array_ref::<2>(); + /// assert_eq!(left, [1, 2, 3, 4]); + /// assert_eq!(right, &[5, 6]); + /// } + /// + /// { + /// let (left, right) = v.rsplit_array_ref::<6>(); + /// assert_eq!(left, []); + /// assert_eq!(right, &[1, 2, 3, 4, 5, 6]); + /// } + /// ``` + #[unstable(feature = "split_array", reason = "new API", issue = "90091")] + #[inline] + pub fn rsplit_array_ref(&self) -> (&[T], &[T; N]) { + assert!(N <= self.len()); + let (a, b) = self.split_at(self.len() - N); + // SAFETY: b points to [T; N]? Yes it's [T] of length N (checked by split_at) + unsafe { (a, &*(b.as_ptr() as *const [T; N])) } + } + + /// Divides one mutable slice into an array and a remainder slice at an + /// index from the end. + /// + /// The slice will contain all indices from `[0, len - N)` (excluding + /// the index `N` itself) and the array will contain all + /// indices from `[len - N, len)` (excluding the index `len` itself). + /// + /// # Panics + /// + /// Panics if `N > len`. + /// + /// # Examples + /// + /// ``` + /// #![feature(split_array)] + /// + /// let mut v = &mut [1, 0, 3, 0, 5, 6][..]; + /// let (left, right) = v.rsplit_array_mut::<4>(); + /// assert_eq!(left, [1, 0]); + /// assert_eq!(right, &mut [3, 0, 5, 6]); + /// left[1] = 2; + /// right[1] = 4; + /// assert_eq!(v, [1, 2, 3, 4, 5, 6]); + /// ``` + #[unstable(feature = "split_array", reason = "new API", issue = "90091")] + #[inline] + pub fn rsplit_array_mut(&mut self) -> (&mut [T], &mut [T; N]) { + assert!(N <= self.len()); + let (a, b) = self.split_at_mut(self.len() - N); + // SAFETY: b points to [T; N]? Yes it's [T] of length N (checked by split_at_mut) + unsafe { (a, &mut *(b.as_mut_ptr() as *mut [T; N])) } + } + /// Returns an iterator over subslices separated by elements that match /// `pred`. The matched element is not contained in the subslices. /// @@ -3411,6 +3519,123 @@ impl [T] { } } + /// Split a slice into a prefix, a middle of aligned SIMD types, and a suffix. + /// + /// This is a safe wrapper around [`slice::align_to`], so has the same weak + /// postconditions as that method. You're only assured that + /// `self.len() == prefix.len() + middle.len() * LANES + suffix.len()`. + /// + /// Notably, all of the following are possible: + /// - `prefix.len() >= LANES`. + /// - `middle.is_empty()` despite `self.len() >= 3 * LANES`. + /// - `suffix.len() >= LANES`. + /// + /// That said, this is a safe method, so if you're only writing safe code, + /// then this can at most cause incorrect logic, not unsoundness. + /// + /// # Panics + /// + /// This will panic if the size of the SIMD type is different from + /// `LANES` times that of the scalar. + /// + /// At the time of writing, the trait restrictions on `Simd` keeps + /// that from ever happening, as only power-of-two numbers of lanes are + /// supported. It's possible that, in the future, those restrictions might + /// be lifted in a way that would make it possible to see panics from this + /// method for something like `LANES == 3`. + /// + /// # Examples + /// + /// ``` + /// #![feature(portable_simd)] + /// + /// let short = &[1, 2, 3]; + /// let (prefix, middle, suffix) = short.as_simd::<4>(); + /// assert_eq!(middle, []); // Not enough elements for anything in the middle + /// + /// // They might be split in any possible way between prefix and suffix + /// let it = prefix.iter().chain(suffix).copied(); + /// assert_eq!(it.collect::>(), vec![1, 2, 3]); + /// + /// fn basic_simd_sum(x: &[f32]) -> f32 { + /// use std::ops::Add; + /// use std::simd::f32x4; + /// let (prefix, middle, suffix) = x.as_simd(); + /// let sums = f32x4::from_array([ + /// prefix.iter().copied().sum(), + /// 0.0, + /// 0.0, + /// suffix.iter().copied().sum(), + /// ]); + /// let sums = middle.iter().copied().fold(sums, f32x4::add); + /// sums.horizontal_sum() + /// } + /// + /// let numbers: Vec = (1..101).map(|x| x as _).collect(); + /// assert_eq!(basic_simd_sum(&numbers[1..99]), 4949.0); + /// ``` + #[unstable(feature = "portable_simd", issue = "86656")] + #[cfg(not(miri))] // Miri does not support all SIMD intrinsics + pub fn as_simd(&self) -> (&[T], &[Simd], &[T]) + where + Simd: AsRef<[T; LANES]>, + T: simd::SimdElement, + simd::LaneCount: simd::SupportedLaneCount, + { + // These are expected to always match, as vector types are laid out like + // arrays per , but we + // might as well double-check since it'll optimize away anyhow. + assert_eq!(mem::size_of::>(), mem::size_of::<[T; LANES]>()); + + // SAFETY: The simd types have the same layout as arrays, just with + // potentially-higher alignment, so the de-facto transmutes are sound. + unsafe { self.align_to() } + } + + /// Split a slice into a prefix, a middle of aligned SIMD types, and a suffix. + /// + /// This is a safe wrapper around [`slice::align_to_mut`], so has the same weak + /// postconditions as that method. You're only assured that + /// `self.len() == prefix.len() + middle.len() * LANES + suffix.len()`. + /// + /// Notably, all of the following are possible: + /// - `prefix.len() >= LANES`. + /// - `middle.is_empty()` despite `self.len() >= 3 * LANES`. + /// - `suffix.len() >= LANES`. + /// + /// That said, this is a safe method, so if you're only writing safe code, + /// then this can at most cause incorrect logic, not unsoundness. + /// + /// This is the mutable version of [`slice::as_simd`]; see that for examples. + /// + /// # Panics + /// + /// This will panic if the size of the SIMD type is different from + /// `LANES` times that of the scalar. + /// + /// At the time of writing, the trait restrictions on `Simd` keeps + /// that from ever happening, as only power-of-two numbers of lanes are + /// supported. It's possible that, in the future, those restrictions might + /// be lifted in a way that would make it possible to see panics from this + /// method for something like `LANES == 3`. + #[unstable(feature = "portable_simd", issue = "86656")] + #[cfg(not(miri))] // Miri does not support all SIMD intrinsics + pub fn as_simd_mut(&mut self) -> (&mut [T], &mut [Simd], &mut [T]) + where + Simd: AsMut<[T; LANES]>, + T: simd::SimdElement, + simd::LaneCount: simd::SupportedLaneCount, + { + // These are expected to always match, as vector types are laid out like + // arrays per , but we + // might as well double-check since it'll optimize away anyhow. + assert_eq!(mem::size_of::>(), mem::size_of::<[T; LANES]>()); + + // SAFETY: The simd types have the same layout as arrays, just with + // potentially-higher alignment, so the de-facto transmutes are sound. + unsafe { self.align_to_mut() } + } + /// Checks if the elements of this slice are sorted. /// /// That is, for each element `a` and its following element `b`, `a <= b` must hold. If the @@ -3517,6 +3742,245 @@ impl [T] { { self.binary_search_by(|x| if pred(x) { Less } else { Greater }).unwrap_or_else(|i| i) } + + /// Removes the subslice corresponding to the given range + /// and returns a reference to it. + /// + /// Returns `None` and does not modify the slice if the given + /// range is out of bounds. + /// + /// Note that this method only accepts one-sided ranges such as + /// `2..` or `..6`, but not `2..6`. + /// + /// # Examples + /// + /// Taking the first three elements of a slice: + /// + /// ``` + /// #![feature(slice_take)] + /// + /// let mut slice: &[_] = &['a', 'b', 'c', 'd']; + /// let mut first_three = slice.take(..3).unwrap(); + /// + /// assert_eq!(slice, &['d']); + /// assert_eq!(first_three, &['a', 'b', 'c']); + /// ``` + /// + /// Taking the last two elements of a slice: + /// + /// ``` + /// #![feature(slice_take)] + /// + /// let mut slice: &[_] = &['a', 'b', 'c', 'd']; + /// let mut tail = slice.take(2..).unwrap(); + /// + /// assert_eq!(slice, &['a', 'b']); + /// assert_eq!(tail, &['c', 'd']); + /// ``` + /// + /// Getting `None` when `range` is out of bounds: + /// + /// ``` + /// #![feature(slice_take)] + /// + /// let mut slice: &[_] = &['a', 'b', 'c', 'd']; + /// + /// assert_eq!(None, slice.take(5..)); + /// assert_eq!(None, slice.take(..5)); + /// assert_eq!(None, slice.take(..=4)); + /// let expected: &[char] = &['a', 'b', 'c', 'd']; + /// assert_eq!(Some(expected), slice.take(..4)); + /// ``` + #[inline] + #[must_use = "method does not modify the slice if the range is out of bounds"] + #[unstable(feature = "slice_take", issue = "62280")] + pub fn take<'a, R: OneSidedRange>(self: &mut &'a Self, range: R) -> Option<&'a Self> { + let (direction, split_index) = split_point_of(range)?; + if split_index > self.len() { + return None; + } + let (front, back) = self.split_at(split_index); + match direction { + Direction::Front => { + *self = back; + Some(front) + } + Direction::Back => { + *self = front; + Some(back) + } + } + } + + /// Removes the subslice corresponding to the given range + /// and returns a mutable reference to it. + /// + /// Returns `None` and does not modify the slice if the given + /// range is out of bounds. + /// + /// Note that this method only accepts one-sided ranges such as + /// `2..` or `..6`, but not `2..6`. + /// + /// # Examples + /// + /// Taking the first three elements of a slice: + /// + /// ``` + /// #![feature(slice_take)] + /// + /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd']; + /// let mut first_three = slice.take_mut(..3).unwrap(); + /// + /// assert_eq!(slice, &mut ['d']); + /// assert_eq!(first_three, &mut ['a', 'b', 'c']); + /// ``` + /// + /// Taking the last two elements of a slice: + /// + /// ``` + /// #![feature(slice_take)] + /// + /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd']; + /// let mut tail = slice.take_mut(2..).unwrap(); + /// + /// assert_eq!(slice, &mut ['a', 'b']); + /// assert_eq!(tail, &mut ['c', 'd']); + /// ``` + /// + /// Getting `None` when `range` is out of bounds: + /// + /// ``` + /// #![feature(slice_take)] + /// + /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd']; + /// + /// assert_eq!(None, slice.take_mut(5..)); + /// assert_eq!(None, slice.take_mut(..5)); + /// assert_eq!(None, slice.take_mut(..=4)); + /// let expected: &mut [_] = &mut ['a', 'b', 'c', 'd']; + /// assert_eq!(Some(expected), slice.take_mut(..4)); + /// ``` + #[inline] + #[must_use = "method does not modify the slice if the range is out of bounds"] + #[unstable(feature = "slice_take", issue = "62280")] + pub fn take_mut<'a, R: OneSidedRange>( + self: &mut &'a mut Self, + range: R, + ) -> Option<&'a mut Self> { + let (direction, split_index) = split_point_of(range)?; + if split_index > self.len() { + return None; + } + let (front, back) = mem::take(self).split_at_mut(split_index); + match direction { + Direction::Front => { + *self = back; + Some(front) + } + Direction::Back => { + *self = front; + Some(back) + } + } + } + + /// Removes the first element of the slice and returns a reference + /// to it. + /// + /// Returns `None` if the slice is empty. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_take)] + /// + /// let mut slice: &[_] = &['a', 'b', 'c']; + /// let first = slice.take_first().unwrap(); + /// + /// assert_eq!(slice, &['b', 'c']); + /// assert_eq!(first, &'a'); + /// ``` + #[inline] + #[unstable(feature = "slice_take", issue = "62280")] + pub fn take_first<'a>(self: &mut &'a Self) -> Option<&'a T> { + let (first, rem) = self.split_first()?; + *self = rem; + Some(first) + } + + /// Removes the first element of the slice and returns a mutable + /// reference to it. + /// + /// Returns `None` if the slice is empty. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_take)] + /// + /// let mut slice: &mut [_] = &mut ['a', 'b', 'c']; + /// let first = slice.take_first_mut().unwrap(); + /// *first = 'd'; + /// + /// assert_eq!(slice, &['b', 'c']); + /// assert_eq!(first, &'d'); + /// ``` + #[inline] + #[unstable(feature = "slice_take", issue = "62280")] + pub fn take_first_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> { + let (first, rem) = mem::take(self).split_first_mut()?; + *self = rem; + Some(first) + } + + /// Removes the last element of the slice and returns a reference + /// to it. + /// + /// Returns `None` if the slice is empty. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_take)] + /// + /// let mut slice: &[_] = &['a', 'b', 'c']; + /// let last = slice.take_last().unwrap(); + /// + /// assert_eq!(slice, &['a', 'b']); + /// assert_eq!(last, &'c'); + /// ``` + #[inline] + #[unstable(feature = "slice_take", issue = "62280")] + pub fn take_last<'a>(self: &mut &'a Self) -> Option<&'a T> { + let (last, rem) = self.split_last()?; + *self = rem; + Some(last) + } + + /// Removes the last element of the slice and returns a mutable + /// reference to it. + /// + /// Returns `None` if the slice is empty. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_take)] + /// + /// let mut slice: &mut [_] = &mut ['a', 'b', 'c']; + /// let last = slice.take_last_mut().unwrap(); + /// *last = 'd'; + /// + /// assert_eq!(slice, &['a', 'b']); + /// assert_eq!(last, &'d'); + /// ``` + #[inline] + #[unstable(feature = "slice_take", issue = "62280")] + pub fn take_last_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> { + let (last, rem) = mem::take(self).split_last_mut()?; + *self = rem; + Some(last) + } } trait CloneFromSpec { diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 81bb16d540..e797283818 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -131,7 +131,7 @@ pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a m } // In debug builds checks that `data` pointer is aligned and non-null and that slice with given `len` would cover less than half the address space -#[cfg(all(not(bootstrap), debug_assertions))] +#[cfg(debug_assertions)] #[unstable(feature = "const_slice_from_raw_parts", issue = "67456")] #[rustc_const_unstable(feature = "const_slice_from_raw_parts", issue = "67456")] const fn debug_check_data_len(data: *const T, len: usize) { @@ -149,8 +149,8 @@ const fn debug_check_data_len(data: *const T, len: usize) { // it is not required for safety (the safety must be guatanteed by // the `from_raw_parts[_mut]` caller). // - // Since the checks are not required, we ignore them in CTFE as they can't - // be done there (alignment does not make much sense there). + // As per our safety precondition, we may assume that assertion above never fails. + // Therefore, noop and rt_check are observably equivalent. unsafe { crate::intrinsics::const_eval_select((data,), noop, rt_check); } @@ -161,7 +161,7 @@ const fn debug_check_data_len(data: *const T, len: usize) { ); } -#[cfg(not(all(not(bootstrap), debug_assertions)))] +#[cfg(not(debug_assertions))] const fn debug_check_data_len(_data: *const T, _len: usize) {} /// Converts a reference to T into a slice of length 1 (without copying). diff --git a/library/core/src/slice/rotate.rs b/library/core/src/slice/rotate.rs index 7528927ef3..4589c6c0f0 100644 --- a/library/core/src/slice/rotate.rs +++ b/library/core/src/slice/rotate.rs @@ -104,7 +104,7 @@ pub unsafe fn ptr_rotate(mut left: usize, mut mid: *mut T, mut right: usize) // - overflows cannot happen for `i` since the function's safety contract ask for // `mid+right-1 = x+left+right` to be valid for writing // - underflows cannot happen because `i` must be bigger or equal to `left` for - // a substraction of `left` to happen. + // a subtraction of `left` to happen. // // So `x+i` is valid for reading and writing if the caller respected the contract tmp = unsafe { x.add(i).replace(tmp) }; @@ -202,7 +202,7 @@ pub unsafe fn ptr_rotate(mut left: usize, mut mid: *mut T, mut right: usize) loop { // SAFETY: // `left >= right` so `[mid-right, mid+right)` is valid for reading and writing - // Substracting `right` from `mid` each turn is counterbalanced by the addition and + // Subtracting `right` from `mid` each turn is counterbalanced by the addition and // check after it. unsafe { ptr::swap_nonoverlapping(mid.sub(right), mid, right); @@ -218,7 +218,7 @@ pub unsafe fn ptr_rotate(mut left: usize, mut mid: *mut T, mut right: usize) loop { // SAFETY: `[mid-left, mid+left)` is valid for reading and writing because // `left < right` so `mid+left < mid+right`. - // Adding `left` to `mid` each turn is counterbalanced by the substraction and check + // Adding `left` to `mid` each turn is counterbalanced by the subtraction and check // after it. unsafe { ptr::swap_nonoverlapping(mid.sub(left), mid, left); diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs index 60b39295ca..8f58e8897b 100644 --- a/library/core/src/slice/sort.rs +++ b/library/core/src/slice/sort.rs @@ -12,7 +12,7 @@ use crate::ptr; /// When dropped, copies from `src` into `dest`. struct CopyOnDrop { - src: *mut T, + src: *const T, dest: *mut T, } @@ -33,8 +33,8 @@ where F: FnMut(&T, &T) -> bool, { let len = v.len(); - // SAFETY: The unsafe operations below involves indexing without a bound check (`get_unchecked` and `get_unchecked_mut`) - // and copying memory (`ptr::copy_nonoverlapping`). + // SAFETY: The unsafe operations below involves indexing without a bounds check (by offsetting a + // pointer) and copying memory (`ptr::copy_nonoverlapping`). // // a. Indexing: // 1. We checked the size of the array to >=2. @@ -54,18 +54,19 @@ where // Read the first element into a stack-allocated variable. If a following comparison // operation panics, `hole` will get dropped and automatically write the element back // into the slice. - let mut tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(0))); - let mut hole = CopyOnDrop { src: &mut *tmp, dest: v.get_unchecked_mut(1) }; - ptr::copy_nonoverlapping(v.get_unchecked(1), v.get_unchecked_mut(0), 1); + let tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(0))); + let v = v.as_mut_ptr(); + let mut hole = CopyOnDrop { src: &*tmp, dest: v.add(1) }; + ptr::copy_nonoverlapping(v.add(1), v.add(0), 1); for i in 2..len { - if !is_less(v.get_unchecked(i), &*tmp) { + if !is_less(&*v.add(i), &*tmp) { break; } // Move `i`-th element one place to the left, thus shifting the hole to the right. - ptr::copy_nonoverlapping(v.get_unchecked(i), v.get_unchecked_mut(i - 1), 1); - hole.dest = v.get_unchecked_mut(i); + ptr::copy_nonoverlapping(v.add(i), v.add(i - 1), 1); + hole.dest = v.add(i); } // `hole` gets dropped and thus copies `tmp` into the remaining hole in `v`. } @@ -78,8 +79,8 @@ where F: FnMut(&T, &T) -> bool, { let len = v.len(); - // SAFETY: The unsafe operations below involves indexing without a bound check (`get_unchecked` and `get_unchecked_mut`) - // and copying memory (`ptr::copy_nonoverlapping`). + // SAFETY: The unsafe operations below involves indexing without a bound check (by offsetting a + // pointer) and copying memory (`ptr::copy_nonoverlapping`). // // a. Indexing: // 1. We checked the size of the array to >= 2. @@ -99,18 +100,19 @@ where // Read the last element into a stack-allocated variable. If a following comparison // operation panics, `hole` will get dropped and automatically write the element back // into the slice. - let mut tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(len - 1))); - let mut hole = CopyOnDrop { src: &mut *tmp, dest: v.get_unchecked_mut(len - 2) }; - ptr::copy_nonoverlapping(v.get_unchecked(len - 2), v.get_unchecked_mut(len - 1), 1); + let tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(len - 1))); + let v = v.as_mut_ptr(); + let mut hole = CopyOnDrop { src: &*tmp, dest: v.add(len - 2) }; + ptr::copy_nonoverlapping(v.add(len - 2), v.add(len - 1), 1); for i in (0..len - 2).rev() { - if !is_less(&*tmp, v.get_unchecked(i)) { + if !is_less(&*tmp, &*v.add(i)) { break; } // Move `i`-th element one place to the right, thus shifting the hole to the left. - ptr::copy_nonoverlapping(v.get_unchecked(i), v.get_unchecked_mut(i + 1), 1); - hole.dest = v.get_unchecked_mut(i); + ptr::copy_nonoverlapping(v.add(i), v.add(i + 1), 1); + hole.dest = v.add(i); } // `hole` gets dropped and thus copies `tmp` into the remaining hole in `v`. } @@ -302,7 +304,7 @@ where if start_l == end_l { // Trace `block_l` elements from the left side. start_l = MaybeUninit::slice_as_mut_ptr(&mut offsets_l); - end_l = MaybeUninit::slice_as_mut_ptr(&mut offsets_l); + end_l = start_l; let mut elem = l; for i in 0..block_l { @@ -328,7 +330,7 @@ where if start_r == end_r { // Trace `block_r` elements from the right side. start_r = MaybeUninit::slice_as_mut_ptr(&mut offsets_r); - end_r = MaybeUninit::slice_as_mut_ptr(&mut offsets_r); + end_r = start_r; let mut elem = r; for i in 0..block_r { @@ -496,8 +498,8 @@ where // operation panics, the pivot will be automatically written back into the slice. // SAFETY: `pivot` is a reference to the first element of `v`, so `ptr::read` is safe. - let mut tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) }); - let _pivot_guard = CopyOnDrop { src: &mut *tmp, dest: pivot }; + let tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) }); + let _pivot_guard = CopyOnDrop { src: &*tmp, dest: pivot }; let pivot = &*tmp; // Find the first pair of out-of-order elements. @@ -549,8 +551,8 @@ where // Read the pivot into a stack-allocated variable for efficiency. If a following comparison // operation panics, the pivot will be automatically written back into the slice. // SAFETY: The pointer here is valid because it is obtained from a reference to a slice. - let mut tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) }); - let _pivot_guard = CopyOnDrop { src: &mut *tmp, dest: pivot }; + let tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) }); + let _pivot_guard = CopyOnDrop { src: &*tmp, dest: pivot }; let pivot = &*tmp; // Now partition the slice. @@ -579,7 +581,8 @@ where // Swap the found pair of out-of-order elements. r -= 1; - ptr::swap(v.get_unchecked_mut(l), v.get_unchecked_mut(r)); + let ptr = v.as_mut_ptr(); + ptr::swap(ptr.add(l), ptr.add(r)); l += 1; } } diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 4841044671..de6e6d52b3 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -748,7 +748,7 @@ generate_pattern_iterators! { } impl<'a, P: Pattern<'a>> Split<'a, P> { - /// Returns remainder of the splitted string + /// Returns remainder of the split string /// /// # Examples /// @@ -769,7 +769,7 @@ impl<'a, P: Pattern<'a>> Split<'a, P> { } impl<'a, P: Pattern<'a>> RSplit<'a, P> { - /// Returns remainder of the splitted string + /// Returns remainder of the split string /// /// # Examples /// @@ -808,7 +808,7 @@ generate_pattern_iterators! { } impl<'a, P: Pattern<'a>> SplitTerminator<'a, P> { - /// Returns remainder of the splitted string + /// Returns remainder of the split string /// /// # Examples /// @@ -829,7 +829,7 @@ impl<'a, P: Pattern<'a>> SplitTerminator<'a, P> { } impl<'a, P: Pattern<'a>> RSplitTerminator<'a, P> { - /// Returns remainder of the splitted string + /// Returns remainder of the split string /// /// # Examples /// @@ -931,7 +931,7 @@ generate_pattern_iterators! { } impl<'a, P: Pattern<'a>> SplitN<'a, P> { - /// Returns remainder of the splitted string + /// Returns remainder of the split string /// /// # Examples /// @@ -952,7 +952,7 @@ impl<'a, P: Pattern<'a>> SplitN<'a, P> { } impl<'a, P: Pattern<'a>> RSplitN<'a, P> { - /// Returns remainder of the splitted string + /// Returns remainder of the split string /// /// # Examples /// @@ -1236,7 +1236,7 @@ impl<'a> DoubleEndedIterator for SplitWhitespace<'a> { impl FusedIterator for SplitWhitespace<'_> {} impl<'a> SplitWhitespace<'a> { - /// Returns remainder of the splitted string + /// Returns remainder of the split string /// /// # Examples /// @@ -1292,7 +1292,7 @@ impl<'a> DoubleEndedIterator for SplitAsciiWhitespace<'a> { impl FusedIterator for SplitAsciiWhitespace<'_> {} impl<'a> SplitAsciiWhitespace<'a> { - /// Returns remainder of the splitted string + /// Returns remainder of the split string /// /// # Examples /// @@ -1360,7 +1360,7 @@ impl<'a, P: Pattern<'a, Searcher: ReverseSearcher<'a>>> DoubleEndedIterator impl<'a, P: Pattern<'a>> FusedIterator for SplitInclusive<'a, P> {} impl<'a, P: Pattern<'a>> SplitInclusive<'a, P> { - /// Returns remainder of the splitted string + /// Returns remainder of the split string /// /// # Examples /// diff --git a/library/core/src/str/lossy.rs b/library/core/src/str/lossy.rs index 6c21a5e802..6ec1c93908 100644 --- a/library/core/src/str/lossy.rs +++ b/library/core/src/str/lossy.rs @@ -12,11 +12,6 @@ pub struct Utf8Lossy { } impl Utf8Lossy { - #[must_use] - pub fn from_str(s: &str) -> &Utf8Lossy { - Utf8Lossy::from_bytes(s.as_bytes()) - } - #[must_use] pub fn from_bytes(bytes: &[u8]) -> &Utf8Lossy { // SAFETY: Both use the same memory layout, and UTF-8 correctness isn't required. @@ -61,36 +56,26 @@ impl<'a> Iterator for Utf8LossyChunksIter<'a> { } let mut i = 0; + let mut valid_up_to = 0; while i < self.source.len() { - let i_ = i; - - // SAFETY: `i` starts at `0`, is less than `self.source.len()`, and - // only increases, so `0 <= i < self.source.len()`. + // SAFETY: `i < self.source.len()` per previous line. + // For some reason the following are both significantly slower: + // while let Some(&byte) = self.source.get(i) { + // while let Some(byte) = self.source.get(i).copied() { let byte = unsafe { *self.source.get_unchecked(i) }; i += 1; if byte < 128 { + // This could be a `1 => ...` case in the match below, but for + // the common case of all-ASCII inputs, we bypass loading the + // sizeable UTF8_CHAR_WIDTH table into cache. } else { let w = utf8_char_width(byte); - macro_rules! error { - () => {{ - // SAFETY: We have checked up to `i` that source is valid UTF-8. - unsafe { - let r = Utf8LossyChunk { - valid: from_utf8_unchecked(&self.source[0..i_]), - broken: &self.source[i_..i], - }; - self.source = &self.source[i..]; - return Some(r); - } - }}; - } - match w { 2 => { if safe_get(self.source, i) & 192 != TAG_CONT_U8 { - error!(); + break; } i += 1; } @@ -100,13 +85,11 @@ impl<'a> Iterator for Utf8LossyChunksIter<'a> { (0xE1..=0xEC, 0x80..=0xBF) => (), (0xED, 0x80..=0x9F) => (), (0xEE..=0xEF, 0x80..=0xBF) => (), - _ => { - error!(); - } + _ => break, } i += 1; if safe_get(self.source, i) & 192 != TAG_CONT_U8 { - error!(); + break; } i += 1; } @@ -115,34 +98,45 @@ impl<'a> Iterator for Utf8LossyChunksIter<'a> { (0xF0, 0x90..=0xBF) => (), (0xF1..=0xF3, 0x80..=0xBF) => (), (0xF4, 0x80..=0x8F) => (), - _ => { - error!(); - } + _ => break, } i += 1; if safe_get(self.source, i) & 192 != TAG_CONT_U8 { - error!(); + break; } i += 1; if safe_get(self.source, i) & 192 != TAG_CONT_U8 { - error!(); + break; } i += 1; } - _ => { - error!(); - } + _ => break, } } + + valid_up_to = i; } - let r = Utf8LossyChunk { - // SAFETY: We have checked that the entire source is valid UTF-8. - valid: unsafe { from_utf8_unchecked(self.source) }, - broken: &[], - }; - self.source = &[]; - Some(r) + // SAFETY: `i <= self.source.len()` because it is only ever incremented + // via `i += 1` and in between every single one of those increments, `i` + // is compared against `self.source.len()`. That happens either + // literally by `i < self.source.len()` in the while-loop's condition, + // or indirectly by `safe_get(self.source, i) & 192 != TAG_CONT_U8`. The + // loop is terminated as soon as the latest `i += 1` has made `i` no + // longer less than `self.source.len()`, which means it'll be at most + // equal to `self.source.len()`. + let (inspected, remaining) = unsafe { self.source.split_at_unchecked(i) }; + self.source = remaining; + + // SAFETY: `valid_up_to <= i` because it is only ever assigned via + // `valid_up_to = i` and `i` only increases. + let (valid, broken) = unsafe { inspected.split_at_unchecked(valid_up_to) }; + + Some(Utf8LossyChunk { + // SAFETY: All bytes up to `valid_up_to` are valid UTF-8. + valid: unsafe { from_utf8_unchecked(valid) }, + broken, + }) } } diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index cd5ed35be7..1d4600fa4a 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -416,7 +416,7 @@ impl str { #[inline] pub unsafe fn get_unchecked>(&self, i: I) -> &I::Output { // SAFETY: the caller must uphold the safety contract for `get_unchecked`; - // the slice is dereferencable because `self` is a safe reference. + // the slice is dereferenceable because `self` is a safe reference. // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is. unsafe { &*i.get_unchecked(self) } } @@ -451,7 +451,7 @@ impl str { #[inline] pub unsafe fn get_unchecked_mut>(&mut self, i: I) -> &mut I::Output { // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`; - // the slice is dereferencable because `self` is a safe reference. + // the slice is dereferenceable because `self` is a safe reference. // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is. unsafe { &mut *i.get_unchecked_mut(self) } } @@ -504,7 +504,7 @@ impl str { #[inline] pub unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str { // SAFETY: the caller must uphold the safety contract for `get_unchecked`; - // the slice is dereferencable because `self` is a safe reference. + // the slice is dereferenceable because `self` is a safe reference. // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is. unsafe { &*(begin..end).get_unchecked(self) } } @@ -537,7 +537,7 @@ impl str { #[inline] pub unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut str { // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`; - // the slice is dereferencable because `self` is a safe reference. + // the slice is dereferenceable because `self` is a safe reference. // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is. unsafe { &mut *(begin..end).get_unchecked_mut(self) } } diff --git a/library/core/src/stream/mod.rs b/library/core/src/stream/mod.rs index 58dc8e1e5e..b59a46d5f3 100644 --- a/library/core/src/stream/mod.rs +++ b/library/core/src/stream/mod.rs @@ -114,9 +114,9 @@ //! # Laziness //! //! Streams are *lazy*. This means that just creating a stream doesn't _do_ a -//! whole lot. Nothing really happens until you call `next`. This is sometimes a -//! source of confusion when creating a stream solely for its side effects. The -//! compiler will warn us about this kind of behavior: +//! whole lot. Nothing really happens until you call `poll_next`. This is +//! sometimes a source of confusion when creating a stream solely for its side +//! effects. The compiler will warn us about this kind of behavior: //! //! ```text //! warning: unused result that must be used: streams do nothing unless polled diff --git a/library/core/src/stream/stream/mod.rs b/library/core/src/stream/stream.rs similarity index 98% rename from library/core/src/stream/stream/mod.rs rename to library/core/src/stream/stream.rs index d102619b8e..2cfddf9ad0 100644 --- a/library/core/src/stream/stream/mod.rs +++ b/library/core/src/stream/stream.rs @@ -95,13 +95,13 @@ impl Stream for &mut S { #[unstable(feature = "async_stream", issue = "79024")] impl

Stream for Pin

where - P: DerefMut + Unpin, + P: DerefMut, P::Target: Stream, { type Item = ::Item; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - self.get_mut().as_mut().poll_next(cx) + ::poll_next(self.as_deref_mut(), cx) } fn size_hint(&self) -> (usize, Option) { diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 5efa04f7e5..746d1cacfd 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -182,7 +182,6 @@ impl Duration { #[inline] #[must_use] #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_panic))] pub const fn new(secs: u64, nanos: u32) -> Duration { let secs = match secs.checked_add((nanos / NANOS_PER_SEC) as u64) { Some(secs) => secs, @@ -482,7 +481,6 @@ impl Duration { without modifying the original"] #[inline] #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_panic))] pub const fn checked_add(self, rhs: Duration) -> Option { if let Some(mut secs) = self.secs.checked_add(rhs.secs) { let mut nanos = self.nanos + rhs.nanos; @@ -543,7 +541,6 @@ impl Duration { without modifying the original"] #[inline] #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_panic))] pub const fn checked_sub(self, rhs: Duration) -> Option { if let Some(mut secs) = self.secs.checked_sub(rhs.secs) { let nanos = if self.nanos >= rhs.nanos { @@ -602,7 +599,6 @@ impl Duration { without modifying the original"] #[inline] #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_panic))] pub const fn checked_mul(self, rhs: u32) -> Option { // Multiply nanoseconds as u64, because it cannot overflow that way. let total_nanos = self.nanos as u64 * rhs as u64; @@ -660,7 +656,6 @@ impl Duration { without modifying the original"] #[inline] #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] - #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_panic))] pub const fn checked_div(self, rhs: u32) -> Option { if rhs != 0 { let secs = self.secs / (rhs as u64); diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs index 7dc071b742..a778779c0f 100644 --- a/library/core/tests/array.rs +++ b/library/core/tests/array.rs @@ -28,11 +28,22 @@ fn array_try_from() { ($($N:expr)+) => { $({ type Array = [u8; $N]; - let array: Array = [0; $N]; + let mut array: Array = [0; $N]; let slice: &[u8] = &array[..]; let result = <&Array>::try_from(slice); assert_eq!(&array, result.unwrap()); + + let result = ::try_from(slice); + assert_eq!(&array, &result.unwrap()); + + let mut_slice: &mut [u8] = &mut array[..]; + let result = <&mut Array>::try_from(mut_slice); + assert_eq!(&[0; $N], result.unwrap()); + + let mut_slice: &mut [u8] = &mut array[..]; + let result = ::try_from(mut_slice); + assert_eq!(&array, &result.unwrap()); })+ } } @@ -248,7 +259,7 @@ fn iterator_drops() { // This test does not work on targets without panic=unwind support. // To work around this problem, test is marked is should_panic, so it will // be automagically skipped on unsuitable targets, such as -// wasm32-unknown-unkown. +// wasm32-unknown-unknown. // // It means that we use panic for indicating success. #[test] @@ -377,7 +388,7 @@ fn array_try_from_fn() { let array = core::array::try_from_fn(|i| Ok::<_, SomeError>(i)); assert_eq!(array, Ok([0, 1, 2, 3, 4])); - let another_array = core::array::try_from_fn::(|_| Err(SomeError::Foo)); + let another_array = core::array::try_from_fn::<_, Result<(), _>, 2>(|_| Err(SomeError::Foo)); assert_eq!(another_array, Err(SomeError::Foo)); } @@ -459,6 +470,23 @@ fn array_split_array_mut() { } } +#[test] +fn array_rsplit_array_mut() { + let mut v = [1, 2, 3, 4, 5, 6]; + + { + let (left, right) = v.rsplit_array_mut::<0>(); + assert_eq!(left, &mut [1, 2, 3, 4, 5, 6]); + assert_eq!(right, &mut []); + } + + { + let (left, right) = v.rsplit_array_mut::<6>(); + assert_eq!(left, &mut []); + assert_eq!(right, &mut [1, 2, 3, 4, 5, 6]); + } +} + #[should_panic] #[test] fn array_split_array_ref_out_of_bounds() { @@ -474,3 +502,169 @@ fn array_split_array_mut_out_of_bounds() { v.split_array_mut::<7>(); } + +#[should_panic] +#[test] +fn array_rsplit_array_ref_out_of_bounds() { + let v = [1, 2, 3, 4, 5, 6]; + + v.rsplit_array_ref::<7>(); +} + +#[should_panic] +#[test] +fn array_rsplit_array_mut_out_of_bounds() { + let mut v = [1, 2, 3, 4, 5, 6]; + + v.rsplit_array_mut::<7>(); +} + +#[test] +fn array_intoiter_advance_by() { + use std::cell::Cell; + struct DropCounter<'a>(usize, &'a Cell); + impl Drop for DropCounter<'_> { + fn drop(&mut self) { + let x = self.1.get(); + self.1.set(x + 1); + } + } + + let counter = Cell::new(0); + let a: [_; 100] = std::array::from_fn(|i| DropCounter(i, &counter)); + let mut it = IntoIterator::into_iter(a); + + let r = it.advance_by(1); + assert_eq!(r, Ok(())); + assert_eq!(it.len(), 99); + assert_eq!(counter.get(), 1); + + let r = it.advance_by(0); + assert_eq!(r, Ok(())); + assert_eq!(it.len(), 99); + assert_eq!(counter.get(), 1); + + let r = it.advance_by(11); + assert_eq!(r, Ok(())); + assert_eq!(it.len(), 88); + assert_eq!(counter.get(), 12); + + let x = it.next(); + assert_eq!(x.as_ref().map(|x| x.0), Some(12)); + assert_eq!(it.len(), 87); + assert_eq!(counter.get(), 12); + drop(x); + assert_eq!(counter.get(), 13); + + let r = it.advance_by(123456); + assert_eq!(r, Err(87)); + assert_eq!(it.len(), 0); + assert_eq!(counter.get(), 100); + + let r = it.advance_by(0); + assert_eq!(r, Ok(())); + assert_eq!(it.len(), 0); + assert_eq!(counter.get(), 100); + + let r = it.advance_by(10); + assert_eq!(r, Err(0)); + assert_eq!(it.len(), 0); + assert_eq!(counter.get(), 100); +} + +#[test] +fn array_intoiter_advance_back_by() { + use std::cell::Cell; + struct DropCounter<'a>(usize, &'a Cell); + impl Drop for DropCounter<'_> { + fn drop(&mut self) { + let x = self.1.get(); + self.1.set(x + 1); + } + } + + let counter = Cell::new(0); + let a: [_; 100] = std::array::from_fn(|i| DropCounter(i, &counter)); + let mut it = IntoIterator::into_iter(a); + + let r = it.advance_back_by(1); + assert_eq!(r, Ok(())); + assert_eq!(it.len(), 99); + assert_eq!(counter.get(), 1); + + let r = it.advance_back_by(0); + assert_eq!(r, Ok(())); + assert_eq!(it.len(), 99); + assert_eq!(counter.get(), 1); + + let r = it.advance_back_by(11); + assert_eq!(r, Ok(())); + assert_eq!(it.len(), 88); + assert_eq!(counter.get(), 12); + + let x = it.next_back(); + assert_eq!(x.as_ref().map(|x| x.0), Some(87)); + assert_eq!(it.len(), 87); + assert_eq!(counter.get(), 12); + drop(x); + assert_eq!(counter.get(), 13); + + let r = it.advance_back_by(123456); + assert_eq!(r, Err(87)); + assert_eq!(it.len(), 0); + assert_eq!(counter.get(), 100); + + let r = it.advance_back_by(0); + assert_eq!(r, Ok(())); + assert_eq!(it.len(), 0); + assert_eq!(counter.get(), 100); + + let r = it.advance_back_by(10); + assert_eq!(r, Err(0)); + assert_eq!(it.len(), 0); + assert_eq!(counter.get(), 100); +} + +#[test] +fn array_mixed_equality_integers() { + let array3: [i32; 3] = [1, 2, 3]; + let array3b: [i32; 3] = [3, 2, 1]; + let array4: [i32; 4] = [1, 2, 3, 4]; + + let slice3: &[i32] = &{ array3 }; + let slice3b: &[i32] = &{ array3b }; + let slice4: &[i32] = &{ array4 }; + assert!(array3 == slice3); + assert!(array3 != slice3b); + assert!(array3 != slice4); + assert!(slice3 == array3); + assert!(slice3b != array3); + assert!(slice4 != array3); + + let mut3: &mut [i32] = &mut { array3 }; + let mut3b: &mut [i32] = &mut { array3b }; + let mut4: &mut [i32] = &mut { array4 }; + assert!(array3 == mut3); + assert!(array3 != mut3b); + assert!(array3 != mut4); + assert!(mut3 == array3); + assert!(mut3b != array3); + assert!(mut4 != array3); +} + +#[test] +fn array_mixed_equality_nans() { + let array3: [f32; 3] = [1.0, std::f32::NAN, 3.0]; + + let slice3: &[f32] = &{ array3 }; + assert!(!(array3 == slice3)); + assert!(array3 != slice3); + assert!(!(slice3 == array3)); + assert!(slice3 != array3); + + let mut3: &mut [f32] = &mut { array3 }; + assert!(!(array3 == mut3)); + assert!(array3 != mut3); + assert!(!(mut3 == array3)); + assert!(mut3 != array3); +} diff --git a/library/core/tests/bool.rs b/library/core/tests/bool.rs index e40f0482ae..4819ce911d 100644 --- a/library/core/tests/bool.rs +++ b/library/core/tests/bool.rs @@ -88,4 +88,18 @@ fn test_bool_to_option() { assert_eq!(true.then_some(0), Some(0)); assert_eq!(false.then(|| 0), None); assert_eq!(true.then(|| 0), Some(0)); + + const fn zero() -> i32 { + 0 + } + + const A: Option = false.then_some(0); + const B: Option = true.then_some(0); + const C: Option = false.then(zero); + const D: Option = true.then(zero); + + assert_eq!(A, None); + assert_eq!(B, Some(0)); + assert_eq!(C, None); + assert_eq!(D, Some(0)); } diff --git a/library/core/tests/char.rs b/library/core/tests/char.rs index 6e434cf1a8..2b857a6591 100644 --- a/library/core/tests/char.rs +++ b/library/core/tests/char.rs @@ -103,6 +103,9 @@ fn test_to_lowercase() { let iter: String = c.to_lowercase().collect(); let disp: String = c.to_lowercase().to_string(); assert_eq!(iter, disp); + let iter_rev: String = c.to_lowercase().rev().collect(); + let disp_rev: String = disp.chars().rev().collect(); + assert_eq!(iter_rev, disp_rev); iter } assert_eq!(lower('A'), "a"); @@ -130,6 +133,9 @@ fn test_to_uppercase() { let iter: String = c.to_uppercase().collect(); let disp: String = c.to_uppercase().to_string(); assert_eq!(iter, disp); + let iter_rev: String = c.to_uppercase().rev().collect(); + let disp_rev: String = disp.chars().rev().collect(); + assert_eq!(iter_rev, disp_rev); iter } assert_eq!(upper('a'), "A"); diff --git a/library/core/tests/cmp.rs b/library/core/tests/cmp.rs index 11cf7add07..58fee19ca7 100644 --- a/library/core/tests/cmp.rs +++ b/library/core/tests/cmp.rs @@ -203,3 +203,36 @@ fn cmp_default() { assert!(Fool(false) != Fool(false)); assert_eq!(Fool(false), Fool(true)); } + +#[cfg(not(bootstrap))] +mod const_cmp { + use super::*; + + struct S(i32); + + impl const PartialEq for S { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } + } + + impl const PartialOrd for S { + fn partial_cmp(&self, other: &Self) -> Option { + let ret = match (self.0, other.0) { + (a, b) if a > b => Ordering::Greater, + (a, b) if a < b => Ordering::Less, + _ => Ordering::Equal, + }; + + Some(ret) + } + } + + const _: () = assert!(S(1) == S(1)); + const _: () = assert!(S(0) != S(1)); + + const _: () = assert!(S(1) <= S(1)); + const _: () = assert!(S(1) >= S(1)); + const _: () = assert!(S(0) < S(1)); + const _: () = assert!(S(1) > S(0)); +} diff --git a/library/core/tests/convert.rs b/library/core/tests/convert.rs new file mode 100644 index 0000000000..f1048f4cf0 --- /dev/null +++ b/library/core/tests/convert.rs @@ -0,0 +1,16 @@ +#[test] +fn convert() { + const fn from(x: i32) -> i32 { + i32::from(x) + } + + const FOO: i32 = from(42); + assert_eq!(FOO, 42); + + const fn into(x: Vec) -> Vec { + x.into() + } + + const BAR: Vec = into(Vec::new()); + assert_eq!(BAR, Vec::::new()); +} diff --git a/library/core/tests/future.rs b/library/core/tests/future.rs new file mode 100644 index 0000000000..0ed8c52c21 --- /dev/null +++ b/library/core/tests/future.rs @@ -0,0 +1,120 @@ +use std::future::{join, Future}; +use std::pin::Pin; +use std::sync::Arc; +use std::task::{Context, Poll, Wake}; +use std::thread; + +struct PollN { + val: usize, + polled: usize, + num: usize, +} + +impl Future for PollN { + type Output = usize; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + self.polled += 1; + + if self.polled == self.num { + return Poll::Ready(self.val); + } + + cx.waker().wake_by_ref(); + Poll::Pending + } +} + +fn poll_n(val: usize, num: usize) -> PollN { + PollN { val, num, polled: 0 } +} + +#[test] +#[cfg_attr(miri, ignore)] // self-referential generators do not work with Miri's aliasing checks +fn test_join() { + block_on(async move { + let x = join!(async { 0 }).await; + assert_eq!(x, 0); + + let x = join!(async { 0 }, async { 1 }).await; + assert_eq!(x, (0, 1)); + + let x = join!(async { 0 }, async { 1 }, async { 2 }).await; + assert_eq!(x, (0, 1, 2)); + + let x = join!( + poll_n(0, 1), + poll_n(1, 5), + poll_n(2, 2), + poll_n(3, 1), + poll_n(4, 2), + poll_n(5, 3), + poll_n(6, 4), + poll_n(7, 1) + ) + .await; + assert_eq!(x, (0, 1, 2, 3, 4, 5, 6, 7)); + + let y = String::new(); + let x = join!(async { + println!("{}", &y); + 1 + }) + .await; + assert_eq!(x, 1); + }); +} + +/// Tests that `join!(…)` behaves "like a function": evaluating its arguments +/// before applying any of its own logic. +/// +/// _e.g._, `join!(async_fn(&borrowed), …)` does not consume `borrowed`; +/// and `join!(opt_fut?, …)` does let that `?` refer to the callsite scope. +mod test_join_function_like_value_arg_semantics { + use super::*; + + async fn async_fn(_: impl Sized) {} + + // no need to _run_ this test, just to compile it. + fn _join_does_not_unnecessarily_move_mentioned_bindings() { + let not_copy = vec![()]; + let _ = join!(async_fn(¬_copy)); // should not move `not_copy` + let _ = ¬_copy; // OK + } + + #[test] + fn join_lets_control_flow_effects_such_as_try_flow_through() { + let maybe_fut = None; + if false { + *&mut { maybe_fut } = Some(async {}); + loop {} + } + assert!(Option::is_none(&try { join!(maybe_fut?, async { unreachable!() }) })); + } + + #[test] + fn join_is_able_to_handle_temporaries() { + let _ = join!(async_fn(&String::from("temporary"))); + let () = block_on(join!(async_fn(&String::from("temporary")))); + } +} + +fn block_on(fut: impl Future) { + struct Waker; + impl Wake for Waker { + fn wake(self: Arc) { + thread::current().unpark() + } + } + + let waker = Arc::new(Waker).into(); + let mut cx = Context::from_waker(&waker); + let mut fut = Box::pin(fut); + + loop { + match fut.as_mut().poll(&mut cx) { + Poll::Ready(_) => break, + Poll::Pending => thread::park(), + } + } +} diff --git a/library/core/tests/intrinsics.rs b/library/core/tests/intrinsics.rs index de163a60c9..7a2e4e2906 100644 --- a/library/core/tests/intrinsics.rs +++ b/library/core/tests/intrinsics.rs @@ -35,3 +35,48 @@ fn test_assume_can_be_in_const_contexts() { let rs = unsafe { foo(42, 97) }; assert_eq!(rs, 0); } + +#[test] +#[cfg(not(bootstrap))] +const fn test_write_bytes_in_const_contexts() { + use core::intrinsics::write_bytes; + + const TEST: [u32; 3] = { + let mut arr = [1u32, 2, 3]; + unsafe { + write_bytes(arr.as_mut_ptr(), 0, 2); + } + arr + }; + + assert!(TEST[0] == 0); + assert!(TEST[1] == 0); + assert!(TEST[2] == 3); + + const TEST2: [u32; 3] = { + let mut arr = [1u32, 2, 3]; + unsafe { + write_bytes(arr.as_mut_ptr(), 1, 2); + } + arr + }; + + assert!(TEST2[0] == 16843009); + assert!(TEST2[1] == 16843009); + assert!(TEST2[2] == 3); +} + +#[test] +fn test_hints_in_const_contexts() { + use core::intrinsics::{likely, unlikely}; + + // In const contexts, they just return their argument. + const { + assert!(true == likely(true)); + assert!(false == likely(false)); + assert!(true == unlikely(true)); + assert!(false == unlikely(false)); + assert!(42u32 == core::intrinsics::black_box(42u32)); + assert!(42u32 == core::hint::black_box(42u32)); + } +} diff --git a/library/core/tests/iter/adapters/chain.rs b/library/core/tests/iter/adapters/chain.rs index 4cd79687b5..f419f9cec1 100644 --- a/library/core/tests/iter/adapters/chain.rs +++ b/library/core/tests/iter/adapters/chain.rs @@ -34,6 +34,7 @@ fn test_iterator_chain_advance_by() { iter.advance_by(i).unwrap(); assert_eq!(iter.next(), Some(&xs[i])); assert_eq!(iter.advance_by(100), Err(len - i - 1)); + iter.advance_by(0).unwrap(); } for i in 0..ys.len() { @@ -41,14 +42,17 @@ fn test_iterator_chain_advance_by() { iter.advance_by(xs.len() + i).unwrap(); assert_eq!(iter.next(), Some(&ys[i])); assert_eq!(iter.advance_by(100), Err(ys.len() - i - 1)); + iter.advance_by(0).unwrap(); } let mut iter = xs.iter().chain(ys); iter.advance_by(len).unwrap(); assert_eq!(iter.next(), None); + iter.advance_by(0).unwrap(); let mut iter = xs.iter().chain(ys); assert_eq!(iter.advance_by(len + 1), Err(len)); + iter.advance_by(0).unwrap(); } test_chain(&[], &[]); @@ -67,6 +71,7 @@ fn test_iterator_chain_advance_back_by() { iter.advance_back_by(i).unwrap(); assert_eq!(iter.next_back(), Some(&ys[ys.len() - i - 1])); assert_eq!(iter.advance_back_by(100), Err(len - i - 1)); + iter.advance_back_by(0).unwrap(); } for i in 0..xs.len() { @@ -74,14 +79,17 @@ fn test_iterator_chain_advance_back_by() { iter.advance_back_by(ys.len() + i).unwrap(); assert_eq!(iter.next_back(), Some(&xs[xs.len() - i - 1])); assert_eq!(iter.advance_back_by(100), Err(xs.len() - i - 1)); + iter.advance_back_by(0).unwrap(); } let mut iter = xs.iter().chain(ys); iter.advance_back_by(len).unwrap(); assert_eq!(iter.next_back(), None); + iter.advance_back_by(0).unwrap(); let mut iter = xs.iter().chain(ys); assert_eq!(iter.advance_back_by(len + 1), Err(len)); + iter.advance_back_by(0).unwrap(); } test_chain(&[], &[]); diff --git a/library/core/tests/iter/adapters/flatten.rs b/library/core/tests/iter/adapters/flatten.rs index 4ae50a2f06..f8ab8c9d44 100644 --- a/library/core/tests/iter/adapters/flatten.rs +++ b/library/core/tests/iter/adapters/flatten.rs @@ -1,5 +1,4 @@ use super::*; -use core::array; use core::iter::*; #[test] @@ -61,6 +60,7 @@ fn test_flatten_try_folds() { #[test] fn test_flatten_advance_by() { let mut it = once(0..10).chain(once(10..30)).chain(once(30..40)).flatten(); + it.advance_by(5).unwrap(); assert_eq!(it.next(), Some(5)); it.advance_by(9).unwrap(); @@ -72,6 +72,8 @@ fn test_flatten_advance_by() { assert_eq!(it.advance_by(usize::MAX), Err(9)); assert_eq!(it.advance_back_by(usize::MAX), Err(0)); + it.advance_by(0).unwrap(); + it.advance_back_by(0).unwrap(); assert_eq!(it.size_hint(), (0, Some(0))); } @@ -131,7 +133,7 @@ fn test_double_ended_flatten() { #[test] fn test_trusted_len_flatten() { fn assert_trusted_len(_: &T) {} - let mut iter = array::IntoIter::new([[0; 3]; 4]).flatten(); + let mut iter = IntoIterator::into_iter([[0; 3]; 4]).flatten(); assert_trusted_len(&iter); assert_eq!(iter.size_hint(), (12, Some(12))); @@ -140,21 +142,21 @@ fn test_trusted_len_flatten() { iter.next_back(); assert_eq!(iter.size_hint(), (10, Some(10))); - let iter = array::IntoIter::new([[(); usize::MAX]; 1]).flatten(); + let iter = IntoIterator::into_iter([[(); usize::MAX]; 1]).flatten(); assert_eq!(iter.size_hint(), (usize::MAX, Some(usize::MAX))); - let iter = array::IntoIter::new([[(); usize::MAX]; 2]).flatten(); + let iter = IntoIterator::into_iter([[(); usize::MAX]; 2]).flatten(); assert_eq!(iter.size_hint(), (usize::MAX, None)); let mut a = [(); 10]; let mut b = [(); 10]; - let iter = array::IntoIter::new([&mut a, &mut b]).flatten(); + let iter = IntoIterator::into_iter([&mut a, &mut b]).flatten(); assert_trusted_len(&iter); assert_eq!(iter.size_hint(), (20, Some(20))); core::mem::drop(iter); - let iter = array::IntoIter::new([&a, &b]).flatten(); + let iter = IntoIterator::into_iter([&a, &b]).flatten(); assert_trusted_len(&iter); assert_eq!(iter.size_hint(), (20, Some(20))); diff --git a/library/core/tests/iter/adapters/skip.rs b/library/core/tests/iter/adapters/skip.rs index cf60057a16..0c464bdd03 100644 --- a/library/core/tests/iter/adapters/skip.rs +++ b/library/core/tests/iter/adapters/skip.rs @@ -69,6 +69,17 @@ fn test_iterator_skip_nth() { assert_eq!(it.nth(0), None); } +#[test] +fn test_skip_advance_by() { + assert_eq!((0..0).skip(10).advance_by(0), Ok(())); + assert_eq!((0..0).skip(10).advance_by(1), Err(0)); + assert_eq!((0u128..(usize::MAX as u128) + 1).skip(usize::MAX).advance_by(usize::MAX), Err(1)); + assert_eq!((0u128..u128::MAX).skip(usize::MAX).advance_by(1), Ok(())); + + assert_eq!((0..2).skip(1).advance_back_by(10), Err(1)); + assert_eq!((0..0).skip(1).advance_back_by(0), Ok(())); +} + #[test] fn test_iterator_skip_count() { let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30]; diff --git a/library/core/tests/iter/adapters/take.rs b/library/core/tests/iter/adapters/take.rs index 89f9cb1e2e..bfb659f0a8 100644 --- a/library/core/tests/iter/adapters/take.rs +++ b/library/core/tests/iter/adapters/take.rs @@ -73,6 +73,28 @@ fn test_iterator_take_nth_back() { assert_eq!(it.nth_back(1), None); } +#[test] +fn test_take_advance_by() { + let mut take = (0..10).take(3); + assert_eq!(take.advance_by(2), Ok(())); + assert_eq!(take.next(), Some(2)); + assert_eq!(take.advance_by(1), Err(0)); + + assert_eq!((0..0).take(10).advance_by(0), Ok(())); + assert_eq!((0..0).take(10).advance_by(1), Err(0)); + assert_eq!((0..10).take(4).advance_by(5), Err(4)); + + let mut take = (0..10).take(3); + assert_eq!(take.advance_back_by(2), Ok(())); + assert_eq!(take.next(), Some(0)); + assert_eq!(take.advance_back_by(1), Err(0)); + + assert_eq!((0..2).take(1).advance_back_by(10), Err(1)); + assert_eq!((0..0).take(1).advance_back_by(1), Err(0)); + assert_eq!((0..0).take(1).advance_back_by(0), Ok(())); + assert_eq!((0..usize::MAX).take(100).advance_back_by(usize::MAX), Err(100)); +} + #[test] fn test_iterator_take_short() { let xs = [0, 1, 2, 3]; diff --git a/library/core/tests/iter/range.rs b/library/core/tests/iter/range.rs index 6b4cf33efe..84498a8eae 100644 --- a/library/core/tests/iter/range.rs +++ b/library/core/tests/iter/range.rs @@ -300,6 +300,9 @@ fn test_range_advance_by() { assert_eq!(r.advance_by(usize::MAX), Err(usize::MAX - 2)); + r.advance_by(0).unwrap(); + r.advance_back_by(0).unwrap(); + let mut r = 0u128..u128::MAX; r.advance_by(usize::MAX).unwrap(); diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs index 422e389e38..d38bca1e3b 100644 --- a/library/core/tests/iter/traits/iterator.rs +++ b/library/core/tests/iter/traits/iterator.rs @@ -454,6 +454,34 @@ fn test_find_map() { } } +#[test] +fn test_try_reduce() { + let v: Vec = vec![1, 2, 3, 4, 5]; + let sum = v.into_iter().try_reduce(|x, y| x.checked_add(y)); + assert_eq!(sum, Some(Some(15))); + + let v: Vec = vec![1, 2, 3, 4, 5, usize::MAX]; + let sum = v.into_iter().try_reduce(|x, y| x.checked_add(y)); + assert_eq!(sum, None); + + let v: Vec = Vec::new(); + let sum = v.into_iter().try_reduce(|x, y| x.checked_add(y)); + assert_eq!(sum, Some(None)); + + let v = vec!["1", "2", "3", "4", "5"]; + let max = v.into_iter().try_reduce(|x, y| { + if x.parse::().ok()? > y.parse::().ok()? { Some(x) } else { Some(y) } + }); + assert_eq!(max, Some(Some("5"))); + + let v = vec!["1", "2", "3", "4", "5"]; + let max: Result, ::Err> = + v.into_iter().try_reduce(|x, y| { + if x.parse::()? > y.parse::()? { Ok(x) } else { Ok(y) } + }); + assert_eq!(max, Ok(Some("5"))); +} + #[test] fn test_iterator_len() { let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 4d37ed1942..ec700346ac 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -2,20 +2,25 @@ #![feature(array_chunks)] #![feature(array_methods)] #![feature(array_windows)] +#![feature(bench_black_box)] #![feature(bool_to_option)] #![feature(box_syntax)] #![feature(cell_update)] #![feature(cfg_panic)] #![feature(cfg_target_has_atomic)] #![feature(const_assume)] +#![feature(const_black_box)] +#![feature(const_bool_to_option)] #![feature(const_cell_into_inner)] #![feature(const_convert)] +#![feature(const_maybe_uninit_as_mut_ptr)] #![feature(const_maybe_uninit_assume_init)] +#![feature(const_num_from_num)] #![feature(const_ptr_read)] #![feature(const_ptr_write)] #![feature(const_ptr_offset)] #![feature(const_trait_impl)] -#![feature(const_num_from_num)] +#![feature(const_likely)] #![feature(core_intrinsics)] #![feature(core_private_bignum)] #![feature(core_private_diy_float)] @@ -28,13 +33,17 @@ #![feature(flt2dec)] #![feature(fmt_internals)] #![feature(float_minimum_maximum)] +#![feature(future_join)] +#![feature(future_poll_fn)] #![feature(array_from_fn)] #![feature(hashmap_internals)] #![feature(try_find)] +#![feature(inline_const)] #![feature(is_sorted)] #![feature(pattern)] #![feature(sort_internals)] #![feature(slice_partition_at_index)] +#![feature(slice_take)] #![feature(maybe_uninit_uninit_array)] #![feature(maybe_uninit_array_assume_init)] #![feature(maybe_uninit_extra)] @@ -45,6 +54,7 @@ #![feature(str_internals)] #![feature(test)] #![feature(trusted_len)] +#![feature(try_blocks)] #![feature(try_trait_v2)] #![feature(slice_internals)] #![feature(slice_partition_dedup)] @@ -54,17 +64,20 @@ #![feature(iter_intersperse)] #![feature(iter_is_partitioned)] #![feature(iter_order_by)] +#![feature(iterator_try_reduce)] #![feature(const_mut_refs)] #![feature(const_pin)] #![feature(const_slice_from_raw_parts)] -#![cfg_attr(bootstrap, feature(const_raw_ptr_deref))] #![feature(never_type)] #![feature(unwrap_infallible)] #![feature(result_into_ok_or_err)] +#![feature(portable_simd)] #![feature(ptr_metadata)] #![feature(once_cell)] +#![feature(option_result_contains)] #![feature(unsized_tuple_coercion)] #![feature(const_option)] +#![feature(const_option_ext)] #![feature(const_result)] #![feature(integer_atomics)] #![feature(int_roundings)] @@ -90,7 +103,9 @@ mod char; mod clone; mod cmp; mod const_ptr; +mod convert; mod fmt; +mod future; mod hash; mod intrinsics; mod iter; @@ -106,6 +121,7 @@ mod pattern; mod pin; mod ptr; mod result; +mod simd; mod slice; mod str; mod str_lossy; diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs index c780bb32ca..3b13dc0832 100644 --- a/library/core/tests/mem.rs +++ b/library/core/tests/mem.rs @@ -269,3 +269,35 @@ fn uninit_const_assume_init_read() { const FOO: u32 = unsafe { MaybeUninit::new(42).assume_init_read() }; assert_eq!(FOO, 42); } + +#[test] +fn const_maybe_uninit() { + use std::ptr; + + #[derive(Debug, PartialEq)] + struct Foo { + x: u8, + y: u8, + } + + const FIELD_BY_FIELD: Foo = unsafe { + let mut val = MaybeUninit::uninit(); + init_y(&mut val); // order shouldn't matter + init_x(&mut val); + val.assume_init() + }; + + const fn init_x(foo: &mut MaybeUninit) { + unsafe { + *ptr::addr_of_mut!((*foo.as_mut_ptr()).x) = 1; + } + } + + const fn init_y(foo: &mut MaybeUninit) { + unsafe { + *ptr::addr_of_mut!((*foo.as_mut_ptr()).y) = 2; + } + } + + assert_eq!(FIELD_BY_FIELD, Foo { x: 1, y: 2 }); +} diff --git a/library/core/tests/num/int_macros.rs b/library/core/tests/num/int_macros.rs index 0ad85bf6d9..d2d655ea2c 100644 --- a/library/core/tests/num/int_macros.rs +++ b/library/core/tests/num/int_macros.rs @@ -294,33 +294,33 @@ macro_rules! int_module { fn test_div_floor() { let a: $T = 8; let b = 3; - assert_eq!(a.unstable_div_floor(b), 2); - assert_eq!(a.unstable_div_floor(-b), -3); - assert_eq!((-a).unstable_div_floor(b), -3); - assert_eq!((-a).unstable_div_floor(-b), 2); + assert_eq!(a.div_floor(b), 2); + assert_eq!(a.div_floor(-b), -3); + assert_eq!((-a).div_floor(b), -3); + assert_eq!((-a).div_floor(-b), 2); } #[test] fn test_div_ceil() { let a: $T = 8; let b = 3; - assert_eq!(a.unstable_div_ceil(b), 3); - assert_eq!(a.unstable_div_ceil(-b), -2); - assert_eq!((-a).unstable_div_ceil(b), -2); - assert_eq!((-a).unstable_div_ceil(-b), 3); + assert_eq!(a.div_ceil(b), 3); + assert_eq!(a.div_ceil(-b), -2); + assert_eq!((-a).div_ceil(b), -2); + assert_eq!((-a).div_ceil(-b), 3); } #[test] fn test_next_multiple_of() { - assert_eq!((16 as $T).unstable_next_multiple_of(8), 16); - assert_eq!((23 as $T).unstable_next_multiple_of(8), 24); - assert_eq!((16 as $T).unstable_next_multiple_of(-8), 16); - assert_eq!((23 as $T).unstable_next_multiple_of(-8), 16); - assert_eq!((-16 as $T).unstable_next_multiple_of(8), -16); - assert_eq!((-23 as $T).unstable_next_multiple_of(8), -16); - assert_eq!((-16 as $T).unstable_next_multiple_of(-8), -16); - assert_eq!((-23 as $T).unstable_next_multiple_of(-8), -24); - assert_eq!(MIN.unstable_next_multiple_of(-1), MIN); + assert_eq!((16 as $T).next_multiple_of(8), 16); + assert_eq!((23 as $T).next_multiple_of(8), 24); + assert_eq!((16 as $T).next_multiple_of(-8), 16); + assert_eq!((23 as $T).next_multiple_of(-8), 16); + assert_eq!((-16 as $T).next_multiple_of(8), -16); + assert_eq!((-23 as $T).next_multiple_of(8), -16); + assert_eq!((-16 as $T).next_multiple_of(-8), -16); + assert_eq!((-23 as $T).next_multiple_of(-8), -24); + assert_eq!(MIN.next_multiple_of(-1), MIN); } #[test] diff --git a/library/core/tests/num/uint_macros.rs b/library/core/tests/num/uint_macros.rs index 35ec88c6af..49f8f1f13f 100644 --- a/library/core/tests/num/uint_macros.rs +++ b/library/core/tests/num/uint_macros.rs @@ -208,19 +208,19 @@ macro_rules! uint_module { #[test] fn test_div_floor() { - assert_eq!((8 as $T).unstable_div_floor(3), 2); + assert_eq!((8 as $T).div_floor(3), 2); } #[test] fn test_div_ceil() { - assert_eq!((8 as $T).unstable_div_ceil(3), 3); + assert_eq!((8 as $T).div_ceil(3), 3); } #[test] fn test_next_multiple_of() { - assert_eq!((16 as $T).unstable_next_multiple_of(8), 16); - assert_eq!((23 as $T).unstable_next_multiple_of(8), 24); - assert_eq!(MAX.unstable_next_multiple_of(1), MAX); + assert_eq!((16 as $T).next_multiple_of(8), 16); + assert_eq!((23 as $T).next_multiple_of(8), 24); + assert_eq!(MAX.next_multiple_of(1), MAX); } #[test] diff --git a/library/core/tests/option.rs b/library/core/tests/option.rs index cd07d6c52c..da69246126 100644 --- a/library/core/tests/option.rs +++ b/library/core/tests/option.rs @@ -86,17 +86,49 @@ fn test_and() { let x: Option = None; assert_eq!(x.and(Some(2)), None); assert_eq!(x.and(None::), None); + + const FOO: Option = Some(1); + const A: Option = FOO.and(Some(2)); + const B: Option = FOO.and(None); + assert_eq!(A, Some(2)); + assert_eq!(B, None); + + const BAR: Option = None; + const C: Option = BAR.and(Some(2)); + const D: Option = BAR.and(None); + assert_eq!(C, None); + assert_eq!(D, None); } #[test] fn test_and_then() { + const fn plus_one(x: isize) -> Option { + Some(x + 1) + } + + const fn none(_: isize) -> Option { + None + } + let x: Option = Some(1); - assert_eq!(x.and_then(|x| Some(x + 1)), Some(2)); - assert_eq!(x.and_then(|_| None::), None); + assert_eq!(x.and_then(plus_one), Some(2)); + assert_eq!(x.and_then(none), None); let x: Option = None; - assert_eq!(x.and_then(|x| Some(x + 1)), None); - assert_eq!(x.and_then(|_| None::), None); + assert_eq!(x.and_then(plus_one), None); + assert_eq!(x.and_then(none), None); + + const FOO: Option = Some(1); + const A: Option = FOO.and_then(plus_one); + const B: Option = FOO.and_then(none); + assert_eq!(A, Some(2)); + assert_eq!(B, None); + + const BAR: Option = None; + const C: Option = BAR.and_then(plus_one); + const D: Option = BAR.and_then(none); + assert_eq!(C, None); + assert_eq!(D, None); } #[test] @@ -108,17 +140,49 @@ fn test_or() { let x: Option = None; assert_eq!(x.or(Some(2)), Some(2)); assert_eq!(x.or(None), None); + + const FOO: Option = Some(1); + const A: Option = FOO.or(Some(2)); + const B: Option = FOO.or(None); + assert_eq!(A, Some(1)); + assert_eq!(B, Some(1)); + + const BAR: Option = None; + const C: Option = BAR.or(Some(2)); + const D: Option = BAR.or(None); + assert_eq!(C, Some(2)); + assert_eq!(D, None); } #[test] fn test_or_else() { + const fn two() -> Option { + Some(2) + } + + const fn none() -> Option { + None + } + let x: Option = Some(1); - assert_eq!(x.or_else(|| Some(2)), Some(1)); - assert_eq!(x.or_else(|| None), Some(1)); + assert_eq!(x.or_else(two), Some(1)); + assert_eq!(x.or_else(none), Some(1)); let x: Option = None; - assert_eq!(x.or_else(|| Some(2)), Some(2)); - assert_eq!(x.or_else(|| None), None); + assert_eq!(x.or_else(two), Some(2)); + assert_eq!(x.or_else(none), None); + + const FOO: Option = Some(1); + const A: Option = FOO.or_else(two); + const B: Option = FOO.or_else(none); + assert_eq!(A, Some(1)); + assert_eq!(B, Some(1)); + + const BAR: Option = None; + const C: Option = BAR.or_else(two); + const D: Option = BAR.or_else(none); + assert_eq!(C, Some(2)); + assert_eq!(D, None); } #[test] @@ -149,15 +213,29 @@ fn test_unwrap_or() { let x: Option = None; assert_eq!(x.unwrap_or(2), 2); + + const A: isize = Some(1).unwrap_or(2); + const B: isize = None.unwrap_or(2); + assert_eq!(A, 1); + assert_eq!(B, 2); } #[test] fn test_unwrap_or_else() { + const fn two() -> isize { + 2 + } + let x: Option = Some(1); - assert_eq!(x.unwrap_or_else(|| 2), 1); + assert_eq!(x.unwrap_or_else(two), 1); let x: Option = None; - assert_eq!(x.unwrap_or_else(|| 2), 2); + assert_eq!(x.unwrap_or_else(two), 2); + + const A: isize = Some(1).unwrap_or_else(two); + const B: isize = None.unwrap_or_else(two); + assert_eq!(A, 1); + assert_eq!(B, 2); } #[test] diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs index 11af8090c3..b9c0d75b70 100644 --- a/library/core/tests/ptr.rs +++ b/library/core/tests/ptr.rs @@ -250,6 +250,21 @@ fn test_set_memory() { assert!(xs == [5u8; 20]); } +#[test] +#[cfg(not(bootstrap))] +fn test_set_memory_const() { + const XS: [u8; 20] = { + let mut xs = [0u8; 20]; + let ptr = xs.as_mut_ptr(); + unsafe { + ptr.write_bytes(5u8, xs.len()); + } + xs + }; + + assert!(XS == [5u8; 20]); +} + #[test] fn test_unsized_nonnull() { let xs: &[i32] = &[1, 2, 3]; diff --git a/library/core/tests/simd.rs b/library/core/tests/simd.rs new file mode 100644 index 0000000000..b84f3228e7 --- /dev/null +++ b/library/core/tests/simd.rs @@ -0,0 +1,15 @@ +#![cfg(not(miri))] // Miri does not support all SIMD intrinsics + +use core::simd::f32x4; + +#[test] +fn testing() { + let x = f32x4::from_array([1.0, 1.0, 1.0, 1.0]); + let y = -x; + + let h = x * f32x4::splat(0.5); + + let r = y.abs(); + assert_eq!(x, r); + assert_eq!(h, f32x4::splat(0.5)); +} diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index 8d05e47edf..20e2d8d47c 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -154,6 +154,7 @@ fn test_iterator_advance_by() { assert_eq!(iter.as_slice(), &v[3..]); iter.advance_by(2).unwrap(); assert_eq!(iter.as_slice(), &[]); + iter.advance_by(0).unwrap(); } #[test] @@ -175,6 +176,7 @@ fn test_iterator_advance_back_by() { assert_eq!(iter.as_slice(), &v[..v.len() - 3]); iter.advance_back_by(2).unwrap(); assert_eq!(iter.as_slice(), &[]); + iter.advance_back_by(0).unwrap(); } #[test] @@ -2217,6 +2219,23 @@ fn slice_split_array_mut() { } } +#[test] +fn slice_rsplit_array_mut() { + let v = &mut [1, 2, 3, 4, 5, 6][..]; + + { + let (left, right) = v.rsplit_array_mut::<0>(); + assert_eq!(left, [1, 2, 3, 4, 5, 6]); + assert_eq!(right, &mut []); + } + + { + let (left, right) = v.rsplit_array_mut::<6>(); + assert_eq!(left, []); + assert_eq!(right, &mut [1, 2, 3, 4, 5, 6]); + } +} + #[should_panic] #[test] fn slice_split_array_ref_out_of_bounds() { @@ -2232,3 +2251,130 @@ fn slice_split_array_mut_out_of_bounds() { v.split_array_mut::<7>(); } + +#[should_panic] +#[test] +fn slice_rsplit_array_ref_out_of_bounds() { + let v = &[1, 2, 3, 4, 5, 6][..]; + + v.rsplit_array_ref::<7>(); +} + +#[should_panic] +#[test] +fn slice_rsplit_array_mut_out_of_bounds() { + let v = &mut [1, 2, 3, 4, 5, 6][..]; + + v.rsplit_array_mut::<7>(); +} + +macro_rules! take_tests { + (slice: &[], $($tts:tt)*) => { + take_tests!(ty: &[()], slice: &[], $($tts)*); + }; + (slice: &mut [], $($tts:tt)*) => { + take_tests!(ty: &mut [()], slice: &mut [], $($tts)*); + }; + (slice: &$slice:expr, $($tts:tt)*) => { + take_tests!(ty: &[_], slice: &$slice, $($tts)*); + }; + (slice: &mut $slice:expr, $($tts:tt)*) => { + take_tests!(ty: &mut [_], slice: &mut $slice, $($tts)*); + }; + (ty: $ty:ty, slice: $slice:expr, method: $method:ident, $(($test_name:ident, ($($args:expr),*), $output:expr, $remaining:expr),)*) => { + $( + #[test] + fn $test_name() { + let mut slice: $ty = $slice; + assert_eq!($output, slice.$method($($args)*)); + let remaining: $ty = $remaining; + assert_eq!(remaining, slice); + } + )* + }; +} + +take_tests! { + slice: &[0, 1, 2, 3], method: take, + (take_in_bounds_range_to, (..1), Some(&[0] as _), &[1, 2, 3]), + (take_in_bounds_range_to_inclusive, (..=0), Some(&[0] as _), &[1, 2, 3]), + (take_in_bounds_range_from, (2..), Some(&[2, 3] as _), &[0, 1]), + (take_oob_range_to, (..5), None, &[0, 1, 2, 3]), + (take_oob_range_to_inclusive, (..=4), None, &[0, 1, 2, 3]), + (take_oob_range_from, (5..), None, &[0, 1, 2, 3]), +} + +take_tests! { + slice: &mut [0, 1, 2, 3], method: take_mut, + (take_mut_in_bounds_range_to, (..1), Some(&mut [0] as _), &mut [1, 2, 3]), + (take_mut_in_bounds_range_to_inclusive, (..=0), Some(&mut [0] as _), &mut [1, 2, 3]), + (take_mut_in_bounds_range_from, (2..), Some(&mut [2, 3] as _), &mut [0, 1]), + (take_mut_oob_range_to, (..5), None, &mut [0, 1, 2, 3]), + (take_mut_oob_range_to_inclusive, (..=4), None, &mut [0, 1, 2, 3]), + (take_mut_oob_range_from, (5..), None, &mut [0, 1, 2, 3]), +} + +take_tests! { + slice: &[1, 2], method: take_first, + (take_first_nonempty, (), Some(&1), &[2]), +} + +take_tests! { + slice: &mut [1, 2], method: take_first_mut, + (take_first_mut_nonempty, (), Some(&mut 1), &mut [2]), +} + +take_tests! { + slice: &[1, 2], method: take_last, + (take_last_nonempty, (), Some(&2), &[1]), +} + +take_tests! { + slice: &mut [1, 2], method: take_last_mut, + (take_last_mut_nonempty, (), Some(&mut 2), &mut [1]), +} + +take_tests! { + slice: &[], method: take_first, + (take_first_empty, (), None, &[]), +} + +take_tests! { + slice: &mut [], method: take_first_mut, + (take_first_mut_empty, (), None, &mut []), +} + +take_tests! { + slice: &[], method: take_last, + (take_last_empty, (), None, &[]), +} + +take_tests! { + slice: &mut [], method: take_last_mut, + (take_last_mut_empty, (), None, &mut []), +} + +const EMPTY_MAX: &'static [()] = &[(); usize::MAX]; + +// can't be a constant due to const mutability rules +macro_rules! empty_max_mut { + () => { + &mut [(); usize::MAX] as _ + }; +} + +#[cfg(not(miri))] // Comparing usize::MAX many elements takes forever in Miri (and in rustc without optimizations) +take_tests! { + slice: &[(); usize::MAX], method: take, + (take_in_bounds_max_range_to, (..usize::MAX), Some(EMPTY_MAX), &[(); 0]), + (take_oob_max_range_to_inclusive, (..=usize::MAX), None, EMPTY_MAX), + (take_in_bounds_max_range_from, (usize::MAX..), Some(&[] as _), EMPTY_MAX), +} + +#[cfg(not(miri))] // Comparing usize::MAX many elements takes forever in Miri (and in rustc without optimizations) +take_tests! { + slice: &mut [(); usize::MAX], method: take_mut, + (take_mut_in_bounds_max_range_to, (..usize::MAX), Some(empty_max_mut!()), &mut [(); 0]), + (take_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()), + (take_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()), +} diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs index dec5e0b212..5c5632a9d0 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -14,7 +14,6 @@ #![feature(std_internals)] #![feature(staged_api)] #![feature(rustc_attrs)] -#![feature(asm)] #![feature(c_unwind)] #[cfg(target_os = "android")] @@ -69,11 +68,11 @@ pub unsafe extern "C-unwind" fn __rust_start_panic(_payload: *mut &mut dyn BoxMe const FAST_FAIL_FATAL_APP_EXIT: usize = 7; cfg_if::cfg_if! { if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] { - asm!("int $$0x29", in("ecx") FAST_FAIL_FATAL_APP_EXIT); + core::arch::asm!("int $$0x29", in("ecx") FAST_FAIL_FATAL_APP_EXIT); } else if #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))] { - asm!(".inst 0xDEFB", in("r0") FAST_FAIL_FATAL_APP_EXIT); + core::arch::asm!(".inst 0xDEFB", in("r0") FAST_FAIL_FATAL_APP_EXIT); } else if #[cfg(target_arch = "aarch64")] { - asm!("brk 0xF003", in("x0") FAST_FAIL_FATAL_APP_EXIT); + core::arch::asm!("brk 0xF003", in("x0") FAST_FAIL_FATAL_APP_EXIT); } else { core::intrinsics::abort(); } diff --git a/library/panic_unwind/src/emcc.rs b/library/panic_unwind/src/emcc.rs index e428f2fdaa..12f0fe9c3c 100644 --- a/library/panic_unwind/src/emcc.rs +++ b/library/panic_unwind/src/emcc.rs @@ -49,7 +49,7 @@ static EXCEPTION_TYPE_INFO: TypeInfo = TypeInfo { }; struct Exception { - // This is necessary because C++ code can capture our execption with + // This is necessary because C++ code can capture our exception with // std::exception_ptr and rethrow it multiple times, possibly even in // another thread. caught: AtomicBool, diff --git a/library/portable-simd/CONTRIBUTING.md b/library/portable-simd/CONTRIBUTING.md index f9ba12d3a1..9612fe871c 100644 --- a/library/portable-simd/CONTRIBUTING.md +++ b/library/portable-simd/CONTRIBUTING.md @@ -15,7 +15,7 @@ SIMD can be quite complex, and even a "simple" issue can be huge. If an issue is ## CI -We currently have 2 CI matrices through Travis CI and GitHub Actions that will automatically build and test your change in order to verify that `std::simd`'s portable API is, in fact, portable. If your change builds locally, but does not build on either, this is likely due to a platform-specific concern that your code has not addressed. Please consult the build logs and address the error, or ask for help if you need it. +We currently use GitHub Actions which will automatically build and test your change in order to verify that `std::simd`'s portable API is, in fact, portable. If your change builds locally, but does not build in CI, this is likely due to a platform-specific concern that your code has not addressed. Please consult the build logs and address the error, or ask for help if you need it. ## Beyond stdsimd diff --git a/library/portable-simd/README.md b/library/portable-simd/README.md index da536a4d6f..db0af2da60 100644 --- a/library/portable-simd/README.md +++ b/library/portable-simd/README.md @@ -1,5 +1,5 @@ # The Rust standard library's portable SIMD API -[![Build Status](https://travis-ci.com/rust-lang/portable-simd.svg?branch=master)](https://travis-ci.com/rust-lang/portable-simd) +![Build Status](https://github.com/rust-lang/portable-simd/actions/workflows/ci.yml/badge.svg?branch=master) Code repository for the [Portable SIMD Project Group](https://github.com/rust-lang/project-portable-simd). Please refer to [CONTRIBUTING.md](./CONTRIBUTING.md) for our contributing guidelines. diff --git a/library/portable-simd/crates/core_simd/examples/nbody.rs b/library/portable-simd/crates/core_simd/examples/nbody.rs index 779575985e..43280feebb 100644 --- a/library/portable-simd/crates/core_simd/examples/nbody.rs +++ b/library/portable-simd/crates/core_simd/examples/nbody.rs @@ -97,7 +97,7 @@ mod nbody { let sun = &mut sun[0]; for body in rest { let m_ratio = body.mass / SOLAR_MASS; - sun.v -= body.v * m_ratio; + sun.v -= body.v * Simd::splat(m_ratio); } } @@ -143,14 +143,14 @@ mod nbody { let mut i = 0; for j in 0..N_BODIES { for k in j + 1..N_BODIES { - let f = r[i] * mag[i]; - bodies[j].v -= f * bodies[k].mass; - bodies[k].v += f * bodies[j].mass; + let f = r[i] * Simd::splat(mag[i]); + bodies[j].v -= f * Simd::splat(bodies[k].mass); + bodies[k].v += f * Simd::splat(bodies[j].mass); i += 1 } } for body in bodies { - body.x += dt * body.v + body.x += Simd::splat(dt) * body.v } } diff --git a/library/portable-simd/crates/core_simd/src/comparisons.rs b/library/portable-simd/crates/core_simd/src/comparisons.rs index 8c51baca8e..edef5af368 100644 --- a/library/portable-simd/crates/core_simd/src/comparisons.rs +++ b/library/portable-simd/crates/core_simd/src/comparisons.rs @@ -8,12 +8,14 @@ where { /// Test if each lane is equal to the corresponding lane in `other`. #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] pub fn lanes_eq(self, other: Self) -> Mask { unsafe { Mask::from_int_unchecked(intrinsics::simd_eq(self, other)) } } /// Test if each lane is not equal to the corresponding lane in `other`. #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] pub fn lanes_ne(self, other: Self) -> Mask { unsafe { Mask::from_int_unchecked(intrinsics::simd_ne(self, other)) } } @@ -26,24 +28,28 @@ where { /// Test if each lane is less than the corresponding lane in `other`. #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] pub fn lanes_lt(self, other: Self) -> Mask { unsafe { Mask::from_int_unchecked(intrinsics::simd_lt(self, other)) } } /// Test if each lane is greater than the corresponding lane in `other`. #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] pub fn lanes_gt(self, other: Self) -> Mask { unsafe { Mask::from_int_unchecked(intrinsics::simd_gt(self, other)) } } /// Test if each lane is less than or equal to the corresponding lane in `other`. #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] pub fn lanes_le(self, other: Self) -> Mask { unsafe { Mask::from_int_unchecked(intrinsics::simd_le(self, other)) } } /// Test if each lane is greater than or equal to the corresponding lane in `other`. #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] pub fn lanes_ge(self, other: Self) -> Mask { unsafe { Mask::from_int_unchecked(intrinsics::simd_ge(self, other)) } } diff --git a/library/portable-simd/crates/core_simd/src/lane_count.rs b/library/portable-simd/crates/core_simd/src/lane_count.rs index b017e7d137..3b316f12b3 100644 --- a/library/portable-simd/crates/core_simd/src/lane_count.rs +++ b/library/portable-simd/crates/core_simd/src/lane_count.rs @@ -15,34 +15,28 @@ impl LaneCount { pub trait SupportedLaneCount: Sealed { #[doc(hidden)] type BitMask: Copy + Default + AsRef<[u8]> + AsMut<[u8]>; - - #[doc(hidden)] - type IntBitMask; } impl Sealed for LaneCount {} impl SupportedLaneCount for LaneCount<1> { type BitMask = [u8; 1]; - type IntBitMask = u8; } impl SupportedLaneCount for LaneCount<2> { type BitMask = [u8; 1]; - type IntBitMask = u8; } impl SupportedLaneCount for LaneCount<4> { type BitMask = [u8; 1]; - type IntBitMask = u8; } impl SupportedLaneCount for LaneCount<8> { type BitMask = [u8; 1]; - type IntBitMask = u8; } impl SupportedLaneCount for LaneCount<16> { type BitMask = [u8; 2]; - type IntBitMask = u16; } impl SupportedLaneCount for LaneCount<32> { type BitMask = [u8; 4]; - type IntBitMask = u32; +} +impl SupportedLaneCount for LaneCount<64> { + type BitMask = [u8; 8]; } diff --git a/library/portable-simd/crates/core_simd/src/masks.rs b/library/portable-simd/crates/core_simd/src/masks.rs index d460da0d04..191e969031 100644 --- a/library/portable-simd/crates/core_simd/src/masks.rs +++ b/library/portable-simd/crates/core_simd/src/masks.rs @@ -129,6 +129,7 @@ where /// # Safety /// All lanes must be either 0 or -1. #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] pub unsafe fn from_int_unchecked(value: Simd) -> Self { unsafe { Self(mask_impl::Mask::from_int_unchecked(value)) } } @@ -139,6 +140,7 @@ where /// # Panics /// Panics if any lane is not 0 or -1. #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] pub fn from_int(value: Simd) -> Self { assert!(T::valid(value), "all values must be either 0 or -1",); unsafe { Self::from_int_unchecked(value) } @@ -147,6 +149,7 @@ where /// Converts the mask to a vector of integers, where 0 represents `false` and -1 /// represents `true`. #[inline] + #[must_use = "method returns a new vector and does not mutate the original value"] pub fn to_int(self) -> Simd { self.0.to_int() } @@ -156,6 +159,7 @@ where /// # Safety /// `lane` must be less than `LANES`. #[inline] + #[must_use = "method returns a new bool and does not mutate the original value"] pub unsafe fn test_unchecked(&self, lane: usize) -> bool { unsafe { self.0.test_unchecked(lane) } } @@ -165,6 +169,7 @@ where /// # Panics /// Panics if `lane` is greater than or equal to the number of lanes in the vector. #[inline] + #[must_use = "method returns a new bool and does not mutate the original value"] pub fn test(&self, lane: usize) -> bool { assert!(lane < LANES, "lane index out of range"); unsafe { self.test_unchecked(lane) } @@ -195,24 +200,30 @@ where /// Convert this mask to a bitmask, with one bit set per lane. #[cfg(feature = "generic_const_exprs")] + #[inline] + #[must_use = "method returns a new array and does not mutate the original value"] pub fn to_bitmask(self) -> [u8; LaneCount::::BITMASK_LEN] { self.0.to_bitmask() } /// Convert a bitmask to a mask. #[cfg(feature = "generic_const_exprs")] + #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] pub fn from_bitmask(bitmask: [u8; LaneCount::::BITMASK_LEN]) -> Self { Self(mask_impl::Mask::from_bitmask(bitmask)) } /// Returns true if any lane is set, or false otherwise. #[inline] + #[must_use = "method returns a new bool and does not mutate the original value"] pub fn any(self) -> bool { self.0.any() } /// Returns true if all lanes are set, or false otherwise. #[inline] + #[must_use = "method returns a new bool and does not mutate the original value"] pub fn all(self) -> bool { self.0.all() } @@ -245,6 +256,7 @@ where LaneCount: SupportedLaneCount, { #[inline] + #[must_use = "method returns a defaulted mask with all lanes set to false (0)"] fn default() -> Self { Self::splat(false) } @@ -256,6 +268,7 @@ where LaneCount: SupportedLaneCount, { #[inline] + #[must_use = "method returns a new bool and does not mutate the original value"] fn eq(&self, other: &Self) -> bool { self.0 == other.0 } @@ -267,6 +280,7 @@ where LaneCount: SupportedLaneCount, { #[inline] + #[must_use = "method returns a new Ordering and does not mutate the original value"] fn partial_cmp(&self, other: &Self) -> Option { self.0.partial_cmp(&other.0) } @@ -291,6 +305,7 @@ where { type Output = Self; #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] fn bitand(self, rhs: Self) -> Self { Self(self.0 & rhs.0) } @@ -303,6 +318,7 @@ where { type Output = Self; #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] fn bitand(self, rhs: bool) -> Self { self & Self::splat(rhs) } @@ -315,6 +331,7 @@ where { type Output = Mask; #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] fn bitand(self, rhs: Mask) -> Mask { Mask::splat(self) & rhs } @@ -327,6 +344,7 @@ where { type Output = Self; #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] fn bitor(self, rhs: Self) -> Self { Self(self.0 | rhs.0) } @@ -339,6 +357,7 @@ where { type Output = Self; #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] fn bitor(self, rhs: bool) -> Self { self | Self::splat(rhs) } @@ -351,6 +370,7 @@ where { type Output = Mask; #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] fn bitor(self, rhs: Mask) -> Mask { Mask::splat(self) | rhs } @@ -363,6 +383,7 @@ where { type Output = Self; #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] fn bitxor(self, rhs: Self) -> Self::Output { Self(self.0 ^ rhs.0) } @@ -375,6 +396,7 @@ where { type Output = Self; #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] fn bitxor(self, rhs: bool) -> Self::Output { self ^ Self::splat(rhs) } @@ -387,6 +409,7 @@ where { type Output = Mask; #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] fn bitxor(self, rhs: Mask) -> Self::Output { Mask::splat(self) ^ rhs } @@ -399,6 +422,7 @@ where { type Output = Mask; #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] fn not(self) -> Self::Output { Self(!self.0) } diff --git a/library/portable-simd/crates/core_simd/src/masks/bitmask.rs b/library/portable-simd/crates/core_simd/src/masks/bitmask.rs index 2689e1a88a..b4217dc87b 100644 --- a/library/portable-simd/crates/core_simd/src/masks/bitmask.rs +++ b/library/portable-simd/crates/core_simd/src/masks/bitmask.rs @@ -1,3 +1,4 @@ +#![allow(unused_imports)] use super::MaskElement; use crate::simd::intrinsics; use crate::simd::{LaneCount, Simd, SupportedLaneCount}; @@ -73,6 +74,7 @@ where LaneCount: SupportedLaneCount, { #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] pub fn splat(value: bool) -> Self { let mut mask = as SupportedLaneCount>::BitMask::default(); if value { @@ -87,6 +89,7 @@ where } #[inline] + #[must_use = "method returns a new bool and does not mutate the original value"] pub unsafe fn test_unchecked(&self, lane: usize) -> bool { (self.0.as_ref()[lane / 8] >> (lane % 8)) & 0x1 > 0 } @@ -99,30 +102,22 @@ where } #[inline] + #[must_use = "method returns a new vector and does not mutate the original value"] pub fn to_int(self) -> Simd { unsafe { - let mask: as SupportedLaneCount>::IntBitMask = - core::mem::transmute_copy(&self); - intrinsics::simd_select_bitmask(mask, Simd::splat(T::TRUE), Simd::splat(T::FALSE)) + intrinsics::simd_select_bitmask(self.0, Simd::splat(T::TRUE), Simd::splat(T::FALSE)) } } #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] pub unsafe fn from_int_unchecked(value: Simd) -> Self { - // TODO remove the transmute when rustc is more flexible - assert_eq!( - core::mem::size_of::< as SupportedLaneCount>::BitMask>(), - core::mem::size_of::< as SupportedLaneCount>::IntBitMask>(), - ); - unsafe { - let mask: as SupportedLaneCount>::IntBitMask = - intrinsics::simd_bitmask(value); - Self(core::mem::transmute_copy(&mask), PhantomData) - } + unsafe { Self(intrinsics::simd_bitmask(value), PhantomData) } } #[cfg(feature = "generic_const_exprs")] #[inline] + #[must_use = "method returns a new array and does not mutate the original value"] pub fn to_bitmask(self) -> [u8; LaneCount::::BITMASK_LEN] { // Safety: these are the same type and we are laundering the generic unsafe { core::mem::transmute_copy(&self.0) } @@ -130,12 +125,14 @@ where #[cfg(feature = "generic_const_exprs")] #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] pub fn from_bitmask(bitmask: [u8; LaneCount::::BITMASK_LEN]) -> Self { // Safety: these are the same type and we are laundering the generic Self(unsafe { core::mem::transmute_copy(&bitmask) }, PhantomData) } #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] pub fn convert(self) -> Mask where U: MaskElement, @@ -144,11 +141,13 @@ where } #[inline] + #[must_use = "method returns a new bool and does not mutate the original value"] pub fn any(self) -> bool { self != Self::splat(false) } #[inline] + #[must_use = "method returns a new bool and does not mutate the original value"] pub fn all(self) -> bool { self == Self::splat(true) } @@ -162,6 +161,7 @@ where { type Output = Self; #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] fn bitand(mut self, rhs: Self) -> Self { for (l, r) in self.0.as_mut().iter_mut().zip(rhs.0.as_ref().iter()) { *l &= r; @@ -178,6 +178,7 @@ where { type Output = Self; #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] fn bitor(mut self, rhs: Self) -> Self { for (l, r) in self.0.as_mut().iter_mut().zip(rhs.0.as_ref().iter()) { *l |= r; @@ -193,6 +194,7 @@ where { type Output = Self; #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] fn bitxor(mut self, rhs: Self) -> Self::Output { for (l, r) in self.0.as_mut().iter_mut().zip(rhs.0.as_ref().iter()) { *l ^= r; @@ -208,6 +210,7 @@ where { type Output = Self; #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] fn not(mut self) -> Self::Output { for x in self.0.as_mut() { *x = !*x; diff --git a/library/portable-simd/crates/core_simd/src/masks/full_masks.rs b/library/portable-simd/crates/core_simd/src/masks/full_masks.rs index dd981cedb9..e5bb784bb9 100644 --- a/library/portable-simd/crates/core_simd/src/masks/full_masks.rs +++ b/library/portable-simd/crates/core_simd/src/masks/full_masks.rs @@ -23,6 +23,7 @@ where LaneCount: SupportedLaneCount, { #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] fn clone(&self) -> Self { *self } @@ -70,11 +71,14 @@ where T: MaskElement, LaneCount: SupportedLaneCount, { + #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] pub fn splat(value: bool) -> Self { Self(Simd::splat(if value { T::TRUE } else { T::FALSE })) } #[inline] + #[must_use = "method returns a new bool and does not mutate the original value"] pub unsafe fn test_unchecked(&self, lane: usize) -> bool { T::eq(self.0[lane], T::TRUE) } @@ -85,16 +89,19 @@ where } #[inline] + #[must_use = "method returns a new vector and does not mutate the original value"] pub fn to_int(self) -> Simd { self.0 } #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] pub unsafe fn from_int_unchecked(value: Simd) -> Self { Self(value) } #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] pub fn convert(self) -> Mask where U: MaskElement, @@ -104,17 +111,11 @@ where #[cfg(feature = "generic_const_exprs")] #[inline] + #[must_use = "method returns a new array and does not mutate the original value"] pub fn to_bitmask(self) -> [u8; LaneCount::::BITMASK_LEN] { unsafe { - // TODO remove the transmute when rustc can use arrays of u8 as bitmasks - assert_eq!( - core::mem::size_of::< as SupportedLaneCount>::IntBitMask>(), - LaneCount::::BITMASK_LEN, - ); - let bitmask: as SupportedLaneCount>::IntBitMask = - intrinsics::simd_bitmask(self.0); let mut bitmask: [u8; LaneCount::::BITMASK_LEN] = - core::mem::transmute_copy(&bitmask); + intrinsics::simd_bitmask(self.0); // There is a bug where LLVM appears to implement this operation with the wrong // bit order. @@ -131,6 +132,7 @@ where #[cfg(feature = "generic_const_exprs")] #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] pub fn from_bitmask(mut bitmask: [u8; LaneCount::::BITMASK_LEN]) -> Self { unsafe { // There is a bug where LLVM appears to implement this operation with the wrong @@ -142,14 +144,6 @@ where } } - // TODO remove the transmute when rustc can use arrays of u8 as bitmasks - assert_eq!( - core::mem::size_of::< as SupportedLaneCount>::IntBitMask>(), - LaneCount::::BITMASK_LEN, - ); - let bitmask: as SupportedLaneCount>::IntBitMask = - core::mem::transmute_copy(&bitmask); - Self::from_int_unchecked(intrinsics::simd_select_bitmask( bitmask, Self::splat(true).to_int(), @@ -159,11 +153,13 @@ where } #[inline] + #[must_use = "method returns a new bool and does not mutate the original value"] pub fn any(self) -> bool { unsafe { intrinsics::simd_reduce_any(self.to_int()) } } #[inline] + #[must_use = "method returns a new vector and does not mutate the original value"] pub fn all(self) -> bool { unsafe { intrinsics::simd_reduce_all(self.to_int()) } } @@ -186,6 +182,7 @@ where { type Output = Self; #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] fn bitand(self, rhs: Self) -> Self { unsafe { Self(intrinsics::simd_and(self.0, rhs.0)) } } @@ -198,6 +195,7 @@ where { type Output = Self; #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] fn bitor(self, rhs: Self) -> Self { unsafe { Self(intrinsics::simd_or(self.0, rhs.0)) } } @@ -210,6 +208,7 @@ where { type Output = Self; #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] fn bitxor(self, rhs: Self) -> Self { unsafe { Self(intrinsics::simd_xor(self.0, rhs.0)) } } @@ -222,6 +221,7 @@ where { type Output = Self; #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] fn not(self) -> Self::Output { Self::splat(true) ^ self } diff --git a/library/portable-simd/crates/core_simd/src/math.rs b/library/portable-simd/crates/core_simd/src/math.rs index 2bae414ebf..7435b6df91 100644 --- a/library/portable-simd/crates/core_simd/src/math.rs +++ b/library/portable-simd/crates/core_simd/src/math.rs @@ -17,7 +17,7 @@ macro_rules! impl_uint_arith { /// let max = Simd::splat(MAX); /// let unsat = x + max; /// let sat = x.saturating_add(max); - /// assert_eq!(x - 1, unsat); + /// assert_eq!(unsat, Simd::from_array([1, 0, MAX, MAX - 1])); /// assert_eq!(sat, max); /// ``` #[inline] @@ -37,7 +37,7 @@ macro_rules! impl_uint_arith { /// let max = Simd::splat(MAX); /// let unsat = x - max; /// let sat = x.saturating_sub(max); - /// assert_eq!(unsat, x + 1); + /// assert_eq!(unsat, Simd::from_array([3, 2, 1, 0])); /// assert_eq!(sat, Simd::splat(0)); #[inline] pub fn saturating_sub(self, second: Self) -> Self { @@ -105,7 +105,7 @@ macro_rules! impl_int_arith { #[inline] pub fn abs(self) -> Self { const SHR: $ty = <$ty>::BITS as $ty - 1; - let m = self >> SHR; + let m = self >> Simd::splat(SHR); (self^m) - m } @@ -128,7 +128,7 @@ macro_rules! impl_int_arith { pub fn saturating_abs(self) -> Self { // arith shift for -1 or 0 mask based on sign bit, giving 2s complement const SHR: $ty = <$ty>::BITS as $ty - 1; - let m = self >> SHR; + let m = self >> Simd::splat(SHR); (self^m).saturating_sub(m) } diff --git a/library/portable-simd/crates/core_simd/src/mod.rs b/library/portable-simd/crates/core_simd/src/mod.rs index ec874a2238..8502626595 100644 --- a/library/portable-simd/crates/core_simd/src/mod.rs +++ b/library/portable-simd/crates/core_simd/src/mod.rs @@ -27,7 +27,6 @@ pub mod simd { pub use crate::core_simd::lane_count::{LaneCount, SupportedLaneCount}; pub use crate::core_simd::masks::*; - pub use crate::core_simd::select::Select; pub use crate::core_simd::swizzle::*; pub use crate::core_simd::vector::*; } diff --git a/library/portable-simd/crates/core_simd/src/ops.rs b/library/portable-simd/crates/core_simd/src/ops.rs index 5d7af474ca..3582c57870 100644 --- a/library/portable-simd/crates/core_simd/src/ops.rs +++ b/library/portable-simd/crates/core_simd/src/ops.rs @@ -1,5 +1,13 @@ use crate::simd::intrinsics; use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount}; +use core::ops::{Add, Mul}; +use core::ops::{BitAnd, BitOr, BitXor}; +use core::ops::{Div, Rem, Sub}; +use core::ops::{Shl, Shr}; + +mod assign; +mod deref; +mod unary; impl core::ops::Index for Simd where @@ -57,166 +65,44 @@ macro_rules! impl_ref_ops { $(#[$attrs])* fn $fn($self_tok, $rhs_arg: $rhs_arg_ty) -> Self::Output $body } - - impl core::ops::$trait<&'_ $rhs> for $type - where - LaneCount<$lanes2>: SupportedLaneCount, - { - type Output = <$type as core::ops::$trait<$rhs>>::Output; - - $(#[$attrs])* - fn $fn($self_tok, $rhs_arg: &$rhs) -> Self::Output { - core::ops::$trait::$fn($self_tok, *$rhs_arg) - } - } - - impl core::ops::$trait<$rhs> for &'_ $type - where - LaneCount<$lanes2>: SupportedLaneCount, - { - type Output = <$type as core::ops::$trait<$rhs>>::Output; - - $(#[$attrs])* - fn $fn($self_tok, $rhs_arg: $rhs) -> Self::Output { - core::ops::$trait::$fn(*$self_tok, $rhs_arg) - } - } - - impl core::ops::$trait<&'_ $rhs> for &'_ $type - where - LaneCount<$lanes2>: SupportedLaneCount, - { - type Output = <$type as core::ops::$trait<$rhs>>::Output; - - $(#[$attrs])* - fn $fn($self_tok, $rhs_arg: &$rhs) -> Self::Output { - core::ops::$trait::$fn(*$self_tok, *$rhs_arg) - } - } }; - - // binary assignment op - { - impl core::ops::$trait:ident<$rhs:ty> for $type:ty - where - LaneCount<$lanes2:ident>: SupportedLaneCount, - { - $(#[$attrs:meta])* - fn $fn:ident(&mut $self_tok:ident, $rhs_arg:ident: $rhs_arg_ty:ty) $body:tt - } - } => { - impl core::ops::$trait<$rhs> for $type - where - LaneCount<$lanes2>: SupportedLaneCount, - { - $(#[$attrs])* - fn $fn(&mut $self_tok, $rhs_arg: $rhs_arg_ty) $body - } - - impl core::ops::$trait<&'_ $rhs> for $type - where - LaneCount<$lanes2>: SupportedLaneCount, - { - $(#[$attrs])* - fn $fn(&mut $self_tok, $rhs_arg: &$rhs_arg_ty) { - core::ops::$trait::$fn($self_tok, *$rhs_arg) - } - } - }; - - // unary op - { - impl core::ops::$trait:ident for $type:ty - where - LaneCount<$lanes2:ident>: SupportedLaneCount, - { - type Output = $output:ty; - fn $fn:ident($self_tok:ident) -> Self::Output $body:tt - } - } => { - impl core::ops::$trait for $type - where - LaneCount<$lanes2>: SupportedLaneCount, - { - type Output = $output; - fn $fn($self_tok) -> Self::Output $body - } - - impl core::ops::$trait for &'_ $type - where - LaneCount<$lanes2>: SupportedLaneCount, - { - type Output = <$type as core::ops::$trait>::Output; - fn $fn($self_tok) -> Self::Output { - core::ops::$trait::$fn(*$self_tok) - } - } - } } /// Automatically implements operators over vectors and scalars for a particular vector. macro_rules! impl_op { { impl Add for $scalar:ty } => { - impl_op! { @binary $scalar, Add::add, AddAssign::add_assign, simd_add } + impl_op! { @binary $scalar, Add::add, simd_add } }; { impl Sub for $scalar:ty } => { - impl_op! { @binary $scalar, Sub::sub, SubAssign::sub_assign, simd_sub } + impl_op! { @binary $scalar, Sub::sub, simd_sub } }; { impl Mul for $scalar:ty } => { - impl_op! { @binary $scalar, Mul::mul, MulAssign::mul_assign, simd_mul } + impl_op! { @binary $scalar, Mul::mul, simd_mul } }; { impl Div for $scalar:ty } => { - impl_op! { @binary $scalar, Div::div, DivAssign::div_assign, simd_div } + impl_op! { @binary $scalar, Div::div, simd_div } }; { impl Rem for $scalar:ty } => { - impl_op! { @binary $scalar, Rem::rem, RemAssign::rem_assign, simd_rem } + impl_op! { @binary $scalar, Rem::rem, simd_rem } }; { impl Shl for $scalar:ty } => { - impl_op! { @binary $scalar, Shl::shl, ShlAssign::shl_assign, simd_shl } + impl_op! { @binary $scalar, Shl::shl, simd_shl } }; { impl Shr for $scalar:ty } => { - impl_op! { @binary $scalar, Shr::shr, ShrAssign::shr_assign, simd_shr } + impl_op! { @binary $scalar, Shr::shr, simd_shr } }; { impl BitAnd for $scalar:ty } => { - impl_op! { @binary $scalar, BitAnd::bitand, BitAndAssign::bitand_assign, simd_and } + impl_op! { @binary $scalar, BitAnd::bitand, simd_and } }; { impl BitOr for $scalar:ty } => { - impl_op! { @binary $scalar, BitOr::bitor, BitOrAssign::bitor_assign, simd_or } + impl_op! { @binary $scalar, BitOr::bitor, simd_or } }; { impl BitXor for $scalar:ty } => { - impl_op! { @binary $scalar, BitXor::bitxor, BitXorAssign::bitxor_assign, simd_xor } - }; - - { impl Not for $scalar:ty } => { - impl_ref_ops! { - impl core::ops::Not for Simd<$scalar, LANES> - where - LaneCount: SupportedLaneCount, - { - type Output = Self; - fn not(self) -> Self::Output { - self ^ Self::splat(!<$scalar>::default()) - } - } - } - }; - - { impl Neg for $scalar:ty } => { - impl_ref_ops! { - impl core::ops::Neg for Simd<$scalar, LANES> - where - LaneCount: SupportedLaneCount, - { - type Output = Self; - fn neg(self) -> Self::Output { - unsafe { intrinsics::simd_neg(self) } - } - } - } + impl_op! { @binary $scalar, BitXor::bitxor, simd_xor } }; // generic binary op with assignment when output is `Self` - { @binary $scalar:ty, $trait:ident :: $trait_fn:ident, $assign_trait:ident :: $assign_trait_fn:ident, $intrinsic:ident } => { + { @binary $scalar:ty, $trait:ident :: $trait_fn:ident, $intrinsic:ident } => { impl_ref_ops! { impl core::ops::$trait for Simd<$scalar, LANES> where @@ -232,60 +118,6 @@ macro_rules! impl_op { } } } - - impl_ref_ops! { - impl core::ops::$trait<$scalar> for Simd<$scalar, LANES> - where - LaneCount: SupportedLaneCount, - { - type Output = Self; - - #[inline] - fn $trait_fn(self, rhs: $scalar) -> Self::Output { - core::ops::$trait::$trait_fn(self, Self::splat(rhs)) - } - } - } - - impl_ref_ops! { - impl core::ops::$trait> for $scalar - where - LaneCount: SupportedLaneCount, - { - type Output = Simd<$scalar, LANES>; - - #[inline] - fn $trait_fn(self, rhs: Simd<$scalar, LANES>) -> Self::Output { - core::ops::$trait::$trait_fn(Simd::splat(self), rhs) - } - } - } - - impl_ref_ops! { - impl core::ops::$assign_trait for Simd<$scalar, LANES> - where - LaneCount: SupportedLaneCount, - { - #[inline] - fn $assign_trait_fn(&mut self, rhs: Self) { - unsafe { - *self = intrinsics::$intrinsic(*self, rhs); - } - } - } - } - - impl_ref_ops! { - impl core::ops::$assign_trait<$scalar> for Simd<$scalar, LANES> - where - LaneCount: SupportedLaneCount, - { - #[inline] - fn $assign_trait_fn(&mut self, rhs: $scalar) { - core::ops::$assign_trait::$assign_trait_fn(self, Self::splat(rhs)); - } - } - } }; } @@ -298,7 +130,6 @@ macro_rules! impl_float_ops { impl_op! { impl Mul for $scalar } impl_op! { impl Div for $scalar } impl_op! { impl Rem for $scalar } - impl_op! { impl Neg for $scalar } )* }; } @@ -313,7 +144,6 @@ macro_rules! impl_unsigned_int_ops { impl_op! { impl BitAnd for $scalar } impl_op! { impl BitOr for $scalar } impl_op! { impl BitXor for $scalar } - impl_op! { impl Not for $scalar } // Integers panic on divide by 0 impl_ref_ops! { @@ -344,67 +174,6 @@ macro_rules! impl_unsigned_int_ops { } } - impl_ref_ops! { - impl core::ops::Div<$scalar> for Simd<$scalar, LANES> - where - LaneCount: SupportedLaneCount, - { - type Output = Self; - - #[inline] - fn div(self, rhs: $scalar) -> Self::Output { - if rhs == 0 { - panic!("attempt to divide by zero"); - } - if <$scalar>::MIN != 0 && - self.as_array().iter().any(|x| *x == <$scalar>::MIN) && - rhs == -1 as _ { - panic!("attempt to divide with overflow"); - } - let rhs = Self::splat(rhs); - unsafe { intrinsics::simd_div(self, rhs) } - } - } - } - - impl_ref_ops! { - impl core::ops::Div> for $scalar - where - LaneCount: SupportedLaneCount, - { - type Output = Simd<$scalar, LANES>; - - #[inline] - fn div(self, rhs: Simd<$scalar, LANES>) -> Self::Output { - Simd::splat(self) / rhs - } - } - } - - impl_ref_ops! { - impl core::ops::DivAssign for Simd<$scalar, LANES> - where - LaneCount: SupportedLaneCount, - { - #[inline] - fn div_assign(&mut self, rhs: Self) { - *self = *self / rhs; - } - } - } - - impl_ref_ops! { - impl core::ops::DivAssign<$scalar> for Simd<$scalar, LANES> - where - LaneCount: SupportedLaneCount, - { - #[inline] - fn div_assign(&mut self, rhs: $scalar) { - *self = *self / rhs; - } - } - } - // remainder panics on zero divisor impl_ref_ops! { impl core::ops::Rem for Simd<$scalar, LANES> @@ -434,67 +203,6 @@ macro_rules! impl_unsigned_int_ops { } } - impl_ref_ops! { - impl core::ops::Rem<$scalar> for Simd<$scalar, LANES> - where - LaneCount: SupportedLaneCount, - { - type Output = Self; - - #[inline] - fn rem(self, rhs: $scalar) -> Self::Output { - if rhs == 0 { - panic!("attempt to calculate the remainder with a divisor of zero"); - } - if <$scalar>::MIN != 0 && - self.as_array().iter().any(|x| *x == <$scalar>::MIN) && - rhs == -1 as _ { - panic!("attempt to calculate the remainder with overflow"); - } - let rhs = Self::splat(rhs); - unsafe { intrinsics::simd_rem(self, rhs) } - } - } - } - - impl_ref_ops! { - impl core::ops::Rem> for $scalar - where - LaneCount: SupportedLaneCount, - { - type Output = Simd<$scalar, LANES>; - - #[inline] - fn rem(self, rhs: Simd<$scalar, LANES>) -> Self::Output { - Simd::splat(self) % rhs - } - } - } - - impl_ref_ops! { - impl core::ops::RemAssign for Simd<$scalar, LANES> - where - LaneCount: SupportedLaneCount, - { - #[inline] - fn rem_assign(&mut self, rhs: Self) { - *self = *self % rhs; - } - } - } - - impl_ref_ops! { - impl core::ops::RemAssign<$scalar> for Simd<$scalar, LANES> - where - LaneCount: SupportedLaneCount, - { - #[inline] - fn rem_assign(&mut self, rhs: $scalar) { - *self = *self % rhs; - } - } - } - // shifts panic on overflow impl_ref_ops! { impl core::ops::Shl for Simd<$scalar, LANES> @@ -518,49 +226,6 @@ macro_rules! impl_unsigned_int_ops { } } - impl_ref_ops! { - impl core::ops::Shl<$scalar> for Simd<$scalar, LANES> - where - LaneCount: SupportedLaneCount, - { - type Output = Self; - - #[inline] - fn shl(self, rhs: $scalar) -> Self::Output { - if invalid_shift_rhs(rhs) { - panic!("attempt to shift left with overflow"); - } - let rhs = Self::splat(rhs); - unsafe { intrinsics::simd_shl(self, rhs) } - } - } - } - - - impl_ref_ops! { - impl core::ops::ShlAssign for Simd<$scalar, LANES> - where - LaneCount: SupportedLaneCount, - { - #[inline] - fn shl_assign(&mut self, rhs: Self) { - *self = *self << rhs; - } - } - } - - impl_ref_ops! { - impl core::ops::ShlAssign<$scalar> for Simd<$scalar, LANES> - where - LaneCount: SupportedLaneCount, - { - #[inline] - fn shl_assign(&mut self, rhs: $scalar) { - *self = *self << rhs; - } - } - } - impl_ref_ops! { impl core::ops::Shr for Simd<$scalar, LANES> where @@ -582,49 +247,6 @@ macro_rules! impl_unsigned_int_ops { } } } - - impl_ref_ops! { - impl core::ops::Shr<$scalar> for Simd<$scalar, LANES> - where - LaneCount: SupportedLaneCount, - { - type Output = Self; - - #[inline] - fn shr(self, rhs: $scalar) -> Self::Output { - if invalid_shift_rhs(rhs) { - panic!("attempt to shift with overflow"); - } - let rhs = Self::splat(rhs); - unsafe { intrinsics::simd_shr(self, rhs) } - } - } - } - - - impl_ref_ops! { - impl core::ops::ShrAssign for Simd<$scalar, LANES> - where - LaneCount: SupportedLaneCount, - { - #[inline] - fn shr_assign(&mut self, rhs: Self) { - *self = *self >> rhs; - } - } - } - - impl_ref_ops! { - impl core::ops::ShrAssign<$scalar> for Simd<$scalar, LANES> - where - LaneCount: SupportedLaneCount, - { - #[inline] - fn shr_assign(&mut self, rhs: $scalar) { - *self = *self >> rhs; - } - } - } )* }; } @@ -633,9 +255,6 @@ macro_rules! impl_unsigned_int_ops { macro_rules! impl_signed_int_ops { { $($scalar:ty),* } => { impl_unsigned_int_ops! { $($scalar),* } - $( // scalar - impl_op! { impl Neg for $scalar } - )* }; } diff --git a/library/portable-simd/crates/core_simd/src/ops/assign.rs b/library/portable-simd/crates/core_simd/src/ops/assign.rs new file mode 100644 index 0000000000..d2b48614fc --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/ops/assign.rs @@ -0,0 +1,124 @@ +//! Assignment operators +use super::*; +use core::ops::{AddAssign, MulAssign}; // commutative binary op-assignment +use core::ops::{BitAndAssign, BitOrAssign, BitXorAssign}; // commutative bit binary op-assignment +use core::ops::{DivAssign, RemAssign, SubAssign}; // non-commutative binary op-assignment +use core::ops::{ShlAssign, ShrAssign}; // non-commutative bit binary op-assignment + +// Arithmetic + +macro_rules! assign_ops { + ($(impl $assignTrait:ident for Simd + where + Self: $trait:ident, + { + fn $assign_call:ident(rhs: U) { + $call:ident + } + })*) => { + $(impl $assignTrait for Simd + where + Self: $trait, + T: SimdElement, + LaneCount: SupportedLaneCount, + { + #[inline] + fn $assign_call(&mut self, rhs: U) { + *self = self.$call(rhs); + } + })* + } +} + +assign_ops! { + // Arithmetic + impl AddAssign for Simd + where + Self: Add, + { + fn add_assign(rhs: U) { + add + } + } + + impl MulAssign for Simd + where + Self: Mul, + { + fn mul_assign(rhs: U) { + mul + } + } + + impl SubAssign for Simd + where + Self: Sub, + { + fn sub_assign(rhs: U) { + sub + } + } + + impl DivAssign for Simd + where + Self: Div, + { + fn div_assign(rhs: U) { + div + } + } + impl RemAssign for Simd + where + Self: Rem, + { + fn rem_assign(rhs: U) { + rem + } + } + + // Bitops + impl BitAndAssign for Simd + where + Self: BitAnd, + { + fn bitand_assign(rhs: U) { + bitand + } + } + + impl BitOrAssign for Simd + where + Self: BitOr, + { + fn bitor_assign(rhs: U) { + bitor + } + } + + impl BitXorAssign for Simd + where + Self: BitXor, + { + fn bitxor_assign(rhs: U) { + bitxor + } + } + + impl ShlAssign for Simd + where + Self: Shl, + { + fn shl_assign(rhs: U) { + shl + } + } + + impl ShrAssign for Simd + where + Self: Shr, + { + fn shr_assign(rhs: U) { + shr + } + } +} diff --git a/library/portable-simd/crates/core_simd/src/ops/deref.rs b/library/portable-simd/crates/core_simd/src/ops/deref.rs new file mode 100644 index 0000000000..9883a74c92 --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/ops/deref.rs @@ -0,0 +1,124 @@ +//! This module hacks in "implicit deref" for Simd's operators. +//! Ideally, Rust would take care of this itself, +//! and method calls usually handle the LHS implicitly. +//! But this is not the case with arithmetic ops. +use super::*; + +macro_rules! deref_lhs { + (impl $trait:ident for $simd:ty { + fn $call:ident + }) => { + impl $trait<$simd> for &$simd + where + T: SimdElement, + $simd: $trait<$simd, Output = $simd>, + LaneCount: SupportedLaneCount, + { + type Output = Simd; + + #[inline] + #[must_use = "operator returns a new vector without mutating the inputs"] + fn $call(self, rhs: $simd) -> Self::Output { + (*self).$call(rhs) + } + } + }; +} + +macro_rules! deref_rhs { + (impl $trait:ident for $simd:ty { + fn $call:ident + }) => { + impl $trait<&$simd> for $simd + where + T: SimdElement, + $simd: $trait<$simd, Output = $simd>, + LaneCount: SupportedLaneCount, + { + type Output = Simd; + + #[inline] + #[must_use = "operator returns a new vector without mutating the inputs"] + fn $call(self, rhs: &$simd) -> Self::Output { + self.$call(*rhs) + } + } + }; +} + +macro_rules! deref_ops { + ($(impl $trait:ident for $simd:ty { + fn $call:ident + })*) => { + $( + deref_rhs! { + impl $trait for $simd { + fn $call + } + } + deref_lhs! { + impl $trait for $simd { + fn $call + } + } + impl<'lhs, 'rhs, T, const LANES: usize> $trait<&'rhs $simd> for &'lhs $simd + where + T: SimdElement, + $simd: $trait<$simd, Output = $simd>, + LaneCount: SupportedLaneCount, + { + type Output = $simd; + + #[inline] + #[must_use = "operator returns a new vector without mutating the inputs"] + fn $call(self, rhs: &$simd) -> Self::Output { + (*self).$call(*rhs) + } + } + )* + } +} + +deref_ops! { + // Arithmetic + impl Add for Simd { + fn add + } + + impl Mul for Simd { + fn mul + } + + impl Sub for Simd { + fn sub + } + + impl Div for Simd { + fn div + } + + impl Rem for Simd { + fn rem + } + + // Bitops + impl BitAnd for Simd { + fn bitand + } + + impl BitOr for Simd { + fn bitor + } + + impl BitXor for Simd { + fn bitxor + } + + impl Shl for Simd { + fn shl + } + + impl Shr for Simd { + fn shr + } +} diff --git a/library/portable-simd/crates/core_simd/src/ops/unary.rs b/library/portable-simd/crates/core_simd/src/ops/unary.rs new file mode 100644 index 0000000000..4ebea560fc --- /dev/null +++ b/library/portable-simd/crates/core_simd/src/ops/unary.rs @@ -0,0 +1,77 @@ +use crate::simd::intrinsics; +use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount}; +use core::ops::{Neg, Not}; // unary ops + +macro_rules! neg { + ($(impl Neg for Simd<$scalar:ty, LANES>)*) => { + $(impl Neg for Simd<$scalar, LANES> + where + $scalar: SimdElement, + LaneCount: SupportedLaneCount, + { + type Output = Self; + + #[inline] + #[must_use = "operator returns a new vector without mutating the input"] + fn neg(self) -> Self::Output { + unsafe { intrinsics::simd_neg(self) } + } + })* + } +} + +neg! { + impl Neg for Simd + + impl Neg for Simd + + impl Neg for Simd + + impl Neg for Simd + + impl Neg for Simd + + impl Neg for Simd + + impl Neg for Simd +} + +macro_rules! not { + ($(impl Not for Simd<$scalar:ty, LANES>)*) => { + $(impl Not for Simd<$scalar, LANES> + where + $scalar: SimdElement, + LaneCount: SupportedLaneCount, + { + type Output = Self; + + #[inline] + #[must_use = "operator returns a new vector without mutating the input"] + fn not(self) -> Self::Output { + self ^ (Simd::splat(!(0 as $scalar))) + } + })* + } +} + +not! { + impl Not for Simd + + impl Not for Simd + + impl Not for Simd + + impl Not for Simd + + impl Not for Simd + + impl Not for Simd + + impl Not for Simd + + impl Not for Simd + + impl Not for Simd + + impl Not for Simd +} diff --git a/library/portable-simd/crates/core_simd/src/reduction.rs b/library/portable-simd/crates/core_simd/src/reduction.rs index db0640aae7..e79a185816 100644 --- a/library/portable-simd/crates/core_simd/src/reduction.rs +++ b/library/portable-simd/crates/core_simd/src/reduction.rs @@ -2,7 +2,8 @@ use crate::simd::intrinsics::{ simd_reduce_add_ordered, simd_reduce_and, simd_reduce_max, simd_reduce_min, simd_reduce_mul_ordered, simd_reduce_or, simd_reduce_xor, }; -use crate::simd::{LaneCount, Simd, SupportedLaneCount}; +use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount}; +use core::ops::{BitAnd, BitOr, BitXor}; macro_rules! impl_integer_reductions { { $scalar:ty } => { @@ -22,27 +23,6 @@ macro_rules! impl_integer_reductions { unsafe { simd_reduce_mul_ordered(self, 1) } } - /// Horizontal bitwise "and". Returns the cumulative bitwise "and" across the lanes of - /// the vector. - #[inline] - pub fn horizontal_and(self) -> $scalar { - unsafe { simd_reduce_and(self) } - } - - /// Horizontal bitwise "or". Returns the cumulative bitwise "or" across the lanes of - /// the vector. - #[inline] - pub fn horizontal_or(self) -> $scalar { - unsafe { simd_reduce_or(self) } - } - - /// Horizontal bitwise "xor". Returns the cumulative bitwise "xor" across the lanes of - /// the vector. - #[inline] - pub fn horizontal_xor(self) -> $scalar { - unsafe { simd_reduce_xor(self) } - } - /// Horizontal maximum. Returns the maximum lane in the vector. #[inline] pub fn horizontal_max(self) -> $scalar { @@ -121,3 +101,45 @@ macro_rules! impl_float_reductions { impl_float_reductions! { f32 } impl_float_reductions! { f64 } + +impl Simd +where + Self: BitAnd, + T: SimdElement + BitAnd, + LaneCount: SupportedLaneCount, +{ + /// Horizontal bitwise "and". Returns the cumulative bitwise "and" across the lanes of + /// the vector. + #[inline] + pub fn horizontal_and(self) -> T { + unsafe { simd_reduce_and(self) } + } +} + +impl Simd +where + Self: BitOr, + T: SimdElement + BitOr, + LaneCount: SupportedLaneCount, +{ + /// Horizontal bitwise "or". Returns the cumulative bitwise "or" across the lanes of + /// the vector. + #[inline] + pub fn horizontal_or(self) -> T { + unsafe { simd_reduce_or(self) } + } +} + +impl Simd +where + Self: BitXor, + T: SimdElement + BitXor, + LaneCount: SupportedLaneCount, +{ + /// Horizontal bitwise "xor". Returns the cumulative bitwise "xor" across the lanes of + /// the vector. + #[inline] + pub fn horizontal_xor(self) -> T { + unsafe { simd_reduce_xor(self) } + } +} diff --git a/library/portable-simd/crates/core_simd/src/select.rs b/library/portable-simd/crates/core_simd/src/select.rs index d976231a03..8d521057fb 100644 --- a/library/portable-simd/crates/core_simd/src/select.rs +++ b/library/portable-simd/crates/core_simd/src/select.rs @@ -1,52 +1,6 @@ use crate::simd::intrinsics; use crate::simd::{LaneCount, Mask, MaskElement, Simd, SimdElement, SupportedLaneCount}; -mod sealed { - pub trait Sealed { - fn select(mask: Mask, true_values: Self, false_values: Self) -> Self; - } -} -use sealed::Sealed; - -/// Supporting trait for vector `select` function -pub trait Select: Sealed {} - -impl Sealed> for Simd -where - T: SimdElement, - LaneCount: SupportedLaneCount, -{ - #[inline] - fn select(mask: Mask, true_values: Self, false_values: Self) -> Self { - unsafe { intrinsics::simd_select(mask.to_int(), true_values, false_values) } - } -} - -impl Select> for Simd -where - T: SimdElement, - LaneCount: SupportedLaneCount, -{ -} - -impl Sealed for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ - #[inline] - fn select(mask: Self, true_values: Self, false_values: Self) -> Self { - mask & true_values | !mask & false_values - } -} - -impl Select for Mask -where - T: MaskElement, - LaneCount: SupportedLaneCount, -{ -} - impl Mask where T: MaskElement, @@ -67,8 +21,24 @@ where /// let c = mask.select(a, b); /// assert_eq!(c.to_array(), [0, 5, 6, 3]); /// ``` + #[inline] + #[must_use = "method returns a new vector and does not mutate the original inputs"] + pub fn select( + self, + true_values: Simd, + false_values: Simd, + ) -> Simd + where + U: SimdElement, + { + unsafe { intrinsics::simd_select(self.to_int(), true_values, false_values) } + } + + /// Choose lanes from two masks. + /// + /// For each lane in the mask, choose the corresponding lane from `true_values` if + /// that lane mask is true, and `false_values` if that lane mask is false. /// - /// `select` can also be used on masks: /// ``` /// # #![feature(portable_simd)] /// # #[cfg(feature = "std")] use core_simd::Mask; @@ -76,11 +46,12 @@ where /// let a = Mask::::from_array([true, true, false, false]); /// let b = Mask::::from_array([false, false, true, true]); /// let mask = Mask::::from_array([true, false, false, true]); - /// let c = mask.select(a, b); + /// let c = mask.select_mask(a, b); /// assert_eq!(c.to_array(), [true, false, true, false]); /// ``` #[inline] - pub fn select>(self, true_values: S, false_values: S) -> S { - S::select(self, true_values, false_values) + #[must_use = "method returns a new mask and does not mutate the original inputs"] + pub fn select_mask(self, true_values: Self, false_values: Self) -> Self { + self & true_values | !self & false_values } } diff --git a/library/portable-simd/crates/core_simd/src/swizzle.rs b/library/portable-simd/crates/core_simd/src/swizzle.rs index 62cda68f0a..bdc489774a 100644 --- a/library/portable-simd/crates/core_simd/src/swizzle.rs +++ b/library/portable-simd/crates/core_simd/src/swizzle.rs @@ -87,6 +87,8 @@ pub trait Swizzle { /// Create a new vector from the lanes of `vector`. /// /// Lane `i` of the output is `vector[Self::INDEX[i]]`. + #[inline] + #[must_use = "method returns a new vector and does not mutate the original inputs"] fn swizzle(vector: Simd) -> Simd where T: SimdElement, @@ -106,6 +108,8 @@ pub trait Swizzle2 { /// /// Lane `i` is `first[j]` when `Self::INDEX[i]` is `First(j)`, or `second[j]` when it is /// `Second(j)`. + #[inline] + #[must_use = "method returns a new vector and does not mutate the original inputs"] fn swizzle2( first: Simd, second: Simd, @@ -182,6 +186,7 @@ where { /// Reverse the order of the lanes in the vector. #[inline] + #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn reverse(self) -> Self { const fn reverse_index() -> [usize; LANES] { let mut index = [0; LANES]; @@ -206,6 +211,7 @@ where /// while the last `LANES - OFFSET` elements move to the front. After calling `rotate_lanes_left`, /// the element previously in lane `OFFSET` will become the first element in the slice. #[inline] + #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn rotate_lanes_left(self) -> Self { const fn rotate_index() -> [usize; LANES] { let offset = OFFSET % LANES; @@ -231,6 +237,7 @@ where /// the end while the last `OFFSET` elements move to the front. After calling `rotate_lanes_right`, /// the element previously at index `LANES - OFFSET` will become the first element in the slice. #[inline] + #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn rotate_lanes_right(self) -> Self { const fn rotate_index() -> [usize; LANES] { let offset = LANES - OFFSET % LANES; @@ -273,6 +280,7 @@ where /// assert_eq!(y.to_array(), [2, 6, 3, 7]); /// ``` #[inline] + #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn interleave(self, other: Self) -> (Self, Self) { const fn lo() -> [Which; LANES] { let mut idx = [Which::First(0); LANES]; @@ -336,6 +344,7 @@ where /// assert_eq!(y.to_array(), [4, 5, 6, 7]); /// ``` #[inline] + #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn deinterleave(self, other: Self) -> (Self, Self) { const fn even() -> [Which; LANES] { let mut idx = [Which::First(0); LANES]; diff --git a/library/portable-simd/crates/core_simd/src/vector/float.rs b/library/portable-simd/crates/core_simd/src/vector/float.rs index c09d0ac84d..4a4b23238c 100644 --- a/library/portable-simd/crates/core_simd/src/vector/float.rs +++ b/library/portable-simd/crates/core_simd/src/vector/float.rs @@ -15,6 +15,7 @@ macro_rules! impl_float_vector { /// Raw transmutation to an unsigned integer vector type with the /// same size and number of lanes. #[inline] + #[must_use = "method returns a new vector and does not mutate the original value"] pub fn to_bits(self) -> Simd<$bits_ty, LANES> { assert_eq!(core::mem::size_of::(), core::mem::size_of::>()); unsafe { core::mem::transmute_copy(&self) } @@ -23,6 +24,7 @@ macro_rules! impl_float_vector { /// Raw transmutation from an unsigned integer vector type with the /// same size and number of lanes. #[inline] + #[must_use = "method returns a new vector and does not mutate the original value"] pub fn from_bits(bits: Simd<$bits_ty, LANES>) -> Self { assert_eq!(core::mem::size_of::(), core::mem::size_of::>()); unsafe { core::mem::transmute_copy(&bits) } @@ -31,6 +33,7 @@ macro_rules! impl_float_vector { /// Produces a vector where every lane has the absolute value of the /// equivalently-indexed lane in `self`. #[inline] + #[must_use = "method returns a new vector and does not mutate the original value"] pub fn abs(self) -> Self { unsafe { intrinsics::simd_fabs(self) } } @@ -44,6 +47,7 @@ macro_rules! impl_float_vector { /// hardware in mind. #[cfg(feature = "std")] #[inline] + #[must_use = "method returns a new vector and does not mutate the original value"] pub fn mul_add(self, a: Self, b: Self) -> Self { unsafe { intrinsics::simd_fma(self, a, b) } } @@ -51,6 +55,7 @@ macro_rules! impl_float_vector { /// Produces a vector where every lane has the square root value /// of the equivalently-indexed lane in `self` #[inline] + #[must_use = "method returns a new vector and does not mutate the original value"] #[cfg(feature = "std")] pub fn sqrt(self) -> Self { unsafe { intrinsics::simd_fsqrt(self) } @@ -58,12 +63,14 @@ macro_rules! impl_float_vector { /// Takes the reciprocal (inverse) of each lane, `1/x`. #[inline] + #[must_use = "method returns a new vector and does not mutate the original value"] pub fn recip(self) -> Self { Self::splat(1.0) / self } /// Converts each lane from radians to degrees. #[inline] + #[must_use = "method returns a new vector and does not mutate the original value"] pub fn to_degrees(self) -> Self { // to_degrees uses a special constant for better precision, so extract that constant self * Self::splat(<$type>::to_degrees(1.)) @@ -71,6 +78,7 @@ macro_rules! impl_float_vector { /// Converts each lane from degrees to radians. #[inline] + #[must_use = "method returns a new vector and does not mutate the original value"] pub fn to_radians(self) -> Self { self * Self::splat(<$type>::to_radians(1.)) } @@ -78,6 +86,7 @@ macro_rules! impl_float_vector { /// Returns true for each lane if it has a positive sign, including /// `+0.0`, `NaN`s with positive sign bit and positive infinity. #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] pub fn is_sign_positive(self) -> Mask<$mask_ty, LANES> { !self.is_sign_negative() } @@ -85,6 +94,7 @@ macro_rules! impl_float_vector { /// Returns true for each lane if it has a negative sign, including /// `-0.0`, `NaN`s with negative sign bit and negative infinity. #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] pub fn is_sign_negative(self) -> Mask<$mask_ty, LANES> { let sign_bits = self.to_bits() & Simd::splat((!0 >> 1) + 1); sign_bits.lanes_gt(Simd::splat(0)) @@ -92,24 +102,28 @@ macro_rules! impl_float_vector { /// Returns true for each lane if its value is `NaN`. #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] pub fn is_nan(self) -> Mask<$mask_ty, LANES> { self.lanes_ne(self) } /// Returns true for each lane if its value is positive infinity or negative infinity. #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] pub fn is_infinite(self) -> Mask<$mask_ty, LANES> { self.abs().lanes_eq(Self::splat(<$type>::INFINITY)) } /// Returns true for each lane if its value is neither infinite nor `NaN`. #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] pub fn is_finite(self) -> Mask<$mask_ty, LANES> { self.abs().lanes_lt(Self::splat(<$type>::INFINITY)) } /// Returns true for each lane if its value is subnormal. #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] pub fn is_subnormal(self) -> Mask<$mask_ty, LANES> { self.abs().lanes_ne(Self::splat(0.0)) & (self.to_bits() & Self::splat(<$type>::INFINITY).to_bits()).lanes_eq(Simd::splat(0)) } @@ -117,6 +131,7 @@ macro_rules! impl_float_vector { /// Returns true for each lane if its value is neither neither zero, infinite, /// subnormal, or `NaN`. #[inline] + #[must_use = "method returns a new mask and does not mutate the original value"] pub fn is_normal(self) -> Mask<$mask_ty, LANES> { !(self.abs().lanes_eq(Self::splat(0.0)) | self.is_nan() | self.is_subnormal() | self.is_infinite()) } @@ -127,6 +142,7 @@ macro_rules! impl_float_vector { /// * `-1.0` if the number is negative, `-0.0`, or `NEG_INFINITY` /// * `NAN` if the number is `NAN` #[inline] + #[must_use = "method returns a new vector and does not mutate the original value"] pub fn signum(self) -> Self { self.is_nan().select(Self::splat(<$type>::NAN), Self::splat(1.0).copysign(self)) } @@ -135,6 +151,7 @@ macro_rules! impl_float_vector { /// /// If any lane is a `NAN`, then a `NAN` with the sign of `sign` is returned. #[inline] + #[must_use = "method returns a new vector and does not mutate the original value"] pub fn copysign(self, sign: Self) -> Self { let sign_bit = sign.to_bits() & Self::splat(-0.).to_bits(); let magnitude = self.to_bits() & !Self::splat(-0.).to_bits(); @@ -145,6 +162,7 @@ macro_rules! impl_float_vector { /// /// If one of the values is `NAN`, then the other value is returned. #[inline] + #[must_use = "method returns a new vector and does not mutate the original value"] pub fn min(self, other: Self) -> Self { // TODO consider using an intrinsic self.is_nan().select( @@ -157,6 +175,7 @@ macro_rules! impl_float_vector { /// /// If one of the values is `NAN`, then the other value is returned. #[inline] + #[must_use = "method returns a new vector and does not mutate the original value"] pub fn max(self, other: Self) -> Self { // TODO consider using an intrinsic self.is_nan().select( @@ -171,6 +190,7 @@ macro_rules! impl_float_vector { /// greater than `max`, and the corresponding lane in `min` if the lane is less /// than `min`. Otherwise returns the lane in `self`. #[inline] + #[must_use = "method returns a new vector and does not mutate the original value"] pub fn clamp(self, min: Self, max: Self) -> Self { assert!( min.lanes_le(max).all(), diff --git a/library/portable-simd/crates/core_simd/src/vector/ptr.rs b/library/portable-simd/crates/core_simd/src/vector/ptr.rs index ac9b98ca03..c668d9a6ea 100644 --- a/library/portable-simd/crates/core_simd/src/vector/ptr.rs +++ b/library/portable-simd/crates/core_simd/src/vector/ptr.rs @@ -23,7 +23,7 @@ where pub fn wrapping_add(self, addend: Simd) -> Self { unsafe { let x: Simd = mem::transmute_copy(&self); - mem::transmute_copy(&{ x + (addend * mem::size_of::()) }) + mem::transmute_copy(&{ x + (addend * Simd::splat(mem::size_of::())) }) } } } @@ -49,7 +49,7 @@ where pub fn wrapping_add(self, addend: Simd) -> Self { unsafe { let x: Simd = mem::transmute_copy(&self); - mem::transmute_copy(&{ x + (addend * mem::size_of::()) }) + mem::transmute_copy(&{ x + (addend * Simd::splat(mem::size_of::())) }) } } } diff --git a/library/portable-simd/crates/core_simd/src/vendor/x86.rs b/library/portable-simd/crates/core_simd/src/vendor/x86.rs index d3c19ccc53..0dd47015ed 100644 --- a/library/portable-simd/crates/core_simd/src/vendor/x86.rs +++ b/library/portable-simd/crates/core_simd/src/vendor/x86.rs @@ -8,10 +8,10 @@ use core::arch::x86_64::*; from_transmute! { unsafe u8x16 => __m128i } from_transmute! { unsafe u8x32 => __m256i } -//from_transmute! { unsafe u8x64 => __m512i } +from_transmute! { unsafe u8x64 => __m512i } from_transmute! { unsafe i8x16 => __m128i } from_transmute! { unsafe i8x32 => __m256i } -//from_transmute! { unsafe i8x64 => __m512i } +from_transmute! { unsafe i8x64 => __m512i } from_transmute! { unsafe u16x8 => __m128i } from_transmute! { unsafe u16x16 => __m256i } diff --git a/library/portable-simd/crates/core_simd/tests/autoderef.rs b/library/portable-simd/crates/core_simd/tests/autoderef.rs new file mode 100644 index 0000000000..9359da16ee --- /dev/null +++ b/library/portable-simd/crates/core_simd/tests/autoderef.rs @@ -0,0 +1,22 @@ +// Test that we handle all our "auto-deref" cases correctly. +#![feature(portable_simd)] +use core_simd::f32x4; + +#[cfg(target_arch = "wasm32")] +use wasm_bindgen_test::*; + +#[cfg(target_arch = "wasm32")] +wasm_bindgen_test_configure!(run_in_browser); + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +fn deref() { + let x = f32x4::splat(1.0); + let y = f32x4::splat(2.0); + let a = &x; + let b = &y; + assert_eq!(f32x4::splat(3.0), x + y); + assert_eq!(f32x4::splat(3.0), x + b); + assert_eq!(f32x4::splat(3.0), a + y); + assert_eq!(f32x4::splat(3.0), a + b); +} diff --git a/library/portable-simd/crates/core_simd/tests/ops_macros.rs b/library/portable-simd/crates/core_simd/tests/ops_macros.rs index 31b7ee2069..43ddde4c55 100644 --- a/library/portable-simd/crates/core_simd/tests/ops_macros.rs +++ b/library/portable-simd/crates/core_simd/tests/ops_macros.rs @@ -38,22 +38,6 @@ macro_rules! impl_binary_op_test { ); } - fn scalar_rhs() { - test_helpers::test_binary_scalar_rhs_elementwise( - & as core::ops::$trait<$scalar>>::$fn, - &$scalar_fn, - &|_, _| true, - ); - } - - fn scalar_lhs() { - test_helpers::test_binary_scalar_lhs_elementwise( - &<$scalar as core::ops::$trait>>::$fn, - &$scalar_fn, - &|_, _| true, - ); - } - fn assign() { test_helpers::test_binary_elementwise( &|mut a, b| { as core::ops::$trait_assign>::$fn_assign(&mut a, b); a }, @@ -61,14 +45,6 @@ macro_rules! impl_binary_op_test { &|_, _| true, ); } - - fn assign_scalar_rhs() { - test_helpers::test_binary_scalar_rhs_elementwise( - &|mut a, b| { as core::ops::$trait_assign<$scalar>>::$fn_assign(&mut a, b); a }, - &$scalar_fn, - &|_, _| true, - ); - } } } }; @@ -99,22 +75,6 @@ macro_rules! impl_binary_checked_op_test { ); } - fn scalar_rhs() { - test_helpers::test_binary_scalar_rhs_elementwise( - & as core::ops::$trait<$scalar>>::$fn, - &$scalar_fn, - &|x, y| x.iter().all(|x| $check_fn(*x, y)), - ); - } - - fn scalar_lhs() { - test_helpers::test_binary_scalar_lhs_elementwise( - &<$scalar as core::ops::$trait>>::$fn, - &$scalar_fn, - &|x, y| y.iter().all(|y| $check_fn(x, *y)), - ); - } - fn assign() { test_helpers::test_binary_elementwise( &|mut a, b| { as core::ops::$trait_assign>::$fn_assign(&mut a, b); a }, @@ -122,14 +82,6 @@ macro_rules! impl_binary_checked_op_test { &|x, y| x.iter().zip(y.iter()).all(|(x, y)| $check_fn(*x, *y)), ) } - - fn assign_scalar_rhs() { - test_helpers::test_binary_scalar_rhs_elementwise( - &|mut a, b| { as core::ops::$trait_assign<$scalar>>::$fn_assign(&mut a, b); a }, - &$scalar_fn, - &|x, y| x.iter().all(|x| $check_fn(*x, y)), - ) - } } } }; diff --git a/library/portable-simd/crates/test_helpers/src/lib.rs b/library/portable-simd/crates/test_helpers/src/lib.rs index 5c6478876f..7edd609638 100644 --- a/library/portable-simd/crates/test_helpers/src/lib.rs +++ b/library/portable-simd/crates/test_helpers/src/lib.rs @@ -376,6 +376,12 @@ macro_rules! test_lanes { fn lanes_32() { implementation::<32>(); } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] + fn lanes_64() { + implementation::<64>(); + } } )* } @@ -431,6 +437,12 @@ macro_rules! test_lanes_panic { fn lanes_32() { implementation::<32>(); } + + #[test] + #[should_panic] + fn lanes_64() { + implementation::<64>(); + } } )* } diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs index 8ae7b6de1a..83a2ac6f0d 100644 --- a/library/proc_macro/src/bridge/client.rs +++ b/library/proc_macro/src/bridge/client.rs @@ -78,7 +78,7 @@ macro_rules! define_handles { } } - impl Decode<'_, 's, HandleStore>> + impl<'s, S: server::Types> Decode<'_, 's, HandleStore>> for &'s Marked { fn decode(r: &mut Reader<'_>, s: &'s HandleStore>) -> Self { @@ -92,7 +92,7 @@ macro_rules! define_handles { } } - impl DecodeMut<'_, 's, HandleStore>> + impl<'s, S: server::Types> DecodeMut<'_, 's, HandleStore>> for &'s mut Marked { fn decode( diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index 2df287f7d9..fbeb585095 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -295,13 +295,13 @@ impl Unmark for Marked { self.value } } -impl Unmark for &'a Marked { +impl<'a, T, M> Unmark for &'a Marked { type Unmarked = &'a T; fn unmark(self) -> Self::Unmarked { &self.value } } -impl Unmark for &'a mut Marked { +impl<'a, T, M> Unmark for &'a mut Marked { type Unmarked = &'a mut T; fn unmark(self) -> Self::Unmarked { &mut self.value @@ -356,8 +356,8 @@ mark_noop! { (), bool, char, - &'a [u8], - &'a str, + &'_ [u8], + &'_ str, String, usize, Delimiter, diff --git a/library/proc_macro/src/bridge/rpc.rs b/library/proc_macro/src/bridge/rpc.rs index 42432563fa..d50564d01a 100644 --- a/library/proc_macro/src/bridge/rpc.rs +++ b/library/proc_macro/src/bridge/rpc.rs @@ -79,7 +79,7 @@ macro_rules! rpc_encode_decode { } } - impl DecodeMut<'a, 's, S>),+)?> DecodeMut<'a, '_, S> + impl<'a, S, $($($T: for<'s> DecodeMut<'a, 's, S>),+)?> DecodeMut<'a, '_, S> for $name $(<$($T),+>)? { fn decode(r: &mut Reader<'a>, s: &mut S) -> Self { @@ -176,7 +176,7 @@ impl, B: Encode> Encode for (A, B) { } } -impl DecodeMut<'a, 's, S>, B: for<'s> DecodeMut<'a, 's, S>> DecodeMut<'a, '_, S> +impl<'a, S, A: for<'s> DecodeMut<'a, 's, S>, B: for<'s> DecodeMut<'a, 's, S>> DecodeMut<'a, '_, S> for (A, B) { fn decode(r: &mut Reader<'a>, s: &mut S) -> Self { @@ -213,7 +213,7 @@ impl Encode for &[u8] { } } -impl DecodeMut<'a, '_, S> for &'a [u8] { +impl<'a, S> DecodeMut<'a, '_, S> for &'a [u8] { fn decode(r: &mut Reader<'a>, s: &mut S) -> Self { let len = usize::decode(r, s); let xs = &r[..len]; @@ -228,7 +228,7 @@ impl Encode for &str { } } -impl DecodeMut<'a, '_, S> for &'a str { +impl<'a, S> DecodeMut<'a, '_, S> for &'a str { fn decode(r: &mut Reader<'a>, s: &mut S) -> Self { str::from_utf8(<&[u8]>::decode(r, s)).unwrap() } diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index ef96d72a38..69af598f91 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -25,7 +25,6 @@ #![feature(allow_internal_unstable)] #![feature(decl_macro)] #![feature(extern_types)] -#![feature(in_band_lifetimes)] #![feature(negative_impls)] #![feature(auto_traits)] #![feature(restricted_std)] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 4147f7ee52..bf54004964 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -4,7 +4,7 @@ version = "0.0.0" license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/rust.git" description = "The Rust Standard Library" -edition = "2018" +edition = "2021" [lib] crate-type = ["dylib", "rlib"] @@ -15,8 +15,8 @@ cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core" } -libc = { version = "0.2.106", default-features = false, features = ['rustc-dep-of-std'] } -compiler_builtins = { version = "0.1.53" } +libc = { version = "0.2.108", default-features = false, features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "0.1.67" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } hashbrown = { version = "0.11", default-features = false, features = ['rustc-dep-of-std'] } diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs index 0b86b4f30b..94e6070c0f 100644 --- a/library/std/src/backtrace.rs +++ b/library/std/src/backtrace.rs @@ -99,7 +99,7 @@ use crate::cell::UnsafeCell; use crate::env; use crate::ffi::c_void; use crate::fmt; -use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst}; +use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed}; use crate::sync::Once; use crate::sys_common::backtrace::{lock, output_filename}; use crate::vec::Vec; @@ -256,7 +256,7 @@ impl Backtrace { // backtrace captures speedy, because otherwise reading environment // variables every time can be somewhat slow. static ENABLED: AtomicUsize = AtomicUsize::new(0); - match ENABLED.load(SeqCst) { + match ENABLED.load(Relaxed) { 0 => {} 1 => return false, _ => return true, @@ -268,7 +268,7 @@ impl Backtrace { Err(_) => false, }, }; - ENABLED.store(enabled as usize + 1, SeqCst); + ENABLED.store(enabled as usize + 1, Relaxed); enabled } diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 12246b5173..efd5785f4c 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -334,10 +334,11 @@ impl HashMap { /// ``` /// use std::collections::HashMap; /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); + /// let map = HashMap::from([ + /// ("a", 1), + /// ("b", 2), + /// ("c", 3), + /// ]); /// /// for key in map.keys() { /// println!("{}", key); @@ -348,6 +349,33 @@ impl HashMap { Keys { inner: self.iter() } } + /// Creates a consuming iterator visiting all the keys in arbitrary order. + /// The map cannot be used after calling this. + /// The iterator element type is `K`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let map = HashMap::from([ + /// ("a", 1), + /// ("b", 2), + /// ("c", 3), + /// ]); + /// + /// let mut vec: Vec<&str> = map.into_keys().collect(); + /// // The `IntoKeys` iterator produces keys in arbitrary order, so the + /// // keys must be sorted to test them against a sorted array. + /// vec.sort_unstable(); + /// assert_eq!(vec, ["a", "b", "c"]); + /// ``` + #[inline] + #[stable(feature = "map_into_keys_values", since = "1.54.0")] + pub fn into_keys(self) -> IntoKeys { + IntoKeys { inner: self.into_iter() } + } + /// An iterator visiting all values in arbitrary order. /// The iterator element type is `&'a V`. /// @@ -356,10 +384,11 @@ impl HashMap { /// ``` /// use std::collections::HashMap; /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); + /// let map = HashMap::from([ + /// ("a", 1), + /// ("b", 2), + /// ("c", 3), + /// ]); /// /// for val in map.values() { /// println!("{}", val); @@ -378,11 +407,11 @@ impl HashMap { /// ``` /// use std::collections::HashMap; /// - /// let mut map = HashMap::new(); - /// - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); + /// let mut map = HashMap::from([ + /// ("a", 1), + /// ("b", 2), + /// ("c", 3), + /// ]); /// /// for val in map.values_mut() { /// *val = *val + 10; @@ -397,6 +426,33 @@ impl HashMap { ValuesMut { inner: self.iter_mut() } } + /// Creates a consuming iterator visiting all the values in arbitrary order. + /// The map cannot be used after calling this. + /// The iterator element type is `V`. + /// + /// # Examples + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let map = HashMap::from([ + /// ("a", 1), + /// ("b", 2), + /// ("c", 3), + /// ]); + /// + /// let mut vec: Vec = map.into_values().collect(); + /// // The `IntoValues` iterator produces values in arbitrary order, so + /// // the values must be sorted to test them against a sorted array. + /// vec.sort_unstable(); + /// assert_eq!(vec, [1, 2, 3]); + /// ``` + #[inline] + #[stable(feature = "map_into_keys_values", since = "1.54.0")] + pub fn into_values(self) -> IntoValues { + IntoValues { inner: self.into_iter() } + } + /// An iterator visiting all key-value pairs in arbitrary order. /// The iterator element type is `(&'a K, &'a V)`. /// @@ -405,10 +461,11 @@ impl HashMap { /// ``` /// use std::collections::HashMap; /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); + /// let map = HashMap::from([ + /// ("a", 1), + /// ("b", 2), + /// ("c", 3), + /// ]); /// /// for (key, val) in map.iter() { /// println!("key: {} val: {}", key, val); @@ -428,10 +485,11 @@ impl HashMap { /// ``` /// use std::collections::HashMap; /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); + /// let mut map = HashMap::from([ + /// ("a", 1), + /// ("b", 2), + /// ("c", 3), + /// ]); /// /// // Update all values /// for (_, val) in map.iter_mut() { @@ -551,6 +609,29 @@ impl HashMap { DrainFilter { base: self.base.drain_filter(pred) } } + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all pairs `(k, v)` such that `f(&k, &mut v)` returns `false`. + /// The elements are visited in unsorted (and unspecified) order. + /// + /// # Examples + /// + /// ``` + /// use std::collections::HashMap; + /// + /// let mut map: HashMap = (0..8).map(|x| (x, x*10)).collect(); + /// map.retain(|&k, _| k % 2 == 0); + /// assert_eq!(map.len(), 4); + /// ``` + #[inline] + #[stable(feature = "retain_hash_collection", since = "1.18.0")] + pub fn retain(&mut self, f: F) + where + F: FnMut(&K, &mut V) -> bool, + { + self.base.retain(f) + } + /// Clears the map, removing all key-value pairs. Keeps the allocated memory /// for reuse. /// @@ -933,81 +1014,6 @@ where { self.base.remove_entry(k) } - - /// Retains only the elements specified by the predicate. - /// - /// In other words, remove all pairs `(k, v)` such that `f(&k, &mut v)` returns `false`. - /// The elements are visited in unsorted (and unspecified) order. - /// - /// # Examples - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map: HashMap = (0..8).map(|x| (x, x*10)).collect(); - /// map.retain(|&k, _| k % 2 == 0); - /// assert_eq!(map.len(), 4); - /// ``` - #[inline] - #[stable(feature = "retain_hash_collection", since = "1.18.0")] - pub fn retain(&mut self, f: F) - where - F: FnMut(&K, &mut V) -> bool, - { - self.base.retain(f) - } - - /// Creates a consuming iterator visiting all the keys in arbitrary order. - /// The map cannot be used after calling this. - /// The iterator element type is `K`. - /// - /// # Examples - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// let mut vec: Vec<&str> = map.into_keys().collect(); - /// // The `IntoKeys` iterator produces keys in arbitrary order, so the - /// // keys must be sorted to test them against a sorted array. - /// vec.sort_unstable(); - /// assert_eq!(vec, ["a", "b", "c"]); - /// ``` - #[inline] - #[stable(feature = "map_into_keys_values", since = "1.54.0")] - pub fn into_keys(self) -> IntoKeys { - IntoKeys { inner: self.into_iter() } - } - - /// Creates a consuming iterator visiting all the values in arbitrary order. - /// The map cannot be used after calling this. - /// The iterator element type is `V`. - /// - /// # Examples - /// - /// ``` - /// use std::collections::HashMap; - /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); - /// - /// let mut vec: Vec = map.into_values().collect(); - /// // The `IntoValues` iterator produces values in arbitrary order, so - /// // the values must be sorted to test them against a sorted array. - /// vec.sort_unstable(); - /// assert_eq!(vec, [1, 2, 3]); - /// ``` - #[inline] - #[stable(feature = "map_into_keys_values", since = "1.54.0")] - pub fn into_values(self) -> IntoValues { - IntoValues { inner: self.into_iter() } - } } impl HashMap @@ -1186,7 +1192,7 @@ where /// assert_eq!(map1, map2); /// ``` fn from(arr: [(K, V); N]) -> Self { - crate::array::IntoIter::new(arr).collect() + Self::from_iter(arr) } } @@ -1202,8 +1208,9 @@ where /// ``` /// use std::collections::HashMap; /// -/// let mut map = HashMap::new(); -/// map.insert("a", 1); +/// let map = HashMap::from([ +/// ("a", 1), +/// ]); /// let iter = map.iter(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -1239,8 +1246,9 @@ impl fmt::Debug for Iter<'_, K, V> { /// ``` /// use std::collections::HashMap; /// -/// let mut map = HashMap::new(); -/// map.insert("a", 1); +/// let mut map = HashMap::from([ +/// ("a", 1), +/// ]); /// let iter = map.iter_mut(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -1269,8 +1277,9 @@ impl<'a, K, V> IterMut<'a, K, V> { /// ``` /// use std::collections::HashMap; /// -/// let mut map = HashMap::new(); -/// map.insert("a", 1); +/// let map = HashMap::from([ +/// ("a", 1), +/// ]); /// let iter = map.into_iter(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -1298,8 +1307,9 @@ impl IntoIter { /// ``` /// use std::collections::HashMap; /// -/// let mut map = HashMap::new(); -/// map.insert("a", 1); +/// let map = HashMap::from([ +/// ("a", 1), +/// ]); /// let iter_keys = map.keys(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -1335,8 +1345,9 @@ impl fmt::Debug for Keys<'_, K, V> { /// ``` /// use std::collections::HashMap; /// -/// let mut map = HashMap::new(); -/// map.insert("a", 1); +/// let map = HashMap::from([ +/// ("a", 1), +/// ]); /// let iter_values = map.values(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -1372,8 +1383,9 @@ impl fmt::Debug for Values<'_, K, V> { /// ``` /// use std::collections::HashMap; /// -/// let mut map = HashMap::new(); -/// map.insert("a", 1); +/// let mut map = HashMap::from([ +/// ("a", 1), +/// ]); /// let iter = map.drain(); /// ``` #[stable(feature = "drain", since = "1.6.0")] @@ -1402,8 +1414,9 @@ impl<'a, K, V> Drain<'a, K, V> { /// /// use std::collections::HashMap; /// -/// let mut map = HashMap::new(); -/// map.insert("a", 1); +/// let mut map = HashMap::from([ +/// ("a", 1), +/// ]); /// let iter = map.drain_filter(|_k, v| *v % 2 == 0); /// ``` #[unstable(feature = "hash_drain_filter", issue = "59618")] @@ -1426,8 +1439,9 @@ where /// ``` /// use std::collections::HashMap; /// -/// let mut map = HashMap::new(); -/// map.insert("a", 1); +/// let mut map = HashMap::from([ +/// ("a", 1), +/// ]); /// let iter_values = map.values_mut(); /// ``` #[stable(feature = "map_values_mut", since = "1.10.0")] @@ -1447,8 +1461,9 @@ pub struct ValuesMut<'a, K: 'a, V: 'a> { /// ``` /// use std::collections::HashMap; /// -/// let mut map = HashMap::new(); -/// map.insert("a", 1); +/// let map = HashMap::from([ +/// ("a", 1), +/// ]); /// let iter_keys = map.into_keys(); /// ``` #[stable(feature = "map_into_keys_values", since = "1.54.0")] @@ -1468,8 +1483,9 @@ pub struct IntoKeys { /// ``` /// use std::collections::HashMap; /// -/// let mut map = HashMap::new(); -/// map.insert("a", 1); +/// let map = HashMap::from([ +/// ("a", 1), +/// ]); /// let iter_keys = map.into_values(); /// ``` #[stable(feature = "map_into_keys_values", since = "1.54.0")] @@ -2004,10 +2020,11 @@ impl IntoIterator for HashMap { /// ``` /// use std::collections::HashMap; /// - /// let mut map = HashMap::new(); - /// map.insert("a", 1); - /// map.insert("b", 2); - /// map.insert("c", 3); + /// let map = HashMap::from([ + /// ("a", 1), + /// ("b", 2), + /// ("c", 3), + /// ]); /// /// // Not possible with .iter() /// let vec: Vec<(&str, i32)> = map.into_iter().collect(); @@ -2449,13 +2466,13 @@ impl<'a, K, V> Entry<'a, K, V> { /// use std::collections::HashMap; /// /// let mut map: HashMap<&str, String> = HashMap::new(); - /// let entry = map.entry("poneyland").insert("hoho".to_string()); + /// let entry = map.entry("poneyland").insert_entry("hoho".to_string()); /// /// assert_eq!(entry.key(), &"poneyland"); /// ``` #[inline] #[unstable(feature = "entry_insert", issue = "65225")] - pub fn insert(self, value: V) -> OccupiedEntry<'a, K, V> { + pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> { match self { Occupied(mut entry) => { entry.insert(value); @@ -2788,18 +2805,20 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { /// # Examples /// /// ``` + /// #![feature(entry_insert)] /// use std::collections::HashMap; /// use std::collections::hash_map::Entry; /// /// let mut map: HashMap<&str, u32> = HashMap::new(); /// /// if let Entry::Vacant(o) = map.entry("poneyland") { - /// o.insert(37); + /// o.insert_entry(37); /// } /// assert_eq!(map["poneyland"], 37); /// ``` #[inline] - fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> { + #[unstable(feature = "entry_insert", issue = "65225")] + pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> { let base = self.base.insert_entry(value); OccupiedEntry { base } } diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index 1fc1d39b18..0d087772bf 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -233,7 +233,7 @@ impl HashSet { /// ``` /// use std::collections::HashSet; /// - /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); + /// let mut set = HashSet::from([1, 2, 3]); /// assert!(!set.is_empty()); /// /// // print 1, 2, 3 in an arbitrary order @@ -290,6 +290,28 @@ impl HashSet { DrainFilter { base: self.base.drain_filter(pred) } } + /// Retains only the elements specified by the predicate. + /// + /// In other words, remove all elements `e` such that `f(&e)` returns `false`. + /// The elements are visited in unsorted (and unspecified) order. + /// + /// # Examples + /// + /// ``` + /// use std::collections::HashSet; + /// + /// let mut set = HashSet::from([1, 2, 3, 4, 5, 6]); + /// set.retain(|&k| k % 2 == 0); + /// assert_eq!(set.len(), 3); + /// ``` + #[stable(feature = "retain_hash_collection", since = "1.18.0")] + pub fn retain(&mut self, f: F) + where + F: FnMut(&T) -> bool, + { + self.base.retain(f) + } + /// Clears the set, removing all values. /// /// # Examples @@ -489,8 +511,8 @@ where /// /// ``` /// use std::collections::HashSet; - /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); + /// let a = HashSet::from([1, 2, 3]); + /// let b = HashSet::from([4, 2, 3, 4]); /// /// // Can be seen as `a - b`. /// for x in a.difference(&b) { @@ -518,8 +540,8 @@ where /// /// ``` /// use std::collections::HashSet; - /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); + /// let a = HashSet::from([1, 2, 3]); + /// let b = HashSet::from([4, 2, 3, 4]); /// /// // Print 1, 4 in arbitrary order. /// for x in a.symmetric_difference(&b) { @@ -548,8 +570,8 @@ where /// /// ``` /// use std::collections::HashSet; - /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); + /// let a = HashSet::from([1, 2, 3]); + /// let b = HashSet::from([4, 2, 3, 4]); /// /// // Print 2, 3 in arbitrary order. /// for x in a.intersection(&b) { @@ -576,8 +598,8 @@ where /// /// ``` /// use std::collections::HashSet; - /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); - /// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); + /// let a = HashSet::from([1, 2, 3]); + /// let b = HashSet::from([4, 2, 3, 4]); /// /// // Print 1, 2, 3, 4 in arbitrary order. /// for x in a.union(&b) { @@ -608,7 +630,7 @@ where /// ``` /// use std::collections::HashSet; /// - /// let set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); + /// let set = HashSet::from([1, 2, 3]); /// assert_eq!(set.contains(&1), true); /// assert_eq!(set.contains(&4), false); /// ``` @@ -633,7 +655,7 @@ where /// ``` /// use std::collections::HashSet; /// - /// let set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); + /// let set = HashSet::from([1, 2, 3]); /// assert_eq!(set.get(&2), Some(&2)); /// assert_eq!(set.get(&4), None); /// ``` @@ -657,7 +679,7 @@ where /// /// use std::collections::HashSet; /// - /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); + /// let mut set = HashSet::from([1, 2, 3]); /// assert_eq!(set.len(), 3); /// assert_eq!(set.get_or_insert(2), &2); /// assert_eq!(set.get_or_insert(100), &100); @@ -744,7 +766,7 @@ where /// ``` /// use std::collections::HashSet; /// - /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect(); + /// let a = HashSet::from([1, 2, 3]); /// let mut b = HashSet::new(); /// /// assert_eq!(a.is_disjoint(&b), true); @@ -770,7 +792,7 @@ where /// ``` /// use std::collections::HashSet; /// - /// let sup: HashSet<_> = [1, 2, 3].iter().cloned().collect(); + /// let sup = HashSet::from([1, 2, 3]); /// let mut set = HashSet::new(); /// /// assert_eq!(set.is_subset(&sup), true); @@ -792,7 +814,7 @@ where /// ``` /// use std::collections::HashSet; /// - /// let sub: HashSet<_> = [1, 2].iter().cloned().collect(); + /// let sub = HashSet::from([1, 2]); /// let mut set = HashSet::new(); /// /// assert_eq!(set.is_superset(&sub), false); @@ -893,7 +915,7 @@ where /// ``` /// use std::collections::HashSet; /// - /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); + /// let mut set = HashSet::from([1, 2, 3]); /// assert_eq!(set.take(&2), Some(2)); /// assert_eq!(set.take(&2), None); /// ``` @@ -906,29 +928,6 @@ where { self.base.take(value) } - - /// Retains only the elements specified by the predicate. - /// - /// In other words, remove all elements `e` such that `f(&e)` returns `false`. - /// The elements are visited in unsorted (and unspecified) order. - /// - /// # Examples - /// - /// ``` - /// use std::collections::HashSet; - /// - /// let xs = [1, 2, 3, 4, 5, 6]; - /// let mut set: HashSet = xs.iter().cloned().collect(); - /// set.retain(|&k| k % 2 == 0); - /// assert_eq!(set.len(), 3); - /// ``` - #[stable(feature = "retain_hash_collection", since = "1.18.0")] - pub fn retain(&mut self, f: F) - where - F: FnMut(&T) -> bool, - { - self.base.retain(f) - } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1022,7 +1021,7 @@ where /// assert_eq!(set1, set2); /// ``` fn from(arr: [T; N]) -> Self { - crate::array::IntoIter::new(arr).collect() + Self::from_iter(arr) } } @@ -1097,8 +1096,8 @@ where /// ``` /// use std::collections::HashSet; /// - /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect(); - /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect(); + /// let a = HashSet::from([1, 2, 3]); + /// let b = HashSet::from([3, 4, 5]); /// /// let set = &a | &b; /// @@ -1130,8 +1129,8 @@ where /// ``` /// use std::collections::HashSet; /// - /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect(); - /// let b: HashSet<_> = vec![2, 3, 4].into_iter().collect(); + /// let a = HashSet::from([1, 2, 3]); + /// let b = HashSet::from([2, 3, 4]); /// /// let set = &a & &b; /// @@ -1163,8 +1162,8 @@ where /// ``` /// use std::collections::HashSet; /// - /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect(); - /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect(); + /// let a = HashSet::from([1, 2, 3]); + /// let b = HashSet::from([3, 4, 5]); /// /// let set = &a ^ &b; /// @@ -1196,8 +1195,8 @@ where /// ``` /// use std::collections::HashSet; /// - /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect(); - /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect(); + /// let a = HashSet::from([1, 2, 3]); + /// let b = HashSet::from([3, 4, 5]); /// /// let set = &a - &b; /// @@ -1226,7 +1225,7 @@ where /// ``` /// use std::collections::HashSet; /// -/// let a: HashSet = vec![1, 2, 3].into_iter().collect(); +/// let a = HashSet::from([1, 2, 3]); /// /// let mut iter = a.iter(); /// ``` @@ -1248,7 +1247,7 @@ pub struct Iter<'a, K: 'a> { /// ``` /// use std::collections::HashSet; /// -/// let a: HashSet = vec![1, 2, 3].into_iter().collect(); +/// let a = HashSet::from([1, 2, 3]); /// /// let mut iter = a.into_iter(); /// ``` @@ -1269,7 +1268,7 @@ pub struct IntoIter { /// ``` /// use std::collections::HashSet; /// -/// let mut a: HashSet = vec![1, 2, 3].into_iter().collect(); +/// let mut a = HashSet::from([1, 2, 3]); /// /// let mut drain = a.drain(); /// ``` @@ -1291,7 +1290,7 @@ pub struct Drain<'a, K: 'a> { /// /// use std::collections::HashSet; /// -/// let mut a: HashSet = vec![1, 2, 3].into_iter().collect(); +/// let mut a = HashSet::from([1, 2, 3]); /// /// let mut drain_filtered = a.drain_filter(|v| v % 2 == 0); /// ``` @@ -1315,8 +1314,8 @@ where /// ``` /// use std::collections::HashSet; /// -/// let a: HashSet = vec![1, 2, 3].into_iter().collect(); -/// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); +/// let a = HashSet::from([1, 2, 3]); +/// let b = HashSet::from([4, 2, 3, 4]); /// /// let mut intersection = a.intersection(&b); /// ``` @@ -1342,8 +1341,8 @@ pub struct Intersection<'a, T: 'a, S: 'a> { /// ``` /// use std::collections::HashSet; /// -/// let a: HashSet = vec![1, 2, 3].into_iter().collect(); -/// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); +/// let a = HashSet::from([1, 2, 3]); +/// let b = HashSet::from([4, 2, 3, 4]); /// /// let mut difference = a.difference(&b); /// ``` @@ -1369,8 +1368,8 @@ pub struct Difference<'a, T: 'a, S: 'a> { /// ``` /// use std::collections::HashSet; /// -/// let a: HashSet = vec![1, 2, 3].into_iter().collect(); -/// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); +/// let a = HashSet::from([1, 2, 3]); +/// let b = HashSet::from([4, 2, 3, 4]); /// /// let mut intersection = a.symmetric_difference(&b); /// ``` @@ -1393,8 +1392,8 @@ pub struct SymmetricDifference<'a, T: 'a, S: 'a> { /// ``` /// use std::collections::HashSet; /// -/// let a: HashSet = vec![1, 2, 3].into_iter().collect(); -/// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect(); +/// let a = HashSet::from([1, 2, 3]); +/// let b = HashSet::from([4, 2, 3, 4]); /// /// let mut union_iter = a.union(&b); /// ``` diff --git a/library/std/src/env.rs b/library/std/src/env.rs index c6af708f6c..c06928647d 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -583,28 +583,25 @@ pub fn home_dir() -> Option { /// may result in "insecure temporary file" security vulnerabilities. Consider /// using a crate that securely creates temporary files or directories. /// -/// # Unix +/// # Platform-specific behavior /// -/// Returns the value of the `TMPDIR` environment variable if it is +/// On Unix, returns the value of the `TMPDIR` environment variable if it is /// set, otherwise for non-Android it returns `/tmp`. If Android, since there /// is no global temporary folder (it is usually allocated per-app), it returns /// `/data/local/tmp`. +/// On Windows, the behavior is equivalent to that of [`GetTempPath2`][GetTempPath2] / +/// [`GetTempPath`][GetTempPath], which this function uses internally. +/// Note that, this [may change in the future][changes]. /// -/// # Windows -/// -/// Returns the value of, in order, the `TMP`, `TEMP`, -/// `USERPROFILE` environment variable if any are set and not the empty -/// string. Otherwise, `temp_dir` returns the path of the Windows directory. -/// This behavior is identical to that of [`GetTempPath`][msdn], which this -/// function uses internally. -/// -/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppatha +/// [changes]: io#platform-specific-behavior +/// [GetTempPath2]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppath2a +/// [GetTempPath]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppatha /// /// ```no_run /// use std::env; /// /// fn main() { -/// let mut dir = env::temp_dir(); +/// let dir = env::temp_dir(); /// println!("Temporary directory: {}", dir.display()); /// } /// ``` diff --git a/library/std/src/error.rs b/library/std/src/error.rs index 6ae0bc47a9..ea0c230fa4 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -478,6 +478,9 @@ impl Error for char::DecodeUtf16Error { } } +#[stable(feature = "u8_from_char", since = "1.59.0")] +impl Error for char::TryFromCharError {} + #[unstable(feature = "map_try_insert", issue = "82766")] impl<'a, K: Debug + Ord, V: Debug> Error for crate::collections::btree_map::OccupiedError<'a, K, V> diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs index 465bbae863..9c1b79d696 100644 --- a/library/std/src/ffi/c_str.rs +++ b/library/std/src/ffi/c_str.rs @@ -1259,7 +1259,7 @@ impl CStr { #[inline] #[must_use] #[stable(feature = "cstr_from_bytes", since = "1.10.0")] - #[rustc_const_unstable(feature = "const_cstr_unchecked", issue = "90343")] + #[rustc_const_stable(feature = "const_cstr_unchecked", since = "1.59.0")] pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr { // SAFETY: Casting to CStr is safe because its internal representation // is a [u8] too (safe only inside std). diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs index 7f3bb83675..019b64c395 100644 --- a/library/std/src/ffi/mod.rs +++ b/library/std/src/ffi/mod.rs @@ -81,9 +81,9 @@ //! [`OsStr`] and Rust strings work similarly to those for [`CString`] //! and [`CStr`]. //! -//! * [`OsString`] represents an owned string in whatever -//! representation the operating system prefers. In the Rust standard -//! library, various APIs that transfer strings to/from the operating +//! * [`OsString`] losslessly represents an owned platform string. However, this +//! representation is not necessarily in a form native to the platform. +//! In the Rust standard library, various APIs that transfer strings to/from the operating //! system use [`OsString`] instead of plain strings. For example, //! [`env::var_os()`] is used to query environment variables; it //! returns an [Option]<[OsString]>. If the environment variable @@ -92,9 +92,9 @@ //! your code can detect errors in case the environment variable did //! not in fact contain valid Unicode data. //! -//! * [`OsStr`] represents a borrowed reference to a string in a -//! format that can be passed to the operating system. It can be -//! converted into a UTF-8 Rust string slice in a similar way to +//! * [`OsStr`] losslessly represents a borrowed reference to a platform string. +//! However, this representation is not necessarily in a form native to the platform. +//! It can be converted into a UTF-8 Rust string slice in a similar way to //! [`OsString`]. //! //! # Conversions @@ -113,16 +113,19 @@ //! //! ## On Windows //! +//! An [`OsStr`] can be losslessly converted to a native Windows string. And +//! a native Windows string can be losslessly converted to an [`OsString`]. +//! //! On Windows, [`OsStr`] implements the //! std::os::windows::ffi::[OsStrExt][windows.OsStrExt] trait, //! which provides an [`encode_wide`] method. This provides an -//! iterator that can be [`collect`]ed into a vector of [`u16`]. +//! iterator that can be [`collect`]ed into a vector of [`u16`]. After a nul +//! characters is appended, this is the same as a native Windows string. //! //! Additionally, on Windows [`OsString`] implements the //! std::os::windows:ffi::[OsStringExt][windows.OsStringExt] -//! trait, which provides a [`from_wide`] method. The result of this -//! method is an [`OsString`] which can be round-tripped to a Windows -//! string losslessly. +//! trait, which provides a [`from_wide`] method to convert a native Windows +//! string (without the terminating nul character) to an [`OsString`]. //! //! [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value //! [Unicode code point]: https://www.unicode.org/glossary/#code_point diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 0f9912fa64..982ad18987 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -3,6 +3,7 @@ mod tests; use crate::borrow::{Borrow, Cow}; use crate::cmp; +use crate::collections::TryReserveError; use crate::fmt; use crate::hash::{Hash, Hasher}; use crate::iter::{Extend, FromIterator}; @@ -265,6 +266,43 @@ impl OsString { self.inner.reserve(additional) } + /// Tries to reserve capacity for at least `additional` more length units + /// in the given `OsString`. The string may reserve more space to avoid + /// frequent reallocations. After calling `try_reserve`, capacity will be + /// greater than or equal to `self.len() + additional`. Does nothing if + /// capacity is already sufficient. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_reserve_2)] + /// use std::ffi::{OsStr, OsString}; + /// use std::collections::TryReserveError; + /// + /// fn process_data(data: &str) -> Result { + /// let mut s = OsString::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// s.try_reserve(OsStr::new(data).len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// s.push(data); + /// + /// Ok(s) + /// } + /// # process_data("123").expect("why is the test harness OOMing on 3 bytes?"); + /// ``` + #[unstable(feature = "try_reserve_2", issue = "91789")] + #[inline] + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.inner.try_reserve(additional) + } + /// Reserves the minimum capacity for exactly `additional` more capacity to /// be inserted in the given `OsString`. Does nothing if the capacity is /// already sufficient. @@ -290,6 +328,49 @@ impl OsString { self.inner.reserve_exact(additional) } + /// Tries to reserve the minimum capacity for exactly `additional` + /// more length units in the given `OsString`. After calling + /// `try_reserve_exact`, capacity will be greater than or equal to + /// `self.len() + additional` if it returns `Ok(())`. + /// Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the `OsString` more space than it + /// requests. Therefore, capacity can not be relied upon to be precisely + /// minimal. Prefer [`try_reserve`] if future insertions are expected. + /// + /// [`try_reserve`]: OsString::try_reserve + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_reserve_2)] + /// use std::ffi::{OsStr, OsString}; + /// use std::collections::TryReserveError; + /// + /// fn process_data(data: &str) -> Result { + /// let mut s = OsString::new(); + /// + /// // Pre-reserve the memory, exiting if we can't + /// s.try_reserve_exact(OsStr::new(data).len())?; + /// + /// // Now we know this can't OOM in the middle of our complex work + /// s.push(data); + /// + /// Ok(s) + /// } + /// # process_data("123").expect("why is the test harness OOMing on 3 bytes?"); + /// ``` + #[unstable(feature = "try_reserve_2", issue = "91789")] + #[inline] + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.inner.try_reserve_exact(additional) + } + /// Shrinks the capacity of the `OsString` to match its length. /// /// # Examples diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index f7f7a9ba4e..0e1363328c 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -13,7 +13,7 @@ mod tests; use crate::ffi::OsString; use crate::fmt; -use crate::io::{self, Initializer, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write}; +use crate::io::{self, IoSlice, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, Write}; use crate::path::{Path, PathBuf}; use crate::sys::fs as fs_imp; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; @@ -623,15 +623,13 @@ impl Read for File { self.inner.read_vectored(bufs) } - #[inline] - fn is_read_vectored(&self) -> bool { - self.inner.is_read_vectored() + fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + self.inner.read_buf(buf) } #[inline] - unsafe fn initializer(&self) -> Initializer { - // SAFETY: Read is guaranteed to work on uninitialized memory - unsafe { Initializer::nop() } + fn is_read_vectored(&self) -> bool { + self.inner.is_read_vectored() } // Reserves space in the buffer based on the file size when available. @@ -677,6 +675,10 @@ impl Read for &File { self.inner.read(buf) } + fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + self.inner.read_buf(buf) + } + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { self.inner.read_vectored(bufs) } @@ -686,12 +688,6 @@ impl Read for &File { self.inner.is_read_vectored() } - #[inline] - unsafe fn initializer(&self) -> Initializer { - // SAFETY: Read is guaranteed to work on uninitialized memory - unsafe { Initializer::nop() } - } - // Reserves space in the buffer based on the file size when available. fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { buf.reserve(buffer_capacity_required(self)); @@ -1062,7 +1058,7 @@ impl Metadata { /// } /// ``` #[must_use] - #[stable(feature = "is_symlink", since = "1.57.0")] + #[stable(feature = "is_symlink", since = "1.58.0")] pub fn is_symlink(&self) -> bool { self.file_type().is_symlink() } diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 4d1959258b..a62c01ef29 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -40,10 +40,9 @@ macro_rules! error { ($e:expr, $s:expr) => { match $e { Ok(_) => panic!("Unexpected success. Should've been: {:?}", $s), - Err(ref err) => assert!( - err.raw_os_error() == Some($s), - format!("`{}` did not have a code of `{}`", err, $s) - ), + Err(ref err) => { + assert!(err.raw_os_error() == Some($s), "`{}` did not have a code of `{}`", err, $s) + } } }; } @@ -60,7 +59,7 @@ macro_rules! error_contains { match $e { Ok(_) => panic!("Unexpected success. Should've been: {:?}", $s), Err(ref err) => { - assert!(err.to_string().contains($s), format!("`{}` did not contain `{}`", err, $s)) + assert!(err.to_string().contains($s), "`{}` did not contain `{}`", err, $s) } } }; @@ -1439,7 +1438,7 @@ fn symlink_hard_link() { // "hard_link" should appear as a symlink. assert!(check!(fs::symlink_metadata(tmpdir.join("hard_link"))).file_type().is_symlink()); - // We sould be able to open "file" via any of the above names. + // We should be able to open "file" via any of the above names. let _ = check!(fs::File::open(tmpdir.join("file"))); assert!(fs::File::open(tmpdir.join("file.renamed")).is_err()); let _ = check!(fs::File::open(tmpdir.join("symlink"))); diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index 2864e94f60..b56dc65f0b 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -1,8 +1,9 @@ use crate::cmp; use crate::fmt; use crate::io::{ - self, BufRead, Initializer, IoSliceMut, Read, Seek, SeekFrom, SizeHint, DEFAULT_BUF_SIZE, + self, BufRead, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, SizeHint, DEFAULT_BUF_SIZE, }; +use crate::mem::MaybeUninit; /// The `BufReader` struct adds buffering to any reader. /// @@ -47,9 +48,10 @@ use crate::io::{ #[stable(feature = "rust1", since = "1.0.0")] pub struct BufReader { inner: R, - buf: Box<[u8]>, + buf: Box<[MaybeUninit]>, pos: usize, cap: usize, + init: usize, } impl BufReader { @@ -91,11 +93,8 @@ impl BufReader { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn with_capacity(capacity: usize, inner: R) -> BufReader { - unsafe { - let mut buf = Box::new_uninit_slice(capacity).assume_init(); - inner.initializer().initialize(&mut buf); - BufReader { inner, buf, pos: 0, cap: 0 } - } + let buf = Box::new_uninit_slice(capacity); + BufReader { inner, buf, pos: 0, cap: 0, init: 0 } } } @@ -171,7 +170,8 @@ impl BufReader { /// ``` #[stable(feature = "bufreader_buffer", since = "1.37.0")] pub fn buffer(&self) -> &[u8] { - &self.buf[self.pos..self.cap] + // SAFETY: self.cap is always <= self.init, so self.buf[self.pos..self.cap] is always init + unsafe { MaybeUninit::slice_assume_init_ref(&self.buf[self.pos..self.cap]) } } /// Returns the number of bytes the internal buffer can hold at once. @@ -271,6 +271,25 @@ impl Read for BufReader { Ok(nread) } + fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + // If we don't have any buffered data and we're doing a massive read + // (larger than our internal buffer), bypass our internal buffer + // entirely. + if self.pos == self.cap && buf.remaining() >= self.buf.len() { + self.discard_buffer(); + return self.inner.read_buf(buf); + } + + let prev = buf.filled_len(); + + let mut rem = self.fill_buf()?; + rem.read_buf(buf)?; + + self.consume(buf.filled_len() - prev); //slice impl of read_buf known to never unfill buf + + Ok(()) + } + // Small read_exacts from a BufReader are extremely common when used with a deserializer. // The default implementation calls read in a loop, which results in surprisingly poor code // generation for the common path where the buffer has enough bytes to fill the passed-in @@ -303,16 +322,11 @@ impl Read for BufReader { self.inner.is_read_vectored() } - // we can't skip unconditionally because of the large buffer case in read. - unsafe fn initializer(&self) -> Initializer { - self.inner.initializer() - } - // The inner reader might have an optimized `read_to_end`. Drain our buffer and then // delegate to the inner implementation. fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { let nread = self.cap - self.pos; - buf.extend_from_slice(&self.buf[self.pos..self.cap]); + buf.extend_from_slice(&self.buffer()); self.discard_buffer(); Ok(nread + self.inner.read_to_end(buf)?) } @@ -363,10 +377,23 @@ impl BufRead for BufReader { // to tell the compiler that the pos..cap slice is always valid. if self.pos >= self.cap { debug_assert!(self.pos == self.cap); - self.cap = self.inner.read(&mut self.buf)?; + + let mut readbuf = ReadBuf::uninit(&mut self.buf); + + // SAFETY: `self.init` is either 0 or set to `readbuf.initialized_len()` + // from the last time this function was called + unsafe { + readbuf.assume_init(self.init); + } + + self.inner.read_buf(&mut readbuf)?; + + self.cap = readbuf.filled_len(); + self.init = readbuf.initialized_len(); + self.pos = 0; } - Ok(&self.buf[self.pos..self.cap]) + Ok(self.buffer()) } fn consume(&mut self, amt: usize) { diff --git a/library/std/src/io/buffered/tests.rs b/library/std/src/io/buffered/tests.rs index feb149c07a..9d429e7090 100644 --- a/library/std/src/io/buffered/tests.rs +++ b/library/std/src/io/buffered/tests.rs @@ -1,5 +1,6 @@ use crate::io::prelude::*; -use crate::io::{self, BufReader, BufWriter, ErrorKind, IoSlice, LineWriter, SeekFrom}; +use crate::io::{self, BufReader, BufWriter, ErrorKind, IoSlice, LineWriter, ReadBuf, SeekFrom}; +use crate::mem::MaybeUninit; use crate::panic; use crate::sync::atomic::{AtomicUsize, Ordering}; use crate::thread; @@ -55,6 +56,55 @@ fn test_buffered_reader() { assert_eq!(reader.read(&mut buf).unwrap(), 0); } +#[test] +fn test_buffered_reader_read_buf() { + let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4]; + let mut reader = BufReader::with_capacity(2, inner); + + let mut buf = [MaybeUninit::uninit(); 3]; + let mut buf = ReadBuf::uninit(&mut buf); + + reader.read_buf(&mut buf).unwrap(); + + assert_eq!(buf.filled(), [5, 6, 7]); + assert_eq!(reader.buffer(), []); + + let mut buf = [MaybeUninit::uninit(); 2]; + let mut buf = ReadBuf::uninit(&mut buf); + + reader.read_buf(&mut buf).unwrap(); + + assert_eq!(buf.filled(), [0, 1]); + assert_eq!(reader.buffer(), []); + + let mut buf = [MaybeUninit::uninit(); 1]; + let mut buf = ReadBuf::uninit(&mut buf); + + reader.read_buf(&mut buf).unwrap(); + + assert_eq!(buf.filled(), [2]); + assert_eq!(reader.buffer(), [3]); + + let mut buf = [MaybeUninit::uninit(); 3]; + let mut buf = ReadBuf::uninit(&mut buf); + + reader.read_buf(&mut buf).unwrap(); + + assert_eq!(buf.filled(), [3]); + assert_eq!(reader.buffer(), []); + + reader.read_buf(&mut buf).unwrap(); + + assert_eq!(buf.filled(), [3, 4]); + assert_eq!(reader.buffer(), []); + + buf.clear(); + + reader.read_buf(&mut buf).unwrap(); + + assert_eq!(buf.filled_len(), 0); +} + #[test] fn test_buffered_reader_seek() { let inner: &[u8] = &[5, 6, 7, 0, 1, 2, 3, 4]; diff --git a/library/std/src/io/copy.rs b/library/std/src/io/copy.rs index eb60df214c..6ab9666230 100644 --- a/library/std/src/io/copy.rs +++ b/library/std/src/io/copy.rs @@ -1,4 +1,4 @@ -use super::{BufWriter, ErrorKind, Read, Result, Write, DEFAULT_BUF_SIZE}; +use super::{BufWriter, ErrorKind, Read, ReadBuf, Result, Write, DEFAULT_BUF_SIZE}; use crate::mem::MaybeUninit; /// Copies the entire contents of a reader into a writer. @@ -82,33 +82,30 @@ impl BufferedCopySpec for BufWriter { return stack_buffer_copy(reader, writer); } - // FIXME: #42788 - // - // - This creates a (mut) reference to a slice of - // _uninitialized_ integers, which is **undefined behavior** - // - // - Only the standard library gets to soundly "ignore" this, - // based on its privileged knowledge of unstable rustc - // internals; - unsafe { - let spare_cap = writer.buffer_mut().spare_capacity_mut(); - reader.initializer().initialize(MaybeUninit::slice_assume_init_mut(spare_cap)); - } - let mut len = 0; + let mut init = 0; loop { let buf = writer.buffer_mut(); - let spare_cap = buf.spare_capacity_mut(); + let mut read_buf = ReadBuf::uninit(buf.spare_capacity_mut()); - if spare_cap.len() >= DEFAULT_BUF_SIZE { - match reader.read(unsafe { MaybeUninit::slice_assume_init_mut(spare_cap) }) { - Ok(0) => return Ok(len), // EOF reached - Ok(bytes_read) => { - assert!(bytes_read <= spare_cap.len()); - // SAFETY: The initializer contract guarantees that either it or `read` - // will have initialized these bytes. And we just checked that the number - // of bytes is within the buffer capacity. + // SAFETY: init is either 0 or the initialized_len of the previous iteration + unsafe { + read_buf.assume_init(init); + } + + if read_buf.capacity() >= DEFAULT_BUF_SIZE { + match reader.read_buf(&mut read_buf) { + Ok(()) => { + let bytes_read = read_buf.filled_len(); + + if bytes_read == 0 { + return Ok(len); + } + + init = read_buf.initialized_len() - bytes_read; + + // SAFETY: ReadBuf guarantees all of its filled bytes are init unsafe { buf.set_len(buf.len() + bytes_read) }; len += bytes_read as u64; // Read again if the buffer still has enough capacity, as BufWriter itself would do @@ -129,28 +126,26 @@ fn stack_buffer_copy( reader: &mut R, writer: &mut W, ) -> Result { - let mut buf = MaybeUninit::<[u8; DEFAULT_BUF_SIZE]>::uninit(); - // FIXME: #42788 - // - // - This creates a (mut) reference to a slice of - // _uninitialized_ integers, which is **undefined behavior** - // - // - Only the standard library gets to soundly "ignore" this, - // based on its privileged knowledge of unstable rustc - // internals; - unsafe { - reader.initializer().initialize(buf.assume_init_mut()); - } + let mut buf = [MaybeUninit::uninit(); DEFAULT_BUF_SIZE]; + let mut buf = ReadBuf::uninit(&mut buf); + + let mut len = 0; - let mut written = 0; loop { - let len = match reader.read(unsafe { buf.assume_init_mut() }) { - Ok(0) => return Ok(written), - Ok(len) => len, - Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, + match reader.read_buf(&mut buf) { + Ok(()) => {} + Err(e) if e.kind() == ErrorKind::Interrupted => continue, Err(e) => return Err(e), }; - writer.write_all(unsafe { &buf.assume_init_ref()[..len] })?; - written += len as u64; + + if buf.filled().is_empty() { + break; + } + + len += buf.filled().len() as u64; + writer.write_all(buf.filled())?; + buf.clear(); } + + Ok(len) } diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index 980b253119..416cc906e6 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -4,7 +4,7 @@ mod tests; use crate::io::prelude::*; use crate::cmp; -use crate::io::{self, Error, ErrorKind, Initializer, IoSlice, IoSliceMut, SeekFrom}; +use crate::io::{self, Error, ErrorKind, IoSlice, IoSliceMut, ReadBuf, SeekFrom}; use core::convert::TryInto; @@ -324,6 +324,16 @@ where Ok(n) } + fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + let prev_filled = buf.filled_len(); + + Read::read_buf(&mut self.fill_buf()?, buf)?; + + self.pos += (buf.filled_len() - prev_filled) as u64; + + Ok(()) + } + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { let mut nread = 0; for buf in bufs { @@ -346,11 +356,6 @@ where self.pos += n as u64; Ok(()) } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index d93c6172cf..210a9ec718 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -417,6 +417,33 @@ impl Error { Self::_new(kind, error.into()) } + /// Creates a new I/O error from an arbitrary error payload. + /// + /// This function is used to generically create I/O errors which do not + /// originate from the OS itself. It is a shortcut for [`Error::new`] + /// with [`ErrorKind::Other`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(io_error_other)] + /// + /// use std::io::Error; + /// + /// // errors can be created from strings + /// let custom_error = Error::other("oh no!"); + /// + /// // errors can also be created from other errors + /// let custom_error2 = Error::other(custom_error); + /// ``` + #[unstable(feature = "io_error_other", issue = "91946")] + pub fn other(error: E) -> Error + where + E: Into>, + { + Self::_new(ErrorKind::Other, error.into()) + } + fn _new(kind: ErrorKind, error: Box) -> Error { Error { repr: Repr::Custom(Box::new(Custom { kind, error })) } } @@ -440,12 +467,18 @@ impl Error { /// `GetLastError` on Windows) and will return a corresponding instance of /// [`Error`] for the error code. /// + /// This should be called immediately after a call to a platform function, + /// otherwise the state of the error value is indeterminate. In particular, + /// other standard library functions may call platform functions that may + /// (or may not) reset the error value even if they succeed. + /// /// # Examples /// /// ``` /// use std::io::Error; /// - /// println!("last OS error: {:?}", Error::last_os_error()); + /// let os_error = Error::last_os_error(); + /// println!("last OS error: {:?}", os_error); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[must_use] diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index 7a2a49ba7d..23201f9fc5 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -5,7 +5,7 @@ use crate::alloc::Allocator; use crate::cmp; use crate::fmt; use crate::io::{ - self, BufRead, Error, ErrorKind, Initializer, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write, + self, BufRead, Error, ErrorKind, IoSlice, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, Write, }; use crate::mem; @@ -19,6 +19,11 @@ impl Read for &mut R { (**self).read(buf) } + #[inline] + fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + (**self).read_buf(buf) + } + #[inline] fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { (**self).read_vectored(bufs) @@ -29,11 +34,6 @@ impl Read for &mut R { (**self).is_read_vectored() } - #[inline] - unsafe fn initializer(&self) -> Initializer { - (**self).initializer() - } - #[inline] fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { (**self).read_to_end(buf) @@ -123,6 +123,11 @@ impl Read for Box { (**self).read(buf) } + #[inline] + fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + (**self).read_buf(buf) + } + #[inline] fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { (**self).read_vectored(bufs) @@ -133,11 +138,6 @@ impl Read for Box { (**self).is_read_vectored() } - #[inline] - unsafe fn initializer(&self) -> Initializer { - (**self).initializer() - } - #[inline] fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { (**self).read_to_end(buf) @@ -247,6 +247,17 @@ impl Read for &[u8] { Ok(amt) } + #[inline] + fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + let amt = cmp::min(buf.remaining(), self.len()); + let (a, b) = self.split_at(amt); + + buf.append(a); + + *self = b; + Ok(()) + } + #[inline] fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { let mut nread = 0; @@ -265,11 +276,6 @@ impl Read for &[u8] { true } - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } - #[inline] fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { if buf.len() > self.len() { diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 8cc9156641..ecc9e91b6b 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -256,7 +256,6 @@ use crate::convert::TryInto; use crate::fmt; use crate::mem::replace; use crate::ops::{Deref, DerefMut}; -use crate::ptr; use crate::slice; use crate::str; use crate::sys; @@ -288,12 +287,16 @@ pub use self::stdio::{_eprint, _print}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::util::{empty, repeat, sink, Empty, Repeat, Sink}; +#[unstable(feature = "read_buf", issue = "78485")] +pub use self::readbuf::ReadBuf; + mod buffered; pub(crate) mod copy; mod cursor; mod error; mod impls; pub mod prelude; +mod readbuf; mod stdio; mod util; @@ -355,52 +358,43 @@ where // of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every // time is 4,500 times (!) slower than a default reservation size of 32 if the // reader has a very small amount of data to return. -// -// Because we're extending the buffer with uninitialized data for trusted -// readers, we need to make sure to truncate that if any of this panics. pub(crate) fn default_read_to_end(r: &mut R, buf: &mut Vec) -> Result { let start_len = buf.len(); let start_cap = buf.capacity(); - let mut g = Guard { len: buf.len(), buf }; + + let mut initialized = 0; // Extra initialized bytes from previous loop iteration loop { - // If we've read all the way up to the capacity, reserve more space. - if g.len == g.buf.capacity() { - g.buf.reserve(32); + if buf.len() == buf.capacity() { + buf.reserve(32); // buf is full, need more space } - // Initialize any excess capacity and adjust the length so we can write - // to it. - if g.buf.len() < g.buf.capacity() { - unsafe { - // FIXME(danielhenrymantilla): #42788 - // - // - This creates a (mut) reference to a slice of - // _uninitialized_ integers, which is **undefined behavior** - // - // - Only the standard library gets to soundly "ignore" this, - // based on its privileged knowledge of unstable rustc - // internals; - let capacity = g.buf.capacity(); - g.buf.set_len(capacity); - r.initializer().initialize(&mut g.buf[g.len..]); - } + let mut read_buf = ReadBuf::uninit(buf.spare_capacity_mut()); + + // SAFETY: These bytes were initialized but not filled in the previous loop + unsafe { + read_buf.assume_init(initialized); } - let buf = &mut g.buf[g.len..]; - match r.read(buf) { - Ok(0) => return Ok(g.len - start_len), - Ok(n) => { - // We can't allow bogus values from read. If it is too large, the returned vec could have its length - // set past its capacity, or if it overflows the vec could be shortened which could create an invalid - // string if this is called via read_to_string. - assert!(n <= buf.len()); - g.len += n; - } - Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, + match r.read_buf(&mut read_buf) { + Ok(()) => {} + Err(e) if e.kind() == ErrorKind::Interrupted => continue, Err(e) => return Err(e), } - if g.len == g.buf.capacity() && g.buf.capacity() == start_cap { + if read_buf.filled_len() == 0 { + return Ok(buf.len() - start_len); + } + + // store how much was initialized but not filled + initialized = read_buf.initialized_len() - read_buf.filled_len(); + let new_len = read_buf.filled_len() + buf.len(); + + // SAFETY: ReadBuf's invariants mean this much memory is init + unsafe { + buf.set_len(new_len); + } + + if buf.len() == buf.capacity() && buf.capacity() == start_cap { // The buffer might be an exact fit. Let's read into a probe buffer // and see if it returns `Ok(0)`. If so, we've avoided an // unnecessary doubling of the capacity. But if not, append the @@ -409,10 +403,9 @@ pub(crate) fn default_read_to_end(r: &mut R, buf: &mut Vec loop { match r.read(&mut probe) { - Ok(0) => return Ok(g.len - start_len), + Ok(0) => return Ok(buf.len() - start_len), Ok(n) => { - g.buf.extend_from_slice(&probe[..n]); - g.len += n; + buf.extend_from_slice(&probe[..n]); break; } Err(ref e) if e.kind() == ErrorKind::Interrupted => continue, @@ -474,6 +467,15 @@ pub(crate) fn default_read_exact(this: &mut R, mut buf: &mut [ } } +pub(crate) fn default_read_buf(read: F, buf: &mut ReadBuf<'_>) -> Result<()> +where + F: FnOnce(&mut [u8]) -> Result, +{ + let n = read(buf.initialize_unfilled())?; + buf.add_filled(n); + Ok(()) +} + /// The `Read` trait allows for reading bytes from a source. /// /// Implementors of the `Read` trait are called 'readers'. @@ -656,31 +658,6 @@ pub trait Read { false } - /// Determines if this `Read`er can work with buffers of uninitialized - /// memory. - /// - /// The default implementation returns an initializer which will zero - /// buffers. - /// - /// If a `Read`er guarantees that it can work properly with uninitialized - /// memory, it should call [`Initializer::nop()`]. See the documentation for - /// [`Initializer`] for details. - /// - /// The behavior of this method must be independent of the state of the - /// `Read`er - the method only takes `&self` so that it can be used through - /// trait objects. - /// - /// # Safety - /// - /// This method is unsafe because a `Read`er could otherwise return a - /// non-zeroing `Initializer` from another `Read` type without an `unsafe` - /// block. - #[unstable(feature = "read_initializer", issue = "42788")] - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::zeroing() - } - /// Read all bytes until EOF in this source, placing them into `buf`. /// /// All bytes read from this source will be appended to the specified buffer @@ -830,7 +807,40 @@ pub trait Read { default_read_exact(self, buf) } - /// Creates a "by reference" adapter for this instance of `Read`. + /// Pull some bytes from this source into the specified buffer. + /// + /// This is equivalent to the [`read`](Read::read) method, except that it is passed a [`ReadBuf`] rather than `[u8]` to allow use + /// with uninitialized buffers. The new data will be appended to any existing contents of `buf`. + /// + /// The default implementation delegates to `read`. + #[unstable(feature = "read_buf", issue = "78485")] + fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> Result<()> { + default_read_buf(|b| self.read(b), buf) + } + + /// Read the exact number of bytes required to fill `buf`. + /// + /// This is equivalent to the [`read_exact`](Read::read_exact) method, except that it is passed a [`ReadBuf`] rather than `[u8]` to + /// allow use with uninitialized buffers. + #[unstable(feature = "read_buf", issue = "78485")] + fn read_buf_exact(&mut self, buf: &mut ReadBuf<'_>) -> Result<()> { + while buf.remaining() > 0 { + let prev_filled = buf.filled().len(); + match self.read_buf(buf) { + Ok(()) => {} + Err(e) if e.kind() == ErrorKind::Interrupted => continue, + Err(e) => return Err(e), + } + + if buf.filled().len() == prev_filled { + return Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill buffer")); + } + } + + Ok(()) + } + + /// Creates a "by reference" adaptor for this instance of `Read`. /// /// The returned adapter also implements `Read` and will simply borrow this /// current reader. @@ -1300,53 +1310,6 @@ impl<'a> Deref for IoSlice<'a> { } } -/// A type used to conditionally initialize buffers passed to `Read` methods. -#[unstable(feature = "read_initializer", issue = "42788")] -#[derive(Debug)] -pub struct Initializer(bool); - -impl Initializer { - /// Returns a new `Initializer` which will zero out buffers. - #[unstable(feature = "read_initializer", issue = "42788")] - #[must_use] - #[inline] - pub fn zeroing() -> Initializer { - Initializer(true) - } - - /// Returns a new `Initializer` which will not zero out buffers. - /// - /// # Safety - /// - /// This may only be called by `Read`ers which guarantee that they will not - /// read from buffers passed to `Read` methods, and that the return value of - /// the method accurately reflects the number of bytes that have been - /// written to the head of the buffer. - #[unstable(feature = "read_initializer", issue = "42788")] - #[must_use] - #[inline] - pub unsafe fn nop() -> Initializer { - Initializer(false) - } - - /// Indicates if a buffer should be initialized. - #[unstable(feature = "read_initializer", issue = "42788")] - #[must_use] - #[inline] - pub fn should_initialize(&self) -> bool { - self.0 - } - - /// Initializes a buffer if necessary. - #[unstable(feature = "read_initializer", issue = "42788")] - #[inline] - pub fn initialize(&self, buf: &mut [u8]) { - if self.should_initialize() { - unsafe { ptr::write_bytes(buf.as_mut_ptr(), 0, buf.len()) } - } - } -} - /// A trait for objects which are byte-oriented sinks. /// /// Implementors of the `Write` trait are sometimes called 'writers'. @@ -2403,11 +2366,6 @@ impl Read for Chain { } self.second.read_vectored(bufs) } - - unsafe fn initializer(&self) -> Initializer { - let initializer = self.first.initializer(); - if initializer.should_initialize() { initializer } else { self.second.initializer() } - } } #[stable(feature = "chain_bufread", since = "1.9.0")] @@ -2610,8 +2568,53 @@ impl Read for Take { Ok(n) } - unsafe fn initializer(&self) -> Initializer { - self.inner.initializer() + fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> Result<()> { + // Don't call into inner reader at all at EOF because it may still block + if self.limit == 0 { + return Ok(()); + } + + let prev_filled = buf.filled_len(); + + if self.limit <= buf.remaining() as u64 { + // if we just use an as cast to convert, limit may wrap around on a 32 bit target + let limit = cmp::min(self.limit, usize::MAX as u64) as usize; + + let extra_init = cmp::min(limit as usize, buf.initialized_len() - buf.filled_len()); + + // SAFETY: no uninit data is written to ibuf + let ibuf = unsafe { &mut buf.unfilled_mut()[..limit] }; + + let mut sliced_buf = ReadBuf::uninit(ibuf); + + // SAFETY: extra_init bytes of ibuf are known to be initialized + unsafe { + sliced_buf.assume_init(extra_init); + } + + self.inner.read_buf(&mut sliced_buf)?; + + let new_init = sliced_buf.initialized_len(); + let filled = sliced_buf.filled_len(); + + // sliced_buf / ibuf must drop here + + // SAFETY: new_init bytes of buf's unfilled buffer have been initialized + unsafe { + buf.assume_init(new_init); + } + + buf.add_filled(filled); + + self.limit -= filled as u64; + } else { + self.inner.read_buf(buf)?; + + //inner may unfill + self.limit -= buf.filled_len().saturating_sub(prev_filled) as u64; + } + + Ok(()) } } diff --git a/library/std/src/io/readbuf.rs b/library/std/src/io/readbuf.rs new file mode 100644 index 0000000000..c655bc8893 --- /dev/null +++ b/library/std/src/io/readbuf.rs @@ -0,0 +1,245 @@ +#![unstable(feature = "read_buf", issue = "78485")] + +#[cfg(test)] +mod tests; + +use crate::cmp; +use crate::fmt::{self, Debug, Formatter}; +use crate::mem::MaybeUninit; + +/// A wrapper around a byte buffer that is incrementally filled and initialized. +/// +/// This type is a sort of "double cursor". It tracks three regions in the buffer: a region at the beginning of the +/// buffer that has been logically filled with data, a region that has been initialized at some point but not yet +/// logically filled, and a region at the end that is fully uninitialized. The filled region is guaranteed to be a +/// subset of the initialized region. +/// +/// In summary, the contents of the buffer can be visualized as: +/// ```not_rust +/// [ capacity ] +/// [ filled | unfilled ] +/// [ initialized | uninitialized ] +/// ``` +pub struct ReadBuf<'a> { + buf: &'a mut [MaybeUninit], + filled: usize, + initialized: usize, +} + +impl Debug for ReadBuf<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.debug_struct("ReadBuf") + .field("init", &self.initialized()) + .field("filled", &self.filled) + .field("capacity", &self.capacity()) + .finish() + } +} + +impl<'a> ReadBuf<'a> { + /// Creates a new `ReadBuf` from a fully initialized buffer. + #[inline] + pub fn new(buf: &'a mut [u8]) -> ReadBuf<'a> { + let len = buf.len(); + + ReadBuf { + //SAFETY: initialized data never becoming uninitialized is an invariant of ReadBuf + buf: unsafe { (buf as *mut [u8]).as_uninit_slice_mut().unwrap() }, + filled: 0, + initialized: len, + } + } + + /// Creates a new `ReadBuf` from a fully uninitialized buffer. + /// + /// Use `assume_init` if part of the buffer is known to be already initialized. + #[inline] + pub fn uninit(buf: &'a mut [MaybeUninit]) -> ReadBuf<'a> { + ReadBuf { buf, filled: 0, initialized: 0 } + } + + /// Returns the total capacity of the buffer. + #[inline] + pub fn capacity(&self) -> usize { + self.buf.len() + } + + /// Returns a shared reference to the filled portion of the buffer. + #[inline] + pub fn filled(&self) -> &[u8] { + //SAFETY: We only slice the filled part of the buffer, which is always valid + unsafe { MaybeUninit::slice_assume_init_ref(&self.buf[0..self.filled]) } + } + + /// Returns a mutable reference to the filled portion of the buffer. + #[inline] + pub fn filled_mut(&mut self) -> &mut [u8] { + //SAFETY: We only slice the filled part of the buffer, which is always valid + unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf[0..self.filled]) } + } + + /// Returns a shared reference to the initialized portion of the buffer. + /// + /// This includes the filled portion. + #[inline] + pub fn initialized(&self) -> &[u8] { + //SAFETY: We only slice the initialized part of the buffer, which is always valid + unsafe { MaybeUninit::slice_assume_init_ref(&self.buf[0..self.initialized]) } + } + + /// Returns a mutable reference to the initialized portion of the buffer. + /// + /// This includes the filled portion. + #[inline] + pub fn initialized_mut(&mut self) -> &mut [u8] { + //SAFETY: We only slice the initialized part of the buffer, which is always valid + unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf[0..self.initialized]) } + } + + /// Returns a mutable reference to the unfilled part of the buffer without ensuring that it has been fully + /// initialized. + /// + /// # Safety + /// + /// The caller must not de-initialize portions of the buffer that have already been initialized. + #[inline] + pub unsafe fn unfilled_mut(&mut self) -> &mut [MaybeUninit] { + &mut self.buf[self.filled..] + } + + /// Returns a mutable reference to the uninitialized part of the buffer. + /// + /// It is safe to uninitialize any of these bytes. + #[inline] + pub fn uninitialized_mut(&mut self) -> &mut [MaybeUninit] { + &mut self.buf[self.initialized..] + } + + /// Returns a mutable reference to the unfilled part of the buffer, ensuring it is fully initialized. + /// + /// Since `ReadBuf` tracks the region of the buffer that has been initialized, this is effectively "free" after + /// the first use. + #[inline] + pub fn initialize_unfilled(&mut self) -> &mut [u8] { + // should optimize out the assertion + self.initialize_unfilled_to(self.remaining()) + } + + /// Returns a mutable reference to the first `n` bytes of the unfilled part of the buffer, ensuring it is + /// fully initialized. + /// + /// # Panics + /// + /// Panics if `self.remaining()` is less than `n`. + #[inline] + pub fn initialize_unfilled_to(&mut self, n: usize) -> &mut [u8] { + assert!(self.remaining() >= n); + + let extra_init = self.initialized - self.filled; + // If we don't have enough initialized, do zeroing + if n > extra_init { + let uninit = n - extra_init; + let unfilled = &mut self.uninitialized_mut()[0..uninit]; + + for byte in unfilled.iter_mut() { + byte.write(0); + } + + // SAFETY: we just initialized uninit bytes, and the previous bytes were already init + unsafe { + self.assume_init(n); + } + } + + let filled = self.filled; + + &mut self.initialized_mut()[filled..filled + n] + } + + /// Returns the number of bytes at the end of the slice that have not yet been filled. + #[inline] + pub fn remaining(&self) -> usize { + self.capacity() - self.filled + } + + /// Clears the buffer, resetting the filled region to empty. + /// + /// The number of initialized bytes is not changed, and the contents of the buffer are not modified. + #[inline] + pub fn clear(&mut self) { + self.set_filled(0); // The assertion in `set_filled` is optimized out + } + + /// Increases the size of the filled region of the buffer. + /// + /// The number of initialized bytes is not changed. + /// + /// # Panics + /// + /// Panics if the filled region of the buffer would become larger than the initialized region. + #[inline] + pub fn add_filled(&mut self, n: usize) { + self.set_filled(self.filled + n); + } + + /// Sets the size of the filled region of the buffer. + /// + /// The number of initialized bytes is not changed. + /// + /// Note that this can be used to *shrink* the filled region of the buffer in addition to growing it (for + /// example, by a `Read` implementation that compresses data in-place). + /// + /// # Panics + /// + /// Panics if the filled region of the buffer would become larger than the initialized region. + #[inline] + pub fn set_filled(&mut self, n: usize) { + assert!(n <= self.initialized); + + self.filled = n; + } + + /// Asserts that the first `n` unfilled bytes of the buffer are initialized. + /// + /// `ReadBuf` assumes that bytes are never de-initialized, so this method does nothing when called with fewer + /// bytes than are already known to be initialized. + /// + /// # Safety + /// + /// The caller must ensure that the first `n` unfilled bytes of the buffer have already been initialized. + #[inline] + pub unsafe fn assume_init(&mut self, n: usize) { + self.initialized = cmp::max(self.initialized, self.filled + n); + } + + /// Appends data to the buffer, advancing the written position and possibly also the initialized position. + /// + /// # Panics + /// + /// Panics if `self.remaining()` is less than `buf.len()`. + #[inline] + pub fn append(&mut self, buf: &[u8]) { + assert!(self.remaining() >= buf.len()); + + // SAFETY: we do not de-initialize any of the elements of the slice + unsafe { + MaybeUninit::write_slice(&mut self.unfilled_mut()[..buf.len()], buf); + } + + // SAFETY: We just added the entire contents of buf to the filled section. + unsafe { self.assume_init(buf.len()) } + self.add_filled(buf.len()); + } + + /// Returns the amount of bytes that have been filled. + #[inline] + pub fn filled_len(&self) -> usize { + self.filled + } + + /// Returns the amount of bytes that have been initialized. + #[inline] + pub fn initialized_len(&self) -> usize { + self.initialized + } +} diff --git a/library/std/src/io/readbuf/tests.rs b/library/std/src/io/readbuf/tests.rs new file mode 100644 index 0000000000..3b7a5a56d2 --- /dev/null +++ b/library/std/src/io/readbuf/tests.rs @@ -0,0 +1,181 @@ +use super::ReadBuf; +use crate::mem::MaybeUninit; + +/// Test that ReadBuf has the correct numbers when created with new +#[test] +fn new() { + let mut buf = [0; 16]; + let rbuf = ReadBuf::new(&mut buf); + + assert_eq!(rbuf.filled_len(), 0); + assert_eq!(rbuf.initialized_len(), 16); + assert_eq!(rbuf.capacity(), 16); + assert_eq!(rbuf.remaining(), 16); +} + +/// Test that ReadBuf has the correct numbers when created with uninit +#[test] +fn uninit() { + let mut buf = [MaybeUninit::uninit(); 16]; + let rbuf = ReadBuf::uninit(&mut buf); + + assert_eq!(rbuf.filled_len(), 0); + assert_eq!(rbuf.initialized_len(), 0); + assert_eq!(rbuf.capacity(), 16); + assert_eq!(rbuf.remaining(), 16); +} + +#[test] +fn initialize_unfilled() { + let mut buf = [MaybeUninit::uninit(); 16]; + let mut rbuf = ReadBuf::uninit(&mut buf); + + rbuf.initialize_unfilled(); + + assert_eq!(rbuf.initialized_len(), 16); +} + +#[test] +fn initialize_unfilled_to() { + let mut buf = [MaybeUninit::uninit(); 16]; + let mut rbuf = ReadBuf::uninit(&mut buf); + + rbuf.initialize_unfilled_to(8); + + assert_eq!(rbuf.initialized_len(), 8); + + rbuf.initialize_unfilled_to(4); + + assert_eq!(rbuf.initialized_len(), 8); + + rbuf.set_filled(8); + + rbuf.initialize_unfilled_to(6); + + assert_eq!(rbuf.initialized_len(), 14); + + rbuf.initialize_unfilled_to(8); + + assert_eq!(rbuf.initialized_len(), 16); +} + +#[test] +fn add_filled() { + let mut buf = [0; 16]; + let mut rbuf = ReadBuf::new(&mut buf); + + rbuf.add_filled(1); + + assert_eq!(rbuf.filled_len(), 1); + assert_eq!(rbuf.remaining(), 15); +} + +#[test] +#[should_panic] +fn add_filled_panic() { + let mut buf = [MaybeUninit::uninit(); 16]; + let mut rbuf = ReadBuf::uninit(&mut buf); + + rbuf.add_filled(1); +} + +#[test] +fn set_filled() { + let mut buf = [0; 16]; + let mut rbuf = ReadBuf::new(&mut buf); + + rbuf.set_filled(16); + + assert_eq!(rbuf.filled_len(), 16); + assert_eq!(rbuf.remaining(), 0); + + rbuf.set_filled(6); + + assert_eq!(rbuf.filled_len(), 6); + assert_eq!(rbuf.remaining(), 10); +} + +#[test] +#[should_panic] +fn set_filled_panic() { + let mut buf = [MaybeUninit::uninit(); 16]; + let mut rbuf = ReadBuf::uninit(&mut buf); + + rbuf.set_filled(16); +} + +#[test] +fn clear() { + let mut buf = [255; 16]; + let mut rbuf = ReadBuf::new(&mut buf); + + rbuf.set_filled(16); + + assert_eq!(rbuf.filled_len(), 16); + assert_eq!(rbuf.remaining(), 0); + + rbuf.clear(); + + assert_eq!(rbuf.filled_len(), 0); + assert_eq!(rbuf.remaining(), 16); + + assert_eq!(rbuf.initialized(), [255; 16]); +} + +#[test] +fn assume_init() { + let mut buf = [MaybeUninit::uninit(); 16]; + let mut rbuf = ReadBuf::uninit(&mut buf); + + unsafe { + rbuf.assume_init(8); + } + + assert_eq!(rbuf.initialized_len(), 8); + + rbuf.add_filled(4); + + unsafe { + rbuf.assume_init(2); + } + + assert_eq!(rbuf.initialized_len(), 8); + + unsafe { + rbuf.assume_init(8); + } + + assert_eq!(rbuf.initialized_len(), 12); +} + +#[test] +fn append() { + let mut buf = [MaybeUninit::new(255); 16]; + let mut rbuf = ReadBuf::uninit(&mut buf); + + rbuf.append(&[0; 8]); + + assert_eq!(rbuf.initialized_len(), 8); + assert_eq!(rbuf.filled_len(), 8); + assert_eq!(rbuf.filled(), [0; 8]); + + rbuf.clear(); + + rbuf.append(&[1; 16]); + + assert_eq!(rbuf.initialized_len(), 16); + assert_eq!(rbuf.filled_len(), 16); + assert_eq!(rbuf.filled(), [1; 16]); +} + +#[test] +fn filled_mut() { + let mut buf = [0; 16]; + let mut rbuf = ReadBuf::new(&mut buf); + + rbuf.add_filled(8); + + let filled = rbuf.filled().to_vec(); + + assert_eq!(&*filled, &*rbuf.filled_mut()); +} diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index f7fc23c1e8..c072f0cafe 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -7,7 +7,7 @@ use crate::io::prelude::*; use crate::cell::{Cell, RefCell}; use crate::fmt; -use crate::io::{self, BufReader, Initializer, IoSlice, IoSliceMut, LineWriter, Lines, Split}; +use crate::io::{self, BufReader, IoSlice, IoSliceMut, LineWriter, Lines, Split}; use crate::lazy::SyncOnceCell; use crate::pin::Pin; use crate::sync::atomic::{AtomicBool, Ordering}; @@ -108,11 +108,6 @@ impl Read for StdinRaw { self.0.is_read_vectored() } - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { handle_ebadf(self.0.read_to_end(buf), 0) } @@ -514,10 +509,6 @@ impl Read for Stdin { fn is_read_vectored(&self) -> bool { self.lock().is_read_vectored() } - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { self.lock().read_to_end(buf) } @@ -552,11 +543,6 @@ impl Read for StdinLock<'_> { self.inner.is_read_vectored() } - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { self.inner.read_to_end(buf) } @@ -1193,7 +1179,7 @@ where }) }) == Ok(Some(())) { - // Succesfully wrote to capture buffer. + // Successfully wrote to capture buffer. return; } diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index 0321a2b60b..ea49bfe342 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -1,7 +1,8 @@ -use super::{repeat, Cursor, SeekFrom}; +use super::{repeat, Cursor, ReadBuf, SeekFrom}; use crate::cmp::{self, min}; use crate::io::{self, IoSlice, IoSliceMut}; use crate::io::{BufRead, BufReader, Read, Seek, Write}; +use crate::mem::MaybeUninit; use crate::ops::Deref; #[test] @@ -156,6 +157,28 @@ fn read_exact_slice() { assert_eq!(c, b"9"); } +#[test] +fn read_buf_exact() { + let mut buf = [0; 4]; + let mut buf = ReadBuf::new(&mut buf); + + let mut c = Cursor::new(&b""[..]); + assert_eq!(c.read_buf_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof); + + let mut c = Cursor::new(&b"123456789"[..]); + c.read_buf_exact(&mut buf).unwrap(); + assert_eq!(buf.filled(), b"1234"); + + buf.clear(); + + c.read_buf_exact(&mut buf).unwrap(); + assert_eq!(buf.filled(), b"5678"); + + buf.clear(); + + assert_eq!(c.read_buf_exact(&mut buf).unwrap_err().kind(), io::ErrorKind::UnexpectedEof); +} + #[test] fn take_eof() { struct R; @@ -559,3 +582,23 @@ fn test_write_all_vectored() { } } } + +#[bench] +fn bench_take_read(b: &mut test::Bencher) { + b.iter(|| { + let mut buf = [0; 64]; + + [255; 128].take(64).read(&mut buf).unwrap(); + }); +} + +#[bench] +fn bench_take_read_buf(b: &mut test::Bencher) { + b.iter(|| { + let mut buf = [MaybeUninit::uninit(); 64]; + + let mut rbuf = ReadBuf::uninit(&mut buf); + + [255; 128].take(64).read_buf(&mut rbuf).unwrap(); + }); +} diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs index 9cd7c51484..c1300cd67c 100644 --- a/library/std/src/io/util.rs +++ b/library/std/src/io/util.rs @@ -5,7 +5,7 @@ mod tests; use crate::fmt; use crate::io::{ - self, BufRead, Initializer, IoSlice, IoSliceMut, Read, Seek, SeekFrom, SizeHint, Write, + self, BufRead, IoSlice, IoSliceMut, Read, ReadBuf, Seek, SeekFrom, SizeHint, Write, }; /// A reader which is always at EOF. @@ -47,8 +47,8 @@ impl Read for Empty { } #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() + fn read_buf(&mut self, _buf: &mut ReadBuf<'_>) -> io::Result<()> { + Ok(()) } } #[stable(feature = "rust1", since = "1.0.0")] @@ -130,6 +130,24 @@ impl Read for Repeat { Ok(buf.len()) } + fn read_buf(&mut self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + // SAFETY: No uninit bytes are being written + for slot in unsafe { buf.unfilled_mut() } { + slot.write(self.byte); + } + + let remaining = buf.remaining(); + + // SAFETY: the entire unfilled portion of buf has been initialized + unsafe { + buf.assume_init(remaining); + } + + buf.add_filled(remaining); + + Ok(()) + } + #[inline] fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { let mut nwritten = 0; @@ -143,11 +161,6 @@ impl Read for Repeat { fn is_read_vectored(&self) -> bool { true } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } } impl SizeHint for Repeat { diff --git a/library/std/src/io/util/tests.rs b/library/std/src/io/util/tests.rs index 7632eaf872..08972a59a8 100644 --- a/library/std/src/io/util/tests.rs +++ b/library/std/src/io/util/tests.rs @@ -1,9 +1,12 @@ use crate::cmp::{max, min}; use crate::io::prelude::*; use crate::io::{ - copy, empty, repeat, sink, BufWriter, Empty, Repeat, Result, SeekFrom, Sink, DEFAULT_BUF_SIZE, + copy, empty, repeat, sink, BufWriter, Empty, ReadBuf, Repeat, Result, SeekFrom, Sink, + DEFAULT_BUF_SIZE, }; +use crate::mem::MaybeUninit; + #[test] fn copy_copies() { let mut r = repeat(0).take(4); @@ -75,6 +78,30 @@ fn empty_reads() { assert_eq!(e.read(&mut [0]).unwrap(), 0); assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0); assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0); + + let mut buf = []; + let mut buf = ReadBuf::uninit(&mut buf); + e.read_buf(&mut buf).unwrap(); + assert_eq!(buf.filled_len(), 0); + assert_eq!(buf.initialized_len(), 0); + + let mut buf = [MaybeUninit::uninit()]; + let mut buf = ReadBuf::uninit(&mut buf); + e.read_buf(&mut buf).unwrap(); + assert_eq!(buf.filled_len(), 0); + assert_eq!(buf.initialized_len(), 0); + + let mut buf = [MaybeUninit::uninit(); 1024]; + let mut buf = ReadBuf::uninit(&mut buf); + e.read_buf(&mut buf).unwrap(); + assert_eq!(buf.filled_len(), 0); + assert_eq!(buf.initialized_len(), 0); + + let mut buf = [MaybeUninit::uninit(); 1024]; + let mut buf = ReadBuf::uninit(&mut buf); + e.by_ref().read_buf(&mut buf).unwrap(); + assert_eq!(buf.filled_len(), 0); + assert_eq!(buf.initialized_len(), 0); } #[test] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 133cda4f45..b002104897 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -216,10 +216,7 @@ // std may use features in a platform-specific way #![allow(unused_features)] #![feature(rustc_allow_const_fn_unstable)] -#![cfg_attr( - test, - feature(internal_output_capture, print_internals, update_panic_count, thread_local_const_init) -)] +#![cfg_attr(test, feature(internal_output_capture, print_internals, update_panic_count))] #![cfg_attr( all(target_vendor = "fortanix", target_env = "sgx"), feature(slice_index_methods, coerce_unsized, sgx_platform) @@ -236,7 +233,6 @@ #![feature(allow_internal_unstable)] #![feature(arbitrary_self_types)] #![feature(array_error_internals)] -#![feature(asm)] #![feature(assert_matches)] #![feature(associated_type_bounds)] #![feature(async_stream)] @@ -253,8 +249,8 @@ #![feature(cfg_target_thread_local)] #![feature(char_error_internals)] #![feature(char_internals)] +#![cfg_attr(not(bootstrap), feature(concat_bytes))] #![feature(concat_idents)] -#![feature(const_cstr_unchecked)] #![feature(const_fn_floating_point_arithmetic)] #![feature(const_fn_fn_ptr_basics)] #![feature(const_fn_trait_bound)] @@ -264,8 +260,7 @@ #![feature(const_ipv4)] #![feature(const_ipv6)] #![feature(const_option)] -#![cfg_attr(bootstrap, feature(const_raw_ptr_deref))] -#![cfg_attr(not(bootstrap), feature(const_mut_refs))] +#![feature(const_mut_refs)] #![feature(const_socketaddr)] #![feature(const_trait_impl)] #![feature(container_error_extra)] @@ -275,9 +270,7 @@ #![feature(decl_macro)] #![feature(doc_cfg)] #![feature(doc_cfg_hide)] -#![cfg_attr(bootstrap, feature(doc_primitive))] -#![cfg_attr(bootstrap, feature(doc_keyword))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![feature(rustdoc_internals)] #![feature(doc_masked)] #![feature(doc_notable_trait)] #![feature(dropck_eyepatch)] @@ -293,14 +286,12 @@ #![feature(gen_future)] #![feature(generator_trait)] #![feature(get_mut_unchecked)] -#![feature(global_asm)] #![feature(hashmap_internals)] #![feature(int_error_internals)] #![feature(integer_atomics)] #![feature(int_log)] #![feature(into_future)] #![feature(intra_doc_pointers)] -#![feature(iter_zip)] #![feature(lang_items)] #![feature(linkage)] #![feature(llvm_asm)] @@ -309,6 +300,7 @@ #![feature(maybe_uninit_extra)] #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array)] +#![feature(maybe_uninit_write_slice)] #![feature(min_specialization)] #![feature(mixed_integer_ops)] #![feature(must_not_suspend)] @@ -323,7 +315,9 @@ #![feature(panic_internals)] #![feature(panic_unwind)] #![feature(pin_static_ref)] +#![feature(portable_simd)] #![feature(prelude_import)] +#![feature(ptr_as_uninit)] #![feature(ptr_internals)] #![feature(rustc_attrs)] #![feature(rustc_private)] @@ -474,6 +468,8 @@ pub use core::pin; pub use core::ptr; #[stable(feature = "rust1", since = "1.0.0")] pub use core::result; +#[unstable(feature = "portable_simd", issue = "86656")] +pub use core::simd; #[unstable(feature = "async_stream", issue = "79024")] pub use core::stream; #[stable(feature = "i128", since = "1.26.0")] @@ -560,6 +556,7 @@ pub use std_detect::*; pub use std_detect::{ is_aarch64_feature_detected, is_arm_feature_detected, is_mips64_feature_detected, is_mips_feature_detected, is_powerpc64_feature_detected, is_powerpc_feature_detected, + is_riscv_feature_detected, }; // Re-export macros defined in libcore. @@ -579,6 +576,14 @@ pub use core::{ log_syntax, module_path, option_env, stringify, trace_macros, }; +#[unstable( + feature = "concat_bytes", + issue = "87555", + reason = "`concat_bytes` is not stable enough for use and is subject to change" +)] +#[cfg(not(bootstrap))] +pub use core::concat_bytes; + #[stable(feature = "core_primitive", since = "1.43.0")] pub use core::primitive; @@ -605,3 +610,7 @@ mod sealed { #[unstable(feature = "sealed", issue = "none")] pub trait Sealed {} } + +#[unstable(feature = "thread_local_const_init", issue = "91543")] +#[allow(unused)] +fn workaround_for_91543_as_racer_needs_this_feature_gate() {} diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index da95fe21ac..70a7d7a8ca 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -1140,8 +1140,8 @@ impl From for u32 { /// ``` /// use std::net::Ipv4Addr; /// - /// let addr = Ipv4Addr::new(0xca, 0xfe, 0xba, 0xbe); - /// assert_eq!(0xcafebabe, u32::from(addr)); + /// let addr = Ipv4Addr::new(0x12, 0x34, 0x56, 0x78); + /// assert_eq!(0x12345678, u32::from(addr)); /// ``` #[inline] fn from(ip: Ipv4Addr) -> u32 { @@ -1159,8 +1159,8 @@ impl From for Ipv4Addr { /// ``` /// use std::net::Ipv4Addr; /// - /// let addr = Ipv4Addr::from(0xcafebabe); - /// assert_eq!(Ipv4Addr::new(0xca, 0xfe, 0xba, 0xbe), addr); + /// let addr = Ipv4Addr::from(0x12345678); + /// assert_eq!(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78), addr); /// ``` #[inline] fn from(ip: u32) -> Ipv4Addr { @@ -1826,7 +1826,7 @@ impl fmt::Display for Ipv6Addr { } } } else { - // Slow path: write the address to a local buffer, the use f.pad. + // Slow path: write the address to a local buffer, then use f.pad. // Defined recursively by using the fast path to write to the // buffer. diff --git a/library/std/src/net/ip/tests.rs b/library/std/src/net/ip/tests.rs index 17581f3302..7956c6a25e 100644 --- a/library/std/src/net/ip/tests.rs +++ b/library/std/src/net/ip/tests.rs @@ -77,10 +77,10 @@ fn test_from_str_ipv4_in_ipv6() { let none: Option = "::127.0.0.1:".parse().ok(); assert_eq!(None, none); // not enough groups - let none: Option = "1.2.3.4.5:127.0.0.1".parse().ok(); + let none: Option = "1:2:3:4:5:127.0.0.1".parse().ok(); assert_eq!(None, none); // too many groups - let none: Option = "1.2.3.4.5:6:7:127.0.0.1".parse().ok(); + let none: Option = "1:2:3:4:5:6:7:127.0.0.1".parse().ok(); assert_eq!(None, none); } @@ -749,7 +749,7 @@ fn ipv4_from_constructors() { } #[test] -fn ipv6_from_contructors() { +fn ipv6_from_constructors() { assert_eq!(Ipv6Addr::LOCALHOST, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); assert!(Ipv6Addr::LOCALHOST.is_loopback()); assert_eq!(Ipv6Addr::UNSPECIFIED, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)); diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs index 5738862fb5..1ba54d892e 100644 --- a/library/std/src/net/tcp.rs +++ b/library/std/src/net/tcp.rs @@ -6,7 +6,7 @@ mod tests; use crate::io::prelude::*; use crate::fmt; -use crate::io::{self, Initializer, IoSlice, IoSliceMut}; +use crate::io::{self, IoSlice, IoSliceMut}; use crate::net::{Shutdown, SocketAddr, ToSocketAddrs}; use crate::sys_common::net as net_imp; use crate::sys_common::{AsInner, FromInner, IntoInner}; @@ -626,12 +626,6 @@ impl Read for TcpStream { fn is_read_vectored(&self) -> bool { self.0.is_read_vectored() } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - // SAFETY: Read is guaranteed to work on uninitialized memory - unsafe { Initializer::nop() } - } } #[stable(feature = "rust1", since = "1.0.0")] impl Write for TcpStream { @@ -666,12 +660,6 @@ impl Read for &TcpStream { fn is_read_vectored(&self) -> bool { self.0.is_read_vectored() } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - // SAFETY: Read is guaranteed to work on uninitialized memory - unsafe { Initializer::nop() } - } } #[stable(feature = "rust1", since = "1.0.0")] impl Write for &TcpStream { diff --git a/library/std/src/os/fortanix_sgx/arch.rs b/library/std/src/os/fortanix_sgx/arch.rs index 4ce482e23c..8358cb9e81 100644 --- a/library/std/src/os/fortanix_sgx/arch.rs +++ b/library/std/src/os/fortanix_sgx/arch.rs @@ -5,6 +5,7 @@ #![unstable(feature = "sgx_platform", issue = "56975")] use crate::mem::MaybeUninit; +use core::arch::asm; /// Wrapper struct to force 16-byte alignment. #[repr(align(16))] diff --git a/library/std/src/os/raw/mod.rs b/library/std/src/os/raw/mod.rs index 01392ffab7..f0b38d2984 100644 --- a/library/std/src/os/raw/mod.rs +++ b/library/std/src/os/raw/mod.rs @@ -69,7 +69,8 @@ type_alias! { "char.md", c_char = u8, NonZero_c_char = NonZeroU8; target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc", - target_arch = "powerpc64" + target_arch = "powerpc64", + target_arch = "riscv64" ) ), all( @@ -112,7 +113,8 @@ type_alias! { "char.md", c_char = i8, NonZero_c_char = NonZeroI8; target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc", - target_arch = "powerpc64" + target_arch = "powerpc64", + target_arch = "riscv64" ) ), all( diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index 6120d55722..583f861a92 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -11,7 +11,7 @@ use super::{recv_vectored_with_ancillary_from, send_vectored_with_ancillary_to, SocketAncillary}; use super::{sockaddr_un, SocketAddr}; use crate::fmt; -use crate::io::{self, Initializer, IoSlice, IoSliceMut}; +use crate::io::{self, IoSlice, IoSliceMut}; use crate::net::Shutdown; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; #[cfg(any( @@ -624,11 +624,6 @@ impl io::Read for UnixStream { fn is_read_vectored(&self) -> bool { io::Read::is_read_vectored(&&*self) } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } } #[stable(feature = "unix_socket", since = "1.10.0")] @@ -645,11 +640,6 @@ impl<'a> io::Read for &'a UnixStream { fn is_read_vectored(&self) -> bool { self.0.is_read_vectored() } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } } #[stable(feature = "unix_socket", since = "1.10.0")] diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index be35ab0ca1..31d1e3c1e4 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -543,6 +543,16 @@ impl FileTypeExt for fs::FileType { /// Ok(()) /// } /// ``` +/// +/// # Limitations +/// +/// Windows treats symlink creation as a [privileged action][symlink-security], +/// therefore this function is likely to fail unless the user makes changes to +/// their system to permit symlink creation. Users can try enabling Developer +/// Mode, granting the `SeCreateSymbolicLinkPrivilege` privilege, or running +/// the process as an administrator. +/// +/// [symlink-security]: https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/create-symbolic-links #[stable(feature = "symlink", since = "1.1.0")] pub fn symlink_file, Q: AsRef>(original: P, link: Q) -> io::Result<()> { sys::fs::symlink_inner(original.as_ref(), link.as_ref(), false) @@ -572,6 +582,16 @@ pub fn symlink_file, Q: AsRef>(original: P, link: Q) -> io: /// Ok(()) /// } /// ``` +/// +/// # Limitations +/// +/// Windows treats symlink creation as a [privileged action][symlink-security], +/// therefore this function is likely to fail unless the user makes changes to +/// their system to permit symlink creation. Users can try enabling Developer +/// Mode, granting the `SeCreateSymbolicLinkPrivilege` privilege, or running +/// the process as an administrator. +/// +/// [symlink-security]: https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/create-symbolic-links #[stable(feature = "symlink", since = "1.1.0")] pub fn symlink_dir, Q: AsRef>(original: P, link: Q) -> io::Result<()> { sys::fs::symlink_inner(original.as_ref(), link.as_ref(), true) diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 6fc6b8daec..87854fe4f2 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -365,7 +365,7 @@ pub unsafe fn r#try R>(f: F) -> Result> // The call to `intrinsics::r#try` is made safe by: // - `do_call`, the first argument, can be called with the initial `data_ptr`. // - `do_catch`, the second argument, can be called with the `data_ptr` as well. - // See their safety preconditions for more informations + // See their safety preconditions for more information unsafe { return if intrinsics::r#try(do_call::, data_ptr, do_catch::) == 0 { Ok(ManuallyDrop::into_inner(data.r)) @@ -398,7 +398,7 @@ pub unsafe fn r#try R>(f: F) -> Result> // expects normal function pointers. #[inline] fn do_call R, R>(data: *mut u8) { - // SAFETY: this is the responsibilty of the caller, see above. + // SAFETY: this is the responsibility of the caller, see above. unsafe { let data = data as *mut Data; let data = &mut (*data); @@ -420,7 +420,7 @@ pub unsafe fn r#try R>(f: F) -> Result> // expects normal function pointers. #[inline] fn do_catch R, R>(data: *mut u8, payload: *mut u8) { - // SAFETY: this is the responsibilty of the caller, see above. + // SAFETY: this is the responsibility of the caller, see above. // // When `__rustc_panic_cleaner` is correctly implemented we can rely // on `obj` being the correct thing to pass to `data.p` (after wrapping diff --git a/library/std/src/path.rs b/library/std/src/path.rs index cf2cd5adc4..bfbcb009f8 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -12,6 +12,13 @@ //! [`PathBuf`]; note that the paths may differ syntactically by the //! normalization described in the documentation for the [`components`] method. //! +//! ## Case sensitivity +//! +//! Unless otherwise indicated path methods that do not access the filesystem, +//! such as [`Path::starts_with`] and [`Path::ends_with`], are case sensitive no +//! matter the platform or filesystem. An exception to this is made for Windows +//! drive letters. +//! //! ## Simple usage //! //! Path manipulation includes both parsing components from slices and building @@ -2810,7 +2817,7 @@ impl Path { /// check errors, call [`fs::symlink_metadata`] and handle its [`Result`]. Then call /// [`fs::Metadata::is_symlink`] if it was [`Ok`]. #[must_use] - #[stable(feature = "is_symlink", since = "1.57.0")] + #[stable(feature = "is_symlink", since = "1.58.0")] pub fn is_symlink(&self) -> bool { fs::symlink_metadata(self).map(|m| m.is_symlink()).unwrap_or(false) } @@ -2892,12 +2899,12 @@ impl cmp::PartialEq for Path { impl Hash for Path { fn hash(&self, h: &mut H) { let bytes = self.as_u8_slice(); - let prefix_len = match parse_prefix(&self.inner) { + let (prefix_len, verbatim) = match parse_prefix(&self.inner) { Some(prefix) => { prefix.hash(h); - prefix.len() + (prefix.len(), prefix.is_verbatim()) } - None => 0, + None => (0, false), }; let bytes = &bytes[prefix_len..]; @@ -2905,7 +2912,8 @@ impl Hash for Path { let mut bytes_hashed = 0; for i in 0..bytes.len() { - if is_sep_byte(bytes[i]) { + let is_sep = if verbatim { is_verbatim_sep(bytes[i]) } else { is_sep_byte(bytes[i]) }; + if is_sep { if i > component_start { let to_hash = &bytes[component_start..i]; h.write(to_hash); @@ -2913,11 +2921,18 @@ impl Hash for Path { } // skip over separator and optionally a following CurDir item - // since components() would normalize these away - component_start = i + match bytes[i..] { - [_, b'.', b'/', ..] | [_, b'.'] => 2, - _ => 1, - }; + // since components() would normalize these away. + component_start = i + 1; + + let tail = &bytes[component_start..]; + + if !verbatim { + component_start += match tail { + [b'.'] => 1, + [b'.', sep @ _, ..] if is_sep_byte(*sep) => 1, + _ => 0, + }; + } } } diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs index 2bf499e1ab..0ab5956e1b 100644 --- a/library/std/src/path/tests.rs +++ b/library/std/src/path/tests.rs @@ -1498,6 +1498,20 @@ pub fn test_compare() { relative_from: Some("") ); + tc!("foo/.", "foo", + eq: true, + starts_with: true, + ends_with: true, + relative_from: Some("") + ); + + tc!("foo/./bar", "foo/bar", + eq: true, + starts_with: true, + ends_with: true, + relative_from: Some("") + ); + tc!("foo/bar", "foo", eq: false, starts_with: true, @@ -1541,6 +1555,27 @@ pub fn test_compare() { ends_with: true, relative_from: Some("") ); + + tc!(r"C:\foo\.\bar.txt", r"C:\foo\bar.txt", + eq: true, + starts_with: true, + ends_with: true, + relative_from: Some("") + ); + + tc!(r"C:\foo\.", r"C:\foo", + eq: true, + starts_with: true, + ends_with: true, + relative_from: Some("") + ); + + tc!(r"\\?\C:\foo\.\bar.txt", r"\\?\C:\foo\bar.txt", + eq: false, + starts_with: false, + ends_with: false, + relative_from: None + ); } } diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs index 772044f014..b52bcdfca9 100644 --- a/library/std/src/prelude/v1.rs +++ b/library/std/src/prelude/v1.rs @@ -46,48 +46,38 @@ pub use core::prelude::v1::{ }; #[unstable( - feature = "asm", - issue = "72016", - reason = "inline assembly is not stable enough for use and is subject to change" + feature = "concat_bytes", + issue = "87555", + reason = "`concat_bytes` is not stable enough for use and is subject to change" )] +#[cfg(not(bootstrap))] #[doc(no_inline)] -pub use core::prelude::v1::asm; +pub use core::prelude::v1::concat_bytes; -#[unstable( - feature = "global_asm", - issue = "35119", - reason = "`global_asm!` is not stable enough for use and is subject to change" -)] -#[doc(no_inline)] -pub use core::prelude::v1::global_asm; - -// FIXME: Attribute and internal derive macros are not documented because for them rustdoc generates -// dead links which fail link checker testing. +// Do not `doc(inline)` these `doc(hidden)` items. #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] -#[allow(deprecated, deprecated_in_future)] -#[doc(hidden)] -pub use core::prelude::v1::{ - bench, global_allocator, test, test_case, RustcDecodable, RustcEncodable, -}; +#[allow(deprecated)] +pub use core::prelude::v1::{RustcDecodable, RustcEncodable}; +// Do not `doc(no_inline)` so that they become doc items on their own +// (no public module for them to be re-exported from). #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] -#[doc(hidden)] -pub use core::prelude::v1::derive; +pub use core::prelude::v1::{bench, derive, global_allocator, test, test_case}; +// Do not `doc(no_inline)` either. #[unstable( feature = "cfg_accessible", issue = "64797", reason = "`cfg_accessible` is not fully implemented" )] -#[doc(hidden)] pub use core::prelude::v1::cfg_accessible; +// Do not `doc(no_inline)` either. #[unstable( feature = "cfg_eval", issue = "82679", reason = "`cfg_eval` is a recently implemented feature" )] -#[doc(hidden)] pub use core::prelude::v1::cfg_eval; // The file so far is equivalent to src/libcore/prelude/v1.rs, diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index f47a30c9b5..8fcd8cdeb1 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -606,8 +606,7 @@ mod prim_pointer {} /// println!("array[{}] = {}", i, x); /// } /// -/// // You can explicitly iterate an array by value using -/// // `IntoIterator::into_iter` or `std::array::IntoIter::new`: +/// // You can explicitly iterate an array by value using `IntoIterator::into_iter` /// for item in IntoIterator::into_iter(array).enumerate() { /// let (i, x): (usize, i32) = item; /// println!("array[{}] = {}", i, x); diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 4e9fd51f28..e012594dd4 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -110,7 +110,7 @@ use crate::convert::Infallible; use crate::ffi::OsStr; use crate::fmt; use crate::fs; -use crate::io::{self, Initializer, IoSlice, IoSliceMut}; +use crate::io::{self, IoSlice, IoSliceMut}; use crate::num::NonZeroI32; use crate::path::Path; use crate::str; @@ -362,12 +362,6 @@ impl Read for ChildStdout { fn is_read_vectored(&self) -> bool { self.inner.is_read_vectored() } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - // SAFETY: Read is guaranteed to work on uninitialized memory - unsafe { Initializer::nop() } - } } impl AsInner for ChildStdout { @@ -429,12 +423,6 @@ impl Read for ChildStderr { fn is_read_vectored(&self) -> bool { self.inner.is_read_vectored() } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - // SAFETY: Read is guaranteed to work on uninitialized memory - unsafe { Initializer::nop() } - } } impl AsInner for ChildStderr { @@ -1612,7 +1600,6 @@ impl ExitStatusError { /// ``` /// #![feature(exit_status_error)] /// # if cfg!(unix) { - /// use std::convert::TryFrom; /// use std::num::NonZeroI32; /// use std::process::Command; /// diff --git a/library/std/src/sync/mpsc/mod.rs b/library/std/src/sync/mpsc/mod.rs index 2cf678ef69..2e54321e12 100644 --- a/library/std/src/sync/mpsc/mod.rs +++ b/library/std/src/sync/mpsc/mod.rs @@ -429,12 +429,13 @@ pub struct TryIter<'a, T: 'a> { } /// An owning iterator over messages on a [`Receiver`], -/// created by **Receiver::into_iter**. +/// created by [`into_iter`]. /// /// This iterator will block whenever [`next`] /// is called, waiting for a new message, and [`None`] will be /// returned if the corresponding channel has hung up. /// +/// [`into_iter`]: Receiver::into_iter /// [`next`]: Iterator::next /// /// # Examples diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs index 1710c00539..f76d075956 100644 --- a/library/std/src/sync/once.rs +++ b/library/std/src/sync/once.rs @@ -90,6 +90,7 @@ mod tests; use crate::cell::Cell; use crate::fmt; use crate::marker; +use crate::panic::{RefUnwindSafe, UnwindSafe}; use crate::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use crate::thread::{self, Thread}; @@ -123,6 +124,12 @@ unsafe impl Sync for Once {} #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Send for Once {} +#[stable(feature = "sync_once_unwind_safe", since = "1.59.0")] +impl UnwindSafe for Once {} + +#[stable(feature = "sync_once_unwind_safe", since = "1.59.0")] +impl RefUnwindSafe for Once {} + /// State yielded to [`Once::call_once_force()`]’s closure parameter. The state /// can be used to query the poison status of the [`Once`]. #[stable(feature = "once_poison", since = "1.51.0")] diff --git a/library/std/src/sys/hermit/fd.rs b/library/std/src/sys/hermit/fd.rs index c400f5f2c2..1179a49c22 100644 --- a/library/std/src/sys/hermit/fd.rs +++ b/library/std/src/sys/hermit/fd.rs @@ -1,6 +1,6 @@ #![unstable(reason = "not public", issue = "none", feature = "fd")] -use crate::io::{self, Read}; +use crate::io::{self, Read, ReadBuf}; use crate::mem; use crate::sys::cvt; use crate::sys::hermit::abi; diff --git a/library/std/src/sys/hermit/fs.rs b/library/std/src/sys/hermit/fs.rs index be019d4435..974c44eb8d 100644 --- a/library/std/src/sys/hermit/fs.rs +++ b/library/std/src/sys/hermit/fs.rs @@ -2,7 +2,7 @@ use crate::ffi::{CStr, CString, OsString}; use crate::fmt; use crate::hash::{Hash, Hasher}; use crate::io::{self, Error, ErrorKind}; -use crate::io::{IoSlice, IoSliceMut, SeekFrom}; +use crate::io::{IoSlice, IoSliceMut, ReadBuf, SeekFrom}; use crate::os::unix::ffi::OsStrExt; use crate::path::{Path, PathBuf}; use crate::sys::cvt; @@ -312,6 +312,10 @@ impl File { false } + pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + crate::io::default_read_buf(|buf| self.read(buf), buf) + } + pub fn write(&self, buf: &[u8]) -> io::Result { self.0.write(buf) } diff --git a/library/std/src/sys/itron/thread.rs b/library/std/src/sys/itron/thread.rs index bb9fa54d02..ebcc9ab26e 100644 --- a/library/std/src/sys/itron/thread.rs +++ b/library/std/src/sys/itron/thread.rs @@ -126,7 +126,7 @@ impl Thread { // In this case, `inner`'s ownership has been moved to us, // And we are responsible for dropping it. The acquire // ordering is not necessary because the parent thread made - // no memory acccess needing synchronization since the call + // no memory access needing synchronization since the call // to `acre_tsk`. // Safety: See above. let _ = unsafe { Box::from_raw(inner as *const _ as *mut ThreadInner) }; @@ -264,7 +264,7 @@ impl Drop for Thread { // one will ever join it. // The ownership of `self.inner` is moved to the child thread. // However, the release ordering is not necessary because we - // made no memory acccess needing synchronization since the call + // made no memory access needing synchronization since the call // to `acre_tsk`. } LIFECYCLE_FINISHED => { diff --git a/library/std/src/sys/sgx/abi/mem.rs b/library/std/src/sys/sgx/abi/mem.rs index 52e8bec937..18e6d5b3fa 100644 --- a/library/std/src/sys/sgx/abi/mem.rs +++ b/library/std/src/sys/sgx/abi/mem.rs @@ -1,3 +1,5 @@ +use core::arch::asm; + // Do not remove inline: will result in relocation failure #[inline(always)] pub(crate) unsafe fn rel_ptr(offset: u64) -> *const T { diff --git a/library/std/src/sys/sgx/abi/mod.rs b/library/std/src/sys/sgx/abi/mod.rs index 231cc15b84..5df08a4ff5 100644 --- a/library/std/src/sys/sgx/abi/mod.rs +++ b/library/std/src/sys/sgx/abi/mod.rs @@ -1,6 +1,7 @@ #![cfg_attr(test, allow(unused))] // RT initialization logic is not compiled for test use crate::io::Write; +use core::arch::global_asm; use core::sync::atomic::{AtomicUsize, Ordering}; // runtime features diff --git a/library/std/src/sys/solid/abi/mod.rs b/library/std/src/sys/solid/abi/mod.rs index 3205f0db85..1afc83f766 100644 --- a/library/std/src/sys/solid/abi/mod.rs +++ b/library/std/src/sys/solid/abi/mod.rs @@ -10,9 +10,9 @@ pub fn breakpoint_program_exited(tid: usize) { match () { // SOLID_BP_PROGRAM_EXITED = 15 #[cfg(target_arch = "arm")] - () => asm!("bkpt #15", in("r0") tid), + () => core::arch::asm!("bkpt #15", in("r0") tid), #[cfg(target_arch = "aarch64")] - () => asm!("hlt #15", in("x0") tid), + () => core::arch::asm!("hlt #15", in("x0") tid), } } } @@ -23,9 +23,9 @@ pub fn breakpoint_abort() { match () { // SOLID_BP_CSABORT = 16 #[cfg(target_arch = "arm")] - () => asm!("bkpt #16"), + () => core::arch::asm!("bkpt #16"), #[cfg(target_arch = "aarch64")] - () => asm!("hlt #16"), + () => core::arch::asm!("hlt #16"), } } } diff --git a/library/std/src/sys/solid/fs.rs b/library/std/src/sys/solid/fs.rs index abc60b56fb..8a0eeff0c4 100644 --- a/library/std/src/sys/solid/fs.rs +++ b/library/std/src/sys/solid/fs.rs @@ -2,7 +2,7 @@ use super::{abi, error}; use crate::{ ffi::{CStr, CString, OsStr, OsString}, fmt, - io::{self, IoSlice, IoSliceMut, SeekFrom}, + io::{self, IoSlice, IoSliceMut, ReadBuf, SeekFrom}, mem::MaybeUninit, os::raw::{c_int, c_short}, os::solid::ffi::OsStrExt, @@ -339,6 +339,32 @@ impl File { } } + pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + unsafe { + let len = buf.remaining(); + let mut out_num_bytes = MaybeUninit::uninit(); + error::SolidError::err_if_negative(abi::SOLID_FS_Read( + self.fd.raw(), + buf.unfilled_mut().as_mut_ptr() as *mut u8, + len, + out_num_bytes.as_mut_ptr(), + )) + .map_err(|e| e.as_io_error())?; + + // Safety: `out_num_bytes` is filled by the successful call to + // `SOLID_FS_Read` + let num_bytes_read = out_num_bytes.assume_init(); + + // Safety: `num_bytes_read` bytes were written to the unfilled + // portion of the buffer + buf.assume_init(num_bytes_read); + + buf.add_filled(num_bytes_read); + + Ok(()) + } + } + pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { crate::io::default_read_vectored(|buf| self.read(buf), bufs) } diff --git a/library/std/src/sys/unix/android.rs b/library/std/src/sys/unix/android.rs index 6a46525f68..73ff10ab8a 100644 --- a/library/std/src/sys/unix/android.rs +++ b/library/std/src/sys/unix/android.rs @@ -18,11 +18,9 @@ #![cfg(target_os = "android")] -use libc::{c_int, c_void, sighandler_t, size_t, ssize_t}; -use libc::{ftruncate, pread, pwrite}; +use libc::{c_int, sighandler_t}; -use super::{cvt, cvt_r, weak::weak}; -use crate::io; +use super::weak::weak; // The `log2` and `log2f` functions apparently appeared in android-18, or at // least you can see they're not present in the android-17 header [1] and they @@ -81,87 +79,3 @@ pub unsafe fn signal(signum: c_int, handler: sighandler_t) -> sighandler_t { let f = f.expect("neither `signal` nor `bsd_signal` symbols found"); f(signum, handler) } - -// The `ftruncate64` symbol apparently appeared in android-12, so we do some -// dynamic detection to see if we can figure out whether `ftruncate64` exists. -// -// If it doesn't we just fall back to `ftruncate`, generating an error for -// too-large values. -#[cfg(target_pointer_width = "32")] -pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> { - weak!(fn ftruncate64(c_int, i64) -> c_int); - - unsafe { - match ftruncate64.get() { - Some(f) => cvt_r(|| f(fd, size as i64)).map(drop), - None => { - if size > i32::MAX as u64 { - Err(io::Error::new_const(io::ErrorKind::InvalidInput, &"cannot truncate >2GB")) - } else { - cvt_r(|| ftruncate(fd, size as i32)).map(drop) - } - } - } - } -} - -#[cfg(target_pointer_width = "64")] -pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> { - unsafe { cvt_r(|| ftruncate(fd, size as i64)).map(drop) } -} - -#[cfg(target_pointer_width = "32")] -pub unsafe fn cvt_pread64( - fd: c_int, - buf: *mut c_void, - count: size_t, - offset: i64, -) -> io::Result { - use crate::convert::TryInto; - weak!(fn pread64(c_int, *mut c_void, size_t, i64) -> ssize_t); - pread64.get().map(|f| cvt(f(fd, buf, count, offset))).unwrap_or_else(|| { - if let Ok(o) = offset.try_into() { - cvt(pread(fd, buf, count, o)) - } else { - Err(io::Error::new_const(io::ErrorKind::InvalidInput, &"cannot pread >2GB")) - } - }) -} - -#[cfg(target_pointer_width = "32")] -pub unsafe fn cvt_pwrite64( - fd: c_int, - buf: *const c_void, - count: size_t, - offset: i64, -) -> io::Result { - use crate::convert::TryInto; - weak!(fn pwrite64(c_int, *const c_void, size_t, i64) -> ssize_t); - pwrite64.get().map(|f| cvt(f(fd, buf, count, offset))).unwrap_or_else(|| { - if let Ok(o) = offset.try_into() { - cvt(pwrite(fd, buf, count, o)) - } else { - Err(io::Error::new_const(io::ErrorKind::InvalidInput, &"cannot pwrite >2GB")) - } - }) -} - -#[cfg(target_pointer_width = "64")] -pub unsafe fn cvt_pread64( - fd: c_int, - buf: *mut c_void, - count: size_t, - offset: i64, -) -> io::Result { - cvt(pread(fd, buf, count, offset)) -} - -#[cfg(target_pointer_width = "64")] -pub unsafe fn cvt_pwrite64( - fd: c_int, - buf: *const c_void, - count: size_t, - offset: i64, -) -> io::Result { - cvt(pwrite(fd, buf, count, offset)) -} diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs index 0956726084..2362bff913 100644 --- a/library/std/src/sys/unix/fd.rs +++ b/library/std/src/sys/unix/fd.rs @@ -4,7 +4,7 @@ mod tests; use crate::cmp; -use crate::io::{self, Initializer, IoSlice, IoSliceMut, Read}; +use crate::io::{self, IoSlice, IoSliceMut, Read, ReadBuf}; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; use crate::sys::cvt; use crate::sys_common::{AsInner, FromInner, IntoInner}; @@ -99,34 +99,39 @@ impl FileDesc { } pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result { - #[cfg(target_os = "android")] - use super::android::cvt_pread64; - - #[cfg(not(target_os = "android"))] - unsafe fn cvt_pread64( - fd: c_int, - buf: *mut c_void, - count: usize, - offset: i64, - ) -> io::Result { - #[cfg(not(target_os = "linux"))] - use libc::pread as pread64; - #[cfg(target_os = "linux")] - use libc::pread64; - cvt(pread64(fd, buf, count, offset)) - } + #[cfg(not(any(target_os = "linux", target_os = "android")))] + use libc::pread as pread64; + #[cfg(any(target_os = "linux", target_os = "android"))] + use libc::pread64; unsafe { - cvt_pread64( + cvt(pread64( self.as_raw_fd(), buf.as_mut_ptr() as *mut c_void, cmp::min(buf.len(), READ_LIMIT), offset as i64, - ) + )) .map(|n| n as usize) } } + pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + let ret = cvt(unsafe { + libc::read( + self.as_raw_fd(), + buf.unfilled_mut().as_mut_ptr() as *mut c_void, + cmp::min(buf.remaining(), READ_LIMIT), + ) + })?; + + // Safety: `ret` bytes were written to the initialized portion of the buffer + unsafe { + buf.assume_init(ret as usize); + } + buf.add_filled(ret as usize); + Ok(()) + } + pub fn write(&self, buf: &[u8]) -> io::Result { let ret = cvt(unsafe { libc::write( @@ -161,30 +166,18 @@ impl FileDesc { } pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result { - #[cfg(target_os = "android")] - use super::android::cvt_pwrite64; - - #[cfg(not(target_os = "android"))] - unsafe fn cvt_pwrite64( - fd: c_int, - buf: *const c_void, - count: usize, - offset: i64, - ) -> io::Result { - #[cfg(not(target_os = "linux"))] - use libc::pwrite as pwrite64; - #[cfg(target_os = "linux")] - use libc::pwrite64; - cvt(pwrite64(fd, buf, count, offset)) - } + #[cfg(not(any(target_os = "linux", target_os = "android")))] + use libc::pwrite as pwrite64; + #[cfg(any(target_os = "linux", target_os = "android"))] + use libc::pwrite64; unsafe { - cvt_pwrite64( + cvt(pwrite64( self.as_raw_fd(), buf.as_ptr() as *const c_void, cmp::min(buf.len(), READ_LIMIT), offset as i64, - ) + )) .map(|n| n as usize) } } @@ -289,11 +282,6 @@ impl<'a> Read for &'a FileDesc { fn read(&mut self, buf: &mut [u8]) -> io::Result { (**self).read(buf) } - - #[inline] - unsafe fn initializer(&self) -> Initializer { - Initializer::nop() - } } impl AsInner for FileDesc { diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 111639d92b..f8deda93fe 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -2,7 +2,7 @@ use crate::os::unix::prelude::*; use crate::ffi::{CStr, CString, OsStr, OsString}; use crate::fmt; -use crate::io::{self, Error, IoSlice, IoSliceMut, SeekFrom}; +use crate::io::{self, Error, IoSlice, IoSliceMut, ReadBuf, SeekFrom}; use crate::mem; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd}; use crate::path::{Path, PathBuf}; @@ -46,8 +46,8 @@ use libc::fstatat64; use libc::readdir_r as readdir64_r; #[cfg(target_os = "android")] use libc::{ - dirent as dirent64, fstat as fstat64, fstatat as fstatat64, lseek64, lstat as lstat64, - open as open64, stat as stat64, + dirent as dirent64, fstat as fstat64, fstatat as fstatat64, ftruncate64, lseek64, + lstat as lstat64, off64_t, open as open64, stat as stat64, }; #[cfg(not(any( target_os = "linux", @@ -843,16 +843,10 @@ impl File { } pub fn truncate(&self, size: u64) -> io::Result<()> { - #[cfg(target_os = "android")] - return crate::sys::android::ftruncate64(self.as_raw_fd(), size); - - #[cfg(not(target_os = "android"))] - { - use crate::convert::TryInto; - let size: off64_t = - size.try_into().map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?; - cvt_r(|| unsafe { ftruncate64(self.as_raw_fd(), size) }).map(drop) - } + use crate::convert::TryInto; + let size: off64_t = + size.try_into().map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?; + cvt_r(|| unsafe { ftruncate64(self.as_raw_fd(), size) }).map(drop) } pub fn read(&self, buf: &mut [u8]) -> io::Result { @@ -872,6 +866,10 @@ impl File { self.0.read_at(buf, offset) } + pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + self.0.read_buf(buf) + } + pub fn write(&self, buf: &[u8]) -> io::Result { self.0.write(buf) } @@ -1162,7 +1160,7 @@ pub fn link(original: &Path, link: &Path) -> io::Result<()> { } else if #[cfg(target_os = "macos")] { // On MacOS, older versions (<=10.9) lack support for linkat while newer // versions have it. We want to use linkat if it is available, so we use weak! - // to check. `linkat` is preferable to `link` ecause it gives us a flag to + // to check. `linkat` is preferable to `link` because it gives us a flag to // specify how symlinks should be handled. We pass 0 as the flags argument, // meaning it shouldn't follow symlinks. weak!(fn linkat(c_int, *const c_char, c_int, *const c_char, c_int) -> c_int); diff --git a/library/std/src/sys/unix/kernel_copy.rs b/library/std/src/sys/unix/kernel_copy.rs index f3155fbc06..e85e4c5d61 100644 --- a/library/std/src/sys/unix/kernel_copy.rs +++ b/library/std/src/sys/unix/kernel_copy.rs @@ -104,7 +104,7 @@ impl FdMeta { fn potential_sendfile_source(&self) -> bool { match self { - // procfs erronously shows 0 length on non-empty readable files. + // procfs erroneously shows 0 length on non-empty readable files. // and if a file is truly empty then a `read` syscall will determine that and skip the write syscall // thus there would be benefit from attempting sendfile FdMeta::Metadata(meta) @@ -614,6 +614,9 @@ fn sendfile_splice(mode: SpliceMode, reader: RawFd, writer: RawFd, len: u64) -> static HAS_SENDFILE: AtomicBool = AtomicBool::new(true); static HAS_SPLICE: AtomicBool = AtomicBool::new(true); + // Android builds use feature level 14, but the libc wrapper for splice is + // gated on feature level 21+, so we have to invoke the syscall directly. + #[cfg(target_os = "android")] syscall! { fn splice( srcfd: libc::c_int, @@ -625,6 +628,9 @@ fn sendfile_splice(mode: SpliceMode, reader: RawFd, writer: RawFd, len: u64) -> ) -> libc::ssize_t } + #[cfg(target_os = "linux")] + use libc::splice; + match mode { SpliceMode::Sendfile if !HAS_SENDFILE.load(Ordering::Relaxed) => { return CopyResult::Fallback(0); diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index 9ae6d12dcb..a82a017212 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -501,7 +501,7 @@ impl FromRawFd for Socket { // res_init unconditionally, we call it only when we detect we're linking // against glibc version < 2.26. (That is, when we both know its needed and // believe it's thread-safe). -#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))] +#[cfg(all(target_os = "linux", target_env = "gnu"))] fn on_resolver_failure() { use crate::sys; @@ -513,5 +513,5 @@ fn on_resolver_failure() { } } -#[cfg(any(not(target_env = "gnu"), target_os = "vxworks"))] +#[cfg(not(all(target_os = "linux", target_env = "gnu")))] fn on_resolver_failure() {} diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs index 87893d2691..8a028d9930 100644 --- a/library/std/src/sys/unix/os.rs +++ b/library/std/src/sys/unix/os.rs @@ -2,7 +2,7 @@ #![allow(unused_imports)] // lots of cfg code here -#[cfg(all(test, target_env = "gnu"))] +#[cfg(test)] mod tests; use crate::os::unix::prelude::*; @@ -97,6 +97,7 @@ pub fn errno() -> i32 { } #[cfg(target_os = "dragonfly")] +#[allow(dead_code)] pub fn set_errno(e: i32) { extern "C" { #[thread_local] @@ -472,10 +473,7 @@ impl Iterator for Env { #[cfg(target_os = "macos")] pub unsafe fn environ() -> *mut *const *const c_char { - extern "C" { - fn _NSGetEnviron() -> *mut *const *const c_char; - } - _NSGetEnviron() + libc::_NSGetEnviron() as *mut *const *const c_char } #[cfg(not(target_os = "macos"))] @@ -636,30 +634,22 @@ pub fn getppid() -> u32 { unsafe { libc::getppid() as u32 } } -#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))] +#[cfg(all(target_os = "linux", target_env = "gnu"))] pub fn glibc_version() -> Option<(usize, usize)> { - if let Some(Ok(version_str)) = glibc_version_cstr().map(CStr::to_str) { + extern "C" { + fn gnu_get_libc_version() -> *const libc::c_char; + } + let version_cstr = unsafe { CStr::from_ptr(gnu_get_libc_version()) }; + if let Ok(version_str) = version_cstr.to_str() { parse_glibc_version(version_str) } else { None } } -#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))] -fn glibc_version_cstr() -> Option<&'static CStr> { - weak! { - fn gnu_get_libc_version() -> *const libc::c_char - } - if let Some(f) = gnu_get_libc_version.get() { - unsafe { Some(CStr::from_ptr(f())) } - } else { - None - } -} - // Returns Some((major, minor)) if the string is a valid "x.y" version, // ignoring any extra dot-separated parts. Otherwise return None. -#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))] +#[cfg(all(target_os = "linux", target_env = "gnu"))] fn parse_glibc_version(version: &str) -> Option<(usize, usize)> { let mut parsed_ints = version.split('.').map(str::parse::).fuse(); match (parsed_ints.next(), parsed_ints.next()) { diff --git a/library/std/src/sys/unix/os/tests.rs b/library/std/src/sys/unix/os/tests.rs index c445acf272..efc29955b0 100644 --- a/library/std/src/sys/unix/os/tests.rs +++ b/library/std/src/sys/unix/os/tests.rs @@ -1,14 +1,12 @@ -use super::*; - #[test] -#[cfg(not(target_os = "vxworks"))] +#[cfg(all(target_os = "linux", target_env = "gnu"))] fn test_glibc_version() { // This mostly just tests that the weak linkage doesn't panic wildly... - glibc_version(); + super::glibc_version(); } #[test] -#[cfg(not(target_os = "vxworks"))] +#[cfg(all(target_os = "linux", target_env = "gnu"))] fn test_parse_glibc_version() { let cases = [ ("0.0", Some((0, 0))), @@ -20,6 +18,6 @@ fn test_parse_glibc_version() { ("foo.1", None), ]; for &(version_str, parsed) in cases.iter() { - assert_eq!(parsed, parse_glibc_version(version_str)); + assert_eq!(parsed, super::parse_glibc_version(version_str)); } } diff --git a/library/std/src/sys/unix/os_str.rs b/library/std/src/sys/unix/os_str.rs index ae96d6b4df..ccbc182240 100644 --- a/library/std/src/sys/unix/os_str.rs +++ b/library/std/src/sys/unix/os_str.rs @@ -2,6 +2,7 @@ //! systems: just a `Vec`/`[u8]`. use crate::borrow::Cow; +use crate::collections::TryReserveError; use crate::fmt; use crate::fmt::Write; use crate::mem; @@ -112,11 +113,21 @@ impl Buf { self.inner.reserve(additional) } + #[inline] + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.inner.try_reserve(additional) + } + #[inline] pub fn reserve_exact(&mut self, additional: usize) { self.inner.reserve_exact(additional) } + #[inline] + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.inner.try_reserve_exact(additional) + } + #[inline] pub fn shrink_to_fit(&mut self) { self.inner.shrink_to_fit() diff --git a/library/std/src/sys/unix/process/process_fuchsia.rs b/library/std/src/sys/unix/process/process_fuchsia.rs index 507abb2787..ce77c210a6 100644 --- a/library/std/src/sys/unix/process/process_fuchsia.rs +++ b/library/std/src/sys/unix/process/process_fuchsia.rs @@ -284,7 +284,7 @@ impl ExitStatus { // // The other view would be to say that the caller on Fuchsia ought to know that `into_raw` // will give a raw Fuchsia status (whatever that is - I don't know, personally). That is - // not possible here becaause we must return a c_int because that's what Unix (including + // not possible here because we must return a c_int because that's what Unix (including // SuS and POSIX) say a wait status is, but Fuchsia apparently uses a u64, so it won't // necessarily fit. // diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index 3bf1493f3b..bce35b380e 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -13,7 +13,7 @@ use crate::sys::process::process_common::*; use crate::os::linux::process::PidFd; #[cfg(target_os = "linux")] -use crate::sys::weak::syscall; +use crate::sys::weak::raw_syscall; #[cfg(any( target_os = "macos", @@ -162,7 +162,7 @@ impl Command { cgroup: u64, } - syscall! { + raw_syscall! { fn clone3(cl_args: *mut clone_args, len: libc::size_t) -> libc::c_long } diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index b99eb2e553..9e02966b57 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -7,7 +7,9 @@ use crate::ptr; use crate::sys::{os, stack_overflow}; use crate::time::Duration; -#[cfg(any(target_os = "linux", target_os = "solaris", target_os = "illumos"))] +#[cfg(all(target_os = "linux", target_env = "gnu"))] +use crate::sys::weak::dlsym; +#[cfg(any(target_os = "solaris", target_os = "illumos"))] use crate::sys::weak::weak; #[cfg(not(any(target_os = "l4re", target_os = "vxworks", target_os = "espidf")))] pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024; @@ -627,10 +629,12 @@ pub mod guard { // We need that information to avoid blowing up when a small stack // is created in an application with big thread-local storage requirements. // See #6233 for rationale and details. -#[cfg(target_os = "linux")] -#[allow(deprecated)] +#[cfg(all(target_os = "linux", target_env = "gnu"))] fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize { - weak!(fn __pthread_get_minstack(*const libc::pthread_attr_t) -> libc::size_t); + // We use dlsym to avoid an ELF version dependency on GLIBC_PRIVATE. (#23628) + // We shouldn't really be using such an internal symbol, but there's currently + // no other way to account for the TLS size. + dlsym!(fn __pthread_get_minstack(*const libc::pthread_attr_t) -> libc::size_t); match __pthread_get_minstack.get() { None => libc::PTHREAD_STACK_MIN, @@ -638,9 +642,8 @@ fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize { } } -// No point in looking up __pthread_get_minstack() on non-glibc -// platforms. -#[cfg(all(not(target_os = "linux"), not(target_os = "netbsd")))] +// No point in looking up __pthread_get_minstack() on non-glibc platforms. +#[cfg(all(not(all(target_os = "linux", target_env = "gnu")), not(target_os = "netbsd")))] fn min_stack_size(_: *const libc::pthread_attr_t) -> usize { libc::PTHREAD_STACK_MIN } diff --git a/library/std/src/sys/unix/weak.rs b/library/std/src/sys/unix/weak.rs index 83ff78fa7a..da63c06838 100644 --- a/library/std/src/sys/unix/weak.rs +++ b/library/std/src/sys/unix/weak.rs @@ -6,7 +6,7 @@ //! detection. //! //! One option to use here is weak linkage, but that is unfortunately only -//! really workable on Linux. Hence, use dlsym to get the symbol value at +//! really workable with ELF. Otherwise, use dlsym to get the symbol value at //! runtime. This is also done for compatibility with older versions of glibc, //! and to avoid creating dependencies on GLIBC_PRIVATE symbols. It assumes that //! we've been dynamically linked to the library the symbol comes from, but that @@ -14,7 +14,8 @@ //! //! A long time ago this used weak linkage for the __pthread_get_minstack //! symbol, but that caused Debian to detect an unnecessarily strict versioned -//! dependency on libc6 (#23628). +//! dependency on libc6 (#23628) because it is GLIBC_PRIVATE. We now use `dlsym` +//! for a runtime lookup of that symbol to avoid the ELF versioned dependency. // There are a variety of `#[cfg]`s controlling which targets are involved in // each instance of `weak!` and `syscall!`. Rather than trying to unify all of @@ -22,34 +23,77 @@ #![allow(dead_code, unused_macros)] use crate::ffi::CStr; -use crate::marker; +use crate::marker::PhantomData; use crate::mem; use crate::sync::atomic::{self, AtomicUsize, Ordering}; +// We can use true weak linkage on ELF targets. +#[cfg(not(any(target_os = "macos", target_os = "ios")))] pub(crate) macro weak { (fn $name:ident($($t:ty),*) -> $ret:ty) => ( - weak!(fn $name($($t),*) -> $ret, stringify!($name)); - ), - (fn $name:ident($($t:ty),*) -> $ret:ty, $sym:expr) => ( - #[allow(non_upper_case_globals)] - static $name: crate::sys::weak::Weak $ret> = - crate::sys::weak::Weak::new(concat!($sym, '\0')); + let ref $name: ExternWeak $ret> = { + extern "C" { + #[linkage = "extern_weak"] + static $name: *const libc::c_void; + } + #[allow(unused_unsafe)] + ExternWeak::new(unsafe { $name }) + }; ) } -pub struct Weak { - name: &'static str, - addr: AtomicUsize, - _marker: marker::PhantomData, +// On non-ELF targets, use the dlsym approximation of weak linkage. +#[cfg(any(target_os = "macos", target_os = "ios"))] +pub(crate) use self::dlsym as weak; + +pub(crate) struct ExternWeak { + weak_ptr: *const libc::c_void, + _marker: PhantomData, } -impl Weak { - pub const fn new(name: &'static str) -> Weak { - Weak { name, addr: AtomicUsize::new(1), _marker: marker::PhantomData } +impl ExternWeak { + #[inline] + pub(crate) fn new(weak_ptr: *const libc::c_void) -> Self { + ExternWeak { weak_ptr, _marker: PhantomData } + } +} + +impl ExternWeak { + #[inline] + pub(crate) fn get(&self) -> Option { + unsafe { + if self.weak_ptr.is_null() { + None + } else { + Some(mem::transmute_copy::<*const libc::c_void, F>(&self.weak_ptr)) + } + } + } +} + +pub(crate) macro dlsym { + (fn $name:ident($($t:ty),*) -> $ret:ty) => ( + dlsym!(fn $name($($t),*) -> $ret, stringify!($name)); + ), + (fn $name:ident($($t:ty),*) -> $ret:ty, $sym:expr) => ( + static DLSYM: DlsymWeak $ret> = + DlsymWeak::new(concat!($sym, '\0')); + let $name = &DLSYM; + ) +} +pub(crate) struct DlsymWeak { + name: &'static str, + addr: AtomicUsize, + _marker: PhantomData, +} + +impl DlsymWeak { + pub(crate) const fn new(name: &'static str) -> Self { + DlsymWeak { name, addr: AtomicUsize::new(1), _marker: PhantomData } } - pub fn get(&self) -> Option { - assert_eq!(mem::size_of::(), mem::size_of::()); + #[inline] + pub(crate) fn get(&self) -> Option { unsafe { // Relaxed is fine here because we fence before reading through the // pointer (see the comment below). @@ -82,9 +126,11 @@ impl Weak { } } - // Cold because it should only happen during first-time initalization. + // Cold because it should only happen during first-time initialization. #[cold] unsafe fn initialize(&self) -> Option { + assert_eq!(mem::size_of::(), mem::size_of::()); + let val = fetch(self.name); // This synchronizes with the acquire fence in `get`. self.addr.store(val, Ordering::Release); @@ -108,14 +154,12 @@ unsafe fn fetch(name: &str) -> usize { pub(crate) macro syscall { (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( unsafe fn $name($($arg_name: $t),*) -> $ret { - use super::os; - weak! { fn $name($($t),*) -> $ret } if let Some(fun) = $name.get() { fun($($arg_name),*) } else { - os::set_errno(libc::ENOSYS); + super::os::set_errno(libc::ENOSYS); -1 } } @@ -126,11 +170,6 @@ pub(crate) macro syscall { pub(crate) macro syscall { (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( unsafe fn $name($($arg_name:$t),*) -> $ret { - use weak; - // This looks like a hack, but concat_idents only accepts idents - // (not paths). - use libc::*; - weak! { fn $name($($t),*) -> $ret } // Use a weak symbol from libc when possible, allowing `LD_PRELOAD` @@ -138,6 +177,10 @@ pub(crate) macro syscall { if let Some(fun) = $name.get() { fun($($arg_name),*) } else { + // This looks like a hack, but concat_idents only accepts idents + // (not paths). + use libc::*; + syscall( concat_idents!(SYS_, $name), $($arg_name),* @@ -146,3 +189,19 @@ pub(crate) macro syscall { } ) } + +#[cfg(any(target_os = "linux", target_os = "android"))] +pub(crate) macro raw_syscall { + (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( + unsafe fn $name($($arg_name:$t),*) -> $ret { + // This looks like a hack, but concat_idents only accepts idents + // (not paths). + use libc::*; + + syscall( + concat_idents!(SYS_, $name), + $($arg_name),* + ) as $ret + } + ) +} diff --git a/library/std/src/sys/unsupported/fs.rs b/library/std/src/sys/unsupported/fs.rs index 6b45e29c14..d1d2847cd3 100644 --- a/library/std/src/sys/unsupported/fs.rs +++ b/library/std/src/sys/unsupported/fs.rs @@ -1,7 +1,7 @@ use crate::ffi::OsString; use crate::fmt; use crate::hash::{Hash, Hasher}; -use crate::io::{self, IoSlice, IoSliceMut, SeekFrom}; +use crate::io::{self, IoSlice, IoSliceMut, ReadBuf, SeekFrom}; use crate::path::{Path, PathBuf}; use crate::sys::time::SystemTime; use crate::sys::unsupported; @@ -206,6 +206,10 @@ impl File { self.0 } + pub fn read_buf(&self, _buf: &mut ReadBuf<'_>) -> io::Result<()> { + self.0 + } + pub fn write(&self, _buf: &[u8]) -> io::Result { self.0 } diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs index 00b9ab3b86..5924789d12 100644 --- a/library/std/src/sys/wasi/fs.rs +++ b/library/std/src/sys/wasi/fs.rs @@ -3,7 +3,7 @@ use super::fd::WasiFd; use crate::ffi::{CStr, CString, OsStr, OsString}; use crate::fmt; -use crate::io::{self, IoSlice, IoSliceMut, SeekFrom}; +use crate::io::{self, IoSlice, IoSliceMut, ReadBuf, SeekFrom}; use crate::iter; use crate::mem::{self, ManuallyDrop}; use crate::os::raw::c_int; @@ -423,6 +423,10 @@ impl File { true } + pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + crate::io::default_read_buf(|buf| self.read(buf), buf) + } + pub fn write(&self, buf: &[u8]) -> io::Result { self.write_vectored(&[IoSlice::new(buf)]) } diff --git a/library/std/src/sys/wasm/alloc.rs b/library/std/src/sys/wasm/alloc.rs index 3223e89410..6dceb1689a 100644 --- a/library/std/src/sys/wasm/alloc.rs +++ b/library/std/src/sys/wasm/alloc.rs @@ -24,7 +24,7 @@ static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::Dlmalloc::new(); unsafe impl GlobalAlloc for System { #[inline] unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - // SAFETY: DLMALLOC access is guranteed to be safe because the lock gives us unique and non-reentrant access. + // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. // Calling malloc() is safe because preconditions on this function match the trait method preconditions. let _lock = lock::lock(); unsafe { DLMALLOC.malloc(layout.size(), layout.align()) } @@ -32,7 +32,7 @@ unsafe impl GlobalAlloc for System { #[inline] unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { - // SAFETY: DLMALLOC access is guranteed to be safe because the lock gives us unique and non-reentrant access. + // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. // Calling calloc() is safe because preconditions on this function match the trait method preconditions. let _lock = lock::lock(); unsafe { DLMALLOC.calloc(layout.size(), layout.align()) } @@ -40,7 +40,7 @@ unsafe impl GlobalAlloc for System { #[inline] unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - // SAFETY: DLMALLOC access is guranteed to be safe because the lock gives us unique and non-reentrant access. + // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. // Calling free() is safe because preconditions on this function match the trait method preconditions. let _lock = lock::lock(); unsafe { DLMALLOC.free(ptr, layout.size(), layout.align()) } @@ -48,7 +48,7 @@ unsafe impl GlobalAlloc for System { #[inline] unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - // SAFETY: DLMALLOC access is guranteed to be safe because the lock gives us unique and non-reentrant access. + // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access. // Calling realloc() is safe because preconditions on this function match the trait method preconditions. let _lock = lock::lock(); unsafe { DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size) } diff --git a/library/std/src/sys/wasm/atomics/mutex.rs b/library/std/src/sys/wasm/atomics/mutex.rs index 5ff0ec052b..3a09f0bf9b 100644 --- a/library/std/src/sys/wasm/atomics/mutex.rs +++ b/library/std/src/sys/wasm/atomics/mutex.rs @@ -73,7 +73,7 @@ pub struct ReentrantMutex { unsafe impl Send for ReentrantMutex {} unsafe impl Sync for ReentrantMutex {} -// Reentrant mutexes are similarly implemented to mutexs above except that +// Reentrant mutexes are similarly implemented to mutexes above except that // instead of "1" meaning unlocked we use the id of a thread to represent // whether it has locked a mutex. That way we have an atomic counter which // always holds the id of the thread that currently holds the lock (or 0 if the @@ -96,7 +96,7 @@ impl ReentrantMutex { pub unsafe fn lock(&self) { let me = thread::my_id(); while let Err(owner) = self._try_lock(me) { - // SAFETY: the caller must gurantee that `self.ptr()` and `owner` are valid i32. + // SAFETY: the caller must guarantee that `self.ptr()` and `owner` are valid i32. let val = unsafe { wasm32::memory_atomic_wait32(self.ptr(), owner as i32, -1) }; debug_assert!(val == 0 || val == 1); } @@ -136,7 +136,7 @@ impl ReentrantMutex { match *self.recursions.get() { 0 => { self.owner.swap(0, SeqCst); - // SAFETY: the caller must gurantee that `self.ptr()` is valid i32. + // SAFETY: the caller must guarantee that `self.ptr()` is valid i32. unsafe { wasm32::memory_atomic_notify(self.ptr() as *mut i32, 1); } // wake up one waiter, if any diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index 1ef6addc11..09d3661e4f 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -1199,6 +1199,12 @@ compat_fn! { -> () { GetSystemTimeAsFileTime(lpSystemTimeAsFileTime) } + + // >= Win11 / Server 2022 + // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppath2a + pub fn GetTempPath2W(nBufferLength: DWORD, lpBuffer: LPCWSTR) -> DWORD { + GetTempPathW(nBufferLength, lpBuffer) + } } compat_fn! { diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index 5894c68034..dd21c6b438 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -2,7 +2,7 @@ use crate::os::windows::prelude::*; use crate::ffi::OsString; use crate::fmt; -use crate::io::{self, Error, IoSlice, IoSliceMut, SeekFrom}; +use crate::io::{self, Error, IoSlice, IoSliceMut, ReadBuf, SeekFrom}; use crate::mem; use crate::os::windows::io::{AsHandle, BorrowedHandle}; use crate::path::{Path, PathBuf}; @@ -420,6 +420,10 @@ impl File { self.handle.read_at(buf, offset) } + pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + self.handle.read_buf(buf) + } + pub fn write(&self, buf: &[u8]) -> io::Result { self.handle.write(buf) } diff --git a/library/std/src/sys/windows/handle.rs b/library/std/src/sys/windows/handle.rs index 21d86b0022..c3a3482f91 100644 --- a/library/std/src/sys/windows/handle.rs +++ b/library/std/src/sys/windows/handle.rs @@ -1,7 +1,7 @@ #![unstable(issue = "none", feature = "windows_handle")] use crate::cmp; -use crate::io::{self, ErrorKind, IoSlice, IoSliceMut, Read}; +use crate::io::{self, ErrorKind, IoSlice, IoSliceMut, Read, ReadBuf}; use crate::mem; use crate::os::windows::io::{ AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle, RawHandle, @@ -130,6 +130,39 @@ impl Handle { } } + pub fn read_buf(&self, buf: &mut ReadBuf<'_>) -> io::Result<()> { + let mut read = 0; + let len = cmp::min(buf.remaining(), ::MAX as usize) as c::DWORD; + let res = cvt(unsafe { + c::ReadFile( + self.as_raw_handle(), + buf.unfilled_mut().as_mut_ptr() as c::LPVOID, + len, + &mut read, + ptr::null_mut(), + ) + }); + + match res { + Ok(_) => { + // Safety: `read` bytes were written to the initialized portion of the buffer + unsafe { + buf.assume_init(read as usize); + } + buf.add_filled(read as usize); + Ok(()) + } + + // The special treatment of BrokenPipe is to deal with Windows + // pipe semantics, which yields this error when *reading* from + // a pipe after the other end has closed; we interpret that as + // EOF on the pipe. + Err(ref e) if e.kind() == ErrorKind::BrokenPipe => Ok(()), + + Err(e) => Err(e), + } + } + pub unsafe fn read_overlapped( &self, buf: &mut [u8], diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs index 28fec817f8..084af4325e 100644 --- a/library/std/src/sys/windows/mod.rs +++ b/library/std/src/sys/windows/mod.rs @@ -288,13 +288,13 @@ pub fn abort_internal() -> ! { unsafe { cfg_if::cfg_if! { if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] { - asm!("int $$0x29", in("ecx") FAST_FAIL_FATAL_APP_EXIT); + core::arch::asm!("int $$0x29", in("ecx") FAST_FAIL_FATAL_APP_EXIT); crate::intrinsics::unreachable(); } else if #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))] { - asm!(".inst 0xDEFB", in("r0") FAST_FAIL_FATAL_APP_EXIT); + core::arch::asm!(".inst 0xDEFB", in("r0") FAST_FAIL_FATAL_APP_EXIT); crate::intrinsics::unreachable(); } else if #[cfg(target_arch = "aarch64")] { - asm!("brk 0xF003", in("x0") FAST_FAIL_FATAL_APP_EXIT); + core::arch::asm!("brk 0xF003", in("x0") FAST_FAIL_FATAL_APP_EXIT); crate::intrinsics::unreachable(); } } diff --git a/library/std/src/sys/windows/os.rs b/library/std/src/sys/windows/os.rs index b5209aa690..5f8556c3bc 100644 --- a/library/std/src/sys/windows/os.rs +++ b/library/std/src/sys/windows/os.rs @@ -275,7 +275,7 @@ pub fn unsetenv(n: &OsStr) -> io::Result<()> { } pub fn temp_dir() -> PathBuf { - super::fill_utf16_buf(|buf, sz| unsafe { c::GetTempPathW(sz, buf) }, super::os2path).unwrap() + super::fill_utf16_buf(|buf, sz| unsafe { c::GetTempPath2W(sz, buf) }, super::os2path).unwrap() } #[cfg(not(target_vendor = "uwp"))] diff --git a/library/std/src/sys/windows/os_str.rs b/library/std/src/sys/windows/os_str.rs index 7e09a4fd56..78e92a3331 100644 --- a/library/std/src/sys/windows/os_str.rs +++ b/library/std/src/sys/windows/os_str.rs @@ -1,6 +1,7 @@ /// The underlying OsString/OsStr implementation on Windows is a /// wrapper around the "WTF-8" encoding; see the `wtf8` module for more. use crate::borrow::Cow; +use crate::collections::TryReserveError; use crate::fmt; use crate::mem; use crate::rc::Rc; @@ -104,10 +105,18 @@ impl Buf { self.inner.reserve(additional) } + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.inner.try_reserve(additional) + } + pub fn reserve_exact(&mut self, additional: usize) { self.inner.reserve_exact(additional) } + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.inner.try_reserve_exact(additional) + } + pub fn shrink_to_fit(&mut self) { self.inner.shrink_to_fit() } diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index e84dfbce4a..5ad5704279 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -268,7 +268,7 @@ impl Command { } else { None }; - let program = resolve_exe(&self.program, child_paths)?; + let program = resolve_exe(&self.program, || env::var_os("PATH"), child_paths)?; let mut cmd_str = make_command_line(program.as_os_str(), &self.args, self.force_quotes_enabled)?; cmd_str.push(0); // add null terminator @@ -362,7 +362,11 @@ impl fmt::Debug for Command { // Therefore this functions first assumes `.exe` was intended. // It falls back to the plain file name if a full path is given and the extension is omitted // or if only a file name is given and it already contains an extension. -fn resolve_exe<'a>(exe_path: &'a OsStr, child_paths: Option<&OsStr>) -> io::Result { +fn resolve_exe<'a>( + exe_path: &'a OsStr, + parent_paths: impl FnOnce() -> Option, + child_paths: Option<&OsStr>, +) -> io::Result { // Early return if there is no filename. if exe_path.is_empty() || path::has_trailing_slash(exe_path) { return Err(io::Error::new_const( @@ -406,7 +410,7 @@ fn resolve_exe<'a>(exe_path: &'a OsStr, child_paths: Option<&OsStr>) -> io::Resu let has_extension = exe_path.bytes().contains(&b'.'); // Search the directories given by `search_paths`. - let result = search_paths(child_paths, |mut path| { + let result = search_paths(parent_paths, child_paths, |mut path| { path.push(&exe_path); if !has_extension { path.set_extension(EXE_EXTENSION); @@ -423,15 +427,20 @@ fn resolve_exe<'a>(exe_path: &'a OsStr, child_paths: Option<&OsStr>) -> io::Resu // Calls `f` for every path that should be used to find an executable. // Returns once `f` returns the path to an executable or all paths have been searched. -fn search_paths(child_paths: Option<&OsStr>, mut f: F) -> Option +fn search_paths( + parent_paths: Paths, + child_paths: Option<&OsStr>, + mut exists: Exists, +) -> Option where - F: FnMut(PathBuf) -> Option, + Paths: FnOnce() -> Option, + Exists: FnMut(PathBuf) -> Option, { // 1. Child paths // This is for consistency with Rust's historic behaviour. if let Some(paths) = child_paths { for path in env::split_paths(paths).filter(|p| !p.as_os_str().is_empty()) { - if let Some(path) = f(path) { + if let Some(path) = exists(path) { return Some(path); } } @@ -440,7 +449,7 @@ where // 2. Application path if let Ok(mut app_path) = env::current_exe() { app_path.pop(); - if let Some(path) = f(app_path) { + if let Some(path) = exists(app_path) { return Some(path); } } @@ -450,7 +459,7 @@ where unsafe { if let Ok(Some(path)) = super::fill_utf16_buf( |buf, size| c::GetSystemDirectoryW(buf, size), - |buf| f(PathBuf::from(OsString::from_wide(buf))), + |buf| exists(PathBuf::from(OsString::from_wide(buf))), ) { return Some(path); } @@ -458,7 +467,7 @@ where { if let Ok(Some(path)) = super::fill_utf16_buf( |buf, size| c::GetWindowsDirectoryW(buf, size), - |buf| f(PathBuf::from(OsString::from_wide(buf))), + |buf| exists(PathBuf::from(OsString::from_wide(buf))), ) { return Some(path); } @@ -466,9 +475,9 @@ where } // 5. Parent paths - if let Some(parent_paths) = env::var_os("PATH") { + if let Some(parent_paths) = parent_paths() { for path in env::split_paths(&parent_paths).filter(|p| !p.as_os_str().is_empty()) { - if let Some(path) = f(path) { + if let Some(path) = exists(path) { return Some(path); } } diff --git a/library/std/src/sys/windows/process/tests.rs b/library/std/src/sys/windows/process/tests.rs index 6159a679c0..f1221767af 100644 --- a/library/std/src/sys/windows/process/tests.rs +++ b/library/std/src/sys/windows/process/tests.rs @@ -136,51 +136,46 @@ fn windows_exe_resolver() { use super::resolve_exe; use crate::io; + let env_paths = || env::var_os("PATH"); + // Test a full path, with and without the `exe` extension. let mut current_exe = env::current_exe().unwrap(); - assert!(resolve_exe(current_exe.as_ref(), None).is_ok()); + assert!(resolve_exe(current_exe.as_ref(), env_paths, None).is_ok()); current_exe.set_extension(""); - assert!(resolve_exe(current_exe.as_ref(), None).is_ok()); + assert!(resolve_exe(current_exe.as_ref(), env_paths, None).is_ok()); // Test lone file names. - assert!(resolve_exe(OsStr::new("cmd"), None).is_ok()); - assert!(resolve_exe(OsStr::new("cmd.exe"), None).is_ok()); - assert!(resolve_exe(OsStr::new("cmd.EXE"), None).is_ok()); - assert!(resolve_exe(OsStr::new("fc"), None).is_ok()); + assert!(resolve_exe(OsStr::new("cmd"), env_paths, None).is_ok()); + assert!(resolve_exe(OsStr::new("cmd.exe"), env_paths, None).is_ok()); + assert!(resolve_exe(OsStr::new("cmd.EXE"), env_paths, None).is_ok()); + assert!(resolve_exe(OsStr::new("fc"), env_paths, None).is_ok()); // Invalid file names should return InvalidInput. - assert_eq!(resolve_exe(OsStr::new(""), None).unwrap_err().kind(), io::ErrorKind::InvalidInput); assert_eq!( - resolve_exe(OsStr::new("\0"), None).unwrap_err().kind(), + resolve_exe(OsStr::new(""), env_paths, None).unwrap_err().kind(), + io::ErrorKind::InvalidInput + ); + assert_eq!( + resolve_exe(OsStr::new("\0"), env_paths, None).unwrap_err().kind(), io::ErrorKind::InvalidInput ); // Trailing slash, therefore there's no file name component. assert_eq!( - resolve_exe(OsStr::new(r"C:\Path\to\"), None).unwrap_err().kind(), + resolve_exe(OsStr::new(r"C:\Path\to\"), env_paths, None).unwrap_err().kind(), io::ErrorKind::InvalidInput ); - /* FIXME: fix and re-enable these tests before making changes to the resolver. - /* Some of the following tests may need to be changed if you are deliberately changing the behaviour of `resolve_exe`. */ - let paths = env::var_os("PATH").unwrap(); - env::set_var("PATH", ""); - - assert_eq!(resolve_exe(OsStr::new("rustc"), None).unwrap_err().kind(), io::ErrorKind::NotFound); - - let child_paths = Some(paths.as_os_str()); - assert!(resolve_exe(OsStr::new("rustc"), child_paths).is_ok()); + let empty_paths = || None; // The resolver looks in system directories even when `PATH` is empty. - assert!(resolve_exe(OsStr::new("cmd.exe"), None).is_ok()); + assert!(resolve_exe(OsStr::new("cmd.exe"), empty_paths, None).is_ok()); // The application's directory is also searched. let current_exe = env::current_exe().unwrap(); - assert!(resolve_exe(current_exe.file_name().unwrap().as_ref(), None).is_ok()); - - */ + assert!(resolve_exe(current_exe.file_name().unwrap().as_ref(), empty_paths, None).is_ok()); } diff --git a/library/std/src/sys/windows/stdio.rs b/library/std/src/sys/windows/stdio.rs index a4fe5f67f6..684b8e3155 100644 --- a/library/std/src/sys/windows/stdio.rs +++ b/library/std/src/sys/windows/stdio.rs @@ -15,7 +15,9 @@ use core::str::utf8_char_width; // the value over time (such as if a process calls `SetStdHandle` while it's running). See #40490. pub struct Stdin { surrogate: u16, + incomplete_utf8: IncompleteUtf8, } + pub struct Stdout { incomplete_utf8: IncompleteUtf8, } @@ -29,6 +31,25 @@ struct IncompleteUtf8 { len: u8, } +impl IncompleteUtf8 { + // Implemented for use in Stdin::read. + fn read(&mut self, buf: &mut [u8]) -> usize { + // Write to buffer until the buffer is full or we run out of bytes. + let to_write = cmp::min(buf.len(), self.len as usize); + buf[..to_write].copy_from_slice(&self.bytes[..to_write]); + + // Rotate the remaining bytes if not enough remaining space in buffer. + if usize::from(self.len) > buf.len() { + self.bytes.copy_within(to_write.., 0); + self.len -= to_write as u8; + } else { + self.len = 0; + } + + to_write + } +} + // Apparently Windows doesn't handle large reads on stdin or writes to stdout/stderr well (see // #13304 for details). // @@ -124,7 +145,7 @@ fn write( // // If the data is not valid UTF-8 we write out as many bytes as are valid. // If the first byte is invalid it is either first byte of a multi-byte sequence but the - // provided byte slice is too short or it is the first byte of an invalide multi-byte sequence. + // provided byte slice is too short or it is the first byte of an invalid multi-byte sequence. let len = cmp::min(data.len(), MAX_BUFFER_SIZE / 2); let utf8 = match str::from_utf8(&data[..len]) { Ok(s) => s, @@ -205,7 +226,7 @@ fn write_u16s(handle: c::HANDLE, data: &[u16]) -> io::Result { impl Stdin { pub const fn new() -> Stdin { - Stdin { surrogate: 0 } + Stdin { surrogate: 0, incomplete_utf8: IncompleteUtf8::new() } } } @@ -221,24 +242,39 @@ impl io::Read for Stdin { } } - if buf.len() == 0 { - return Ok(0); - } else if buf.len() < 4 { - return Err(io::Error::new_const( - io::ErrorKind::InvalidInput, - &"Windows stdin in console mode does not support a buffer too small to \ - guarantee holding one arbitrary UTF-8 character (4 bytes)", - )); + // If there are bytes in the incomplete utf-8, start with those. + // (No-op if there is nothing in the buffer.) + let mut bytes_copied = self.incomplete_utf8.read(buf); + + if bytes_copied == buf.len() { + return Ok(bytes_copied); + } else if buf.len() - bytes_copied < 4 { + // Not enough space to get a UTF-8 byte. We will use the incomplete UTF8. + let mut utf16_buf = [0u16; 1]; + // Read one u16 character. + let read = read_u16s_fixup_surrogates(handle, &mut utf16_buf, 1, &mut self.surrogate)?; + // Read bytes, using the (now-empty) self.incomplete_utf8 as extra space. + let read_bytes = utf16_to_utf8(&utf16_buf[..read], &mut self.incomplete_utf8.bytes)?; + + // Read in the bytes from incomplete_utf8 until the buffer is full. + self.incomplete_utf8.len = read_bytes as u8; + // No-op if no bytes. + bytes_copied += self.incomplete_utf8.read(&mut buf[bytes_copied..]); + Ok(bytes_copied) + } else { + let mut utf16_buf = [0u16; MAX_BUFFER_SIZE / 2]; + // In the worst case, a UTF-8 string can take 3 bytes for every `u16` of a UTF-16. So + // we can read at most a third of `buf.len()` chars and uphold the guarantee no data gets + // lost. + let amount = cmp::min(buf.len() / 3, utf16_buf.len()); + let read = + read_u16s_fixup_surrogates(handle, &mut utf16_buf, amount, &mut self.surrogate)?; + + match utf16_to_utf8(&utf16_buf[..read], buf) { + Ok(value) => return Ok(bytes_copied + value), + Err(e) => return Err(e), + } } - - let mut utf16_buf = [0u16; MAX_BUFFER_SIZE / 2]; - // In the worst case, a UTF-8 string can take 3 bytes for every `u16` of a UTF-16. So - // we can read at most a third of `buf.len()` chars and uphold the guarantee no data gets - // lost. - let amount = cmp::min(buf.len() / 3, utf16_buf.len()); - let read = read_u16s_fixup_surrogates(handle, &mut utf16_buf, amount, &mut self.surrogate)?; - - utf16_to_utf8(&utf16_buf[..read], buf) } } diff --git a/library/std/src/sys/windows/thread_parker.rs b/library/std/src/sys/windows/thread_parker.rs index 4f59d4dd45..5a8011a958 100644 --- a/library/std/src/sys/windows/thread_parker.rs +++ b/library/std/src/sys/windows/thread_parker.rs @@ -22,7 +22,7 @@ // // Unlike WaitOnAddress, NtWaitForKeyedEvent/NtReleaseKeyedEvent operate on a // HANDLE (created with NtCreateKeyedEvent). This means that we can be sure -// a succesfully awoken park() was awoken by unpark() and not a +// a successfully awoken park() was awoken by unpark() and not a // NtReleaseKeyedEvent call from some other code, as these events are not only // matched by the key (address of the parker (state)), but also by this HANDLE. // We lazily allocate this handle the first time it is needed. diff --git a/library/std/src/sys_common/process.rs b/library/std/src/sys_common/process.rs index 2cd1e29f6c..9f978789a6 100644 --- a/library/std/src/sys_common/process.rs +++ b/library/std/src/sys_common/process.rs @@ -39,22 +39,6 @@ impl CommandEnv { result } - // Apply these changes directly to the current environment - pub fn apply(&self) { - if self.clear { - for (k, _) in env::vars_os() { - env::remove_var(k); - } - } - for (key, maybe_val) in self.vars.iter() { - if let Some(ref val) = maybe_val { - env::set_var(key, val); - } else { - env::remove_var(key); - } - } - } - pub fn is_unchanged(&self) -> bool { !self.clear && self.vars.is_empty() } diff --git a/library/std/src/sys_common/thread_parker/generic.rs b/library/std/src/sys_common/thread_parker/generic.rs index 14cfa958e5..d99e901bb5 100644 --- a/library/std/src/sys_common/thread_parker/generic.rs +++ b/library/std/src/sys_common/thread_parker/generic.rs @@ -1,4 +1,4 @@ -//! Parker implementaiton based on a Mutex and Condvar. +//! Parker implementation based on a Mutex and Condvar. use crate::sync::atomic::AtomicUsize; use crate::sync::atomic::Ordering::SeqCst; @@ -20,7 +20,7 @@ impl Parker { Parker { state: AtomicUsize::new(EMPTY), lock: Mutex::new(()), cvar: Condvar::new() } } - // This implementaiton doesn't require `unsafe`, but other implementations + // This implementation doesn't require `unsafe`, but other implementations // may assume this is only called by the thread that owns the Parker. pub unsafe fn park(&self) { // If we were previously notified then we consume this notification and @@ -55,7 +55,7 @@ impl Parker { } } - // This implementaiton doesn't require `unsafe`, but other implementations + // This implementation doesn't require `unsafe`, but other implementations // may assume this is only called by the thread that owns the Parker. pub unsafe fn park_timeout(&self, dur: Duration) { // Like `park` above we have a fast path for an already-notified thread, and diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs index 6e29bc6145..7a6e624635 100644 --- a/library/std/src/sys_common/wtf8.rs +++ b/library/std/src/sys_common/wtf8.rs @@ -22,6 +22,7 @@ use core::str::next_code_point; use crate::borrow::Cow; use crate::char; +use crate::collections::TryReserveError; use crate::fmt; use crate::hash::{Hash, Hasher}; use crate::iter::FromIterator; @@ -231,11 +232,47 @@ impl Wtf8Buf { self.bytes.reserve(additional) } + /// Tries to reserve capacity for at least `additional` more length units + /// in the given `Wtf8Buf`. The `Wtf8Buf` may reserve more space to avoid + /// frequent reallocations. After calling `try_reserve`, capacity will be + /// greater than or equal to `self.len() + additional`. Does nothing if + /// capacity is already sufficient. + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + #[inline] + pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.bytes.try_reserve(additional) + } + #[inline] pub fn reserve_exact(&mut self, additional: usize) { self.bytes.reserve_exact(additional) } + /// Tries to reserve the minimum capacity for exactly `additional` + /// length units in the given `Wtf8Buf`. After calling + /// `try_reserve_exact`, capacity will be greater than or equal to + /// `self.len() + additional` if it returns `Ok(())`. + /// Does nothing if the capacity is already sufficient. + /// + /// Note that the allocator may give the `Wtf8Buf` more space than it + /// requests. Therefore, capacity can not be relied upon to be precisely + /// minimal. Prefer [`try_reserve`] if future insertions are expected. + /// + /// [`try_reserve`]: Wtf8Buf::try_reserve + /// + /// # Errors + /// + /// If the capacity overflows, or the allocator reports a failure, then an error + /// is returned. + #[inline] + pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { + self.bytes.try_reserve_exact(additional) + } + #[inline] pub fn shrink_to_fit(&mut self) { self.bytes.shrink_to_fit() diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 4da59577d7..1d2f6e9768 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -76,7 +76,21 @@ use crate::fmt; /// destroyed, but not all platforms have this guard. Those platforms that do /// not guard typically have a synthetic limit after which point no more /// destructors are run. +/// 3. When the process exits on Windows systems, TLS destructors may only be +/// run on the thread that causes the process to exit. This is because the +/// other threads may be forcibly terminated. /// +/// ## Synchronization in thread-local destructors +/// +/// On Windows, synchronization operations (such as [`JoinHandle::join`]) in +/// thread local destructors are prone to deadlocks and so should be avoided. +/// This is because the [loader lock] is held while a destructor is run. The +/// lock is acquired whenever a thread starts or exits or when a DLL is loaded +/// or unloaded. Therefore these events are blocked for as long as a thread +/// local destructor is running. +/// +/// [loader lock]: https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices +/// [`JoinHandle::join`]: crate::thread::JoinHandle::join /// [`with`]: LocalKey::with #[stable(feature = "rust1", since = "1.0.0")] pub struct LocalKey { @@ -164,7 +178,6 @@ macro_rules! __thread_local_inner { (@key $t:ty, const $init:expr) => {{ #[cfg_attr(not(windows), inline)] // see comments below unsafe fn __getit() -> $crate::option::Option<&'static $t> { - const _REQUIRE_UNSTABLE: () = $crate::thread::require_unstable_const_init_thread_local(); const INIT_EXPR: $t = $init; // wasm without atomics maps directly to `static mut`, and dtors @@ -569,7 +582,7 @@ pub mod fast { Key { inner: LazyKeyInner::new(), dtor_state: Cell::new(DtorState::Unregistered) } } - // note that this is just a publically-callable function only for the + // note that this is just a publicly-callable function only for the // const-initialized form of thread locals, basically a way to call the // free `register_dtor` function defined elsewhere in libstd. pub unsafe fn register_dtor(a: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { @@ -580,7 +593,7 @@ pub mod fast { pub unsafe fn get T>(&self, init: F) -> Option<&'static T> { // SAFETY: See the definitions of `LazyKeyInner::get` and - // `try_initialize` for more informations. + // `try_initialize` for more information. // // The caller must ensure no mutable references are ever active to // the inner cell or the inner T when this is called. diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 39b53b51bf..ae4b65871e 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -204,13 +204,6 @@ pub use self::local::os::Key as __OsLocalKeyInner; #[doc(hidden)] pub use self::local::statik::Key as __StaticLocalKeyInner; -// This is only used to make thread locals with `const { .. }` initialization -// expressions unstable. If and/or when that syntax is stabilized with thread -// locals this will simply be removed. -#[doc(hidden)] -#[unstable(feature = "thread_local_const_init", issue = "84223")] -pub const fn require_unstable_const_init_thread_local() {} - //////////////////////////////////////////////////////////////////////////////// // Builder //////////////////////////////////////////////////////////////////////////////// @@ -979,10 +972,13 @@ pub fn park_timeout(dur: Duration) { /// A unique identifier for a running thread. /// -/// A `ThreadId` is an opaque object that has a unique value for each thread -/// that creates one. `ThreadId`s are not guaranteed to correspond to a thread's -/// system-designated identifier. A `ThreadId` can be retrieved from the [`id`] -/// method on a [`Thread`]. +/// A `ThreadId` is an opaque object that uniquely identifies each thread +/// created during the lifetime of a process. `ThreadId`s are guaranteed not to +/// be reused, even when a thread terminates. `ThreadId`s are under the control +/// of Rust's standard library and there may not be any relationship between +/// `ThreadId` and the underlying platform's notion of a thread identifier -- +/// the two concepts cannot, therefore, be used interchangeably. A `ThreadId` +/// can be retrieved from the [`id`] method on a [`Thread`]. /// /// # Examples /// @@ -1280,7 +1276,7 @@ impl JoinInner { /// An owned permission to join on a thread (block on its termination). /// /// A `JoinHandle` *detaches* the associated thread when it is dropped, which -/// means that there is no longer any handle to thread and no way to `join` +/// means that there is no longer any handle to the thread and no way to `join` /// on it. /// /// Due to platform restrictions, it is not possible to [`Clone`] this @@ -1460,9 +1456,12 @@ fn _assert_sync_and_send() { /// The purpose of this API is to provide an easy and portable way to query /// the default amount of parallelism the program should use. Among other things it /// does not expose information on NUMA regions, does not account for -/// differences in (co)processor capabilities, and will not modify the program's -/// global state in order to more accurately query the amount of available -/// parallelism. +/// differences in (co)processor capabilities or current system load, +/// and will not modify the program's global state in order to more accurately +/// query the amount of available parallelism. +/// +/// Where both fixed steady-state and burst limits are available the steady-state +/// capacity will be used to ensure more predictable latencies. /// /// Resource limits can be changed during the runtime of a program, therefore the value is /// not cached and instead recomputed every time this function is called. It should not be @@ -1505,7 +1504,6 @@ fn _assert_sync_and_send() { /// /// ``` /// # #![allow(dead_code)] -/// #![feature(available_parallelism)] /// use std::{io, thread}; /// /// fn main() -> io::Result<()> { @@ -1517,7 +1515,7 @@ fn _assert_sync_and_send() { #[doc(alias = "available_concurrency")] // Alias for a previous name we gave this API on unstable. #[doc(alias = "hardware_concurrency")] // Alias for C++ `std::thread::hardware_concurrency`. #[doc(alias = "num_cpus")] // Alias for a popular ecosystem crate which provides similar functionality. -#[unstable(feature = "available_parallelism", issue = "74479")] +#[stable(feature = "available_parallelism", since = "1.59.0")] pub fn available_parallelism() -> io::Result { imp::available_parallelism() } diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs index ca0d88135a..4f2c81731a 100644 --- a/library/std/src/thread/tests.rs +++ b/library/std/src/thread/tests.rs @@ -1,6 +1,7 @@ use super::Builder; use crate::any::Any; use crate::mem; +use crate::panic::panic_any; use crate::result; use crate::sync::{ mpsc::{channel, Sender}, @@ -183,7 +184,7 @@ fn test_simple_newsched_spawn() { } #[test] -fn test_try_panic_message_static_str() { +fn test_try_panic_message_string_literal() { match thread::spawn(move || { panic!("static string"); }) @@ -199,9 +200,9 @@ fn test_try_panic_message_static_str() { } #[test] -fn test_try_panic_message_owned_str() { +fn test_try_panic_any_message_owned_str() { match thread::spawn(move || { - panic!("owned string".to_string()); + panic_any("owned string".to_string()); }) .join() { @@ -215,9 +216,9 @@ fn test_try_panic_message_owned_str() { } #[test] -fn test_try_panic_message_any() { +fn test_try_panic_any_message_any() { match thread::spawn(move || { - panic!(box 413u16 as Box); + panic_any(box 413u16 as Box); }) .join() { @@ -233,10 +234,10 @@ fn test_try_panic_message_any() { } #[test] -fn test_try_panic_message_unit_struct() { +fn test_try_panic_any_message_unit_struct() { struct Juju; - match thread::spawn(move || panic!(Juju)).join() { + match thread::spawn(move || panic_any(Juju)).join() { Err(ref e) if e.is::() => {} Err(_) | Ok(()) => panic!(), } diff --git a/library/std/src/time.rs b/library/std/src/time.rs index a5e3bd0c29..86cc93c445 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -273,7 +273,7 @@ impl Instant { // While issues have been seen on arm64 platforms the Arm architecture // requires that the counter monotonically increases and that it must // provide a uniform view of system time (e.g. it must not be possible - // for a core to recieve a message from another core with a time stamp + // for a core to receive a message from another core with a time stamp // and observe time going backwards (ARM DDI 0487G.b D11.1.2). While // there have been a few 64bit SoCs that have bugs which cause time to // not monoticially increase, these have been fixed in the Linux kernel diff --git a/library/stdarch/.github/workflows/main.yml b/library/stdarch/.github/workflows/main.yml index 6412075a4a..fd8713ff8a 100644 --- a/library/stdarch/.github/workflows/main.yml +++ b/library/stdarch/.github/workflows/main.yml @@ -72,6 +72,7 @@ jobs: - arm-unknown-linux-gnueabihf - armv7-unknown-linux-gnueabihf - aarch64-unknown-linux-gnu + - riscv64gc-unknown-linux-gnu - powerpc64le-unknown-linux-gnu - mips-unknown-linux-gnu - mips64-unknown-linux-gnuabi64 @@ -116,7 +117,6 @@ jobs: os: ubuntu-latest - target: armv7-unknown-linux-gnueabihf os: ubuntu-latest - rustflags: -C target-feature=+neon - target: mips-unknown-linux-gnu os: ubuntu-latest norun: true @@ -168,6 +168,8 @@ jobs: os: ubuntu-latest - target: thumbv7em-none-eabihf os: ubuntu-latest + - target: riscv64gc-unknown-linux-gnu + os: ubuntu-latest steps: - uses: actions/checkout@master diff --git a/library/stdarch/ci/docker/aarch64-unknown-linux-gnu/Dockerfile b/library/stdarch/ci/docker/aarch64-unknown-linux-gnu/Dockerfile index 2b43841907..49464dacfc 100644 --- a/library/stdarch/ci/docker/aarch64-unknown-linux-gnu/Dockerfile +++ b/library/stdarch/ci/docker/aarch64-unknown-linux-gnu/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:20.04 +FROM ubuntu:21.10 RUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ g++ \ @@ -10,7 +10,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ qemu-user \ make \ file \ - clang-12 \ + clang-13 \ lld ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc \ diff --git a/library/stdarch/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile b/library/stdarch/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile index 2539062933..74181a4cb8 100644 --- a/library/stdarch/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile +++ b/library/stdarch/ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile @@ -1,13 +1,17 @@ -FROM ubuntu:18.04 +FROM ubuntu:21.10 RUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ + g++ \ ca-certificates \ libc6-dev \ gcc-arm-linux-gnueabihf \ + g++-arm-linux-gnueabihf \ libc6-dev-armhf-cross \ qemu-user \ make \ - file + file \ + clang-13 \ + lld ENV CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc \ CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_RUNNER="qemu-arm -L /usr/arm-linux-gnueabihf" \ OBJDUMP=arm-linux-gnueabihf-objdump diff --git a/library/stdarch/ci/docker/riscv64gc-unknown-linux-gnu/Dockerfile b/library/stdarch/ci/docker/riscv64gc-unknown-linux-gnu/Dockerfile new file mode 100644 index 0000000000..1618db22fb --- /dev/null +++ b/library/stdarch/ci/docker/riscv64gc-unknown-linux-gnu/Dockerfile @@ -0,0 +1,10 @@ +FROM ubuntu:21.10 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + gcc libc6-dev qemu-user ca-certificates \ + gcc-riscv64-linux-gnu libc6-dev-riscv64-cross \ + qemu-user + +ENV CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_LINKER=riscv64-linux-gnu-gcc \ + CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_RUNNER="qemu-riscv64 -L /usr/riscv64-linux-gnu" \ + OBJDUMP=riscv64-linux-gnu-objdump diff --git a/library/stdarch/ci/docker/x86_64-linux-android/Dockerfile b/library/stdarch/ci/docker/x86_64-linux-android/Dockerfile index d52dd45b12..c2830b15fb 100644 --- a/library/stdarch/ci/docker/x86_64-linux-android/Dockerfile +++ b/library/stdarch/ci/docker/x86_64-linux-android/Dockerfile @@ -17,7 +17,7 @@ COPY android-install-ndk.sh /android/ RUN sh /android/android-install-ndk.sh $ANDROID_ARCH # We do not run x86_64-linux-android tests on an android emulator. -# See ci/android-sysimage.sh for informations about how tests are run. +# See ci/android-sysimage.sh for information about how tests are run. COPY android-sysimage.sh /android/ RUN bash /android/android-sysimage.sh x86_64 x86_64-24_r07.zip diff --git a/library/stdarch/ci/run-docker.sh b/library/stdarch/ci/run-docker.sh index fb47b752d5..32209d96c6 100755 --- a/library/stdarch/ci/run-docker.sh +++ b/library/stdarch/ci/run-docker.sh @@ -25,7 +25,7 @@ run() { --env NORUN \ --env RUSTFLAGS \ --env STDARCH_TEST_NORUN \ - --volume "$(dirname "$(dirname "$(command -v cargo)")")":/cargo \ + --volume "${HOME}/.cargo":/cargo \ --volume "$(rustc --print sysroot)":/rust:ro \ --volume "$(pwd)":/checkout:ro \ --volume "$(pwd)"/target:/checkout/target \ diff --git a/library/stdarch/ci/run.sh b/library/stdarch/ci/run.sh index b8482478f6..54145a0e73 100755 --- a/library/stdarch/ci/run.sh +++ b/library/stdarch/ci/run.sh @@ -37,6 +37,18 @@ case ${TARGET} in mips-* | mipsel-*) export RUSTFLAGS="${RUSTFLAGS} -C llvm-args=-fast-isel=false" ;; + # Some of our test dependencies use the deprecated `gcc` crates which is + # missing a fix from https://github.com/alexcrichton/cc-rs/pull/627. Apply + # the workaround manually here. + armv7-*eabihf | thumbv7-*eabihf) + export RUSTFLAGS="${RUSTFLAGS} -Ctarget-feature=+neon" + export TARGET_CFLAGS="-mfpu=vfpv3-d16" + ;; + # Some of our test dependencies use the deprecated `gcc` crates which + # doesn't detect RISC-V compilers automatically, so do it manually here. + riscv64*) + export TARGET_CC="riscv64-linux-gnu-gcc" + ;; esac echo "RUSTFLAGS=${RUSTFLAGS}" @@ -122,7 +134,10 @@ esac if [ "${TARGET}" = "aarch64-unknown-linux-gnu" ]; then export CPPFLAGS="-fuse-ld=lld -I/usr/aarch64-linux-gnu/include/ -I/usr/aarch64-linux-gnu/include/c++/9/aarch64-linux-gnu/" - cargo run ${INTRINSIC_TEST} --release --bin intrinsic-test -- crates/intrinsic-test/acle/tools/intrinsic_db/advsimd.csv --runner "${CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUNNER}" --cppcompiler "clang++-12" --skip crates/intrinsic-test/missing.txt + RUST_LOG=warn cargo run ${INTRINSIC_TEST} --release --bin intrinsic-test -- crates/intrinsic-test/acle/tools/intrinsic_db/advsimd.csv --runner "${CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUNNER}" --cppcompiler "clang++-13" --skip crates/intrinsic-test/missing_aarch64.txt +elif [ "${TARGET}" = "armv7-unknown-linux-gnueabihf" ]; then + export CPPFLAGS="-fuse-ld=lld -I/usr/arm-linux-gnueabihf/include/ -I/usr/arm-linux-gnueabihf/include/c++/9/arm-linux-gnueabihf/" + RUST_LOG=warn cargo run ${INTRINSIC_TEST} --release --bin intrinsic-test -- crates/intrinsic-test/acle/tools/intrinsic_db/advsimd.csv --runner "${CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_RUNNER}" --cppcompiler "clang++-13" --skip crates/intrinsic-test/missing_arm.txt --a32 fi if [ "$NORUN" != "1" ] && [ "$NOSTD" != 1 ]; then diff --git a/library/stdarch/crates/core_arch/avx512f.md b/library/stdarch/crates/core_arch/avx512f.md index 1ad80147cf..9d95f0c492 100644 --- a/library/stdarch/crates/core_arch/avx512f.md +++ b/library/stdarch/crates/core_arch/avx512f.md @@ -1784,113 +1784,113 @@ * [x] [`_mm512_setzero_si512`] * [x] [`_mm512_setzero`] * [x] [`_mm512_load_epi32`] - * [ ] [`_mm512_mask_load_epi32`] //need i1 - * [ ] [`_mm512_maskz_load_epi32`] //need i1 + * [x] [`_mm512_mask_load_epi32`] //need i1 + * [x] [`_mm512_maskz_load_epi32`] //need i1 * [x] [`_mm_load_epi32`] - * [_] [`_mm_mask_load_epi32`] //need i1 - * [_] [`_mm_maskz_load_epi32`] //need i1 + * [x] [`_mm_mask_load_epi32`] //need i1 + * [x] [`_mm_maskz_load_epi32`] //need i1 * [x] [`_mm256_load_epi32`] - * [_] [`_mm256_mask_load_epi32`] //need i1 - * [_] [`_mm256_maskz_load_epi32`] //need i1 + * [x] [`_mm256_mask_load_epi32`] //need i1 + * [x] [`_mm256_maskz_load_epi32`] //need i1 * [x] [`_mm512_load_epi64`] - * [ ] [`_mm512_mask_load_epi64`] //need i1 - * [ ] [`_mm512_maskz_load_epi64`] //need i1 + * [x] [`_mm512_mask_load_epi64`] //need i1 + * [x] [`_mm512_maskz_load_epi64`] //need i1 * [x] [`_mm_load_epi64`] //need i1 - * [_] [`_mm_mask_load_epi64`] //need i1 - * [_] [`_mm_maskz_load_epi64`] //need i1 + * [x] [`_mm_mask_load_epi64`] //need i1 + * [x] [`_mm_maskz_load_epi64`] //need i1 * [x] [`_mm256_load_epi64`] //need i1 - * [_] [`_mm256_mask_load_epi64`] //need i1 - * [_] [`_mm256_maskz_load_epi64`] //need i1 + * [x] [`_mm256_mask_load_epi64`] //need i1 + * [x] [`_mm256_maskz_load_epi64`] //need i1 * [x] [`_mm512_load_ps`] - * [ ] [`_mm512_mask_load_ps`] //need i1 - * [ ] [`_mm512_maskz_load_ps`] //need i1 - * [_] [`_mm_maskz_load_ps`] //need i - * [_] [`_mm_mask_load_ps`] //need i1 - * [_] [`_mm_maskz_load_ps`] //need i1 - * [_] [`_mm256_mask_load_ps`] //need i1 - * [_] [`_mm256_maskz_load_ps`] //need i1 + * [x] [`_mm512_mask_load_ps`] //need i1 + * [x] [`_mm512_maskz_load_ps`] //need i1 + * [x] [`_mm_maskz_load_ps`] //need i + * [x] [`_mm_mask_load_ps`] //need i1 + * [x] [`_mm_maskz_load_ps`] //need i1 + * [x] [`_mm256_mask_load_ps`] //need i1 + * [x] [`_mm256_maskz_load_ps`] //need i1 * [x] [`_mm512_load_pd`] - * [ ] [`_mm512_mask_load_pd`] //need i1 - * [ ] [`_mm512_maskz_load_pd`] //need i1 - * [_] [`_mm_mask_load_pd`] //need i1 - * [_] [`_mm_maskz_load_pd`] //need i1 - * [_] [`_mm256_mask_load_pd`] //need i1 - * [_] [`_mm256_maskz_load_pd`] //need i1 + * [x] [`_mm512_mask_load_pd`] //need i1 + * [x] [`_mm512_maskz_load_pd`] //need i1 + * [x] [`_mm_mask_load_pd`] //need i1 + * [x] [`_mm_maskz_load_pd`] //need i1 + * [x] [`_mm256_mask_load_pd`] //need i1 + * [x] [`_mm256_maskz_load_pd`] //need i1 * [x] [`_mm512_load_si512`] * [x] [`_mm512_loadu_epi32`] - * [ ] [`_mm512_mask_loadu_epi32`] //need i1 + * [x] [`_mm512_mask_loadu_epi32`] //need i1 * [x] [`_mm_loadu_epi32`] - * [_] [`_mm_mask_loadu_epi32`] //need i1 - * [_] [`_mm_maskz_loadu_epi32`] //need i1 - * [ ] [`_mm512_maskz_loadu_epi32`] //need i1 + * [x] [`_mm_mask_loadu_epi32`] //need i1 + * [x] [`_mm_maskz_loadu_epi32`] //need i1 + * [x] [`_mm512_maskz_loadu_epi32`] //need i1 * [x] [`_mm256_loadu_epi32`] - * [_] [`_mm256_mask_loadu_epi32`] //need i1 - * [_] [`_mm256_maskz_loadu_epi32`] //need i1 + * [x] [`_mm256_mask_loadu_epi32`] //need i1 + * [x] [`_mm256_maskz_loadu_epi32`] //need i1 * [x] [`_mm512_loadu_epi64`] - * [ ] [`_mm512_mask_loadu_epi64`] //need i1 - * [ ] [`_mm512_maskz_loadu_epi64`] //need i1 + * [x] [`_mm512_mask_loadu_epi64`] //need i1 + * [x] [`_mm512_maskz_loadu_epi64`] //need i1 * [x] [`_mm_loadu_epi64`] - * [_] [`_mm_mask_loadu_epi64`] //need i1 - * [_] [`_mm_maskz_loadu_epi64`] //need i1 + * [x] [`_mm_mask_loadu_epi64`] //need i1 + * [x] [`_mm_maskz_loadu_epi64`] //need i1 * [x] [`_mm256_loadu_epi64`] - * [_] [`_mm256_mask_loadu_epi64`] //need i1 - * [_] [`_mm256_maskz_loadu_epi64`] //need i1 + * [x] [`_mm256_mask_loadu_epi64`] //need i1 + * [x] [`_mm256_maskz_loadu_epi64`] //need i1 * [x] [`_mm512_loadu_ps`] - * [ ] [`_mm512_mask_loadu_ps`] //need i1 - * [ ] [`_mm512_maskz_loadu_ps`] //need i1 - * [_] [`_mm_mask_loadu_ps`] //need i1 - * [_] [`_mm_maskz_loadu_ps`] //need i1 - * [_] [`_mm256_mask_loadu_ps`] //need i1 - * [_] [`_mm256_maskz_loadu_ps`] //need i1 + * [x] [`_mm512_mask_loadu_ps`] //need i1 + * [x] [`_mm512_maskz_loadu_ps`] //need i1 + * [x] [`_mm_mask_loadu_ps`] //need i1 + * [x] [`_mm_maskz_loadu_ps`] //need i1 + * [x] [`_mm256_mask_loadu_ps`] //need i1 + * [x] [`_mm256_maskz_loadu_ps`] //need i1 * [x] [`_mm512_loadu_pd`] - * [ ] [`_mm512_mask_loadu_pd`] //need i1 - * [ ] [`_mm512_maskz_loadu_pd`] //need i1 - * [_] [`_mm_mask_loadu_pd`] //need i1 - * [_] [`_mm_maskz_loadu_pd`] //need i1 - * [_] [`_mm256_mask_loadu_pd`] //need i1 - * [_] [`_mm256_maskz_loadu_pd`] //need i1 + * [x] [`_mm512_mask_loadu_pd`] //need i1 + * [x] [`_mm512_maskz_loadu_pd`] //need i1 + * [x] [`_mm_mask_loadu_pd`] //need i1 + * [x] [`_mm_maskz_loadu_pd`] //need i1 + * [x] [`_mm256_mask_loadu_pd`] //need i1 + * [x] [`_mm256_maskz_loadu_pd`] //need i1 * [x] [`_mm512_loadu_si512`] * [x] [`_mm512_store_epi32`] - * [ ] [`_mm512_mask_store_epi32`] //need i1 - * [_] [`_mm_mask_store_epi32`] //need i1 + * [x] [`_mm512_mask_store_epi32`] //need i1 + * [x] [`_mm_mask_store_epi32`] //need i1 * [x] [`_mm_store_epi32`] - * [_] [`_mm256_mask_store_epi32`] //need i1 + * [x] [`_mm256_mask_store_epi32`] //need i1 * [x] [`_mm256_store_epi32`] * [x] [`_mm512_store_epi64`] - * [ ] [`_mm512_mask_store_epi64`] //need i1 - * [_] [`_mm_mask_store_epi64`] //need i1 + * [x] [`_mm512_mask_store_epi64`] //need i1 + * [x] [`_mm_mask_store_epi64`] //need i1 * [x] [`_mm_store_epi64`] - * [_] [`_mm256_mask_store_epi64`] //need i1 + * [x] [`_mm256_mask_store_epi64`] //need i1 * [x] [`_mm256_store_epi64`] * [x] [`_mm512_store_ps`] - * [ ] [`_mm512_mask_store_ps`] //need i1 - * [_] [`_mm_mask_store_ps`] //need i1 - * [_] [`_mm256_mask_store_ps`] //need i1 + * [x] [`_mm512_mask_store_ps`] //need i1 + * [x] [`_mm_mask_store_ps`] //need i1 + * [x] [`_mm256_mask_store_ps`] //need i1 * [x] [`_mm512_store_pd`] - * [ ] [`_mm512_mask_store_pd`] //need i1 - * [_] [`_mm_mask_store_pd`] //need i1 - * [_] [`_mm256_mask_store_pd`] //need i1 + * [x] [`_mm512_mask_store_pd`] //need i1 + * [x] [`_mm_mask_store_pd`] //need i1 + * [x] [`_mm256_mask_store_pd`] //need i1 * [x] [`_mm512_store_si512`] * [x] [`_mm512_storeu_epi32`] - * [ ] [`_mm512_mask_storeu_epi32`] //need i1 - * [_] [`_mm_mask_storeu_epi32`] //need i1 + * [x] [`_mm512_mask_storeu_epi32`] //need i1 + * [x] [`_mm_mask_storeu_epi32`] //need i1 * [x] [`_mm_storeu_epi32`] - * [_] [`_mm256_mask_storeu_epi32`] //need i1 + * [x] [`_mm256_mask_storeu_epi32`] //need i1 * [x] [`_mm256_storeu_epi32`] * [x] [`_mm512_storeu_epi64`] - * [ ] [`_mm512_mask_storeu_epi64`] //need i1 - * [_] [`_mm_mask_storeu_epi64`] //need i1 + * [x] [`_mm512_mask_storeu_epi64`] //need i1 + * [x] [`_mm_mask_storeu_epi64`] //need i1 * [x] [`_mm_storeu_epi64`] - * [_] [`_mm256_mask_storeu_epi64`] //need i1 + * [x] [`_mm256_mask_storeu_epi64`] //need i1 * [x] [`_mm256_storeu_epi64`] * [x] [`_mm512_storeu_ps`] - * [ ] [`_mm512_mask_storeu_ps`] //need i1 - * [_] [`_mm_mask_storeu_ps`] //need i1 - * [_] [`_mm256_mask_storeu_ps`] //need i1 + * [x] [`_mm512_mask_storeu_ps`] //need i1 + * [x] [`_mm_mask_storeu_ps`] //need i1 + * [x] [`_mm256_mask_storeu_ps`] //need i1 * [x] [`_mm512_storeu_pd`] - * [ ] [`_mm512_mask_storeu_pd`] //need i1 - * [_] [`_mm_mask_storeu_pd`] //need i1 - * [_] [`_mm256_mask_storeu_pd`] //need i1 + * [x] [`_mm512_mask_storeu_pd`] //need i1 + * [x] [`_mm_mask_storeu_pd`] //need i1 + * [x] [`_mm256_mask_storeu_pd`] //need i1 * [x] [`_mm512_storeu_si512`] * [ ] [`_mm512_stream_load_si512`] //stream_load_si256, ... not implment yet * [x] [`_mm512_stream_pd`] diff --git a/library/stdarch/crates/core_arch/src/aarch64/armclang.rs b/library/stdarch/crates/core_arch/src/aarch64/armclang.rs index 54847be7b1..7ad6ae50c1 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/armclang.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/armclang.rs @@ -19,5 +19,5 @@ use stdarch_test::assert_instr; #[rustc_legacy_const_generics(0)] pub unsafe fn __breakpoint() { static_assert_imm16!(VAL); - asm!("brk {}", const VAL); + crate::arch::asm!("brk {}", const VAL); } diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs index 5bfa4fa59b..e5df1b72c0 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs @@ -117,6 +117,7 @@ pub unsafe fn veor3q_u64(a: uint64x2_t, b: uint64x2_t, c: uint64x2_t) -> uint64x #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fabd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vabd_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -130,6 +131,7 @@ pub unsafe fn vabd_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fabd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vabdq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -143,6 +145,7 @@ pub unsafe fn vabdq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fabd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vabds_f32(a: f32, b: f32) -> f32 { simd_extract(vabd_f32(vdup_n_f32(a), vdup_n_f32(b)), 0) } @@ -151,6 +154,7 @@ pub unsafe fn vabds_f32(a: f32, b: f32) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fabd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vabdd_f64(a: f64, b: f64) -> f64 { simd_extract(vabd_f64(vdup_n_f64(a), vdup_n_f64(b)), 0) } @@ -159,6 +163,7 @@ pub unsafe fn vabdd_f64(a: f64, b: f64) -> f64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uabdl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vabdl_high_u8(a: uint8x16_t, b: uint8x16_t) -> uint16x8_t { let c: uint8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); let d: uint8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); @@ -169,6 +174,7 @@ pub unsafe fn vabdl_high_u8(a: uint8x16_t, b: uint8x16_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uabdl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vabdl_high_u16(a: uint16x8_t, b: uint16x8_t) -> uint32x4_t { let c: uint16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); let d: uint16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); @@ -179,6 +185,7 @@ pub unsafe fn vabdl_high_u16(a: uint16x8_t, b: uint16x8_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uabdl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vabdl_high_u32(a: uint32x4_t, b: uint32x4_t) -> uint64x2_t { let c: uint32x2_t = simd_shuffle2!(a, a, [2, 3]); let d: uint32x2_t = simd_shuffle2!(b, b, [2, 3]); @@ -189,6 +196,7 @@ pub unsafe fn vabdl_high_u32(a: uint32x4_t, b: uint32x4_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sabdl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vabdl_high_s8(a: int8x16_t, b: int8x16_t) -> int16x8_t { let c: int8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); let d: int8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); @@ -200,6 +208,7 @@ pub unsafe fn vabdl_high_s8(a: int8x16_t, b: int8x16_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sabdl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vabdl_high_s16(a: int16x8_t, b: int16x8_t) -> int32x4_t { let c: int16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); let d: int16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); @@ -211,6 +220,7 @@ pub unsafe fn vabdl_high_s16(a: int16x8_t, b: int16x8_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sabdl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vabdl_high_s32(a: int32x4_t, b: int32x4_t) -> int64x2_t { let c: int32x2_t = simd_shuffle2!(a, a, [2, 3]); let d: int32x2_t = simd_shuffle2!(b, b, [2, 3]); @@ -222,6 +232,7 @@ pub unsafe fn vabdl_high_s32(a: int32x4_t, b: int32x4_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceq_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { simd_eq(a, b) } @@ -230,6 +241,7 @@ pub unsafe fn vceq_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { simd_eq(a, b) } @@ -238,6 +250,7 @@ pub unsafe fn vceqq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceq_s64(a: int64x1_t, b: int64x1_t) -> uint64x1_t { simd_eq(a, b) } @@ -246,6 +259,7 @@ pub unsafe fn vceq_s64(a: int64x1_t, b: int64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqq_s64(a: int64x2_t, b: int64x2_t) -> uint64x2_t { simd_eq(a, b) } @@ -254,6 +268,7 @@ pub unsafe fn vceqq_s64(a: int64x2_t, b: int64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceq_p64(a: poly64x1_t, b: poly64x1_t) -> uint64x1_t { simd_eq(a, b) } @@ -262,6 +277,7 @@ pub unsafe fn vceq_p64(a: poly64x1_t, b: poly64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqq_p64(a: poly64x2_t, b: poly64x2_t) -> uint64x2_t { simd_eq(a, b) } @@ -270,6 +286,7 @@ pub unsafe fn vceqq_p64(a: poly64x2_t, b: poly64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceq_f64(a: float64x1_t, b: float64x1_t) -> uint64x1_t { simd_eq(a, b) } @@ -278,6 +295,7 @@ pub unsafe fn vceq_f64(a: float64x1_t, b: float64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { simd_eq(a, b) } @@ -286,6 +304,7 @@ pub unsafe fn vceqq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqd_s64(a: i64, b: i64) -> u64 { transmute(vceq_s64(transmute(a), transmute(b))) } @@ -294,6 +313,7 @@ pub unsafe fn vceqd_s64(a: i64, b: i64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqd_u64(a: u64, b: u64) -> u64 { transmute(vceq_u64(transmute(a), transmute(b))) } @@ -302,6 +322,7 @@ pub unsafe fn vceqd_u64(a: u64, b: u64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqs_f32(a: f32, b: f32) -> u32 { simd_extract(vceq_f32(vdup_n_f32(a), vdup_n_f32(b)), 0) } @@ -310,6 +331,7 @@ pub unsafe fn vceqs_f32(a: f32, b: f32) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqd_f64(a: f64, b: f64) -> u64 { simd_extract(vceq_f64(vdup_n_f64(a), vdup_n_f64(b)), 0) } @@ -318,6 +340,7 @@ pub unsafe fn vceqd_f64(a: f64, b: f64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqz_s8(a: int8x8_t) -> uint8x8_t { let b: i8x8 = i8x8::new(0, 0, 0, 0, 0, 0, 0, 0); simd_eq(a, transmute(b)) @@ -327,6 +350,7 @@ pub unsafe fn vceqz_s8(a: int8x8_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqzq_s8(a: int8x16_t) -> uint8x16_t { let b: i8x16 = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); simd_eq(a, transmute(b)) @@ -336,6 +360,7 @@ pub unsafe fn vceqzq_s8(a: int8x16_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqz_s16(a: int16x4_t) -> uint16x4_t { let b: i16x4 = i16x4::new(0, 0, 0, 0); simd_eq(a, transmute(b)) @@ -345,6 +370,7 @@ pub unsafe fn vceqz_s16(a: int16x4_t) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqzq_s16(a: int16x8_t) -> uint16x8_t { let b: i16x8 = i16x8::new(0, 0, 0, 0, 0, 0, 0, 0); simd_eq(a, transmute(b)) @@ -354,6 +380,7 @@ pub unsafe fn vceqzq_s16(a: int16x8_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqz_s32(a: int32x2_t) -> uint32x2_t { let b: i32x2 = i32x2::new(0, 0); simd_eq(a, transmute(b)) @@ -363,6 +390,7 @@ pub unsafe fn vceqz_s32(a: int32x2_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqzq_s32(a: int32x4_t) -> uint32x4_t { let b: i32x4 = i32x4::new(0, 0, 0, 0); simd_eq(a, transmute(b)) @@ -372,6 +400,7 @@ pub unsafe fn vceqzq_s32(a: int32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqz_s64(a: int64x1_t) -> uint64x1_t { let b: i64x1 = i64x1::new(0); simd_eq(a, transmute(b)) @@ -381,6 +410,7 @@ pub unsafe fn vceqz_s64(a: int64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqzq_s64(a: int64x2_t) -> uint64x2_t { let b: i64x2 = i64x2::new(0, 0); simd_eq(a, transmute(b)) @@ -390,6 +420,7 @@ pub unsafe fn vceqzq_s64(a: int64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqz_p8(a: poly8x8_t) -> uint8x8_t { let b: i8x8 = i8x8::new(0, 0, 0, 0, 0, 0, 0, 0); simd_eq(a, transmute(b)) @@ -399,6 +430,7 @@ pub unsafe fn vceqz_p8(a: poly8x8_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqzq_p8(a: poly8x16_t) -> uint8x16_t { let b: i8x16 = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); simd_eq(a, transmute(b)) @@ -408,6 +440,7 @@ pub unsafe fn vceqzq_p8(a: poly8x16_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqz_p64(a: poly64x1_t) -> uint64x1_t { let b: i64x1 = i64x1::new(0); simd_eq(a, transmute(b)) @@ -417,6 +450,7 @@ pub unsafe fn vceqz_p64(a: poly64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqzq_p64(a: poly64x2_t) -> uint64x2_t { let b: i64x2 = i64x2::new(0, 0); simd_eq(a, transmute(b)) @@ -426,6 +460,7 @@ pub unsafe fn vceqzq_p64(a: poly64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqz_u8(a: uint8x8_t) -> uint8x8_t { let b: u8x8 = u8x8::new(0, 0, 0, 0, 0, 0, 0, 0); simd_eq(a, transmute(b)) @@ -435,6 +470,7 @@ pub unsafe fn vceqz_u8(a: uint8x8_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqzq_u8(a: uint8x16_t) -> uint8x16_t { let b: u8x16 = u8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); simd_eq(a, transmute(b)) @@ -444,6 +480,7 @@ pub unsafe fn vceqzq_u8(a: uint8x16_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqz_u16(a: uint16x4_t) -> uint16x4_t { let b: u16x4 = u16x4::new(0, 0, 0, 0); simd_eq(a, transmute(b)) @@ -453,6 +490,7 @@ pub unsafe fn vceqz_u16(a: uint16x4_t) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqzq_u16(a: uint16x8_t) -> uint16x8_t { let b: u16x8 = u16x8::new(0, 0, 0, 0, 0, 0, 0, 0); simd_eq(a, transmute(b)) @@ -462,6 +500,7 @@ pub unsafe fn vceqzq_u16(a: uint16x8_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqz_u32(a: uint32x2_t) -> uint32x2_t { let b: u32x2 = u32x2::new(0, 0); simd_eq(a, transmute(b)) @@ -471,6 +510,7 @@ pub unsafe fn vceqz_u32(a: uint32x2_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqzq_u32(a: uint32x4_t) -> uint32x4_t { let b: u32x4 = u32x4::new(0, 0, 0, 0); simd_eq(a, transmute(b)) @@ -480,6 +520,7 @@ pub unsafe fn vceqzq_u32(a: uint32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqz_u64(a: uint64x1_t) -> uint64x1_t { let b: u64x1 = u64x1::new(0); simd_eq(a, transmute(b)) @@ -489,6 +530,7 @@ pub unsafe fn vceqz_u64(a: uint64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqzq_u64(a: uint64x2_t) -> uint64x2_t { let b: u64x2 = u64x2::new(0, 0); simd_eq(a, transmute(b)) @@ -498,6 +540,7 @@ pub unsafe fn vceqzq_u64(a: uint64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqz_f32(a: float32x2_t) -> uint32x2_t { let b: f32x2 = f32x2::new(0.0, 0.0); simd_eq(a, transmute(b)) @@ -507,6 +550,7 @@ pub unsafe fn vceqz_f32(a: float32x2_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqzq_f32(a: float32x4_t) -> uint32x4_t { let b: f32x4 = f32x4::new(0.0, 0.0, 0.0, 0.0); simd_eq(a, transmute(b)) @@ -516,6 +560,7 @@ pub unsafe fn vceqzq_f32(a: float32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqz_f64(a: float64x1_t) -> uint64x1_t { let b: f64 = 0.0; simd_eq(a, transmute(b)) @@ -525,6 +570,7 @@ pub unsafe fn vceqz_f64(a: float64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmeq))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqzq_f64(a: float64x2_t) -> uint64x2_t { let b: f64x2 = f64x2::new(0.0, 0.0); simd_eq(a, transmute(b)) @@ -534,6 +580,7 @@ pub unsafe fn vceqzq_f64(a: float64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqzd_s64(a: i64) -> u64 { transmute(vceqz_s64(transmute(a))) } @@ -542,6 +589,7 @@ pub unsafe fn vceqzd_s64(a: i64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqzd_u64(a: u64) -> u64 { transmute(vceqz_u64(transmute(a))) } @@ -550,6 +598,7 @@ pub unsafe fn vceqzd_u64(a: u64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqzs_f32(a: f32) -> u32 { simd_extract(vceqz_f32(vdup_n_f32(a)), 0) } @@ -558,6 +607,7 @@ pub unsafe fn vceqzs_f32(a: f32) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vceqzd_f64(a: f64) -> u64 { simd_extract(vceqz_f64(vdup_n_f64(a)), 0) } @@ -566,6 +616,7 @@ pub unsafe fn vceqzd_f64(a: f64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmtst))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtst_s64(a: int64x1_t, b: int64x1_t) -> uint64x1_t { let c: int64x1_t = simd_and(a, b); let d: i64x1 = i64x1::new(0); @@ -576,6 +627,7 @@ pub unsafe fn vtst_s64(a: int64x1_t, b: int64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmtst))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtstq_s64(a: int64x2_t, b: int64x2_t) -> uint64x2_t { let c: int64x2_t = simd_and(a, b); let d: i64x2 = i64x2::new(0, 0); @@ -586,6 +638,7 @@ pub unsafe fn vtstq_s64(a: int64x2_t, b: int64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmtst))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtst_p64(a: poly64x1_t, b: poly64x1_t) -> uint64x1_t { let c: poly64x1_t = simd_and(a, b); let d: i64x1 = i64x1::new(0); @@ -596,6 +649,7 @@ pub unsafe fn vtst_p64(a: poly64x1_t, b: poly64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmtst))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtstq_p64(a: poly64x2_t, b: poly64x2_t) -> uint64x2_t { let c: poly64x2_t = simd_and(a, b); let d: i64x2 = i64x2::new(0, 0); @@ -606,6 +660,7 @@ pub unsafe fn vtstq_p64(a: poly64x2_t, b: poly64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmtst))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtst_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { let c: uint64x1_t = simd_and(a, b); let d: u64x1 = u64x1::new(0); @@ -616,6 +671,7 @@ pub unsafe fn vtst_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmtst))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtstq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { let c: uint64x2_t = simd_and(a, b); let d: u64x2 = u64x2::new(0, 0); @@ -626,6 +682,7 @@ pub unsafe fn vtstq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tst))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtstd_s64(a: i64, b: i64) -> u64 { transmute(vtst_s64(transmute(a), transmute(b))) } @@ -634,6 +691,7 @@ pub unsafe fn vtstd_s64(a: i64, b: i64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tst))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtstd_u64(a: u64, b: u64) -> u64 { transmute(vtst_u64(transmute(a), transmute(b))) } @@ -642,6 +700,7 @@ pub unsafe fn vtstd_u64(a: u64, b: u64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(suqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuqadds_s32(a: i32, b: u32) -> i32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -655,6 +714,7 @@ pub unsafe fn vuqadds_s32(a: i32, b: u32) -> i32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(suqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuqaddd_s64(a: i64, b: u64) -> i64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -668,6 +728,7 @@ pub unsafe fn vuqaddd_s64(a: i64, b: u64) -> i64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(suqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuqaddb_s8(a: i8, b: u8) -> i8 { simd_extract(vuqadd_s8(vdup_n_s8(a), vdup_n_u8(b)), 0) } @@ -676,6 +737,7 @@ pub unsafe fn vuqaddb_s8(a: i8, b: u8) -> i8 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(suqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuqaddh_s16(a: i16, b: u16) -> i16 { simd_extract(vuqadd_s16(vdup_n_s16(a), vdup_n_u16(b)), 0) } @@ -684,6 +746,7 @@ pub unsafe fn vuqaddh_s16(a: i16, b: u16) -> i16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fabs))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vabs_f64(a: float64x1_t) -> float64x1_t { simd_fabs(a) } @@ -692,6 +755,7 @@ pub unsafe fn vabs_f64(a: float64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fabs))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vabsq_f64(a: float64x2_t) -> float64x2_t { simd_fabs(a) } @@ -700,6 +764,7 @@ pub unsafe fn vabsq_f64(a: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgt_s64(a: int64x1_t, b: int64x1_t) -> uint64x1_t { simd_gt(a, b) } @@ -708,6 +773,7 @@ pub unsafe fn vcgt_s64(a: int64x1_t, b: int64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgtq_s64(a: int64x2_t, b: int64x2_t) -> uint64x2_t { simd_gt(a, b) } @@ -716,6 +782,7 @@ pub unsafe fn vcgtq_s64(a: int64x2_t, b: int64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmhi))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgt_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { simd_gt(a, b) } @@ -724,6 +791,7 @@ pub unsafe fn vcgt_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmhi))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgtq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { simd_gt(a, b) } @@ -732,6 +800,7 @@ pub unsafe fn vcgtq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgt_f64(a: float64x1_t, b: float64x1_t) -> uint64x1_t { simd_gt(a, b) } @@ -740,6 +809,7 @@ pub unsafe fn vcgt_f64(a: float64x1_t, b: float64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgtq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { simd_gt(a, b) } @@ -748,6 +818,7 @@ pub unsafe fn vcgtq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgtd_s64(a: i64, b: i64) -> u64 { transmute(vcgt_s64(transmute(a), transmute(b))) } @@ -756,6 +827,7 @@ pub unsafe fn vcgtd_s64(a: i64, b: i64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgtd_u64(a: u64, b: u64) -> u64 { transmute(vcgt_u64(transmute(a), transmute(b))) } @@ -764,6 +836,7 @@ pub unsafe fn vcgtd_u64(a: u64, b: u64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgts_f32(a: f32, b: f32) -> u32 { simd_extract(vcgt_f32(vdup_n_f32(a), vdup_n_f32(b)), 0) } @@ -772,6 +845,7 @@ pub unsafe fn vcgts_f32(a: f32, b: f32) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgtd_f64(a: f64, b: f64) -> u64 { simd_extract(vcgt_f64(vdup_n_f64(a), vdup_n_f64(b)), 0) } @@ -780,6 +854,7 @@ pub unsafe fn vcgtd_f64(a: f64, b: f64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vclt_s64(a: int64x1_t, b: int64x1_t) -> uint64x1_t { simd_lt(a, b) } @@ -788,6 +863,7 @@ pub unsafe fn vclt_s64(a: int64x1_t, b: int64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcltq_s64(a: int64x2_t, b: int64x2_t) -> uint64x2_t { simd_lt(a, b) } @@ -796,6 +872,7 @@ pub unsafe fn vcltq_s64(a: int64x2_t, b: int64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmhi))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vclt_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { simd_lt(a, b) } @@ -804,6 +881,7 @@ pub unsafe fn vclt_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmhi))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcltq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { simd_lt(a, b) } @@ -812,6 +890,7 @@ pub unsafe fn vcltq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vclt_f64(a: float64x1_t, b: float64x1_t) -> uint64x1_t { simd_lt(a, b) } @@ -820,6 +899,7 @@ pub unsafe fn vclt_f64(a: float64x1_t, b: float64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcltq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { simd_lt(a, b) } @@ -828,6 +908,7 @@ pub unsafe fn vcltq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcltd_s64(a: i64, b: i64) -> u64 { transmute(vclt_s64(transmute(a), transmute(b))) } @@ -836,6 +917,7 @@ pub unsafe fn vcltd_s64(a: i64, b: i64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcltd_u64(a: u64, b: u64) -> u64 { transmute(vclt_u64(transmute(a), transmute(b))) } @@ -844,6 +926,7 @@ pub unsafe fn vcltd_u64(a: u64, b: u64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vclts_f32(a: f32, b: f32) -> u32 { simd_extract(vclt_f32(vdup_n_f32(a), vdup_n_f32(b)), 0) } @@ -852,6 +935,7 @@ pub unsafe fn vclts_f32(a: f32, b: f32) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcltd_f64(a: f64, b: f64) -> u64 { simd_extract(vclt_f64(vdup_n_f64(a), vdup_n_f64(b)), 0) } @@ -860,6 +944,7 @@ pub unsafe fn vcltd_f64(a: f64, b: f64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcle_s64(a: int64x1_t, b: int64x1_t) -> uint64x1_t { simd_le(a, b) } @@ -868,6 +953,7 @@ pub unsafe fn vcle_s64(a: int64x1_t, b: int64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcleq_s64(a: int64x2_t, b: int64x2_t) -> uint64x2_t { simd_le(a, b) } @@ -876,6 +962,7 @@ pub unsafe fn vcleq_s64(a: int64x2_t, b: int64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcged_s64(a: i64, b: i64) -> u64 { transmute(vcge_s64(transmute(a), transmute(b))) } @@ -884,6 +971,7 @@ pub unsafe fn vcged_s64(a: i64, b: i64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcged_u64(a: u64, b: u64) -> u64 { transmute(vcge_u64(transmute(a), transmute(b))) } @@ -892,6 +980,7 @@ pub unsafe fn vcged_u64(a: u64, b: u64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcges_f32(a: f32, b: f32) -> u32 { simd_extract(vcge_f32(vdup_n_f32(a), vdup_n_f32(b)), 0) } @@ -900,6 +989,7 @@ pub unsafe fn vcges_f32(a: f32, b: f32) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcged_f64(a: f64, b: f64) -> u64 { simd_extract(vcge_f64(vdup_n_f64(a), vdup_n_f64(b)), 0) } @@ -908,6 +998,7 @@ pub unsafe fn vcged_f64(a: f64, b: f64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmhs))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcle_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { simd_le(a, b) } @@ -916,6 +1007,7 @@ pub unsafe fn vcle_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmhs))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcleq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { simd_le(a, b) } @@ -924,6 +1016,7 @@ pub unsafe fn vcleq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcle_f64(a: float64x1_t, b: float64x1_t) -> uint64x1_t { simd_le(a, b) } @@ -932,6 +1025,7 @@ pub unsafe fn vcle_f64(a: float64x1_t, b: float64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcleq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { simd_le(a, b) } @@ -940,6 +1034,7 @@ pub unsafe fn vcleq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcled_s64(a: i64, b: i64) -> u64 { transmute(vcle_s64(transmute(a), transmute(b))) } @@ -948,6 +1043,7 @@ pub unsafe fn vcled_s64(a: i64, b: i64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcled_u64(a: u64, b: u64) -> u64 { transmute(vcle_u64(transmute(a), transmute(b))) } @@ -956,6 +1052,7 @@ pub unsafe fn vcled_u64(a: u64, b: u64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcles_f32(a: f32, b: f32) -> u32 { simd_extract(vcle_f32(vdup_n_f32(a), vdup_n_f32(b)), 0) } @@ -964,6 +1061,7 @@ pub unsafe fn vcles_f32(a: f32, b: f32) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcled_f64(a: f64, b: f64) -> u64 { simd_extract(vcle_f64(vdup_n_f64(a), vdup_n_f64(b)), 0) } @@ -972,6 +1070,7 @@ pub unsafe fn vcled_f64(a: f64, b: f64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcge_s64(a: int64x1_t, b: int64x1_t) -> uint64x1_t { simd_ge(a, b) } @@ -980,6 +1079,7 @@ pub unsafe fn vcge_s64(a: int64x1_t, b: int64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgeq_s64(a: int64x2_t, b: int64x2_t) -> uint64x2_t { simd_ge(a, b) } @@ -988,6 +1088,7 @@ pub unsafe fn vcgeq_s64(a: int64x2_t, b: int64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmhs))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcge_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { simd_ge(a, b) } @@ -996,6 +1097,7 @@ pub unsafe fn vcge_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmhs))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgeq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { simd_ge(a, b) } @@ -1004,6 +1106,7 @@ pub unsafe fn vcgeq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcge_f64(a: float64x1_t, b: float64x1_t) -> uint64x1_t { simd_ge(a, b) } @@ -1012,6 +1115,7 @@ pub unsafe fn vcge_f64(a: float64x1_t, b: float64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgeq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { simd_ge(a, b) } @@ -1020,6 +1124,7 @@ pub unsafe fn vcgeq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgez_s8(a: int8x8_t) -> uint8x8_t { let b: i8x8 = i8x8::new(0, 0, 0, 0, 0, 0, 0, 0); simd_ge(a, transmute(b)) @@ -1029,6 +1134,7 @@ pub unsafe fn vcgez_s8(a: int8x8_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgezq_s8(a: int8x16_t) -> uint8x16_t { let b: i8x16 = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); simd_ge(a, transmute(b)) @@ -1038,6 +1144,7 @@ pub unsafe fn vcgezq_s8(a: int8x16_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgez_s16(a: int16x4_t) -> uint16x4_t { let b: i16x4 = i16x4::new(0, 0, 0, 0); simd_ge(a, transmute(b)) @@ -1047,6 +1154,7 @@ pub unsafe fn vcgez_s16(a: int16x4_t) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgezq_s16(a: int16x8_t) -> uint16x8_t { let b: i16x8 = i16x8::new(0, 0, 0, 0, 0, 0, 0, 0); simd_ge(a, transmute(b)) @@ -1056,6 +1164,7 @@ pub unsafe fn vcgezq_s16(a: int16x8_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgez_s32(a: int32x2_t) -> uint32x2_t { let b: i32x2 = i32x2::new(0, 0); simd_ge(a, transmute(b)) @@ -1065,6 +1174,7 @@ pub unsafe fn vcgez_s32(a: int32x2_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgezq_s32(a: int32x4_t) -> uint32x4_t { let b: i32x4 = i32x4::new(0, 0, 0, 0); simd_ge(a, transmute(b)) @@ -1074,6 +1184,7 @@ pub unsafe fn vcgezq_s32(a: int32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgez_s64(a: int64x1_t) -> uint64x1_t { let b: i64x1 = i64x1::new(0); simd_ge(a, transmute(b)) @@ -1083,6 +1194,7 @@ pub unsafe fn vcgez_s64(a: int64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgezq_s64(a: int64x2_t) -> uint64x2_t { let b: i64x2 = i64x2::new(0, 0); simd_ge(a, transmute(b)) @@ -1092,6 +1204,7 @@ pub unsafe fn vcgezq_s64(a: int64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgez_f32(a: float32x2_t) -> uint32x2_t { let b: f32x2 = f32x2::new(0.0, 0.0); simd_ge(a, transmute(b)) @@ -1101,6 +1214,7 @@ pub unsafe fn vcgez_f32(a: float32x2_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgezq_f32(a: float32x4_t) -> uint32x4_t { let b: f32x4 = f32x4::new(0.0, 0.0, 0.0, 0.0); simd_ge(a, transmute(b)) @@ -1110,6 +1224,7 @@ pub unsafe fn vcgezq_f32(a: float32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgez_f64(a: float64x1_t) -> uint64x1_t { let b: f64 = 0.0; simd_ge(a, transmute(b)) @@ -1119,6 +1234,7 @@ pub unsafe fn vcgez_f64(a: float64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgezq_f64(a: float64x2_t) -> uint64x2_t { let b: f64x2 = f64x2::new(0.0, 0.0); simd_ge(a, transmute(b)) @@ -1128,6 +1244,7 @@ pub unsafe fn vcgezq_f64(a: float64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(eor))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgezd_s64(a: i64) -> u64 { transmute(vcgez_s64(transmute(a))) } @@ -1136,6 +1253,7 @@ pub unsafe fn vcgezd_s64(a: i64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgezs_f32(a: f32) -> u32 { simd_extract(vcgez_f32(vdup_n_f32(a)), 0) } @@ -1144,6 +1262,7 @@ pub unsafe fn vcgezs_f32(a: f32) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgezd_f64(a: f64) -> u64 { simd_extract(vcgez_f64(vdup_n_f64(a)), 0) } @@ -1152,6 +1271,7 @@ pub unsafe fn vcgezd_f64(a: f64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgtz_s8(a: int8x8_t) -> uint8x8_t { let b: i8x8 = i8x8::new(0, 0, 0, 0, 0, 0, 0, 0); simd_gt(a, transmute(b)) @@ -1161,6 +1281,7 @@ pub unsafe fn vcgtz_s8(a: int8x8_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgtzq_s8(a: int8x16_t) -> uint8x16_t { let b: i8x16 = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); simd_gt(a, transmute(b)) @@ -1170,6 +1291,7 @@ pub unsafe fn vcgtzq_s8(a: int8x16_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgtz_s16(a: int16x4_t) -> uint16x4_t { let b: i16x4 = i16x4::new(0, 0, 0, 0); simd_gt(a, transmute(b)) @@ -1179,6 +1301,7 @@ pub unsafe fn vcgtz_s16(a: int16x4_t) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgtzq_s16(a: int16x8_t) -> uint16x8_t { let b: i16x8 = i16x8::new(0, 0, 0, 0, 0, 0, 0, 0); simd_gt(a, transmute(b)) @@ -1188,6 +1311,7 @@ pub unsafe fn vcgtzq_s16(a: int16x8_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgtz_s32(a: int32x2_t) -> uint32x2_t { let b: i32x2 = i32x2::new(0, 0); simd_gt(a, transmute(b)) @@ -1197,6 +1321,7 @@ pub unsafe fn vcgtz_s32(a: int32x2_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgtzq_s32(a: int32x4_t) -> uint32x4_t { let b: i32x4 = i32x4::new(0, 0, 0, 0); simd_gt(a, transmute(b)) @@ -1206,6 +1331,7 @@ pub unsafe fn vcgtzq_s32(a: int32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgtz_s64(a: int64x1_t) -> uint64x1_t { let b: i64x1 = i64x1::new(0); simd_gt(a, transmute(b)) @@ -1215,6 +1341,7 @@ pub unsafe fn vcgtz_s64(a: int64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgtzq_s64(a: int64x2_t) -> uint64x2_t { let b: i64x2 = i64x2::new(0, 0); simd_gt(a, transmute(b)) @@ -1224,6 +1351,7 @@ pub unsafe fn vcgtzq_s64(a: int64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgtz_f32(a: float32x2_t) -> uint32x2_t { let b: f32x2 = f32x2::new(0.0, 0.0); simd_gt(a, transmute(b)) @@ -1233,6 +1361,7 @@ pub unsafe fn vcgtz_f32(a: float32x2_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgtzq_f32(a: float32x4_t) -> uint32x4_t { let b: f32x4 = f32x4::new(0.0, 0.0, 0.0, 0.0); simd_gt(a, transmute(b)) @@ -1242,6 +1371,7 @@ pub unsafe fn vcgtzq_f32(a: float32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgtz_f64(a: float64x1_t) -> uint64x1_t { let b: f64 = 0.0; simd_gt(a, transmute(b)) @@ -1251,6 +1381,7 @@ pub unsafe fn vcgtz_f64(a: float64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgtzq_f64(a: float64x2_t) -> uint64x2_t { let b: f64x2 = f64x2::new(0.0, 0.0); simd_gt(a, transmute(b)) @@ -1260,6 +1391,7 @@ pub unsafe fn vcgtzq_f64(a: float64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgtzd_s64(a: i64) -> u64 { transmute(vcgtz_s64(transmute(a))) } @@ -1268,6 +1400,7 @@ pub unsafe fn vcgtzd_s64(a: i64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgtzs_f32(a: f32) -> u32 { simd_extract(vcgtz_f32(vdup_n_f32(a)), 0) } @@ -1276,6 +1409,7 @@ pub unsafe fn vcgtzs_f32(a: f32) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcgtzd_f64(a: f64) -> u64 { simd_extract(vcgtz_f64(vdup_n_f64(a)), 0) } @@ -1284,6 +1418,7 @@ pub unsafe fn vcgtzd_f64(a: f64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vclez_s8(a: int8x8_t) -> uint8x8_t { let b: i8x8 = i8x8::new(0, 0, 0, 0, 0, 0, 0, 0); simd_le(a, transmute(b)) @@ -1293,6 +1428,7 @@ pub unsafe fn vclez_s8(a: int8x8_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vclezq_s8(a: int8x16_t) -> uint8x16_t { let b: i8x16 = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); simd_le(a, transmute(b)) @@ -1302,6 +1438,7 @@ pub unsafe fn vclezq_s8(a: int8x16_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vclez_s16(a: int16x4_t) -> uint16x4_t { let b: i16x4 = i16x4::new(0, 0, 0, 0); simd_le(a, transmute(b)) @@ -1311,6 +1448,7 @@ pub unsafe fn vclez_s16(a: int16x4_t) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vclezq_s16(a: int16x8_t) -> uint16x8_t { let b: i16x8 = i16x8::new(0, 0, 0, 0, 0, 0, 0, 0); simd_le(a, transmute(b)) @@ -1320,6 +1458,7 @@ pub unsafe fn vclezq_s16(a: int16x8_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vclez_s32(a: int32x2_t) -> uint32x2_t { let b: i32x2 = i32x2::new(0, 0); simd_le(a, transmute(b)) @@ -1329,6 +1468,7 @@ pub unsafe fn vclez_s32(a: int32x2_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vclezq_s32(a: int32x4_t) -> uint32x4_t { let b: i32x4 = i32x4::new(0, 0, 0, 0); simd_le(a, transmute(b)) @@ -1338,6 +1478,7 @@ pub unsafe fn vclezq_s32(a: int32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vclez_s64(a: int64x1_t) -> uint64x1_t { let b: i64x1 = i64x1::new(0); simd_le(a, transmute(b)) @@ -1347,6 +1488,7 @@ pub unsafe fn vclez_s64(a: int64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vclezq_s64(a: int64x2_t) -> uint64x2_t { let b: i64x2 = i64x2::new(0, 0); simd_le(a, transmute(b)) @@ -1356,6 +1498,7 @@ pub unsafe fn vclezq_s64(a: int64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmle))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vclez_f32(a: float32x2_t) -> uint32x2_t { let b: f32x2 = f32x2::new(0.0, 0.0); simd_le(a, transmute(b)) @@ -1365,6 +1508,7 @@ pub unsafe fn vclez_f32(a: float32x2_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmle))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vclezq_f32(a: float32x4_t) -> uint32x4_t { let b: f32x4 = f32x4::new(0.0, 0.0, 0.0, 0.0); simd_le(a, transmute(b)) @@ -1374,6 +1518,7 @@ pub unsafe fn vclezq_f32(a: float32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmle))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vclez_f64(a: float64x1_t) -> uint64x1_t { let b: f64 = 0.0; simd_le(a, transmute(b)) @@ -1383,6 +1528,7 @@ pub unsafe fn vclez_f64(a: float64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmle))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vclezq_f64(a: float64x2_t) -> uint64x2_t { let b: f64x2 = f64x2::new(0.0, 0.0); simd_le(a, transmute(b)) @@ -1392,6 +1538,7 @@ pub unsafe fn vclezq_f64(a: float64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(cmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vclezd_s64(a: i64) -> u64 { transmute(vclez_s64(transmute(a))) } @@ -1400,6 +1547,7 @@ pub unsafe fn vclezd_s64(a: i64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vclezs_f32(a: f32) -> u32 { simd_extract(vclez_f32(vdup_n_f32(a)), 0) } @@ -1408,6 +1556,7 @@ pub unsafe fn vclezs_f32(a: f32) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vclezd_f64(a: f64) -> u64 { simd_extract(vclez_f64(vdup_n_f64(a)), 0) } @@ -1416,6 +1565,7 @@ pub unsafe fn vclezd_f64(a: f64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sshr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcltz_s8(a: int8x8_t) -> uint8x8_t { let b: i8x8 = i8x8::new(0, 0, 0, 0, 0, 0, 0, 0); simd_lt(a, transmute(b)) @@ -1425,6 +1575,7 @@ pub unsafe fn vcltz_s8(a: int8x8_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sshr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcltzq_s8(a: int8x16_t) -> uint8x16_t { let b: i8x16 = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); simd_lt(a, transmute(b)) @@ -1434,6 +1585,7 @@ pub unsafe fn vcltzq_s8(a: int8x16_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sshr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcltz_s16(a: int16x4_t) -> uint16x4_t { let b: i16x4 = i16x4::new(0, 0, 0, 0); simd_lt(a, transmute(b)) @@ -1443,6 +1595,7 @@ pub unsafe fn vcltz_s16(a: int16x4_t) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sshr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcltzq_s16(a: int16x8_t) -> uint16x8_t { let b: i16x8 = i16x8::new(0, 0, 0, 0, 0, 0, 0, 0); simd_lt(a, transmute(b)) @@ -1452,6 +1605,7 @@ pub unsafe fn vcltzq_s16(a: int16x8_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sshr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcltz_s32(a: int32x2_t) -> uint32x2_t { let b: i32x2 = i32x2::new(0, 0); simd_lt(a, transmute(b)) @@ -1461,6 +1615,7 @@ pub unsafe fn vcltz_s32(a: int32x2_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sshr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcltzq_s32(a: int32x4_t) -> uint32x4_t { let b: i32x4 = i32x4::new(0, 0, 0, 0); simd_lt(a, transmute(b)) @@ -1470,6 +1625,7 @@ pub unsafe fn vcltzq_s32(a: int32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sshr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcltz_s64(a: int64x1_t) -> uint64x1_t { let b: i64x1 = i64x1::new(0); simd_lt(a, transmute(b)) @@ -1479,6 +1635,7 @@ pub unsafe fn vcltz_s64(a: int64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sshr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcltzq_s64(a: int64x2_t) -> uint64x2_t { let b: i64x2 = i64x2::new(0, 0); simd_lt(a, transmute(b)) @@ -1488,6 +1645,7 @@ pub unsafe fn vcltzq_s64(a: int64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmlt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcltz_f32(a: float32x2_t) -> uint32x2_t { let b: f32x2 = f32x2::new(0.0, 0.0); simd_lt(a, transmute(b)) @@ -1497,6 +1655,7 @@ pub unsafe fn vcltz_f32(a: float32x2_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmlt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcltzq_f32(a: float32x4_t) -> uint32x4_t { let b: f32x4 = f32x4::new(0.0, 0.0, 0.0, 0.0); simd_lt(a, transmute(b)) @@ -1506,6 +1665,7 @@ pub unsafe fn vcltzq_f32(a: float32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmlt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcltz_f64(a: float64x1_t) -> uint64x1_t { let b: f64 = 0.0; simd_lt(a, transmute(b)) @@ -1515,6 +1675,7 @@ pub unsafe fn vcltz_f64(a: float64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmlt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcltzq_f64(a: float64x2_t) -> uint64x2_t { let b: f64x2 = f64x2::new(0.0, 0.0); simd_lt(a, transmute(b)) @@ -1524,6 +1685,7 @@ pub unsafe fn vcltzq_f64(a: float64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(asr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcltzd_s64(a: i64) -> u64 { transmute(vcltz_s64(transmute(a))) } @@ -1532,6 +1694,7 @@ pub unsafe fn vcltzd_s64(a: i64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcltzs_f32(a: f32) -> u32 { simd_extract(vcltz_f32(vdup_n_f32(a)), 0) } @@ -1540,6 +1703,7 @@ pub unsafe fn vcltzs_f32(a: f32) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcltzd_f64(a: f64) -> u64 { simd_extract(vcltz_f64(vdup_n_f64(a)), 0) } @@ -1548,6 +1712,7 @@ pub unsafe fn vcltzd_f64(a: f64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(facgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcagt_f64(a: float64x1_t, b: float64x1_t) -> uint64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -1561,6 +1726,7 @@ pub unsafe fn vcagt_f64(a: float64x1_t, b: float64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(facgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcagtq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -1574,6 +1740,7 @@ pub unsafe fn vcagtq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(facgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcagts_f32(a: f32, b: f32) -> u32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -1587,6 +1754,7 @@ pub unsafe fn vcagts_f32(a: f32, b: f32) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(facgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcagtd_f64(a: f64, b: f64) -> u64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -1600,6 +1768,7 @@ pub unsafe fn vcagtd_f64(a: f64, b: f64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(facge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcage_f64(a: float64x1_t, b: float64x1_t) -> uint64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -1613,6 +1782,7 @@ pub unsafe fn vcage_f64(a: float64x1_t, b: float64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(facge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcageq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -1626,6 +1796,7 @@ pub unsafe fn vcageq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(facge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcages_f32(a: f32, b: f32) -> u32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -1639,6 +1810,7 @@ pub unsafe fn vcages_f32(a: f32, b: f32) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(facge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcaged_f64(a: f64, b: f64) -> u64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -1652,6 +1824,7 @@ pub unsafe fn vcaged_f64(a: f64, b: f64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(facgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcalt_f64(a: float64x1_t, b: float64x1_t) -> uint64x1_t { vcagt_f64(b, a) } @@ -1660,6 +1833,7 @@ pub unsafe fn vcalt_f64(a: float64x1_t, b: float64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(facgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcaltq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { vcagtq_f64(b, a) } @@ -1668,6 +1842,7 @@ pub unsafe fn vcaltq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(facgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcalts_f32(a: f32, b: f32) -> u32 { vcagts_f32(b, a) } @@ -1676,6 +1851,7 @@ pub unsafe fn vcalts_f32(a: f32, b: f32) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(facgt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcaltd_f64(a: f64, b: f64) -> u64 { vcagtd_f64(b, a) } @@ -1684,6 +1860,7 @@ pub unsafe fn vcaltd_f64(a: f64, b: f64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(facge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcale_f64(a: float64x1_t, b: float64x1_t) -> uint64x1_t { vcage_f64(b, a) } @@ -1692,6 +1869,7 @@ pub unsafe fn vcale_f64(a: float64x1_t, b: float64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(facge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcaleq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { vcageq_f64(b, a) } @@ -1700,6 +1878,7 @@ pub unsafe fn vcaleq_f64(a: float64x2_t, b: float64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(facge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcales_f32(a: f32, b: f32) -> u32 { vcages_f32(b, a) } @@ -1708,6 +1887,7 @@ pub unsafe fn vcales_f32(a: f32, b: f32) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(facge))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcaled_f64(a: f64, b: f64) -> u64 { vcaged_f64(b, a) } @@ -1717,6 +1897,7 @@ pub unsafe fn vcaled_f64(a: f64, b: f64) -> u64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_lane_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { static_assert_imm3!(LANE1); static_assert_imm3!(LANE2); @@ -1738,6 +1919,7 @@ pub unsafe fn vcopy_lane_s8(a: int8x8_t, b: #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_laneq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { static_assert_imm4!(LANE1); static_assert_imm4!(LANE2); @@ -1767,6 +1949,7 @@ pub unsafe fn vcopyq_laneq_s8(a: int8x16_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_lane_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { static_assert_imm2!(LANE1); static_assert_imm2!(LANE2); @@ -1784,6 +1967,7 @@ pub unsafe fn vcopy_lane_s16(a: int16x4_t, b #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_laneq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { static_assert_imm3!(LANE1); static_assert_imm3!(LANE2); @@ -1805,6 +1989,7 @@ pub unsafe fn vcopyq_laneq_s16(a: int16x8_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_lane_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { static_assert_imm1!(LANE1); static_assert_imm1!(LANE2); @@ -1820,6 +2005,7 @@ pub unsafe fn vcopy_lane_s32(a: int32x2_t, b #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_laneq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { static_assert_imm2!(LANE1); static_assert_imm2!(LANE2); @@ -1837,6 +2023,7 @@ pub unsafe fn vcopyq_laneq_s32(a: int32x4_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_laneq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { static_assert_imm1!(LANE1); static_assert_imm1!(LANE2); @@ -1852,6 +2039,7 @@ pub unsafe fn vcopyq_laneq_s64(a: int64x2_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_lane_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { static_assert_imm3!(LANE1); static_assert_imm3!(LANE2); @@ -1873,6 +2061,7 @@ pub unsafe fn vcopy_lane_u8(a: uint8x8_t, b: #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_laneq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { static_assert_imm4!(LANE1); static_assert_imm4!(LANE2); @@ -1902,6 +2091,7 @@ pub unsafe fn vcopyq_laneq_u8(a: uint8x16_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_lane_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { static_assert_imm2!(LANE1); static_assert_imm2!(LANE2); @@ -1919,6 +2109,7 @@ pub unsafe fn vcopy_lane_u16(a: uint16x4_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_laneq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { static_assert_imm3!(LANE1); static_assert_imm3!(LANE2); @@ -1940,6 +2131,7 @@ pub unsafe fn vcopyq_laneq_u16(a: uint16x8_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_lane_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { static_assert_imm1!(LANE1); static_assert_imm1!(LANE2); @@ -1955,6 +2147,7 @@ pub unsafe fn vcopy_lane_u32(a: uint32x2_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_laneq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { static_assert_imm2!(LANE1); static_assert_imm2!(LANE2); @@ -1972,6 +2165,7 @@ pub unsafe fn vcopyq_laneq_u32(a: uint32x4_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_laneq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { static_assert_imm1!(LANE1); static_assert_imm1!(LANE2); @@ -1987,6 +2181,7 @@ pub unsafe fn vcopyq_laneq_u64(a: uint64x2_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_lane_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { static_assert_imm3!(LANE1); static_assert_imm3!(LANE2); @@ -2008,6 +2203,7 @@ pub unsafe fn vcopy_lane_p8(a: poly8x8_t, b: #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_laneq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { static_assert_imm4!(LANE1); static_assert_imm4!(LANE2); @@ -2037,6 +2233,7 @@ pub unsafe fn vcopyq_laneq_p8(a: poly8x16_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_lane_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { static_assert_imm2!(LANE1); static_assert_imm2!(LANE2); @@ -2054,6 +2251,7 @@ pub unsafe fn vcopy_lane_p16(a: poly16x4_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_laneq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { static_assert_imm3!(LANE1); static_assert_imm3!(LANE2); @@ -2075,6 +2273,7 @@ pub unsafe fn vcopyq_laneq_p16(a: poly16x8_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_laneq_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { static_assert_imm1!(LANE1); static_assert_imm1!(LANE2); @@ -2090,6 +2289,7 @@ pub unsafe fn vcopyq_laneq_p64(a: poly64x2_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_lane_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { static_assert_imm1!(LANE1); static_assert_imm1!(LANE2); @@ -2105,6 +2305,7 @@ pub unsafe fn vcopy_lane_f32(a: float32x2_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_laneq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { static_assert_imm2!(LANE1); static_assert_imm2!(LANE2); @@ -2122,6 +2323,7 @@ pub unsafe fn vcopyq_laneq_f32(a: float32x4_ #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_laneq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { static_assert_imm1!(LANE1); static_assert_imm1!(LANE2); @@ -2137,6 +2339,7 @@ pub unsafe fn vcopyq_laneq_f64(a: float64x2_ #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_laneq_s8(a: int8x8_t, b: int8x16_t) -> int8x8_t { static_assert_imm3!(LANE1); static_assert_imm4!(LANE2); @@ -2159,6 +2362,7 @@ pub unsafe fn vcopy_laneq_s8(a: int8x8_t, b: #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_laneq_s16(a: int16x4_t, b: int16x8_t) -> int16x4_t { static_assert_imm2!(LANE1); static_assert_imm3!(LANE2); @@ -2177,6 +2381,7 @@ pub unsafe fn vcopy_laneq_s16(a: int16x4_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_laneq_s32(a: int32x2_t, b: int32x4_t) -> int32x2_t { static_assert_imm1!(LANE1); static_assert_imm2!(LANE2); @@ -2193,6 +2398,7 @@ pub unsafe fn vcopy_laneq_s32(a: int32x2_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_laneq_u8(a: uint8x8_t, b: uint8x16_t) -> uint8x8_t { static_assert_imm3!(LANE1); static_assert_imm4!(LANE2); @@ -2215,6 +2421,7 @@ pub unsafe fn vcopy_laneq_u8(a: uint8x8_t, b #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_laneq_u16(a: uint16x4_t, b: uint16x8_t) -> uint16x4_t { static_assert_imm2!(LANE1); static_assert_imm3!(LANE2); @@ -2233,6 +2440,7 @@ pub unsafe fn vcopy_laneq_u16(a: uint16x4_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_laneq_u32(a: uint32x2_t, b: uint32x4_t) -> uint32x2_t { static_assert_imm1!(LANE1); static_assert_imm2!(LANE2); @@ -2249,6 +2457,7 @@ pub unsafe fn vcopy_laneq_u32(a: uint32x2_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_laneq_p8(a: poly8x8_t, b: poly8x16_t) -> poly8x8_t { static_assert_imm3!(LANE1); static_assert_imm4!(LANE2); @@ -2271,6 +2480,7 @@ pub unsafe fn vcopy_laneq_p8(a: poly8x8_t, b #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_laneq_p16(a: poly16x4_t, b: poly16x8_t) -> poly16x4_t { static_assert_imm2!(LANE1); static_assert_imm3!(LANE2); @@ -2289,6 +2499,7 @@ pub unsafe fn vcopy_laneq_p16(a: poly16x4_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_laneq_f32(a: float32x2_t, b: float32x4_t) -> float32x2_t { static_assert_imm1!(LANE1); static_assert_imm2!(LANE2); @@ -2305,6 +2516,7 @@ pub unsafe fn vcopy_laneq_f32(a: float32x2_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_lane_s8(a: int8x16_t, b: int8x8_t) -> int8x16_t { static_assert_imm4!(LANE1); static_assert_imm3!(LANE2); @@ -2335,6 +2547,7 @@ pub unsafe fn vcopyq_lane_s8(a: int8x16_t, b #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_lane_s16(a: int16x8_t, b: int16x4_t) -> int16x8_t { static_assert_imm3!(LANE1); static_assert_imm2!(LANE2); @@ -2357,6 +2570,7 @@ pub unsafe fn vcopyq_lane_s16(a: int16x8_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_lane_s32(a: int32x4_t, b: int32x2_t) -> int32x4_t { static_assert_imm2!(LANE1); static_assert_imm1!(LANE2); @@ -2375,6 +2589,7 @@ pub unsafe fn vcopyq_lane_s32(a: int32x4_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_lane_u8(a: uint8x16_t, b: uint8x8_t) -> uint8x16_t { static_assert_imm4!(LANE1); static_assert_imm3!(LANE2); @@ -2405,6 +2620,7 @@ pub unsafe fn vcopyq_lane_u8(a: uint8x16_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_lane_u16(a: uint16x8_t, b: uint16x4_t) -> uint16x8_t { static_assert_imm3!(LANE1); static_assert_imm2!(LANE2); @@ -2427,6 +2643,7 @@ pub unsafe fn vcopyq_lane_u16(a: uint16x8_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_lane_u32(a: uint32x4_t, b: uint32x2_t) -> uint32x4_t { static_assert_imm2!(LANE1); static_assert_imm1!(LANE2); @@ -2445,6 +2662,7 @@ pub unsafe fn vcopyq_lane_u32(a: uint32x4_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_lane_p8(a: poly8x16_t, b: poly8x8_t) -> poly8x16_t { static_assert_imm4!(LANE1); static_assert_imm3!(LANE2); @@ -2475,6 +2693,7 @@ pub unsafe fn vcopyq_lane_p8(a: poly8x16_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_lane_p16(a: poly16x8_t, b: poly16x4_t) -> poly16x8_t { static_assert_imm3!(LANE1); static_assert_imm2!(LANE2); @@ -2497,6 +2716,7 @@ pub unsafe fn vcopyq_lane_p16(a: poly16x8_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1, LANE1 = 1, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_lane_s64(a: int64x2_t, b: int64x1_t) -> int64x2_t { static_assert_imm1!(LANE1); static_assert!(LANE2 : i32 where LANE2 == 0); @@ -2513,6 +2733,7 @@ pub unsafe fn vcopyq_lane_s64(a: int64x2_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1, LANE1 = 1, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_lane_u64(a: uint64x2_t, b: uint64x1_t) -> uint64x2_t { static_assert_imm1!(LANE1); static_assert!(LANE2 : i32 where LANE2 == 0); @@ -2529,6 +2750,7 @@ pub unsafe fn vcopyq_lane_u64(a: uint64x2_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1, LANE1 = 1, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_lane_p64(a: poly64x2_t, b: poly64x1_t) -> poly64x2_t { static_assert_imm1!(LANE1); static_assert!(LANE2 : i32 where LANE2 == 0); @@ -2545,6 +2767,7 @@ pub unsafe fn vcopyq_lane_p64(a: poly64x2_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov, LANE1 = 1, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_lane_f32(a: float32x4_t, b: float32x2_t) -> float32x4_t { static_assert_imm2!(LANE1); static_assert_imm1!(LANE2); @@ -2563,6 +2786,7 @@ pub unsafe fn vcopyq_lane_f32(a: float32x4_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1, LANE1 = 1, LANE2 = 0))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopyq_lane_f64(a: float64x2_t, b: float64x1_t) -> float64x2_t { static_assert_imm1!(LANE1); static_assert!(LANE2 : i32 where LANE2 == 0); @@ -2578,6 +2802,7 @@ pub unsafe fn vcopyq_lane_f64(a: float64x2_t #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcreate_f64(a: u64) -> float64x1_t { transmute(a) } @@ -2586,6 +2811,7 @@ pub unsafe fn vcreate_f64(a: u64) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(scvtf))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvt_f64_s64(a: int64x1_t) -> float64x1_t { simd_cast(a) } @@ -2594,6 +2820,7 @@ pub unsafe fn vcvt_f64_s64(a: int64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(scvtf))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtq_f64_s64(a: int64x2_t) -> float64x2_t { simd_cast(a) } @@ -2602,6 +2829,7 @@ pub unsafe fn vcvtq_f64_s64(a: int64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ucvtf))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvt_f64_u64(a: uint64x1_t) -> float64x1_t { simd_cast(a) } @@ -2610,6 +2838,7 @@ pub unsafe fn vcvt_f64_u64(a: uint64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ucvtf))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtq_f64_u64(a: uint64x2_t) -> float64x2_t { simd_cast(a) } @@ -2618,6 +2847,7 @@ pub unsafe fn vcvtq_f64_u64(a: uint64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvt_f64_f32(a: float32x2_t) -> float64x2_t { simd_cast(a) } @@ -2626,6 +2856,7 @@ pub unsafe fn vcvt_f64_f32(a: float32x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvt_high_f64_f32(a: float32x4_t) -> float64x2_t { let b: float32x2_t = simd_shuffle2!(a, a, [2, 3]); simd_cast(b) @@ -2635,6 +2866,7 @@ pub unsafe fn vcvt_high_f64_f32(a: float32x4_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtn))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvt_f32_f64(a: float64x2_t) -> float32x2_t { simd_cast(a) } @@ -2643,6 +2875,7 @@ pub unsafe fn vcvt_f32_f64(a: float64x2_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtn))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvt_high_f32_f64(a: float32x2_t, b: float64x2_t) -> float32x4_t { simd_shuffle4!(a, simd_cast(b), [0, 1, 2, 3]) } @@ -2651,6 +2884,7 @@ pub unsafe fn vcvt_high_f32_f64(a: float32x2_t, b: float64x2_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtxn))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtx_f32_f64(a: float64x2_t) -> float32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -2664,6 +2898,7 @@ pub unsafe fn vcvtx_f32_f64(a: float64x2_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtxn))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtxd_f32_f64(a: f64) -> f32 { simd_extract(vcvtx_f32_f64(vdupq_n_f64(a)), 0) } @@ -2672,6 +2907,7 @@ pub unsafe fn vcvtxd_f32_f64(a: f64) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtxn))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtx_high_f32_f64(a: float32x2_t, b: float64x2_t) -> float32x4_t { simd_shuffle4!(a, vcvtx_f32_f64(b), [0, 1, 2, 3]) } @@ -2681,6 +2917,7 @@ pub unsafe fn vcvtx_high_f32_f64(a: float32x2_t, b: float64x2_t) -> float32x4_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(scvtf, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvt_n_f64_s64(a: int64x1_t) -> float64x1_t { static_assert!(N : i32 where N >= 1 && N <= 64); #[allow(improper_ctypes)] @@ -2696,6 +2933,7 @@ pub unsafe fn vcvt_n_f64_s64(a: int64x1_t) -> float64x1_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(scvtf, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtq_n_f64_s64(a: int64x2_t) -> float64x2_t { static_assert!(N : i32 where N >= 1 && N <= 64); #[allow(improper_ctypes)] @@ -2711,6 +2949,7 @@ pub unsafe fn vcvtq_n_f64_s64(a: int64x2_t) -> float64x2_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(scvtf, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvts_n_f32_s32(a: i32) -> f32 { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] @@ -2726,6 +2965,7 @@ pub unsafe fn vcvts_n_f32_s32(a: i32) -> f32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(scvtf, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtd_n_f64_s64(a: i64) -> f64 { static_assert!(N : i32 where N >= 1 && N <= 64); #[allow(improper_ctypes)] @@ -2741,6 +2981,7 @@ pub unsafe fn vcvtd_n_f64_s64(a: i64) -> f64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ucvtf, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvt_n_f64_u64(a: uint64x1_t) -> float64x1_t { static_assert!(N : i32 where N >= 1 && N <= 64); #[allow(improper_ctypes)] @@ -2756,6 +2997,7 @@ pub unsafe fn vcvt_n_f64_u64(a: uint64x1_t) -> float64x1_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ucvtf, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtq_n_f64_u64(a: uint64x2_t) -> float64x2_t { static_assert!(N : i32 where N >= 1 && N <= 64); #[allow(improper_ctypes)] @@ -2771,6 +3013,7 @@ pub unsafe fn vcvtq_n_f64_u64(a: uint64x2_t) -> float64x2_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ucvtf, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvts_n_f32_u32(a: u32) -> f32 { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] @@ -2786,6 +3029,7 @@ pub unsafe fn vcvts_n_f32_u32(a: u32) -> f32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ucvtf, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtd_n_f64_u64(a: u64) -> f64 { static_assert!(N : i32 where N >= 1 && N <= 64); #[allow(improper_ctypes)] @@ -2801,6 +3045,7 @@ pub unsafe fn vcvtd_n_f64_u64(a: u64) -> f64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtzs, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvt_n_s64_f64(a: float64x1_t) -> int64x1_t { static_assert!(N : i32 where N >= 1 && N <= 64); #[allow(improper_ctypes)] @@ -2816,6 +3061,7 @@ pub unsafe fn vcvt_n_s64_f64(a: float64x1_t) -> int64x1_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtzs, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtq_n_s64_f64(a: float64x2_t) -> int64x2_t { static_assert!(N : i32 where N >= 1 && N <= 64); #[allow(improper_ctypes)] @@ -2831,6 +3077,7 @@ pub unsafe fn vcvtq_n_s64_f64(a: float64x2_t) -> int64x2_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtzs, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvts_n_s32_f32(a: f32) -> i32 { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] @@ -2846,6 +3093,7 @@ pub unsafe fn vcvts_n_s32_f32(a: f32) -> i32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtzs, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtd_n_s64_f64(a: f64) -> i64 { static_assert!(N : i32 where N >= 1 && N <= 64); #[allow(improper_ctypes)] @@ -2861,6 +3109,7 @@ pub unsafe fn vcvtd_n_s64_f64(a: f64) -> i64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtzu, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvt_n_u64_f64(a: float64x1_t) -> uint64x1_t { static_assert!(N : i32 where N >= 1 && N <= 64); #[allow(improper_ctypes)] @@ -2876,6 +3125,7 @@ pub unsafe fn vcvt_n_u64_f64(a: float64x1_t) -> uint64x1_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtzu, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtq_n_u64_f64(a: float64x2_t) -> uint64x2_t { static_assert!(N : i32 where N >= 1 && N <= 64); #[allow(improper_ctypes)] @@ -2891,6 +3141,7 @@ pub unsafe fn vcvtq_n_u64_f64(a: float64x2_t) -> uint64x2_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtzu, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvts_n_u32_f32(a: f32) -> u32 { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] @@ -2906,6 +3157,7 @@ pub unsafe fn vcvts_n_u32_f32(a: f32) -> u32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtzu, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtd_n_u64_f64(a: f64) -> u64 { static_assert!(N : i32 where N >= 1 && N <= 64); #[allow(improper_ctypes)] @@ -2920,6 +3172,7 @@ pub unsafe fn vcvtd_n_u64_f64(a: f64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(scvtf))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvts_f32_s32(a: i32) -> f32 { a as f32 } @@ -2928,6 +3181,7 @@ pub unsafe fn vcvts_f32_s32(a: i32) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(scvtf))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtd_f64_s64(a: i64) -> f64 { a as f64 } @@ -2936,6 +3190,7 @@ pub unsafe fn vcvtd_f64_s64(a: i64) -> f64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ucvtf))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvts_f32_u32(a: u32) -> f32 { a as f32 } @@ -2944,6 +3199,7 @@ pub unsafe fn vcvts_f32_u32(a: u32) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ucvtf))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtd_f64_u64(a: u64) -> f64 { a as f64 } @@ -2952,6 +3208,7 @@ pub unsafe fn vcvtd_f64_u64(a: u64) -> f64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtzs))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvts_s32_f32(a: f32) -> i32 { a as i32 } @@ -2960,6 +3217,7 @@ pub unsafe fn vcvts_s32_f32(a: f32) -> i32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtzs))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtd_s64_f64(a: f64) -> i64 { a as i64 } @@ -2968,6 +3226,7 @@ pub unsafe fn vcvtd_s64_f64(a: f64) -> i64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtzu))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvts_u32_f32(a: f32) -> u32 { a as u32 } @@ -2976,6 +3235,7 @@ pub unsafe fn vcvts_u32_f32(a: f32) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtzu))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtd_u64_f64(a: f64) -> u64 { a as u64 } @@ -2984,6 +3244,7 @@ pub unsafe fn vcvtd_u64_f64(a: f64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtzs))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvt_s64_f64(a: float64x1_t) -> int64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -2997,6 +3258,7 @@ pub unsafe fn vcvt_s64_f64(a: float64x1_t) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtzs))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtq_s64_f64(a: float64x2_t) -> int64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3010,6 +3272,7 @@ pub unsafe fn vcvtq_s64_f64(a: float64x2_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtzu))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvt_u64_f64(a: float64x1_t) -> uint64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3023,6 +3286,7 @@ pub unsafe fn vcvt_u64_f64(a: float64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtzu))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtq_u64_f64(a: float64x2_t) -> uint64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3036,6 +3300,7 @@ pub unsafe fn vcvtq_u64_f64(a: float64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtas))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvta_s32_f32(a: float32x2_t) -> int32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3049,6 +3314,7 @@ pub unsafe fn vcvta_s32_f32(a: float32x2_t) -> int32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtas))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtaq_s32_f32(a: float32x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3062,6 +3328,7 @@ pub unsafe fn vcvtaq_s32_f32(a: float32x4_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtas))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvta_s64_f64(a: float64x1_t) -> int64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3075,6 +3342,7 @@ pub unsafe fn vcvta_s64_f64(a: float64x1_t) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtas))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtaq_s64_f64(a: float64x2_t) -> int64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3088,6 +3356,7 @@ pub unsafe fn vcvtaq_s64_f64(a: float64x2_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtas))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtas_s32_f32(a: f32) -> i32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3101,6 +3370,7 @@ pub unsafe fn vcvtas_s32_f32(a: f32) -> i32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtas))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtad_s64_f64(a: f64) -> i64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3114,6 +3384,7 @@ pub unsafe fn vcvtad_s64_f64(a: f64) -> i64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtau))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtas_u32_f32(a: f32) -> u32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3127,6 +3398,7 @@ pub unsafe fn vcvtas_u32_f32(a: f32) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtau))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtad_u64_f64(a: f64) -> u64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3140,6 +3412,7 @@ pub unsafe fn vcvtad_u64_f64(a: f64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtns))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtn_s32_f32(a: float32x2_t) -> int32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3153,6 +3426,7 @@ pub unsafe fn vcvtn_s32_f32(a: float32x2_t) -> int32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtns))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtnq_s32_f32(a: float32x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3166,6 +3440,7 @@ pub unsafe fn vcvtnq_s32_f32(a: float32x4_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtns))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtn_s64_f64(a: float64x1_t) -> int64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3179,6 +3454,7 @@ pub unsafe fn vcvtn_s64_f64(a: float64x1_t) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtns))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtnq_s64_f64(a: float64x2_t) -> int64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3192,6 +3468,7 @@ pub unsafe fn vcvtnq_s64_f64(a: float64x2_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtns))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtns_s32_f32(a: f32) -> i32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3205,6 +3482,7 @@ pub unsafe fn vcvtns_s32_f32(a: f32) -> i32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtns))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtnd_s64_f64(a: f64) -> i64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3218,6 +3496,7 @@ pub unsafe fn vcvtnd_s64_f64(a: f64) -> i64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtms))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtm_s32_f32(a: float32x2_t) -> int32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3231,6 +3510,7 @@ pub unsafe fn vcvtm_s32_f32(a: float32x2_t) -> int32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtms))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtmq_s32_f32(a: float32x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3244,6 +3524,7 @@ pub unsafe fn vcvtmq_s32_f32(a: float32x4_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtms))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtm_s64_f64(a: float64x1_t) -> int64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3257,6 +3538,7 @@ pub unsafe fn vcvtm_s64_f64(a: float64x1_t) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtms))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtmq_s64_f64(a: float64x2_t) -> int64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3270,6 +3552,7 @@ pub unsafe fn vcvtmq_s64_f64(a: float64x2_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtms))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtms_s32_f32(a: f32) -> i32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3283,6 +3566,7 @@ pub unsafe fn vcvtms_s32_f32(a: f32) -> i32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtms))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtmd_s64_f64(a: f64) -> i64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3296,6 +3580,7 @@ pub unsafe fn vcvtmd_s64_f64(a: f64) -> i64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtps))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtp_s32_f32(a: float32x2_t) -> int32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3309,6 +3594,7 @@ pub unsafe fn vcvtp_s32_f32(a: float32x2_t) -> int32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtps))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtpq_s32_f32(a: float32x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3322,6 +3608,7 @@ pub unsafe fn vcvtpq_s32_f32(a: float32x4_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtps))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtp_s64_f64(a: float64x1_t) -> int64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3335,6 +3622,7 @@ pub unsafe fn vcvtp_s64_f64(a: float64x1_t) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtps))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtpq_s64_f64(a: float64x2_t) -> int64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3348,6 +3636,7 @@ pub unsafe fn vcvtpq_s64_f64(a: float64x2_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtps))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtps_s32_f32(a: f32) -> i32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3361,6 +3650,7 @@ pub unsafe fn vcvtps_s32_f32(a: f32) -> i32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtps))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtpd_s64_f64(a: f64) -> i64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3374,6 +3664,7 @@ pub unsafe fn vcvtpd_s64_f64(a: f64) -> i64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtau))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvta_u32_f32(a: float32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3387,6 +3678,7 @@ pub unsafe fn vcvta_u32_f32(a: float32x2_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtau))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtaq_u32_f32(a: float32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3400,6 +3692,7 @@ pub unsafe fn vcvtaq_u32_f32(a: float32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtau))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvta_u64_f64(a: float64x1_t) -> uint64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3413,6 +3706,7 @@ pub unsafe fn vcvta_u64_f64(a: float64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtau))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtaq_u64_f64(a: float64x2_t) -> uint64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3426,6 +3720,7 @@ pub unsafe fn vcvtaq_u64_f64(a: float64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtnu))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtn_u32_f32(a: float32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3439,6 +3734,7 @@ pub unsafe fn vcvtn_u32_f32(a: float32x2_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtnu))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtnq_u32_f32(a: float32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3452,6 +3748,7 @@ pub unsafe fn vcvtnq_u32_f32(a: float32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtnu))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtn_u64_f64(a: float64x1_t) -> uint64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3465,6 +3762,7 @@ pub unsafe fn vcvtn_u64_f64(a: float64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtnu))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtnq_u64_f64(a: float64x2_t) -> uint64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3478,6 +3776,7 @@ pub unsafe fn vcvtnq_u64_f64(a: float64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtnu))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtns_u32_f32(a: f32) -> u32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3491,6 +3790,7 @@ pub unsafe fn vcvtns_u32_f32(a: f32) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtnu))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtnd_u64_f64(a: f64) -> u64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3504,6 +3804,7 @@ pub unsafe fn vcvtnd_u64_f64(a: f64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtmu))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtm_u32_f32(a: float32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3517,6 +3818,7 @@ pub unsafe fn vcvtm_u32_f32(a: float32x2_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtmu))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtmq_u32_f32(a: float32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3530,6 +3832,7 @@ pub unsafe fn vcvtmq_u32_f32(a: float32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtmu))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtm_u64_f64(a: float64x1_t) -> uint64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3543,6 +3846,7 @@ pub unsafe fn vcvtm_u64_f64(a: float64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtmu))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtmq_u64_f64(a: float64x2_t) -> uint64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3556,6 +3860,7 @@ pub unsafe fn vcvtmq_u64_f64(a: float64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtmu))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtms_u32_f32(a: f32) -> u32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3569,6 +3874,7 @@ pub unsafe fn vcvtms_u32_f32(a: f32) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtmu))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtmd_u64_f64(a: f64) -> u64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3582,6 +3888,7 @@ pub unsafe fn vcvtmd_u64_f64(a: f64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtpu))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtp_u32_f32(a: float32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3595,6 +3902,7 @@ pub unsafe fn vcvtp_u32_f32(a: float32x2_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtpu))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtpq_u32_f32(a: float32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3608,6 +3916,7 @@ pub unsafe fn vcvtpq_u32_f32(a: float32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtpu))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtp_u64_f64(a: float64x1_t) -> uint64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3621,6 +3930,7 @@ pub unsafe fn vcvtp_u64_f64(a: float64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtpu))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtpq_u64_f64(a: float64x2_t) -> uint64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3634,6 +3944,7 @@ pub unsafe fn vcvtpq_u64_f64(a: float64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtpu))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtps_u32_f32(a: f32) -> u32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3647,6 +3958,7 @@ pub unsafe fn vcvtps_u32_f32(a: f32) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fcvtpu))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtpd_u64_f64(a: f64) -> u64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -3661,6 +3973,7 @@ pub unsafe fn vcvtpd_u64_f64(a: f64) -> u64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(dup, N = 1))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdupq_laneq_p64(a: poly64x2_t) -> poly64x2_t { static_assert_imm1!(N); simd_shuffle2!(a, a, [N as u32, N as u32]) @@ -3671,6 +3984,7 @@ pub unsafe fn vdupq_laneq_p64(a: poly64x2_t) -> poly64x2_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(dup, N = 0))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdupq_lane_p64(a: poly64x1_t) -> poly64x2_t { static_assert!(N : i32 where N == 0); simd_shuffle2!(a, a, [N as u32, N as u32]) @@ -3681,6 +3995,7 @@ pub unsafe fn vdupq_lane_p64(a: poly64x1_t) -> poly64x2_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(dup, N = 1))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdupq_laneq_f64(a: float64x2_t) -> float64x2_t { static_assert_imm1!(N); simd_shuffle2!(a, a, [N as u32, N as u32]) @@ -3691,6 +4006,7 @@ pub unsafe fn vdupq_laneq_f64(a: float64x2_t) -> float64x2_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(dup, N = 0))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdupq_lane_f64(a: float64x1_t) -> float64x2_t { static_assert!(N : i32 where N == 0); simd_shuffle2!(a, a, [N as u32, N as u32]) @@ -3701,6 +4017,7 @@ pub unsafe fn vdupq_lane_f64(a: float64x1_t) -> float64x2_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 0))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdup_lane_p64(a: poly64x1_t) -> poly64x1_t { static_assert!(N : i32 where N == 0); a @@ -3711,6 +4028,7 @@ pub unsafe fn vdup_lane_p64(a: poly64x1_t) -> poly64x1_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 0))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdup_lane_f64(a: float64x1_t) -> float64x1_t { static_assert!(N : i32 where N == 0); a @@ -3721,6 +4039,7 @@ pub unsafe fn vdup_lane_f64(a: float64x1_t) -> float64x1_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 1))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdup_laneq_p64(a: poly64x2_t) -> poly64x1_t { static_assert_imm1!(N); transmute::(simd_extract(a, N as u32)) @@ -3731,6 +4050,7 @@ pub unsafe fn vdup_laneq_p64(a: poly64x2_t) -> poly64x1_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 1))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdup_laneq_f64(a: float64x2_t) -> float64x1_t { static_assert_imm1!(N); transmute::(simd_extract(a, N as u32)) @@ -3741,6 +4061,7 @@ pub unsafe fn vdup_laneq_f64(a: float64x2_t) -> float64x1_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 4))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdupb_lane_s8(a: int8x8_t) -> i8 { static_assert_imm3!(N); simd_extract(a, N as u32) @@ -3751,6 +4072,7 @@ pub unsafe fn vdupb_lane_s8(a: int8x8_t) -> i8 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 8))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdupb_laneq_s8(a: int8x16_t) -> i8 { static_assert_imm4!(N); simd_extract(a, N as u32) @@ -3761,6 +4083,7 @@ pub unsafe fn vdupb_laneq_s8(a: int8x16_t) -> i8 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vduph_lane_s16(a: int16x4_t) -> i16 { static_assert_imm2!(N); simd_extract(a, N as u32) @@ -3771,6 +4094,7 @@ pub unsafe fn vduph_lane_s16(a: int16x4_t) -> i16 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 4))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vduph_laneq_s16(a: int16x8_t) -> i16 { static_assert_imm3!(N); simd_extract(a, N as u32) @@ -3781,6 +4105,7 @@ pub unsafe fn vduph_laneq_s16(a: int16x8_t) -> i16 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 1))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdups_lane_s32(a: int32x2_t) -> i32 { static_assert_imm1!(N); simd_extract(a, N as u32) @@ -3791,6 +4116,7 @@ pub unsafe fn vdups_lane_s32(a: int32x2_t) -> i32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdups_laneq_s32(a: int32x4_t) -> i32 { static_assert_imm2!(N); simd_extract(a, N as u32) @@ -3801,6 +4127,7 @@ pub unsafe fn vdups_laneq_s32(a: int32x4_t) -> i32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 0))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdupd_lane_s64(a: int64x1_t) -> i64 { static_assert!(N : i32 where N == 0); simd_extract(a, N as u32) @@ -3811,6 +4138,7 @@ pub unsafe fn vdupd_lane_s64(a: int64x1_t) -> i64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 1))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdupd_laneq_s64(a: int64x2_t) -> i64 { static_assert_imm1!(N); simd_extract(a, N as u32) @@ -3821,6 +4149,7 @@ pub unsafe fn vdupd_laneq_s64(a: int64x2_t) -> i64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 4))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdupb_lane_u8(a: uint8x8_t) -> u8 { static_assert_imm3!(N); simd_extract(a, N as u32) @@ -3831,6 +4160,7 @@ pub unsafe fn vdupb_lane_u8(a: uint8x8_t) -> u8 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 8))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdupb_laneq_u8(a: uint8x16_t) -> u8 { static_assert_imm4!(N); simd_extract(a, N as u32) @@ -3841,6 +4171,7 @@ pub unsafe fn vdupb_laneq_u8(a: uint8x16_t) -> u8 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vduph_lane_u16(a: uint16x4_t) -> u16 { static_assert_imm2!(N); simd_extract(a, N as u32) @@ -3851,6 +4182,7 @@ pub unsafe fn vduph_lane_u16(a: uint16x4_t) -> u16 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 4))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vduph_laneq_u16(a: uint16x8_t) -> u16 { static_assert_imm3!(N); simd_extract(a, N as u32) @@ -3861,6 +4193,7 @@ pub unsafe fn vduph_laneq_u16(a: uint16x8_t) -> u16 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 1))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdups_lane_u32(a: uint32x2_t) -> u32 { static_assert_imm1!(N); simd_extract(a, N as u32) @@ -3871,6 +4204,7 @@ pub unsafe fn vdups_lane_u32(a: uint32x2_t) -> u32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdups_laneq_u32(a: uint32x4_t) -> u32 { static_assert_imm2!(N); simd_extract(a, N as u32) @@ -3881,6 +4215,7 @@ pub unsafe fn vdups_laneq_u32(a: uint32x4_t) -> u32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 0))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdupd_lane_u64(a: uint64x1_t) -> u64 { static_assert!(N : i32 where N == 0); simd_extract(a, N as u32) @@ -3891,6 +4226,7 @@ pub unsafe fn vdupd_lane_u64(a: uint64x1_t) -> u64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 1))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdupd_laneq_u64(a: uint64x2_t) -> u64 { static_assert_imm1!(N); simd_extract(a, N as u32) @@ -3901,6 +4237,7 @@ pub unsafe fn vdupd_laneq_u64(a: uint64x2_t) -> u64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 4))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdupb_lane_p8(a: poly8x8_t) -> p8 { static_assert_imm3!(N); simd_extract(a, N as u32) @@ -3911,6 +4248,7 @@ pub unsafe fn vdupb_lane_p8(a: poly8x8_t) -> p8 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 8))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdupb_laneq_p8(a: poly8x16_t) -> p8 { static_assert_imm4!(N); simd_extract(a, N as u32) @@ -3921,6 +4259,7 @@ pub unsafe fn vdupb_laneq_p8(a: poly8x16_t) -> p8 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vduph_lane_p16(a: poly16x4_t) -> p16 { static_assert_imm2!(N); simd_extract(a, N as u32) @@ -3931,6 +4270,7 @@ pub unsafe fn vduph_lane_p16(a: poly16x4_t) -> p16 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 4))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vduph_laneq_p16(a: poly16x8_t) -> p16 { static_assert_imm3!(N); simd_extract(a, N as u32) @@ -3941,6 +4281,7 @@ pub unsafe fn vduph_laneq_p16(a: poly16x8_t) -> p16 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 1))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdups_lane_f32(a: float32x2_t) -> f32 { static_assert_imm1!(N); simd_extract(a, N as u32) @@ -3951,6 +4292,7 @@ pub unsafe fn vdups_lane_f32(a: float32x2_t) -> f32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdups_laneq_f32(a: float32x4_t) -> f32 { static_assert_imm2!(N); simd_extract(a, N as u32) @@ -3961,6 +4303,7 @@ pub unsafe fn vdups_laneq_f32(a: float32x4_t) -> f32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 0))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdupd_lane_f64(a: float64x1_t) -> f64 { static_assert!(N : i32 where N == 0); simd_extract(a, N as u32) @@ -3971,6 +4314,7 @@ pub unsafe fn vdupd_lane_f64(a: float64x1_t) -> f64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 1))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdupd_laneq_f64(a: float64x2_t) -> f64 { static_assert_imm1!(N); simd_extract(a, N as u32) @@ -3981,6 +4325,7 @@ pub unsafe fn vdupd_laneq_f64(a: float64x2_t) -> f64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ext, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vextq_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { static_assert_imm1!(N); match N & 0b1 { @@ -3995,6 +4340,7 @@ pub unsafe fn vextq_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_ #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ext, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vextq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { static_assert_imm1!(N); match N & 0b1 { @@ -4008,6 +4354,7 @@ pub unsafe fn vextq_f64(a: float64x2_t, b: float64x2_t) -> float64 #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmul))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmla_f64(a: float64x1_t, b: float64x1_t, c: float64x1_t) -> float64x1_t { simd_add(a, simd_mul(b, c)) } @@ -4016,6 +4363,7 @@ pub unsafe fn vmla_f64(a: float64x1_t, b: float64x1_t, c: float64x1_t) -> float6 #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmul))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlaq_f64(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float64x2_t { simd_add(a, simd_mul(b, c)) } @@ -4024,6 +4372,7 @@ pub unsafe fn vmlaq_f64(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smlal2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlal_high_s8(a: int16x8_t, b: int8x16_t, c: int8x16_t) -> int16x8_t { let b: int8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); let c: int8x8_t = simd_shuffle8!(c, c, [8, 9, 10, 11, 12, 13, 14, 15]); @@ -4034,6 +4383,7 @@ pub unsafe fn vmlal_high_s8(a: int16x8_t, b: int8x16_t, c: int8x16_t) -> int16x8 #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smlal2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlal_high_s16(a: int32x4_t, b: int16x8_t, c: int16x8_t) -> int32x4_t { let b: int16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); let c: int16x4_t = simd_shuffle4!(c, c, [4, 5, 6, 7]); @@ -4044,6 +4394,7 @@ pub unsafe fn vmlal_high_s16(a: int32x4_t, b: int16x8_t, c: int16x8_t) -> int32x #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smlal2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlal_high_s32(a: int64x2_t, b: int32x4_t, c: int32x4_t) -> int64x2_t { let b: int32x2_t = simd_shuffle2!(b, b, [2, 3]); let c: int32x2_t = simd_shuffle2!(c, c, [2, 3]); @@ -4054,6 +4405,7 @@ pub unsafe fn vmlal_high_s32(a: int64x2_t, b: int32x4_t, c: int32x4_t) -> int64x #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umlal2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlal_high_u8(a: uint16x8_t, b: uint8x16_t, c: uint8x16_t) -> uint16x8_t { let b: uint8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); let c: uint8x8_t = simd_shuffle8!(c, c, [8, 9, 10, 11, 12, 13, 14, 15]); @@ -4064,6 +4416,7 @@ pub unsafe fn vmlal_high_u8(a: uint16x8_t, b: uint8x16_t, c: uint8x16_t) -> uint #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umlal2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlal_high_u16(a: uint32x4_t, b: uint16x8_t, c: uint16x8_t) -> uint32x4_t { let b: uint16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); let c: uint16x4_t = simd_shuffle4!(c, c, [4, 5, 6, 7]); @@ -4074,6 +4427,7 @@ pub unsafe fn vmlal_high_u16(a: uint32x4_t, b: uint16x8_t, c: uint16x8_t) -> uin #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umlal2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlal_high_u32(a: uint64x2_t, b: uint32x4_t, c: uint32x4_t) -> uint64x2_t { let b: uint32x2_t = simd_shuffle2!(b, b, [2, 3]); let c: uint32x2_t = simd_shuffle2!(c, c, [2, 3]); @@ -4084,6 +4438,7 @@ pub unsafe fn vmlal_high_u32(a: uint64x2_t, b: uint32x4_t, c: uint32x4_t) -> uin #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smlal2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlal_high_n_s16(a: int32x4_t, b: int16x8_t, c: i16) -> int32x4_t { vmlal_high_s16(a, b, vdupq_n_s16(c)) } @@ -4092,6 +4447,7 @@ pub unsafe fn vmlal_high_n_s16(a: int32x4_t, b: int16x8_t, c: i16) -> int32x4_t #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smlal2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlal_high_n_s32(a: int64x2_t, b: int32x4_t, c: i32) -> int64x2_t { vmlal_high_s32(a, b, vdupq_n_s32(c)) } @@ -4100,6 +4456,7 @@ pub unsafe fn vmlal_high_n_s32(a: int64x2_t, b: int32x4_t, c: i32) -> int64x2_t #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umlal2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlal_high_n_u16(a: uint32x4_t, b: uint16x8_t, c: u16) -> uint32x4_t { vmlal_high_u16(a, b, vdupq_n_u16(c)) } @@ -4108,6 +4465,7 @@ pub unsafe fn vmlal_high_n_u16(a: uint32x4_t, b: uint16x8_t, c: u16) -> uint32x4 #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umlal2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlal_high_n_u32(a: uint64x2_t, b: uint32x4_t, c: u32) -> uint64x2_t { vmlal_high_u32(a, b, vdupq_n_u32(c)) } @@ -4117,6 +4475,7 @@ pub unsafe fn vmlal_high_n_u32(a: uint64x2_t, b: uint32x4_t, c: u32) -> uint64x2 #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smlal2, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlal_high_lane_s16(a: int32x4_t, b: int16x8_t, c: int16x4_t) -> int32x4_t { static_assert_imm2!(LANE); vmlal_high_s16(a, b, simd_shuffle8!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4127,6 +4486,7 @@ pub unsafe fn vmlal_high_lane_s16(a: int32x4_t, b: int16x8_t, c #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smlal2, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlal_high_laneq_s16(a: int32x4_t, b: int16x8_t, c: int16x8_t) -> int32x4_t { static_assert_imm3!(LANE); vmlal_high_s16(a, b, simd_shuffle8!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4137,6 +4497,7 @@ pub unsafe fn vmlal_high_laneq_s16(a: int32x4_t, b: int16x8_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smlal2, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlal_high_lane_s32(a: int64x2_t, b: int32x4_t, c: int32x2_t) -> int64x2_t { static_assert_imm1!(LANE); vmlal_high_s32(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4147,6 +4508,7 @@ pub unsafe fn vmlal_high_lane_s32(a: int64x2_t, b: int32x4_t, c #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smlal2, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlal_high_laneq_s32(a: int64x2_t, b: int32x4_t, c: int32x4_t) -> int64x2_t { static_assert_imm2!(LANE); vmlal_high_s32(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4157,6 +4519,7 @@ pub unsafe fn vmlal_high_laneq_s32(a: int64x2_t, b: int32x4_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umlal2, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlal_high_lane_u16(a: uint32x4_t, b: uint16x8_t, c: uint16x4_t) -> uint32x4_t { static_assert_imm2!(LANE); vmlal_high_u16(a, b, simd_shuffle8!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4167,6 +4530,7 @@ pub unsafe fn vmlal_high_lane_u16(a: uint32x4_t, b: uint16x8_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umlal2, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlal_high_laneq_u16(a: uint32x4_t, b: uint16x8_t, c: uint16x8_t) -> uint32x4_t { static_assert_imm3!(LANE); vmlal_high_u16(a, b, simd_shuffle8!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4177,6 +4541,7 @@ pub unsafe fn vmlal_high_laneq_u16(a: uint32x4_t, b: uint16x8_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umlal2, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlal_high_lane_u32(a: uint64x2_t, b: uint32x4_t, c: uint32x2_t) -> uint64x2_t { static_assert_imm1!(LANE); vmlal_high_u32(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4187,6 +4552,7 @@ pub unsafe fn vmlal_high_lane_u32(a: uint64x2_t, b: uint32x4_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umlal2, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlal_high_laneq_u32(a: uint64x2_t, b: uint32x4_t, c: uint32x4_t) -> uint64x2_t { static_assert_imm2!(LANE); vmlal_high_u32(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4196,6 +4562,7 @@ pub unsafe fn vmlal_high_laneq_u32(a: uint64x2_t, b: uint32x4_t #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmul))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmls_f64(a: float64x1_t, b: float64x1_t, c: float64x1_t) -> float64x1_t { simd_sub(a, simd_mul(b, c)) } @@ -4204,6 +4571,7 @@ pub unsafe fn vmls_f64(a: float64x1_t, b: float64x1_t, c: float64x1_t) -> float6 #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmul))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlsq_f64(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float64x2_t { simd_sub(a, simd_mul(b, c)) } @@ -4212,6 +4580,7 @@ pub unsafe fn vmlsq_f64(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smlsl2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlsl_high_s8(a: int16x8_t, b: int8x16_t, c: int8x16_t) -> int16x8_t { let b: int8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); let c: int8x8_t = simd_shuffle8!(c, c, [8, 9, 10, 11, 12, 13, 14, 15]); @@ -4222,6 +4591,7 @@ pub unsafe fn vmlsl_high_s8(a: int16x8_t, b: int8x16_t, c: int8x16_t) -> int16x8 #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smlsl2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlsl_high_s16(a: int32x4_t, b: int16x8_t, c: int16x8_t) -> int32x4_t { let b: int16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); let c: int16x4_t = simd_shuffle4!(c, c, [4, 5, 6, 7]); @@ -4232,6 +4602,7 @@ pub unsafe fn vmlsl_high_s16(a: int32x4_t, b: int16x8_t, c: int16x8_t) -> int32x #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smlsl2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlsl_high_s32(a: int64x2_t, b: int32x4_t, c: int32x4_t) -> int64x2_t { let b: int32x2_t = simd_shuffle2!(b, b, [2, 3]); let c: int32x2_t = simd_shuffle2!(c, c, [2, 3]); @@ -4242,6 +4613,7 @@ pub unsafe fn vmlsl_high_s32(a: int64x2_t, b: int32x4_t, c: int32x4_t) -> int64x #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umlsl2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlsl_high_u8(a: uint16x8_t, b: uint8x16_t, c: uint8x16_t) -> uint16x8_t { let b: uint8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); let c: uint8x8_t = simd_shuffle8!(c, c, [8, 9, 10, 11, 12, 13, 14, 15]); @@ -4252,6 +4624,7 @@ pub unsafe fn vmlsl_high_u8(a: uint16x8_t, b: uint8x16_t, c: uint8x16_t) -> uint #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umlsl2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlsl_high_u16(a: uint32x4_t, b: uint16x8_t, c: uint16x8_t) -> uint32x4_t { let b: uint16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); let c: uint16x4_t = simd_shuffle4!(c, c, [4, 5, 6, 7]); @@ -4262,6 +4635,7 @@ pub unsafe fn vmlsl_high_u16(a: uint32x4_t, b: uint16x8_t, c: uint16x8_t) -> uin #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umlsl2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlsl_high_u32(a: uint64x2_t, b: uint32x4_t, c: uint32x4_t) -> uint64x2_t { let b: uint32x2_t = simd_shuffle2!(b, b, [2, 3]); let c: uint32x2_t = simd_shuffle2!(c, c, [2, 3]); @@ -4272,6 +4646,7 @@ pub unsafe fn vmlsl_high_u32(a: uint64x2_t, b: uint32x4_t, c: uint32x4_t) -> uin #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smlsl2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlsl_high_n_s16(a: int32x4_t, b: int16x8_t, c: i16) -> int32x4_t { vmlsl_high_s16(a, b, vdupq_n_s16(c)) } @@ -4280,6 +4655,7 @@ pub unsafe fn vmlsl_high_n_s16(a: int32x4_t, b: int16x8_t, c: i16) -> int32x4_t #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smlsl2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlsl_high_n_s32(a: int64x2_t, b: int32x4_t, c: i32) -> int64x2_t { vmlsl_high_s32(a, b, vdupq_n_s32(c)) } @@ -4288,6 +4664,7 @@ pub unsafe fn vmlsl_high_n_s32(a: int64x2_t, b: int32x4_t, c: i32) -> int64x2_t #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umlsl2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlsl_high_n_u16(a: uint32x4_t, b: uint16x8_t, c: u16) -> uint32x4_t { vmlsl_high_u16(a, b, vdupq_n_u16(c)) } @@ -4296,6 +4673,7 @@ pub unsafe fn vmlsl_high_n_u16(a: uint32x4_t, b: uint16x8_t, c: u16) -> uint32x4 #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umlsl2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlsl_high_n_u32(a: uint64x2_t, b: uint32x4_t, c: u32) -> uint64x2_t { vmlsl_high_u32(a, b, vdupq_n_u32(c)) } @@ -4305,6 +4683,7 @@ pub unsafe fn vmlsl_high_n_u32(a: uint64x2_t, b: uint32x4_t, c: u32) -> uint64x2 #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smlsl2, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlsl_high_lane_s16(a: int32x4_t, b: int16x8_t, c: int16x4_t) -> int32x4_t { static_assert_imm2!(LANE); vmlsl_high_s16(a, b, simd_shuffle8!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4315,6 +4694,7 @@ pub unsafe fn vmlsl_high_lane_s16(a: int32x4_t, b: int16x8_t, c #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smlsl2, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlsl_high_laneq_s16(a: int32x4_t, b: int16x8_t, c: int16x8_t) -> int32x4_t { static_assert_imm3!(LANE); vmlsl_high_s16(a, b, simd_shuffle8!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4325,6 +4705,7 @@ pub unsafe fn vmlsl_high_laneq_s16(a: int32x4_t, b: int16x8_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smlsl2, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlsl_high_lane_s32(a: int64x2_t, b: int32x4_t, c: int32x2_t) -> int64x2_t { static_assert_imm1!(LANE); vmlsl_high_s32(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4335,6 +4716,7 @@ pub unsafe fn vmlsl_high_lane_s32(a: int64x2_t, b: int32x4_t, c #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smlsl2, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlsl_high_laneq_s32(a: int64x2_t, b: int32x4_t, c: int32x4_t) -> int64x2_t { static_assert_imm2!(LANE); vmlsl_high_s32(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4345,6 +4727,7 @@ pub unsafe fn vmlsl_high_laneq_s32(a: int64x2_t, b: int32x4_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umlsl2, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlsl_high_lane_u16(a: uint32x4_t, b: uint16x8_t, c: uint16x4_t) -> uint32x4_t { static_assert_imm2!(LANE); vmlsl_high_u16(a, b, simd_shuffle8!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4355,6 +4738,7 @@ pub unsafe fn vmlsl_high_lane_u16(a: uint32x4_t, b: uint16x8_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umlsl2, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlsl_high_laneq_u16(a: uint32x4_t, b: uint16x8_t, c: uint16x8_t) -> uint32x4_t { static_assert_imm3!(LANE); vmlsl_high_u16(a, b, simd_shuffle8!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4365,6 +4749,7 @@ pub unsafe fn vmlsl_high_laneq_u16(a: uint32x4_t, b: uint16x8_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umlsl2, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlsl_high_lane_u32(a: uint64x2_t, b: uint32x4_t, c: uint32x2_t) -> uint64x2_t { static_assert_imm1!(LANE); vmlsl_high_u32(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4375,6 +4760,7 @@ pub unsafe fn vmlsl_high_lane_u32(a: uint64x2_t, b: uint32x4_t, #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umlsl2, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmlsl_high_laneq_u32(a: uint64x2_t, b: uint32x4_t, c: uint32x4_t) -> uint64x2_t { static_assert_imm2!(LANE); vmlsl_high_u32(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4384,6 +4770,7 @@ pub unsafe fn vmlsl_high_laneq_u32(a: uint64x2_t, b: uint32x4_t #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(xtn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmovn_high_s16(a: int8x8_t, b: int16x8_t) -> int8x16_t { let c: int8x8_t = simd_cast(b); simd_shuffle16!(a, c, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) @@ -4393,6 +4780,7 @@ pub unsafe fn vmovn_high_s16(a: int8x8_t, b: int16x8_t) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(xtn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmovn_high_s32(a: int16x4_t, b: int32x4_t) -> int16x8_t { let c: int16x4_t = simd_cast(b); simd_shuffle8!(a, c, [0, 1, 2, 3, 4, 5, 6, 7]) @@ -4402,6 +4790,7 @@ pub unsafe fn vmovn_high_s32(a: int16x4_t, b: int32x4_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(xtn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmovn_high_s64(a: int32x2_t, b: int64x2_t) -> int32x4_t { let c: int32x2_t = simd_cast(b); simd_shuffle4!(a, c, [0, 1, 2, 3]) @@ -4411,6 +4800,7 @@ pub unsafe fn vmovn_high_s64(a: int32x2_t, b: int64x2_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(xtn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmovn_high_u16(a: uint8x8_t, b: uint16x8_t) -> uint8x16_t { let c: uint8x8_t = simd_cast(b); simd_shuffle16!(a, c, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) @@ -4420,6 +4810,7 @@ pub unsafe fn vmovn_high_u16(a: uint8x8_t, b: uint16x8_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(xtn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmovn_high_u32(a: uint16x4_t, b: uint32x4_t) -> uint16x8_t { let c: uint16x4_t = simd_cast(b); simd_shuffle8!(a, c, [0, 1, 2, 3, 4, 5, 6, 7]) @@ -4429,6 +4820,7 @@ pub unsafe fn vmovn_high_u32(a: uint16x4_t, b: uint32x4_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(xtn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmovn_high_u64(a: uint32x2_t, b: uint64x2_t) -> uint32x4_t { let c: uint32x2_t = simd_cast(b); simd_shuffle4!(a, c, [0, 1, 2, 3]) @@ -4438,6 +4830,7 @@ pub unsafe fn vmovn_high_u64(a: uint32x2_t, b: uint64x2_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(neg))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vneg_s64(a: int64x1_t) -> int64x1_t { simd_neg(a) } @@ -4446,6 +4839,7 @@ pub unsafe fn vneg_s64(a: int64x1_t) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(neg))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vnegq_s64(a: int64x2_t) -> int64x2_t { simd_neg(a) } @@ -4454,14 +4848,16 @@ pub unsafe fn vnegq_s64(a: int64x2_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(neg))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vnegd_s64(a: i64) -> i64 { - -a + a.wrapping_neg() } /// Negate #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fneg))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vneg_f64(a: float64x1_t) -> float64x1_t { simd_neg(a) } @@ -4470,6 +4866,7 @@ pub unsafe fn vneg_f64(a: float64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fneg))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vnegq_f64(a: float64x2_t) -> float64x2_t { simd_neg(a) } @@ -4478,6 +4875,7 @@ pub unsafe fn vnegq_f64(a: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqneg))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqneg_s64(a: int64x1_t) -> int64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4491,6 +4889,7 @@ pub unsafe fn vqneg_s64(a: int64x1_t) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqneg))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqnegq_s64(a: int64x2_t) -> int64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4504,6 +4903,7 @@ pub unsafe fn vqnegq_s64(a: int64x2_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqneg))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqnegb_s8(a: i8) -> i8 { simd_extract(vqneg_s8(vdup_n_s8(a)), 0) } @@ -4512,6 +4912,7 @@ pub unsafe fn vqnegb_s8(a: i8) -> i8 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqneg))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqnegh_s16(a: i16) -> i16 { simd_extract(vqneg_s16(vdup_n_s16(a)), 0) } @@ -4520,6 +4921,7 @@ pub unsafe fn vqnegh_s16(a: i16) -> i16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqneg))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqnegs_s32(a: i32) -> i32 { simd_extract(vqneg_s32(vdup_n_s32(a)), 0) } @@ -4528,6 +4930,7 @@ pub unsafe fn vqnegs_s32(a: i32) -> i32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqneg))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqnegd_s64(a: i64) -> i64 { simd_extract(vqneg_s64(vdup_n_s64(a)), 0) } @@ -4536,6 +4939,7 @@ pub unsafe fn vqnegd_s64(a: i64) -> i64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqsub))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqsubb_s8(a: i8, b: i8) -> i8 { let a: int8x8_t = vdup_n_s8(a); let b: int8x8_t = vdup_n_s8(b); @@ -4546,6 +4950,7 @@ pub unsafe fn vqsubb_s8(a: i8, b: i8) -> i8 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqsub))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqsubh_s16(a: i16, b: i16) -> i16 { let a: int16x4_t = vdup_n_s16(a); let b: int16x4_t = vdup_n_s16(b); @@ -4556,6 +4961,7 @@ pub unsafe fn vqsubh_s16(a: i16, b: i16) -> i16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqsub))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqsubb_u8(a: u8, b: u8) -> u8 { let a: uint8x8_t = vdup_n_u8(a); let b: uint8x8_t = vdup_n_u8(b); @@ -4566,6 +4972,7 @@ pub unsafe fn vqsubb_u8(a: u8, b: u8) -> u8 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqsub))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqsubh_u16(a: u16, b: u16) -> u16 { let a: uint16x4_t = vdup_n_u16(a); let b: uint16x4_t = vdup_n_u16(b); @@ -4576,6 +4983,7 @@ pub unsafe fn vqsubh_u16(a: u16, b: u16) -> u16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqsub))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqsubs_u32(a: u32, b: u32) -> u32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4589,6 +4997,7 @@ pub unsafe fn vqsubs_u32(a: u32, b: u32) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqsub))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqsubd_u64(a: u64, b: u64) -> u64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4602,6 +5011,7 @@ pub unsafe fn vqsubd_u64(a: u64, b: u64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqsub))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqsubs_s32(a: i32, b: i32) -> i32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4615,6 +5025,7 @@ pub unsafe fn vqsubs_s32(a: i32, b: i32) -> i32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqsub))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqsubd_s64(a: i64, b: i64) -> i64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4628,6 +5039,7 @@ pub unsafe fn vqsubd_s64(a: i64, b: i64) -> i64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(rbit))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrbit_s8(a: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4641,6 +5053,7 @@ pub unsafe fn vrbit_s8(a: int8x8_t) -> int8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(rbit))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrbitq_s8(a: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4654,6 +5067,7 @@ pub unsafe fn vrbitq_s8(a: int8x16_t) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(rbit))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrbit_u8(a: uint8x8_t) -> uint8x8_t { transmute(vrbit_s8(transmute(a))) } @@ -4662,6 +5076,7 @@ pub unsafe fn vrbit_u8(a: uint8x8_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(rbit))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrbitq_u8(a: uint8x16_t) -> uint8x16_t { transmute(vrbitq_s8(transmute(a))) } @@ -4670,6 +5085,7 @@ pub unsafe fn vrbitq_u8(a: uint8x16_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(rbit))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrbit_p8(a: poly8x8_t) -> poly8x8_t { transmute(vrbit_s8(transmute(a))) } @@ -4678,6 +5094,7 @@ pub unsafe fn vrbit_p8(a: poly8x8_t) -> poly8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(rbit))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrbitq_p8(a: poly8x16_t) -> poly8x16_t { transmute(vrbitq_s8(transmute(a))) } @@ -4686,6 +5103,7 @@ pub unsafe fn vrbitq_p8(a: poly8x16_t) -> poly8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frintx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrndx_f32(a: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4699,6 +5117,7 @@ pub unsafe fn vrndx_f32(a: float32x2_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frintx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrndxq_f32(a: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4712,6 +5131,7 @@ pub unsafe fn vrndxq_f32(a: float32x4_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frintx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrndx_f64(a: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4725,6 +5145,7 @@ pub unsafe fn vrndx_f64(a: float64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frintx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrndxq_f64(a: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4738,6 +5159,7 @@ pub unsafe fn vrndxq_f64(a: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frinta))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrnda_f32(a: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4751,6 +5173,7 @@ pub unsafe fn vrnda_f32(a: float32x2_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frinta))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrndaq_f32(a: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4764,6 +5187,7 @@ pub unsafe fn vrndaq_f32(a: float32x4_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frinta))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrnda_f64(a: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4777,6 +5201,7 @@ pub unsafe fn vrnda_f64(a: float64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frinta))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrndaq_f64(a: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4790,6 +5215,7 @@ pub unsafe fn vrndaq_f64(a: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frintn))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrndn_f64(a: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4803,6 +5229,7 @@ pub unsafe fn vrndn_f64(a: float64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frintn))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrndnq_f64(a: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4816,6 +5243,7 @@ pub unsafe fn vrndnq_f64(a: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frintn))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrndns_f32(a: f32) -> f32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4829,6 +5257,7 @@ pub unsafe fn vrndns_f32(a: f32) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frintm))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrndm_f32(a: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4842,6 +5271,7 @@ pub unsafe fn vrndm_f32(a: float32x2_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frintm))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrndmq_f32(a: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4855,6 +5285,7 @@ pub unsafe fn vrndmq_f32(a: float32x4_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frintm))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrndm_f64(a: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4868,6 +5299,7 @@ pub unsafe fn vrndm_f64(a: float64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frintm))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrndmq_f64(a: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4881,6 +5313,7 @@ pub unsafe fn vrndmq_f64(a: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frintp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrndp_f32(a: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4894,6 +5327,7 @@ pub unsafe fn vrndp_f32(a: float32x2_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frintp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrndpq_f32(a: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4907,6 +5341,7 @@ pub unsafe fn vrndpq_f32(a: float32x4_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frintp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrndp_f64(a: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4920,6 +5355,7 @@ pub unsafe fn vrndp_f64(a: float64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frintp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrndpq_f64(a: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4933,6 +5369,7 @@ pub unsafe fn vrndpq_f64(a: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frintz))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrnd_f32(a: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4946,6 +5383,7 @@ pub unsafe fn vrnd_f32(a: float32x2_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frintz))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrndq_f32(a: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4959,6 +5397,7 @@ pub unsafe fn vrndq_f32(a: float32x4_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frintz))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrnd_f64(a: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4972,6 +5411,7 @@ pub unsafe fn vrnd_f64(a: float64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frintz))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrndq_f64(a: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4985,6 +5425,7 @@ pub unsafe fn vrndq_f64(a: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frinti))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrndi_f32(a: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4998,6 +5439,7 @@ pub unsafe fn vrndi_f32(a: float32x2_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frinti))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrndiq_f32(a: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5011,6 +5453,7 @@ pub unsafe fn vrndiq_f32(a: float32x4_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frinti))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrndi_f64(a: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5024,6 +5467,7 @@ pub unsafe fn vrndi_f64(a: float64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frinti))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrndiq_f64(a: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5037,6 +5481,7 @@ pub unsafe fn vrndiq_f64(a: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqaddb_s8(a: i8, b: i8) -> i8 { let a: int8x8_t = vdup_n_s8(a); let b: int8x8_t = vdup_n_s8(b); @@ -5047,6 +5492,7 @@ pub unsafe fn vqaddb_s8(a: i8, b: i8) -> i8 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqaddh_s16(a: i16, b: i16) -> i16 { let a: int16x4_t = vdup_n_s16(a); let b: int16x4_t = vdup_n_s16(b); @@ -5057,6 +5503,7 @@ pub unsafe fn vqaddh_s16(a: i16, b: i16) -> i16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqaddb_u8(a: u8, b: u8) -> u8 { let a: uint8x8_t = vdup_n_u8(a); let b: uint8x8_t = vdup_n_u8(b); @@ -5067,6 +5514,7 @@ pub unsafe fn vqaddb_u8(a: u8, b: u8) -> u8 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqaddh_u16(a: u16, b: u16) -> u16 { let a: uint16x4_t = vdup_n_u16(a); let b: uint16x4_t = vdup_n_u16(b); @@ -5077,6 +5525,7 @@ pub unsafe fn vqaddh_u16(a: u16, b: u16) -> u16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqadds_u32(a: u32, b: u32) -> u32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5090,6 +5539,7 @@ pub unsafe fn vqadds_u32(a: u32, b: u32) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqaddd_u64(a: u64, b: u64) -> u64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5103,6 +5553,7 @@ pub unsafe fn vqaddd_u64(a: u64, b: u64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqadds_s32(a: i32, b: i32) -> i32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5116,6 +5567,7 @@ pub unsafe fn vqadds_s32(a: i32, b: i32) -> i32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqaddd_s64(a: i64, b: i64) -> i64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5129,6 +5581,7 @@ pub unsafe fn vqaddd_s64(a: i64, b: i64) -> i64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1_f64_x2(a: *const f64) -> float64x1x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5142,6 +5595,7 @@ pub unsafe fn vld1_f64_x2(a: *const f64) -> float64x1x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1q_f64_x2(a: *const f64) -> float64x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5155,6 +5609,7 @@ pub unsafe fn vld1q_f64_x2(a: *const f64) -> float64x2x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1_f64_x3(a: *const f64) -> float64x1x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5168,6 +5623,7 @@ pub unsafe fn vld1_f64_x3(a: *const f64) -> float64x1x3_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1q_f64_x3(a: *const f64) -> float64x2x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5181,6 +5637,7 @@ pub unsafe fn vld1q_f64_x3(a: *const f64) -> float64x2x3_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1_f64_x4(a: *const f64) -> float64x1x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5194,6 +5651,7 @@ pub unsafe fn vld1_f64_x4(a: *const f64) -> float64x1x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1q_f64_x4(a: *const f64) -> float64x2x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5207,19 +5665,21 @@ pub unsafe fn vld1q_f64_x4(a: *const f64) -> float64x2x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_s64(a: *const i64) -> int64x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2.v2i64.p0v2i64")] fn vld2q_s64_(ptr: *const int64x2_t) -> int64x2x2_t; } - vld2q_s64_(a.cast()) + vld2q_s64_(a as _) } /// Load multiple 2-element structures to two registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_u64(a: *const u64) -> uint64x2x2_t { transmute(vld2q_s64(transmute(a))) } @@ -5228,6 +5688,7 @@ pub unsafe fn vld2q_u64(a: *const u64) -> uint64x2x2_t { #[inline] #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(ld2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_p64(a: *const p64) -> poly64x2x2_t { transmute(vld2q_s64(transmute(a))) } @@ -5236,45 +5697,49 @@ pub unsafe fn vld2q_p64(a: *const p64) -> poly64x2x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2_f64(a: *const f64) -> float64x1x2_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2.v1f64.p0v1f64")] fn vld2_f64_(ptr: *const float64x1_t) -> float64x1x2_t; } - vld2_f64_(a.cast()) + vld2_f64_(a as _) } /// Load multiple 2-element structures to two registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_f64(a: *const f64) -> float64x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2.v2f64.p0v2f64")] fn vld2q_f64_(ptr: *const float64x2_t) -> float64x2x2_t; } - vld2q_f64_(a.cast()) + vld2q_f64_(a as _) } /// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld2r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_dup_s64(a: *const i64) -> int64x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2r.v2i64.p0i64")] fn vld2q_dup_s64_(ptr: *const i64) -> int64x2x2_t; } - vld2q_dup_s64_(a.cast()) + vld2q_dup_s64_(a as _) } /// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld2r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_dup_u64(a: *const u64) -> uint64x2x2_t { transmute(vld2q_dup_s64(transmute(a))) } @@ -5283,6 +5748,7 @@ pub unsafe fn vld2q_dup_u64(a: *const u64) -> uint64x2x2_t { #[inline] #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(ld2r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_dup_p64(a: *const p64) -> poly64x2x2_t { transmute(vld2q_dup_s64(transmute(a))) } @@ -5291,26 +5757,28 @@ pub unsafe fn vld2q_dup_p64(a: *const p64) -> poly64x2x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld2r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2_dup_f64(a: *const f64) -> float64x1x2_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2r.v1f64.p0f64")] fn vld2_dup_f64_(ptr: *const f64) -> float64x1x2_t; } - vld2_dup_f64_(a.cast()) + vld2_dup_f64_(a as _) } /// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld2r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_dup_f64(a: *const f64) -> float64x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2r.v2f64.p0f64")] fn vld2q_dup_f64_(ptr: *const f64) -> float64x2x2_t; } - vld2q_dup_f64_(a.cast()) + vld2q_dup_f64_(a as _) } /// Load multiple 2-element structures to two registers @@ -5318,6 +5786,7 @@ pub unsafe fn vld2q_dup_f64(a: *const f64) -> float64x2x2_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_lane_s8(a: *const i8, b: int8x16x2_t) -> int8x16x2_t { static_assert_imm4!(LANE); #[allow(improper_ctypes)] @@ -5325,7 +5794,7 @@ pub unsafe fn vld2q_lane_s8(a: *const i8, b: int8x16x2_t) -> in #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2lane.v16i8.p0i8")] fn vld2q_lane_s8_(a: int8x16_t, b: int8x16_t, n: i64, ptr: *const i8) -> int8x16x2_t; } - vld2q_lane_s8_(b.0, b.1, LANE as i64, a.cast()) + vld2q_lane_s8_(b.0, b.1, LANE as i64, a as _) } /// Load multiple 2-element structures to two registers @@ -5333,6 +5802,7 @@ pub unsafe fn vld2q_lane_s8(a: *const i8, b: int8x16x2_t) -> in #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2_lane_s64(a: *const i64, b: int64x1x2_t) -> int64x1x2_t { static_assert!(LANE : i32 where LANE == 0); #[allow(improper_ctypes)] @@ -5340,7 +5810,7 @@ pub unsafe fn vld2_lane_s64(a: *const i64, b: int64x1x2_t) -> i #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2lane.v1i64.p0i8")] fn vld2_lane_s64_(a: int64x1_t, b: int64x1_t, n: i64, ptr: *const i8) -> int64x1x2_t; } - vld2_lane_s64_(b.0, b.1, LANE as i64, a.cast()) + vld2_lane_s64_(b.0, b.1, LANE as i64, a as _) } /// Load multiple 2-element structures to two registers @@ -5348,6 +5818,7 @@ pub unsafe fn vld2_lane_s64(a: *const i64, b: int64x1x2_t) -> i #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_lane_s64(a: *const i64, b: int64x2x2_t) -> int64x2x2_t { static_assert_imm1!(LANE); #[allow(improper_ctypes)] @@ -5355,7 +5826,7 @@ pub unsafe fn vld2q_lane_s64(a: *const i64, b: int64x2x2_t) -> #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2lane.v2i64.p0i8")] fn vld2q_lane_s64_(a: int64x2_t, b: int64x2_t, n: i64, ptr: *const i8) -> int64x2x2_t; } - vld2q_lane_s64_(b.0, b.1, LANE as i64, a.cast()) + vld2q_lane_s64_(b.0, b.1, LANE as i64, a as _) } /// Load multiple 2-element structures to two registers @@ -5363,6 +5834,7 @@ pub unsafe fn vld2q_lane_s64(a: *const i64, b: int64x2x2_t) -> #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2_lane_p64(a: *const p64, b: poly64x1x2_t) -> poly64x1x2_t { static_assert!(LANE : i32 where LANE == 0); transmute(vld2_lane_s64::(transmute(a), transmute(b))) @@ -5373,6 +5845,7 @@ pub unsafe fn vld2_lane_p64(a: *const p64, b: poly64x1x2_t) -> #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_lane_p64(a: *const p64, b: poly64x2x2_t) -> poly64x2x2_t { static_assert_imm1!(LANE); transmute(vld2q_lane_s64::(transmute(a), transmute(b))) @@ -5383,6 +5856,7 @@ pub unsafe fn vld2q_lane_p64(a: *const p64, b: poly64x2x2_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_lane_u8(a: *const u8, b: uint8x16x2_t) -> uint8x16x2_t { static_assert_imm4!(LANE); transmute(vld2q_lane_s8::(transmute(a), transmute(b))) @@ -5393,6 +5867,7 @@ pub unsafe fn vld2q_lane_u8(a: *const u8, b: uint8x16x2_t) -> u #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2_lane_u64(a: *const u64, b: uint64x1x2_t) -> uint64x1x2_t { static_assert!(LANE : i32 where LANE == 0); transmute(vld2_lane_s64::(transmute(a), transmute(b))) @@ -5403,6 +5878,7 @@ pub unsafe fn vld2_lane_u64(a: *const u64, b: uint64x1x2_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_lane_u64(a: *const u64, b: uint64x2x2_t) -> uint64x2x2_t { static_assert_imm1!(LANE); transmute(vld2q_lane_s64::(transmute(a), transmute(b))) @@ -5413,6 +5889,7 @@ pub unsafe fn vld2q_lane_u64(a: *const u64, b: uint64x2x2_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_lane_p8(a: *const p8, b: poly8x16x2_t) -> poly8x16x2_t { static_assert_imm4!(LANE); transmute(vld2q_lane_s8::(transmute(a), transmute(b))) @@ -5423,6 +5900,7 @@ pub unsafe fn vld2q_lane_p8(a: *const p8, b: poly8x16x2_t) -> p #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2_lane_f64(a: *const f64, b: float64x1x2_t) -> float64x1x2_t { static_assert!(LANE : i32 where LANE == 0); #[allow(improper_ctypes)] @@ -5430,7 +5908,7 @@ pub unsafe fn vld2_lane_f64(a: *const f64, b: float64x1x2_t) -> #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2lane.v1f64.p0i8")] fn vld2_lane_f64_(a: float64x1_t, b: float64x1_t, n: i64, ptr: *const i8) -> float64x1x2_t; } - vld2_lane_f64_(b.0, b.1, LANE as i64, a.cast()) + vld2_lane_f64_(b.0, b.1, LANE as i64, a as _) } /// Load multiple 2-element structures to two registers @@ -5438,6 +5916,7 @@ pub unsafe fn vld2_lane_f64(a: *const f64, b: float64x1x2_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_lane_f64(a: *const f64, b: float64x2x2_t) -> float64x2x2_t { static_assert_imm1!(LANE); #[allow(improper_ctypes)] @@ -5445,26 +5924,28 @@ pub unsafe fn vld2q_lane_f64(a: *const f64, b: float64x2x2_t) - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2lane.v2f64.p0i8")] fn vld2q_lane_f64_(a: float64x2_t, b: float64x2_t, n: i64, ptr: *const i8) -> float64x2x2_t; } - vld2q_lane_f64_(b.0, b.1, LANE as i64, a.cast()) + vld2q_lane_f64_(b.0, b.1, LANE as i64, a as _) } /// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld3))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_s64(a: *const i64) -> int64x2x3_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3.v2i64.p0v2i64")] fn vld3q_s64_(ptr: *const int64x2_t) -> int64x2x3_t; } - vld3q_s64_(a.cast()) + vld3q_s64_(a as _) } /// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld3))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_u64(a: *const u64) -> uint64x2x3_t { transmute(vld3q_s64(transmute(a))) } @@ -5473,6 +5954,7 @@ pub unsafe fn vld3q_u64(a: *const u64) -> uint64x2x3_t { #[inline] #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(ld3))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_p64(a: *const p64) -> poly64x2x3_t { transmute(vld3q_s64(transmute(a))) } @@ -5481,45 +5963,49 @@ pub unsafe fn vld3q_p64(a: *const p64) -> poly64x2x3_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3_f64(a: *const f64) -> float64x1x3_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3.v1f64.p0v1f64")] fn vld3_f64_(ptr: *const float64x1_t) -> float64x1x3_t; } - vld3_f64_(a.cast()) + vld3_f64_(a as _) } /// Load multiple 3-element structures to three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld3))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_f64(a: *const f64) -> float64x2x3_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3.v2f64.p0v2f64")] fn vld3q_f64_(ptr: *const float64x2_t) -> float64x2x3_t; } - vld3q_f64_(a.cast()) + vld3q_f64_(a as _) } /// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld3r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_dup_s64(a: *const i64) -> int64x2x3_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3r.v2i64.p0i64")] fn vld3q_dup_s64_(ptr: *const i64) -> int64x2x3_t; } - vld3q_dup_s64_(a.cast()) + vld3q_dup_s64_(a as _) } /// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld3r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_dup_u64(a: *const u64) -> uint64x2x3_t { transmute(vld3q_dup_s64(transmute(a))) } @@ -5528,6 +6014,7 @@ pub unsafe fn vld3q_dup_u64(a: *const u64) -> uint64x2x3_t { #[inline] #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(ld3r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_dup_p64(a: *const p64) -> poly64x2x3_t { transmute(vld3q_dup_s64(transmute(a))) } @@ -5536,26 +6023,28 @@ pub unsafe fn vld3q_dup_p64(a: *const p64) -> poly64x2x3_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld3r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3_dup_f64(a: *const f64) -> float64x1x3_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3r.v1f64.p0f64")] fn vld3_dup_f64_(ptr: *const f64) -> float64x1x3_t; } - vld3_dup_f64_(a.cast()) + vld3_dup_f64_(a as _) } /// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld3r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_dup_f64(a: *const f64) -> float64x2x3_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3r.v2f64.p0f64")] fn vld3q_dup_f64_(ptr: *const f64) -> float64x2x3_t; } - vld3q_dup_f64_(a.cast()) + vld3q_dup_f64_(a as _) } /// Load multiple 3-element structures to two registers @@ -5563,6 +6052,7 @@ pub unsafe fn vld3q_dup_f64(a: *const f64) -> float64x2x3_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_lane_s8(a: *const i8, b: int8x16x3_t) -> int8x16x3_t { static_assert_imm4!(LANE); #[allow(improper_ctypes)] @@ -5570,7 +6060,7 @@ pub unsafe fn vld3q_lane_s8(a: *const i8, b: int8x16x3_t) -> in #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3lane.v16i8.p0i8")] fn vld3q_lane_s8_(a: int8x16_t, b: int8x16_t, c: int8x16_t, n: i64, ptr: *const i8) -> int8x16x3_t; } - vld3q_lane_s8_(b.0, b.1, b.2, LANE as i64, a.cast()) + vld3q_lane_s8_(b.0, b.1, b.2, LANE as i64, a as _) } /// Load multiple 3-element structures to two registers @@ -5578,6 +6068,7 @@ pub unsafe fn vld3q_lane_s8(a: *const i8, b: int8x16x3_t) -> in #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3_lane_s64(a: *const i64, b: int64x1x3_t) -> int64x1x3_t { static_assert!(LANE : i32 where LANE == 0); #[allow(improper_ctypes)] @@ -5585,7 +6076,7 @@ pub unsafe fn vld3_lane_s64(a: *const i64, b: int64x1x3_t) -> i #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3lane.v1i64.p0i8")] fn vld3_lane_s64_(a: int64x1_t, b: int64x1_t, c: int64x1_t, n: i64, ptr: *const i8) -> int64x1x3_t; } - vld3_lane_s64_(b.0, b.1, b.2, LANE as i64, a.cast()) + vld3_lane_s64_(b.0, b.1, b.2, LANE as i64, a as _) } /// Load multiple 3-element structures to two registers @@ -5593,6 +6084,7 @@ pub unsafe fn vld3_lane_s64(a: *const i64, b: int64x1x3_t) -> i #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_lane_s64(a: *const i64, b: int64x2x3_t) -> int64x2x3_t { static_assert_imm1!(LANE); #[allow(improper_ctypes)] @@ -5600,7 +6092,7 @@ pub unsafe fn vld3q_lane_s64(a: *const i64, b: int64x2x3_t) -> #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3lane.v2i64.p0i8")] fn vld3q_lane_s64_(a: int64x2_t, b: int64x2_t, c: int64x2_t, n: i64, ptr: *const i8) -> int64x2x3_t; } - vld3q_lane_s64_(b.0, b.1, b.2, LANE as i64, a.cast()) + vld3q_lane_s64_(b.0, b.1, b.2, LANE as i64, a as _) } /// Load multiple 3-element structures to three registers @@ -5608,6 +6100,7 @@ pub unsafe fn vld3q_lane_s64(a: *const i64, b: int64x2x3_t) -> #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3_lane_p64(a: *const p64, b: poly64x1x3_t) -> poly64x1x3_t { static_assert!(LANE : i32 where LANE == 0); transmute(vld3_lane_s64::(transmute(a), transmute(b))) @@ -5618,6 +6111,7 @@ pub unsafe fn vld3_lane_p64(a: *const p64, b: poly64x1x3_t) -> #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_lane_p64(a: *const p64, b: poly64x2x3_t) -> poly64x2x3_t { static_assert_imm1!(LANE); transmute(vld3q_lane_s64::(transmute(a), transmute(b))) @@ -5628,6 +6122,7 @@ pub unsafe fn vld3q_lane_p64(a: *const p64, b: poly64x2x3_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_lane_p8(a: *const p8, b: poly8x16x3_t) -> poly8x16x3_t { static_assert_imm4!(LANE); transmute(vld3q_lane_s8::(transmute(a), transmute(b))) @@ -5638,6 +6133,7 @@ pub unsafe fn vld3q_lane_p8(a: *const p8, b: poly8x16x3_t) -> p #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_lane_u8(a: *const u8, b: uint8x16x3_t) -> uint8x16x3_t { static_assert_imm4!(LANE); transmute(vld3q_lane_s8::(transmute(a), transmute(b))) @@ -5648,6 +6144,7 @@ pub unsafe fn vld3q_lane_u8(a: *const u8, b: uint8x16x3_t) -> u #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3_lane_u64(a: *const u64, b: uint64x1x3_t) -> uint64x1x3_t { static_assert!(LANE : i32 where LANE == 0); transmute(vld3_lane_s64::(transmute(a), transmute(b))) @@ -5658,6 +6155,7 @@ pub unsafe fn vld3_lane_u64(a: *const u64, b: uint64x1x3_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_lane_u64(a: *const u64, b: uint64x2x3_t) -> uint64x2x3_t { static_assert_imm1!(LANE); transmute(vld3q_lane_s64::(transmute(a), transmute(b))) @@ -5668,6 +6166,7 @@ pub unsafe fn vld3q_lane_u64(a: *const u64, b: uint64x2x3_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3_lane_f64(a: *const f64, b: float64x1x3_t) -> float64x1x3_t { static_assert!(LANE : i32 where LANE == 0); #[allow(improper_ctypes)] @@ -5675,7 +6174,7 @@ pub unsafe fn vld3_lane_f64(a: *const f64, b: float64x1x3_t) -> #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3lane.v1f64.p0i8")] fn vld3_lane_f64_(a: float64x1_t, b: float64x1_t, c: float64x1_t, n: i64, ptr: *const i8) -> float64x1x3_t; } - vld3_lane_f64_(b.0, b.1, b.2, LANE as i64, a.cast()) + vld3_lane_f64_(b.0, b.1, b.2, LANE as i64, a as _) } /// Load multiple 3-element structures to three registers @@ -5683,6 +6182,7 @@ pub unsafe fn vld3_lane_f64(a: *const f64, b: float64x1x3_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_lane_f64(a: *const f64, b: float64x2x3_t) -> float64x2x3_t { static_assert_imm1!(LANE); #[allow(improper_ctypes)] @@ -5690,26 +6190,28 @@ pub unsafe fn vld3q_lane_f64(a: *const f64, b: float64x2x3_t) - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3lane.v2f64.p0i8")] fn vld3q_lane_f64_(a: float64x2_t, b: float64x2_t, c: float64x2_t, n: i64, ptr: *const i8) -> float64x2x3_t; } - vld3q_lane_f64_(b.0, b.1, b.2, LANE as i64, a.cast()) + vld3q_lane_f64_(b.0, b.1, b.2, LANE as i64, a as _) } /// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld4))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_s64(a: *const i64) -> int64x2x4_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4.v2i64.p0v2i64")] fn vld4q_s64_(ptr: *const int64x2_t) -> int64x2x4_t; } - vld4q_s64_(a.cast()) + vld4q_s64_(a as _) } /// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld4))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_u64(a: *const u64) -> uint64x2x4_t { transmute(vld4q_s64(transmute(a))) } @@ -5718,6 +6220,7 @@ pub unsafe fn vld4q_u64(a: *const u64) -> uint64x2x4_t { #[inline] #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(ld4))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_p64(a: *const p64) -> poly64x2x4_t { transmute(vld4q_s64(transmute(a))) } @@ -5726,45 +6229,49 @@ pub unsafe fn vld4q_p64(a: *const p64) -> poly64x2x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4_f64(a: *const f64) -> float64x1x4_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4.v1f64.p0v1f64")] fn vld4_f64_(ptr: *const float64x1_t) -> float64x1x4_t; } - vld4_f64_(a.cast()) + vld4_f64_(a as _) } /// Load multiple 4-element structures to four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld4))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_f64(a: *const f64) -> float64x2x4_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4.v2f64.p0v2f64")] fn vld4q_f64_(ptr: *const float64x2_t) -> float64x2x4_t; } - vld4q_f64_(a.cast()) + vld4q_f64_(a as _) } /// Load single 4-element structure and replicate to all lanes of four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld4r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_dup_s64(a: *const i64) -> int64x2x4_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4r.v2i64.p0i64")] fn vld4q_dup_s64_(ptr: *const i64) -> int64x2x4_t; } - vld4q_dup_s64_(a.cast()) + vld4q_dup_s64_(a as _) } /// Load single 4-element structure and replicate to all lanes of four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld4r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_dup_u64(a: *const u64) -> uint64x2x4_t { transmute(vld4q_dup_s64(transmute(a))) } @@ -5773,6 +6280,7 @@ pub unsafe fn vld4q_dup_u64(a: *const u64) -> uint64x2x4_t { #[inline] #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(ld4r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_dup_p64(a: *const p64) -> poly64x2x4_t { transmute(vld4q_dup_s64(transmute(a))) } @@ -5781,26 +6289,28 @@ pub unsafe fn vld4q_dup_p64(a: *const p64) -> poly64x2x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld4r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4_dup_f64(a: *const f64) -> float64x1x4_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4r.v1f64.p0f64")] fn vld4_dup_f64_(ptr: *const f64) -> float64x1x4_t; } - vld4_dup_f64_(a.cast()) + vld4_dup_f64_(a as _) } /// Load single 4-element structure and replicate to all lanes of four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld4r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_dup_f64(a: *const f64) -> float64x2x4_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4r.v2f64.p0f64")] fn vld4q_dup_f64_(ptr: *const f64) -> float64x2x4_t; } - vld4q_dup_f64_(a.cast()) + vld4q_dup_f64_(a as _) } /// Load multiple 4-element structures to four registers @@ -5808,6 +6318,7 @@ pub unsafe fn vld4q_dup_f64(a: *const f64) -> float64x2x4_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_lane_s8(a: *const i8, b: int8x16x4_t) -> int8x16x4_t { static_assert_imm4!(LANE); #[allow(improper_ctypes)] @@ -5815,7 +6326,7 @@ pub unsafe fn vld4q_lane_s8(a: *const i8, b: int8x16x4_t) -> in #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4lane.v16i8.p0i8")] fn vld4q_lane_s8_(a: int8x16_t, b: int8x16_t, c: int8x16_t, d: int8x16_t, n: i64, ptr: *const i8) -> int8x16x4_t; } - vld4q_lane_s8_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) + vld4q_lane_s8_(b.0, b.1, b.2, b.3, LANE as i64, a as _) } /// Load multiple 4-element structures to four registers @@ -5823,6 +6334,7 @@ pub unsafe fn vld4q_lane_s8(a: *const i8, b: int8x16x4_t) -> in #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4_lane_s64(a: *const i64, b: int64x1x4_t) -> int64x1x4_t { static_assert!(LANE : i32 where LANE == 0); #[allow(improper_ctypes)] @@ -5830,7 +6342,7 @@ pub unsafe fn vld4_lane_s64(a: *const i64, b: int64x1x4_t) -> i #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4lane.v1i64.p0i8")] fn vld4_lane_s64_(a: int64x1_t, b: int64x1_t, c: int64x1_t, d: int64x1_t, n: i64, ptr: *const i8) -> int64x1x4_t; } - vld4_lane_s64_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) + vld4_lane_s64_(b.0, b.1, b.2, b.3, LANE as i64, a as _) } /// Load multiple 4-element structures to four registers @@ -5838,6 +6350,7 @@ pub unsafe fn vld4_lane_s64(a: *const i64, b: int64x1x4_t) -> i #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_lane_s64(a: *const i64, b: int64x2x4_t) -> int64x2x4_t { static_assert_imm1!(LANE); #[allow(improper_ctypes)] @@ -5845,7 +6358,7 @@ pub unsafe fn vld4q_lane_s64(a: *const i64, b: int64x2x4_t) -> #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4lane.v2i64.p0i8")] fn vld4q_lane_s64_(a: int64x2_t, b: int64x2_t, c: int64x2_t, d: int64x2_t, n: i64, ptr: *const i8) -> int64x2x4_t; } - vld4q_lane_s64_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) + vld4q_lane_s64_(b.0, b.1, b.2, b.3, LANE as i64, a as _) } /// Load multiple 4-element structures to four registers @@ -5853,6 +6366,7 @@ pub unsafe fn vld4q_lane_s64(a: *const i64, b: int64x2x4_t) -> #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4_lane_p64(a: *const p64, b: poly64x1x4_t) -> poly64x1x4_t { static_assert!(LANE : i32 where LANE == 0); transmute(vld4_lane_s64::(transmute(a), transmute(b))) @@ -5863,6 +6377,7 @@ pub unsafe fn vld4_lane_p64(a: *const p64, b: poly64x1x4_t) -> #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_lane_p64(a: *const p64, b: poly64x2x4_t) -> poly64x2x4_t { static_assert_imm1!(LANE); transmute(vld4q_lane_s64::(transmute(a), transmute(b))) @@ -5873,6 +6388,7 @@ pub unsafe fn vld4q_lane_p64(a: *const p64, b: poly64x2x4_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_lane_p8(a: *const p8, b: poly8x16x4_t) -> poly8x16x4_t { static_assert_imm4!(LANE); transmute(vld4q_lane_s8::(transmute(a), transmute(b))) @@ -5883,6 +6399,7 @@ pub unsafe fn vld4q_lane_p8(a: *const p8, b: poly8x16x4_t) -> p #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_lane_u8(a: *const u8, b: uint8x16x4_t) -> uint8x16x4_t { static_assert_imm4!(LANE); transmute(vld4q_lane_s8::(transmute(a), transmute(b))) @@ -5893,6 +6410,7 @@ pub unsafe fn vld4q_lane_u8(a: *const u8, b: uint8x16x4_t) -> u #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4_lane_u64(a: *const u64, b: uint64x1x4_t) -> uint64x1x4_t { static_assert!(LANE : i32 where LANE == 0); transmute(vld4_lane_s64::(transmute(a), transmute(b))) @@ -5903,6 +6421,7 @@ pub unsafe fn vld4_lane_u64(a: *const u64, b: uint64x1x4_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_lane_u64(a: *const u64, b: uint64x2x4_t) -> uint64x2x4_t { static_assert_imm1!(LANE); transmute(vld4q_lane_s64::(transmute(a), transmute(b))) @@ -5913,6 +6432,7 @@ pub unsafe fn vld4q_lane_u64(a: *const u64, b: uint64x2x4_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4_lane_f64(a: *const f64, b: float64x1x4_t) -> float64x1x4_t { static_assert!(LANE : i32 where LANE == 0); #[allow(improper_ctypes)] @@ -5920,7 +6440,7 @@ pub unsafe fn vld4_lane_f64(a: *const f64, b: float64x1x4_t) -> #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4lane.v1f64.p0i8")] fn vld4_lane_f64_(a: float64x1_t, b: float64x1_t, c: float64x1_t, d: float64x1_t, n: i64, ptr: *const i8) -> float64x1x4_t; } - vld4_lane_f64_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) + vld4_lane_f64_(b.0, b.1, b.2, b.3, LANE as i64, a as _) } /// Load multiple 4-element structures to four registers @@ -5928,6 +6448,7 @@ pub unsafe fn vld4_lane_f64(a: *const f64, b: float64x1x4_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_lane_f64(a: *const f64, b: float64x2x4_t) -> float64x2x4_t { static_assert_imm1!(LANE); #[allow(improper_ctypes)] @@ -5935,7 +6456,7 @@ pub unsafe fn vld4q_lane_f64(a: *const f64, b: float64x2x4_t) - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4lane.v2f64.p0i8")] fn vld4q_lane_f64_(a: float64x2_t, b: float64x2_t, c: float64x2_t, d: float64x2_t, n: i64, ptr: *const i8) -> float64x2x4_t; } - vld4q_lane_f64_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) + vld4q_lane_f64_(b.0, b.1, b.2, b.3, LANE as i64, a as _) } /// Store multiple single-element structures from one, two, three, or four registers @@ -5943,6 +6464,7 @@ pub unsafe fn vld4q_lane_f64(a: *const f64, b: float64x2x4_t) - #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_lane_f64(a: *mut f64, b: float64x1_t) { static_assert!(LANE : i32 where LANE == 0); *a = simd_extract(b, LANE as u32); @@ -5953,6 +6475,7 @@ pub unsafe fn vst1_lane_f64(a: *mut f64, b: float64x1_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_lane_f64(a: *mut f64, b: float64x2_t) { static_assert_imm1!(LANE); *a = simd_extract(b, LANE as u32); @@ -5962,6 +6485,7 @@ pub unsafe fn vst1q_lane_f64(a: *mut f64, b: float64x2_t) { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_f64_x2(a: *mut f64, b: float64x1x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5975,6 +6499,7 @@ pub unsafe fn vst1_f64_x2(a: *mut f64, b: float64x1x2_t) { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_f64_x2(a: *mut f64, b: float64x2x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5988,6 +6513,7 @@ pub unsafe fn vst1q_f64_x2(a: *mut f64, b: float64x2x2_t) { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_f64_x3(a: *mut f64, b: float64x1x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6001,6 +6527,7 @@ pub unsafe fn vst1_f64_x3(a: *mut f64, b: float64x1x3_t) { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_f64_x3(a: *mut f64, b: float64x2x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6014,6 +6541,7 @@ pub unsafe fn vst1q_f64_x3(a: *mut f64, b: float64x2x3_t) { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_f64_x4(a: *mut f64, b: float64x1x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6027,6 +6555,7 @@ pub unsafe fn vst1_f64_x4(a: *mut f64, b: float64x1x4_t) { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_f64_x4(a: *mut f64, b: float64x2x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6040,19 +6569,21 @@ pub unsafe fn vst1q_f64_x4(a: *mut f64, b: float64x2x4_t) { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2q_s64(a: *mut i64, b: int64x2x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2.v2i64.p0i8")] fn vst2q_s64_(a: int64x2_t, b: int64x2_t, ptr: *mut i8); } - vst2q_s64_(b.0, b.1, a.cast()) + vst2q_s64_(b.0, b.1, a as _) } /// Store multiple 2-element structures from two registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2q_u64(a: *mut u64, b: uint64x2x2_t) { transmute(vst2q_s64(transmute(a), transmute(b))) } @@ -6061,6 +6592,7 @@ pub unsafe fn vst2q_u64(a: *mut u64, b: uint64x2x2_t) { #[inline] #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(st2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2q_p64(a: *mut p64, b: poly64x2x2_t) { transmute(vst2q_s64(transmute(a), transmute(b))) } @@ -6069,26 +6601,28 @@ pub unsafe fn vst2q_p64(a: *mut p64, b: poly64x2x2_t) { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2_f64(a: *mut f64, b: float64x1x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2.v1f64.p0i8")] fn vst2_f64_(a: float64x1_t, b: float64x1_t, ptr: *mut i8); } - vst2_f64_(b.0, b.1, a.cast()) + vst2_f64_(b.0, b.1, a as _) } /// Store multiple 2-element structures from two registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2q_f64(a: *mut f64, b: float64x2x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2.v2f64.p0i8")] fn vst2q_f64_(a: float64x2_t, b: float64x2_t, ptr: *mut i8); } - vst2q_f64_(b.0, b.1, a.cast()) + vst2q_f64_(b.0, b.1, a as _) } /// Store multiple 2-element structures from two registers @@ -6096,6 +6630,7 @@ pub unsafe fn vst2q_f64(a: *mut f64, b: float64x2x2_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2q_lane_s8(a: *mut i8, b: int8x16x2_t) { static_assert_imm4!(LANE); #[allow(improper_ctypes)] @@ -6103,7 +6638,7 @@ pub unsafe fn vst2q_lane_s8(a: *mut i8, b: int8x16x2_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2lane.v16i8.p0i8")] fn vst2q_lane_s8_(a: int8x16_t, b: int8x16_t, n: i64, ptr: *mut i8); } - vst2q_lane_s8_(b.0, b.1, LANE as i64, a.cast()) + vst2q_lane_s8_(b.0, b.1, LANE as i64, a as _) } /// Store multiple 2-element structures from two registers @@ -6111,6 +6646,7 @@ pub unsafe fn vst2q_lane_s8(a: *mut i8, b: int8x16x2_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2_lane_s64(a: *mut i64, b: int64x1x2_t) { static_assert!(LANE : i32 where LANE == 0); #[allow(improper_ctypes)] @@ -6118,7 +6654,7 @@ pub unsafe fn vst2_lane_s64(a: *mut i64, b: int64x1x2_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2lane.v1i64.p0i8")] fn vst2_lane_s64_(a: int64x1_t, b: int64x1_t, n: i64, ptr: *mut i8); } - vst2_lane_s64_(b.0, b.1, LANE as i64, a.cast()) + vst2_lane_s64_(b.0, b.1, LANE as i64, a as _) } /// Store multiple 2-element structures from two registers @@ -6126,6 +6662,7 @@ pub unsafe fn vst2_lane_s64(a: *mut i64, b: int64x1x2_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2q_lane_s64(a: *mut i64, b: int64x2x2_t) { static_assert_imm1!(LANE); #[allow(improper_ctypes)] @@ -6133,7 +6670,7 @@ pub unsafe fn vst2q_lane_s64(a: *mut i64, b: int64x2x2_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2lane.v2i64.p0i8")] fn vst2q_lane_s64_(a: int64x2_t, b: int64x2_t, n: i64, ptr: *mut i8); } - vst2q_lane_s64_(b.0, b.1, LANE as i64, a.cast()) + vst2q_lane_s64_(b.0, b.1, LANE as i64, a as _) } /// Store multiple 2-element structures from two registers @@ -6141,6 +6678,7 @@ pub unsafe fn vst2q_lane_s64(a: *mut i64, b: int64x2x2_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2q_lane_u8(a: *mut u8, b: uint8x16x2_t) { static_assert_imm4!(LANE); transmute(vst2q_lane_s8::(transmute(a), transmute(b))) @@ -6151,6 +6689,7 @@ pub unsafe fn vst2q_lane_u8(a: *mut u8, b: uint8x16x2_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2_lane_u64(a: *mut u64, b: uint64x1x2_t) { static_assert!(LANE : i32 where LANE == 0); transmute(vst2_lane_s64::(transmute(a), transmute(b))) @@ -6161,6 +6700,7 @@ pub unsafe fn vst2_lane_u64(a: *mut u64, b: uint64x1x2_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2q_lane_u64(a: *mut u64, b: uint64x2x2_t) { static_assert_imm1!(LANE); transmute(vst2q_lane_s64::(transmute(a), transmute(b))) @@ -6171,6 +6711,7 @@ pub unsafe fn vst2q_lane_u64(a: *mut u64, b: uint64x2x2_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2q_lane_p8(a: *mut p8, b: poly8x16x2_t) { static_assert_imm4!(LANE); transmute(vst2q_lane_s8::(transmute(a), transmute(b))) @@ -6181,6 +6722,7 @@ pub unsafe fn vst2q_lane_p8(a: *mut p8, b: poly8x16x2_t) { #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2_lane_p64(a: *mut p64, b: poly64x1x2_t) { static_assert!(LANE : i32 where LANE == 0); transmute(vst2_lane_s64::(transmute(a), transmute(b))) @@ -6191,6 +6733,7 @@ pub unsafe fn vst2_lane_p64(a: *mut p64, b: poly64x1x2_t) { #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2q_lane_p64(a: *mut p64, b: poly64x2x2_t) { static_assert_imm1!(LANE); transmute(vst2q_lane_s64::(transmute(a), transmute(b))) @@ -6201,6 +6744,7 @@ pub unsafe fn vst2q_lane_p64(a: *mut p64, b: poly64x2x2_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2_lane_f64(a: *mut f64, b: float64x1x2_t) { static_assert!(LANE : i32 where LANE == 0); #[allow(improper_ctypes)] @@ -6208,7 +6752,7 @@ pub unsafe fn vst2_lane_f64(a: *mut f64, b: float64x1x2_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2lane.v1f64.p0i8")] fn vst2_lane_f64_(a: float64x1_t, b: float64x1_t, n: i64, ptr: *mut i8); } - vst2_lane_f64_(b.0, b.1, LANE as i64, a.cast()) + vst2_lane_f64_(b.0, b.1, LANE as i64, a as _) } /// Store multiple 2-element structures from two registers @@ -6216,6 +6760,7 @@ pub unsafe fn vst2_lane_f64(a: *mut f64, b: float64x1x2_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2q_lane_f64(a: *mut f64, b: float64x2x2_t) { static_assert_imm1!(LANE); #[allow(improper_ctypes)] @@ -6223,26 +6768,28 @@ pub unsafe fn vst2q_lane_f64(a: *mut f64, b: float64x2x2_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2lane.v2f64.p0i8")] fn vst2q_lane_f64_(a: float64x2_t, b: float64x2_t, n: i64, ptr: *mut i8); } - vst2q_lane_f64_(b.0, b.1, LANE as i64, a.cast()) + vst2q_lane_f64_(b.0, b.1, LANE as i64, a as _) } /// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st3))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3q_s64(a: *mut i64, b: int64x2x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3.v2i64.p0i8")] fn vst3q_s64_(a: int64x2_t, b: int64x2_t, c: int64x2_t, ptr: *mut i8); } - vst3q_s64_(b.0, b.1, b.2, a.cast()) + vst3q_s64_(b.0, b.1, b.2, a as _) } /// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st3))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3q_u64(a: *mut u64, b: uint64x2x3_t) { transmute(vst3q_s64(transmute(a), transmute(b))) } @@ -6251,6 +6798,7 @@ pub unsafe fn vst3q_u64(a: *mut u64, b: uint64x2x3_t) { #[inline] #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(st3))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3q_p64(a: *mut p64, b: poly64x2x3_t) { transmute(vst3q_s64(transmute(a), transmute(b))) } @@ -6259,26 +6807,28 @@ pub unsafe fn vst3q_p64(a: *mut p64, b: poly64x2x3_t) { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3_f64(a: *mut f64, b: float64x1x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3.v1f64.p0i8")] fn vst3_f64_(a: float64x1_t, b: float64x1_t, c: float64x1_t, ptr: *mut i8); } - vst3_f64_(b.0, b.1, b.2, a.cast()) + vst3_f64_(b.0, b.1, b.2, a as _) } /// Store multiple 3-element structures from three registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st3))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3q_f64(a: *mut f64, b: float64x2x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3.v2f64.p0i8")] fn vst3q_f64_(a: float64x2_t, b: float64x2_t, c: float64x2_t, ptr: *mut i8); } - vst3q_f64_(b.0, b.1, b.2, a.cast()) + vst3q_f64_(b.0, b.1, b.2, a as _) } /// Store multiple 3-element structures from three registers @@ -6286,6 +6836,7 @@ pub unsafe fn vst3q_f64(a: *mut f64, b: float64x2x3_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3q_lane_s8(a: *mut i8, b: int8x16x3_t) { static_assert_imm4!(LANE); #[allow(improper_ctypes)] @@ -6293,7 +6844,7 @@ pub unsafe fn vst3q_lane_s8(a: *mut i8, b: int8x16x3_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3lane.v16i8.p0i8")] fn vst3q_lane_s8_(a: int8x16_t, b: int8x16_t, c: int8x16_t, n: i64, ptr: *mut i8); } - vst3q_lane_s8_(b.0, b.1, b.2, LANE as i64, a.cast()) + vst3q_lane_s8_(b.0, b.1, b.2, LANE as i64, a as _) } /// Store multiple 3-element structures from three registers @@ -6301,6 +6852,7 @@ pub unsafe fn vst3q_lane_s8(a: *mut i8, b: int8x16x3_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3_lane_s64(a: *mut i64, b: int64x1x3_t) { static_assert!(LANE : i32 where LANE == 0); #[allow(improper_ctypes)] @@ -6308,7 +6860,7 @@ pub unsafe fn vst3_lane_s64(a: *mut i64, b: int64x1x3_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3lane.v1i64.p0i8")] fn vst3_lane_s64_(a: int64x1_t, b: int64x1_t, c: int64x1_t, n: i64, ptr: *mut i8); } - vst3_lane_s64_(b.0, b.1, b.2, LANE as i64, a.cast()) + vst3_lane_s64_(b.0, b.1, b.2, LANE as i64, a as _) } /// Store multiple 3-element structures from three registers @@ -6316,6 +6868,7 @@ pub unsafe fn vst3_lane_s64(a: *mut i64, b: int64x1x3_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3q_lane_s64(a: *mut i64, b: int64x2x3_t) { static_assert_imm1!(LANE); #[allow(improper_ctypes)] @@ -6323,7 +6876,7 @@ pub unsafe fn vst3q_lane_s64(a: *mut i64, b: int64x2x3_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3lane.v2i64.p0i8")] fn vst3q_lane_s64_(a: int64x2_t, b: int64x2_t, c: int64x2_t, n: i64, ptr: *mut i8); } - vst3q_lane_s64_(b.0, b.1, b.2, LANE as i64, a.cast()) + vst3q_lane_s64_(b.0, b.1, b.2, LANE as i64, a as _) } /// Store multiple 3-element structures from three registers @@ -6331,6 +6884,7 @@ pub unsafe fn vst3q_lane_s64(a: *mut i64, b: int64x2x3_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3q_lane_u8(a: *mut u8, b: uint8x16x3_t) { static_assert_imm4!(LANE); transmute(vst3q_lane_s8::(transmute(a), transmute(b))) @@ -6341,6 +6895,7 @@ pub unsafe fn vst3q_lane_u8(a: *mut u8, b: uint8x16x3_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3_lane_u64(a: *mut u64, b: uint64x1x3_t) { static_assert!(LANE : i32 where LANE == 0); transmute(vst3_lane_s64::(transmute(a), transmute(b))) @@ -6351,6 +6906,7 @@ pub unsafe fn vst3_lane_u64(a: *mut u64, b: uint64x1x3_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3q_lane_u64(a: *mut u64, b: uint64x2x3_t) { static_assert_imm1!(LANE); transmute(vst3q_lane_s64::(transmute(a), transmute(b))) @@ -6361,6 +6917,7 @@ pub unsafe fn vst3q_lane_u64(a: *mut u64, b: uint64x2x3_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3q_lane_p8(a: *mut p8, b: poly8x16x3_t) { static_assert_imm4!(LANE); transmute(vst3q_lane_s8::(transmute(a), transmute(b))) @@ -6371,6 +6928,7 @@ pub unsafe fn vst3q_lane_p8(a: *mut p8, b: poly8x16x3_t) { #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3_lane_p64(a: *mut p64, b: poly64x1x3_t) { static_assert!(LANE : i32 where LANE == 0); transmute(vst3_lane_s64::(transmute(a), transmute(b))) @@ -6381,6 +6939,7 @@ pub unsafe fn vst3_lane_p64(a: *mut p64, b: poly64x1x3_t) { #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3q_lane_p64(a: *mut p64, b: poly64x2x3_t) { static_assert_imm1!(LANE); transmute(vst3q_lane_s64::(transmute(a), transmute(b))) @@ -6391,6 +6950,7 @@ pub unsafe fn vst3q_lane_p64(a: *mut p64, b: poly64x2x3_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3_lane_f64(a: *mut f64, b: float64x1x3_t) { static_assert!(LANE : i32 where LANE == 0); #[allow(improper_ctypes)] @@ -6398,7 +6958,7 @@ pub unsafe fn vst3_lane_f64(a: *mut f64, b: float64x1x3_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3lane.v1f64.p0i8")] fn vst3_lane_f64_(a: float64x1_t, b: float64x1_t, c: float64x1_t, n: i64, ptr: *mut i8); } - vst3_lane_f64_(b.0, b.1, b.2, LANE as i64, a.cast()) + vst3_lane_f64_(b.0, b.1, b.2, LANE as i64, a as _) } /// Store multiple 3-element structures from three registers @@ -6406,6 +6966,7 @@ pub unsafe fn vst3_lane_f64(a: *mut f64, b: float64x1x3_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3q_lane_f64(a: *mut f64, b: float64x2x3_t) { static_assert_imm1!(LANE); #[allow(improper_ctypes)] @@ -6413,26 +6974,28 @@ pub unsafe fn vst3q_lane_f64(a: *mut f64, b: float64x2x3_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3lane.v2f64.p0i8")] fn vst3q_lane_f64_(a: float64x2_t, b: float64x2_t, c: float64x2_t, n: i64, ptr: *mut i8); } - vst3q_lane_f64_(b.0, b.1, b.2, LANE as i64, a.cast()) + vst3q_lane_f64_(b.0, b.1, b.2, LANE as i64, a as _) } /// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st4))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4q_s64(a: *mut i64, b: int64x2x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4.v2i64.p0i8")] fn vst4q_s64_(a: int64x2_t, b: int64x2_t, c: int64x2_t, d: int64x2_t, ptr: *mut i8); } - vst4q_s64_(b.0, b.1, b.2, b.3, a.cast()) + vst4q_s64_(b.0, b.1, b.2, b.3, a as _) } /// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st4))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4q_u64(a: *mut u64, b: uint64x2x4_t) { transmute(vst4q_s64(transmute(a), transmute(b))) } @@ -6441,6 +7004,7 @@ pub unsafe fn vst4q_u64(a: *mut u64, b: uint64x2x4_t) { #[inline] #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(st4))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4q_p64(a: *mut p64, b: poly64x2x4_t) { transmute(vst4q_s64(transmute(a), transmute(b))) } @@ -6449,26 +7013,28 @@ pub unsafe fn vst4q_p64(a: *mut p64, b: poly64x2x4_t) { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4_f64(a: *mut f64, b: float64x1x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4.v1f64.p0i8")] fn vst4_f64_(a: float64x1_t, b: float64x1_t, c: float64x1_t, d: float64x1_t, ptr: *mut i8); } - vst4_f64_(b.0, b.1, b.2, b.3, a.cast()) + vst4_f64_(b.0, b.1, b.2, b.3, a as _) } /// Store multiple 4-element structures from four registers #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st4))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4q_f64(a: *mut f64, b: float64x2x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4.v2f64.p0i8")] fn vst4q_f64_(a: float64x2_t, b: float64x2_t, c: float64x2_t, d: float64x2_t, ptr: *mut i8); } - vst4q_f64_(b.0, b.1, b.2, b.3, a.cast()) + vst4q_f64_(b.0, b.1, b.2, b.3, a as _) } /// Store multiple 4-element structures from four registers @@ -6476,6 +7042,7 @@ pub unsafe fn vst4q_f64(a: *mut f64, b: float64x2x4_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4q_lane_s8(a: *mut i8, b: int8x16x4_t) { static_assert_imm4!(LANE); #[allow(improper_ctypes)] @@ -6483,7 +7050,7 @@ pub unsafe fn vst4q_lane_s8(a: *mut i8, b: int8x16x4_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4lane.v16i8.p0i8")] fn vst4q_lane_s8_(a: int8x16_t, b: int8x16_t, c: int8x16_t, d: int8x16_t, n: i64, ptr: *mut i8); } - vst4q_lane_s8_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) + vst4q_lane_s8_(b.0, b.1, b.2, b.3, LANE as i64, a as _) } /// Store multiple 4-element structures from four registers @@ -6491,6 +7058,7 @@ pub unsafe fn vst4q_lane_s8(a: *mut i8, b: int8x16x4_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4_lane_s64(a: *mut i64, b: int64x1x4_t) { static_assert!(LANE : i32 where LANE == 0); #[allow(improper_ctypes)] @@ -6498,7 +7066,7 @@ pub unsafe fn vst4_lane_s64(a: *mut i64, b: int64x1x4_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4lane.v1i64.p0i8")] fn vst4_lane_s64_(a: int64x1_t, b: int64x1_t, c: int64x1_t, d: int64x1_t, n: i64, ptr: *mut i8); } - vst4_lane_s64_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) + vst4_lane_s64_(b.0, b.1, b.2, b.3, LANE as i64, a as _) } /// Store multiple 4-element structures from four registers @@ -6506,6 +7074,7 @@ pub unsafe fn vst4_lane_s64(a: *mut i64, b: int64x1x4_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4q_lane_s64(a: *mut i64, b: int64x2x4_t) { static_assert_imm1!(LANE); #[allow(improper_ctypes)] @@ -6513,7 +7082,7 @@ pub unsafe fn vst4q_lane_s64(a: *mut i64, b: int64x2x4_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4lane.v2i64.p0i8")] fn vst4q_lane_s64_(a: int64x2_t, b: int64x2_t, c: int64x2_t, d: int64x2_t, n: i64, ptr: *mut i8); } - vst4q_lane_s64_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) + vst4q_lane_s64_(b.0, b.1, b.2, b.3, LANE as i64, a as _) } /// Store multiple 4-element structures from four registers @@ -6521,6 +7090,7 @@ pub unsafe fn vst4q_lane_s64(a: *mut i64, b: int64x2x4_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4q_lane_u8(a: *mut u8, b: uint8x16x4_t) { static_assert_imm4!(LANE); transmute(vst4q_lane_s8::(transmute(a), transmute(b))) @@ -6531,6 +7101,7 @@ pub unsafe fn vst4q_lane_u8(a: *mut u8, b: uint8x16x4_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4_lane_u64(a: *mut u64, b: uint64x1x4_t) { static_assert!(LANE : i32 where LANE == 0); transmute(vst4_lane_s64::(transmute(a), transmute(b))) @@ -6541,6 +7112,7 @@ pub unsafe fn vst4_lane_u64(a: *mut u64, b: uint64x1x4_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4q_lane_u64(a: *mut u64, b: uint64x2x4_t) { static_assert_imm1!(LANE); transmute(vst4q_lane_s64::(transmute(a), transmute(b))) @@ -6551,6 +7123,7 @@ pub unsafe fn vst4q_lane_u64(a: *mut u64, b: uint64x2x4_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4q_lane_p8(a: *mut p8, b: poly8x16x4_t) { static_assert_imm4!(LANE); transmute(vst4q_lane_s8::(transmute(a), transmute(b))) @@ -6561,6 +7134,7 @@ pub unsafe fn vst4q_lane_p8(a: *mut p8, b: poly8x16x4_t) { #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4_lane_p64(a: *mut p64, b: poly64x1x4_t) { static_assert!(LANE : i32 where LANE == 0); transmute(vst4_lane_s64::(transmute(a), transmute(b))) @@ -6571,6 +7145,7 @@ pub unsafe fn vst4_lane_p64(a: *mut p64, b: poly64x1x4_t) { #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4q_lane_p64(a: *mut p64, b: poly64x2x4_t) { static_assert_imm1!(LANE); transmute(vst4q_lane_s64::(transmute(a), transmute(b))) @@ -6581,6 +7156,7 @@ pub unsafe fn vst4q_lane_p64(a: *mut p64, b: poly64x2x4_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4_lane_f64(a: *mut f64, b: float64x1x4_t) { static_assert!(LANE : i32 where LANE == 0); #[allow(improper_ctypes)] @@ -6588,7 +7164,7 @@ pub unsafe fn vst4_lane_f64(a: *mut f64, b: float64x1x4_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4lane.v1f64.p0i8")] fn vst4_lane_f64_(a: float64x1_t, b: float64x1_t, c: float64x1_t, d: float64x1_t, n: i64, ptr: *mut i8); } - vst4_lane_f64_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) + vst4_lane_f64_(b.0, b.1, b.2, b.3, LANE as i64, a as _) } /// Store multiple 4-element structures from four registers @@ -6596,6 +7172,7 @@ pub unsafe fn vst4_lane_f64(a: *mut f64, b: float64x1x4_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4q_lane_f64(a: *mut f64, b: float64x2x4_t) { static_assert_imm1!(LANE); #[allow(improper_ctypes)] @@ -6603,13 +7180,14 @@ pub unsafe fn vst4q_lane_f64(a: *mut f64, b: float64x2x4_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4lane.v2f64.p0i8")] fn vst4q_lane_f64_(a: float64x2_t, b: float64x2_t, c: float64x2_t, d: float64x2_t, n: i64, ptr: *mut i8); } - vst4q_lane_f64_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) + vst4q_lane_f64_(b.0, b.1, b.2, b.3, LANE as i64, a as _) } /// Multiply #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmul))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmul_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { simd_mul(a, b) } @@ -6618,6 +7196,7 @@ pub unsafe fn vmul_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmul))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmulq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { simd_mul(a, b) } @@ -6626,6 +7205,7 @@ pub unsafe fn vmulq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmul))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmul_n_f64(a: float64x1_t, b: f64) -> float64x1_t { simd_mul(a, vdup_n_f64(b)) } @@ -6634,6 +7214,7 @@ pub unsafe fn vmul_n_f64(a: float64x1_t, b: f64) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmul))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmulq_n_f64(a: float64x2_t, b: f64) -> float64x2_t { simd_mul(a, vdupq_n_f64(b)) } @@ -6643,6 +7224,7 @@ pub unsafe fn vmulq_n_f64(a: float64x2_t, b: f64) -> float64x2_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmul, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmul_lane_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { static_assert!(LANE : i32 where LANE == 0); simd_mul(a, transmute::(simd_extract(b, LANE as u32))) @@ -6653,6 +7235,7 @@ pub unsafe fn vmul_lane_f64(a: float64x1_t, b: float64x1_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmul, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmul_laneq_f64(a: float64x1_t, b: float64x2_t) -> float64x1_t { static_assert_imm1!(LANE); simd_mul(a, transmute::(simd_extract(b, LANE as u32))) @@ -6663,6 +7246,7 @@ pub unsafe fn vmul_laneq_f64(a: float64x1_t, b: float64x2_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmul, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmulq_lane_f64(a: float64x2_t, b: float64x1_t) -> float64x2_t { static_assert!(LANE : i32 where LANE == 0); simd_mul(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) @@ -6673,6 +7257,7 @@ pub unsafe fn vmulq_lane_f64(a: float64x2_t, b: float64x1_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmul, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmulq_laneq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { static_assert_imm1!(LANE); simd_mul(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) @@ -6683,6 +7268,7 @@ pub unsafe fn vmulq_laneq_f64(a: float64x2_t, b: float64x2_t) - #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmul, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmuls_lane_f32(a: f32, b: float32x2_t) -> f32 { static_assert_imm1!(LANE); let b: f32 = simd_extract(b, LANE as u32); @@ -6694,6 +7280,7 @@ pub unsafe fn vmuls_lane_f32(a: f32, b: float32x2_t) -> f32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmul, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmuls_laneq_f32(a: f32, b: float32x4_t) -> f32 { static_assert_imm2!(LANE); let b: f32 = simd_extract(b, LANE as u32); @@ -6705,6 +7292,7 @@ pub unsafe fn vmuls_laneq_f32(a: f32, b: float32x4_t) -> f32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmul, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmuld_lane_f64(a: f64, b: float64x1_t) -> f64 { static_assert!(LANE : i32 where LANE == 0); let b: f64 = simd_extract(b, LANE as u32); @@ -6716,6 +7304,7 @@ pub unsafe fn vmuld_lane_f64(a: f64, b: float64x1_t) -> f64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmul, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmuld_laneq_f64(a: f64, b: float64x2_t) -> f64 { static_assert_imm1!(LANE); let b: f64 = simd_extract(b, LANE as u32); @@ -6726,6 +7315,7 @@ pub unsafe fn vmuld_laneq_f64(a: f64, b: float64x2_t) -> f64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smull2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmull_high_s8(a: int8x16_t, b: int8x16_t) -> int16x8_t { let a: int8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); let b: int8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); @@ -6736,6 +7326,7 @@ pub unsafe fn vmull_high_s8(a: int8x16_t, b: int8x16_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smull2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmull_high_s16(a: int16x8_t, b: int16x8_t) -> int32x4_t { let a: int16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); let b: int16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); @@ -6746,6 +7337,7 @@ pub unsafe fn vmull_high_s16(a: int16x8_t, b: int16x8_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smull2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmull_high_s32(a: int32x4_t, b: int32x4_t) -> int64x2_t { let a: int32x2_t = simd_shuffle2!(a, a, [2, 3]); let b: int32x2_t = simd_shuffle2!(b, b, [2, 3]); @@ -6756,6 +7348,7 @@ pub unsafe fn vmull_high_s32(a: int32x4_t, b: int32x4_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umull2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmull_high_u8(a: uint8x16_t, b: uint8x16_t) -> uint16x8_t { let a: uint8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); let b: uint8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); @@ -6766,6 +7359,7 @@ pub unsafe fn vmull_high_u8(a: uint8x16_t, b: uint8x16_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umull2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmull_high_u16(a: uint16x8_t, b: uint16x8_t) -> uint32x4_t { let a: uint16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); let b: uint16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); @@ -6776,6 +7370,7 @@ pub unsafe fn vmull_high_u16(a: uint16x8_t, b: uint16x8_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umull2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmull_high_u32(a: uint32x4_t, b: uint32x4_t) -> uint64x2_t { let a: uint32x2_t = simd_shuffle2!(a, a, [2, 3]); let b: uint32x2_t = simd_shuffle2!(b, b, [2, 3]); @@ -6786,6 +7381,7 @@ pub unsafe fn vmull_high_u32(a: uint32x4_t, b: uint32x4_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(pmull))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmull_p64(a: p64, b: p64) -> p128 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6799,6 +7395,7 @@ pub unsafe fn vmull_p64(a: p64, b: p64) -> p128 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(pmull))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmull_high_p8(a: poly8x16_t, b: poly8x16_t) -> poly16x8_t { let a: poly8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); let b: poly8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); @@ -6809,6 +7406,7 @@ pub unsafe fn vmull_high_p8(a: poly8x16_t, b: poly8x16_t) -> poly16x8_t { #[inline] #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(pmull))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmull_high_p64(a: poly64x2_t, b: poly64x2_t) -> p128 { vmull_p64(simd_extract(a, 1), simd_extract(b, 1)) } @@ -6817,6 +7415,7 @@ pub unsafe fn vmull_high_p64(a: poly64x2_t, b: poly64x2_t) -> p128 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smull2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmull_high_n_s16(a: int16x8_t, b: i16) -> int32x4_t { vmull_high_s16(a, vdupq_n_s16(b)) } @@ -6825,6 +7424,7 @@ pub unsafe fn vmull_high_n_s16(a: int16x8_t, b: i16) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smull2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmull_high_n_s32(a: int32x4_t, b: i32) -> int64x2_t { vmull_high_s32(a, vdupq_n_s32(b)) } @@ -6833,6 +7433,7 @@ pub unsafe fn vmull_high_n_s32(a: int32x4_t, b: i32) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umull2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmull_high_n_u16(a: uint16x8_t, b: u16) -> uint32x4_t { vmull_high_u16(a, vdupq_n_u16(b)) } @@ -6841,6 +7442,7 @@ pub unsafe fn vmull_high_n_u16(a: uint16x8_t, b: u16) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umull2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmull_high_n_u32(a: uint32x4_t, b: u32) -> uint64x2_t { vmull_high_u32(a, vdupq_n_u32(b)) } @@ -6850,6 +7452,7 @@ pub unsafe fn vmull_high_n_u32(a: uint32x4_t, b: u32) -> uint64x2_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smull2, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmull_high_lane_s16(a: int16x8_t, b: int16x4_t) -> int32x4_t { static_assert_imm2!(LANE); vmull_high_s16(a, simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -6860,6 +7463,7 @@ pub unsafe fn vmull_high_lane_s16(a: int16x8_t, b: int16x4_t) - #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smull2, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmull_high_laneq_s16(a: int16x8_t, b: int16x8_t) -> int32x4_t { static_assert_imm3!(LANE); vmull_high_s16(a, simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -6870,6 +7474,7 @@ pub unsafe fn vmull_high_laneq_s16(a: int16x8_t, b: int16x8_t) #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smull2, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmull_high_lane_s32(a: int32x4_t, b: int32x2_t) -> int64x2_t { static_assert_imm1!(LANE); vmull_high_s32(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -6880,6 +7485,7 @@ pub unsafe fn vmull_high_lane_s32(a: int32x4_t, b: int32x2_t) - #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smull2, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmull_high_laneq_s32(a: int32x4_t, b: int32x4_t) -> int64x2_t { static_assert_imm2!(LANE); vmull_high_s32(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -6890,6 +7496,7 @@ pub unsafe fn vmull_high_laneq_s32(a: int32x4_t, b: int32x4_t) #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umull2, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmull_high_lane_u16(a: uint16x8_t, b: uint16x4_t) -> uint32x4_t { static_assert_imm2!(LANE); vmull_high_u16(a, simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -6900,6 +7507,7 @@ pub unsafe fn vmull_high_lane_u16(a: uint16x8_t, b: uint16x4_t) #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umull2, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmull_high_laneq_u16(a: uint16x8_t, b: uint16x8_t) -> uint32x4_t { static_assert_imm3!(LANE); vmull_high_u16(a, simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -6910,6 +7518,7 @@ pub unsafe fn vmull_high_laneq_u16(a: uint16x8_t, b: uint16x8_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umull2, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmull_high_lane_u32(a: uint32x4_t, b: uint32x2_t) -> uint64x2_t { static_assert_imm1!(LANE); vmull_high_u32(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -6920,6 +7529,7 @@ pub unsafe fn vmull_high_lane_u32(a: uint32x4_t, b: uint32x2_t) #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umull2, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmull_high_laneq_u32(a: uint32x4_t, b: uint32x4_t) -> uint64x2_t { static_assert_imm2!(LANE); vmull_high_u32(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -6929,6 +7539,7 @@ pub unsafe fn vmull_high_laneq_u32(a: uint32x4_t, b: uint32x4_t #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmulx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmulx_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6942,6 +7553,7 @@ pub unsafe fn vmulx_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmulx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmulxq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6955,6 +7567,7 @@ pub unsafe fn vmulxq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmulx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmulx_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6968,6 +7581,7 @@ pub unsafe fn vmulx_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmulx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmulxq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6982,6 +7596,7 @@ pub unsafe fn vmulxq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmulx, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmulx_lane_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { static_assert!(LANE : i32 where LANE == 0); vmulx_f64(a, transmute::(simd_extract(b, LANE as u32))) @@ -6992,6 +7607,7 @@ pub unsafe fn vmulx_lane_f64(a: float64x1_t, b: float64x1_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmulx, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmulx_laneq_f64(a: float64x1_t, b: float64x2_t) -> float64x1_t { static_assert_imm1!(LANE); vmulx_f64(a, transmute::(simd_extract(b, LANE as u32))) @@ -7002,6 +7618,7 @@ pub unsafe fn vmulx_laneq_f64(a: float64x1_t, b: float64x2_t) - #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmulx, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmulx_lane_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { static_assert_imm1!(LANE); vmulx_f32(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) @@ -7012,6 +7629,7 @@ pub unsafe fn vmulx_lane_f32(a: float32x2_t, b: float32x2_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmulx, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmulx_laneq_f32(a: float32x2_t, b: float32x4_t) -> float32x2_t { static_assert_imm2!(LANE); vmulx_f32(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) @@ -7022,6 +7640,7 @@ pub unsafe fn vmulx_laneq_f32(a: float32x2_t, b: float32x4_t) - #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmulx, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmulxq_lane_f32(a: float32x4_t, b: float32x2_t) -> float32x4_t { static_assert_imm1!(LANE); vmulxq_f32(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -7032,6 +7651,7 @@ pub unsafe fn vmulxq_lane_f32(a: float32x4_t, b: float32x2_t) - #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmulx, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmulxq_laneq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { static_assert_imm2!(LANE); vmulxq_f32(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -7042,6 +7662,7 @@ pub unsafe fn vmulxq_laneq_f32(a: float32x4_t, b: float32x4_t) #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmulx, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmulxq_lane_f64(a: float64x2_t, b: float64x1_t) -> float64x2_t { static_assert!(LANE : i32 where LANE == 0); vmulxq_f64(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) @@ -7052,6 +7673,7 @@ pub unsafe fn vmulxq_lane_f64(a: float64x2_t, b: float64x1_t) - #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmulx, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmulxq_laneq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { static_assert_imm1!(LANE); vmulxq_f64(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) @@ -7061,6 +7683,7 @@ pub unsafe fn vmulxq_laneq_f64(a: float64x2_t, b: float64x2_t) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmulx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmulxs_f32(a: f32, b: f32) -> f32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7074,6 +7697,7 @@ pub unsafe fn vmulxs_f32(a: f32, b: f32) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmulx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmulxd_f64(a: f64, b: f64) -> f64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7088,6 +7712,7 @@ pub unsafe fn vmulxd_f64(a: f64, b: f64) -> f64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmulx, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmulxs_lane_f32(a: f32, b: float32x2_t) -> f32 { static_assert_imm1!(LANE); vmulxs_f32(a, simd_extract(b, LANE as u32)) @@ -7098,6 +7723,7 @@ pub unsafe fn vmulxs_lane_f32(a: f32, b: float32x2_t) -> f32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmulx, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmulxs_laneq_f32(a: f32, b: float32x4_t) -> f32 { static_assert_imm2!(LANE); vmulxs_f32(a, simd_extract(b, LANE as u32)) @@ -7108,6 +7734,7 @@ pub unsafe fn vmulxs_laneq_f32(a: f32, b: float32x4_t) -> f32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmulx, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmulxd_lane_f64(a: f64, b: float64x1_t) -> f64 { static_assert!(LANE : i32 where LANE == 0); vmulxd_f64(a, simd_extract(b, LANE as u32)) @@ -7118,6 +7745,7 @@ pub unsafe fn vmulxd_lane_f64(a: f64, b: float64x1_t) -> f64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmulx, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmulxd_laneq_f64(a: f64, b: float64x2_t) -> f64 { static_assert_imm1!(LANE); vmulxd_f64(a, simd_extract(b, LANE as u32)) @@ -7127,6 +7755,7 @@ pub unsafe fn vmulxd_laneq_f64(a: f64, b: float64x2_t) -> f64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfma_f64(a: float64x1_t, b: float64x1_t, c: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7140,6 +7769,7 @@ pub unsafe fn vfma_f64(a: float64x1_t, b: float64x1_t, c: float64x1_t) -> float6 #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmla))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfmaq_f64(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7153,6 +7783,7 @@ pub unsafe fn vfmaq_f64(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfma_n_f64(a: float64x1_t, b: float64x1_t, c: f64) -> float64x1_t { vfma_f64(a, b, vdup_n_f64(c)) } @@ -7161,6 +7792,7 @@ pub unsafe fn vfma_n_f64(a: float64x1_t, b: float64x1_t, c: f64) -> float64x1_t #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmla))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfmaq_n_f64(a: float64x2_t, b: float64x2_t, c: f64) -> float64x2_t { vfmaq_f64(a, b, vdupq_n_f64(c)) } @@ -7170,6 +7802,7 @@ pub unsafe fn vfmaq_n_f64(a: float64x2_t, b: float64x2_t, c: f64) -> float64x2_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmla, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfma_lane_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t { static_assert_imm1!(LANE); vfma_f32(a, b, vdup_n_f32(simd_extract(c, LANE as u32))) @@ -7180,6 +7813,7 @@ pub unsafe fn vfma_lane_f32(a: float32x2_t, b: float32x2_t, c: #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmla, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfma_laneq_f32(a: float32x2_t, b: float32x2_t, c: float32x4_t) -> float32x2_t { static_assert_imm2!(LANE); vfma_f32(a, b, vdup_n_f32(simd_extract(c, LANE as u32))) @@ -7190,6 +7824,7 @@ pub unsafe fn vfma_laneq_f32(a: float32x2_t, b: float32x2_t, c: #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmla, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfmaq_lane_f32(a: float32x4_t, b: float32x4_t, c: float32x2_t) -> float32x4_t { static_assert_imm1!(LANE); vfmaq_f32(a, b, vdupq_n_f32(simd_extract(c, LANE as u32))) @@ -7200,6 +7835,7 @@ pub unsafe fn vfmaq_lane_f32(a: float32x4_t, b: float32x4_t, c: #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmla, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfmaq_laneq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t { static_assert_imm2!(LANE); vfmaq_f32(a, b, vdupq_n_f32(simd_extract(c, LANE as u32))) @@ -7210,6 +7846,7 @@ pub unsafe fn vfmaq_laneq_f32(a: float32x4_t, b: float32x4_t, c #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmadd, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfma_lane_f64(a: float64x1_t, b: float64x1_t, c: float64x1_t) -> float64x1_t { static_assert!(LANE : i32 where LANE == 0); vfma_f64(a, b, vdup_n_f64(simd_extract(c, LANE as u32))) @@ -7220,6 +7857,7 @@ pub unsafe fn vfma_lane_f64(a: float64x1_t, b: float64x1_t, c: #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmla, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfma_laneq_f64(a: float64x1_t, b: float64x1_t, c: float64x2_t) -> float64x1_t { static_assert_imm1!(LANE); vfma_f64(a, b, vdup_n_f64(simd_extract(c, LANE as u32))) @@ -7230,6 +7868,7 @@ pub unsafe fn vfma_laneq_f64(a: float64x1_t, b: float64x1_t, c: #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmla, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfmaq_lane_f64(a: float64x2_t, b: float64x2_t, c: float64x1_t) -> float64x2_t { static_assert!(LANE : i32 where LANE == 0); vfmaq_f64(a, b, vdupq_n_f64(simd_extract(c, LANE as u32))) @@ -7240,6 +7879,7 @@ pub unsafe fn vfmaq_lane_f64(a: float64x2_t, b: float64x2_t, c: #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmla, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfmaq_laneq_f64(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float64x2_t { static_assert_imm1!(LANE); vfmaq_f64(a, b, vdupq_n_f64(simd_extract(c, LANE as u32))) @@ -7250,6 +7890,7 @@ pub unsafe fn vfmaq_laneq_f64(a: float64x2_t, b: float64x2_t, c #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmla, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfmas_lane_f32(a: f32, b: f32, c: float32x2_t) -> f32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7266,6 +7907,7 @@ pub unsafe fn vfmas_lane_f32(a: f32, b: f32, c: float32x2_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmla, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfmas_laneq_f32(a: f32, b: f32, c: float32x4_t) -> f32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7282,6 +7924,7 @@ pub unsafe fn vfmas_laneq_f32(a: f32, b: f32, c: float32x4_t) - #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmadd, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfmad_lane_f64(a: f64, b: f64, c: float64x1_t) -> f64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7298,6 +7941,7 @@ pub unsafe fn vfmad_lane_f64(a: f64, b: f64, c: float64x1_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmla, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfmad_laneq_f64(a: f64, b: f64, c: float64x2_t) -> f64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7313,6 +7957,7 @@ pub unsafe fn vfmad_laneq_f64(a: f64, b: f64, c: float64x2_t) - #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmsub))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfms_f64(a: float64x1_t, b: float64x1_t, c: float64x1_t) -> float64x1_t { let b: float64x1_t = simd_neg(b); vfma_f64(a, b, c) @@ -7322,6 +7967,7 @@ pub unsafe fn vfms_f64(a: float64x1_t, b: float64x1_t, c: float64x1_t) -> float6 #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmls))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfmsq_f64(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float64x2_t { let b: float64x2_t = simd_neg(b); vfmaq_f64(a, b, c) @@ -7331,6 +7977,7 @@ pub unsafe fn vfmsq_f64(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmsub))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfms_n_f64(a: float64x1_t, b: float64x1_t, c: f64) -> float64x1_t { vfms_f64(a, b, vdup_n_f64(c)) } @@ -7339,6 +7986,7 @@ pub unsafe fn vfms_n_f64(a: float64x1_t, b: float64x1_t, c: f64) -> float64x1_t #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmls))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfmsq_n_f64(a: float64x2_t, b: float64x2_t, c: f64) -> float64x2_t { vfmsq_f64(a, b, vdupq_n_f64(c)) } @@ -7348,6 +7996,7 @@ pub unsafe fn vfmsq_n_f64(a: float64x2_t, b: float64x2_t, c: f64) -> float64x2_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmls, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfms_lane_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t { static_assert_imm1!(LANE); vfms_f32(a, b, vdup_n_f32(simd_extract(c, LANE as u32))) @@ -7358,6 +8007,7 @@ pub unsafe fn vfms_lane_f32(a: float32x2_t, b: float32x2_t, c: #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmls, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfms_laneq_f32(a: float32x2_t, b: float32x2_t, c: float32x4_t) -> float32x2_t { static_assert_imm2!(LANE); vfms_f32(a, b, vdup_n_f32(simd_extract(c, LANE as u32))) @@ -7368,6 +8018,7 @@ pub unsafe fn vfms_laneq_f32(a: float32x2_t, b: float32x2_t, c: #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmls, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfmsq_lane_f32(a: float32x4_t, b: float32x4_t, c: float32x2_t) -> float32x4_t { static_assert_imm1!(LANE); vfmsq_f32(a, b, vdupq_n_f32(simd_extract(c, LANE as u32))) @@ -7378,6 +8029,7 @@ pub unsafe fn vfmsq_lane_f32(a: float32x4_t, b: float32x4_t, c: #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmls, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfmsq_laneq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t { static_assert_imm2!(LANE); vfmsq_f32(a, b, vdupq_n_f32(simd_extract(c, LANE as u32))) @@ -7388,6 +8040,7 @@ pub unsafe fn vfmsq_laneq_f32(a: float32x4_t, b: float32x4_t, c #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmsub, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfms_lane_f64(a: float64x1_t, b: float64x1_t, c: float64x1_t) -> float64x1_t { static_assert!(LANE : i32 where LANE == 0); vfms_f64(a, b, vdup_n_f64(simd_extract(c, LANE as u32))) @@ -7398,6 +8051,7 @@ pub unsafe fn vfms_lane_f64(a: float64x1_t, b: float64x1_t, c: #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmls, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfms_laneq_f64(a: float64x1_t, b: float64x1_t, c: float64x2_t) -> float64x1_t { static_assert_imm1!(LANE); vfms_f64(a, b, vdup_n_f64(simd_extract(c, LANE as u32))) @@ -7408,6 +8062,7 @@ pub unsafe fn vfms_laneq_f64(a: float64x1_t, b: float64x1_t, c: #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmls, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfmsq_lane_f64(a: float64x2_t, b: float64x2_t, c: float64x1_t) -> float64x2_t { static_assert!(LANE : i32 where LANE == 0); vfmsq_f64(a, b, vdupq_n_f64(simd_extract(c, LANE as u32))) @@ -7418,6 +8073,7 @@ pub unsafe fn vfmsq_lane_f64(a: float64x2_t, b: float64x2_t, c: #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmls, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfmsq_laneq_f64(a: float64x2_t, b: float64x2_t, c: float64x2_t) -> float64x2_t { static_assert_imm1!(LANE); vfmsq_f64(a, b, vdupq_n_f64(simd_extract(c, LANE as u32))) @@ -7428,6 +8084,7 @@ pub unsafe fn vfmsq_laneq_f64(a: float64x2_t, b: float64x2_t, c #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmls, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfmss_lane_f32(a: f32, b: f32, c: float32x2_t) -> f32 { vfmas_lane_f32::(a, -b, c) } @@ -7437,6 +8094,7 @@ pub unsafe fn vfmss_lane_f32(a: f32, b: f32, c: float32x2_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmls, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfmss_laneq_f32(a: f32, b: f32, c: float32x4_t) -> f32 { vfmas_laneq_f32::(a, -b, c) } @@ -7446,6 +8104,7 @@ pub unsafe fn vfmss_laneq_f32(a: f32, b: f32, c: float32x4_t) - #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmsub, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfmsd_lane_f64(a: f64, b: f64, c: float64x1_t) -> f64 { vfmad_lane_f64::(a, -b, c) } @@ -7455,6 +8114,7 @@ pub unsafe fn vfmsd_lane_f64(a: f64, b: f64, c: float64x1_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmls, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vfmsd_laneq_f64(a: f64, b: f64, c: float64x2_t) -> f64 { vfmad_laneq_f64::(a, -b, c) } @@ -7463,6 +8123,7 @@ pub unsafe fn vfmsd_laneq_f64(a: f64, b: f64, c: float64x2_t) - #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fdiv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdiv_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { simd_div(a, b) } @@ -7471,6 +8132,7 @@ pub unsafe fn vdiv_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fdiv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdivq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { simd_div(a, b) } @@ -7479,6 +8141,7 @@ pub unsafe fn vdivq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fdiv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdiv_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { simd_div(a, b) } @@ -7487,6 +8150,7 @@ pub unsafe fn vdiv_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fdiv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdivq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { simd_div(a, b) } @@ -7495,6 +8159,7 @@ pub unsafe fn vdivq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fsub))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsub_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { simd_sub(a, b) } @@ -7503,6 +8168,7 @@ pub unsafe fn vsub_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fsub))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsubq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { simd_sub(a, b) } @@ -7511,38 +8177,43 @@ pub unsafe fn vsubq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsubd_s64(a: i64, b: i64) -> i64 { - a - b + a.wrapping_sub(b) } /// Subtract #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsubd_u64(a: u64, b: u64) -> u64 { - a - b + a.wrapping_sub(b) } /// Add #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddd_s64(a: i64, b: i64) -> i64 { - a + b + a.wrapping_add(b) } /// Add #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddd_u64(a: u64, b: u64) -> u64 { - a + b + a.wrapping_add(b) } /// Floating-point add across vector #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(faddp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddv_f32(a: float32x2_t) -> f32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7556,6 +8227,7 @@ pub unsafe fn vaddv_f32(a: float32x2_t) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(faddp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddvq_f32(a: float32x4_t) -> f32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7569,6 +8241,7 @@ pub unsafe fn vaddvq_f32(a: float32x4_t) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(faddp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddvq_f64(a: float64x2_t) -> f64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7582,6 +8255,7 @@ pub unsafe fn vaddvq_f64(a: float64x2_t) -> f64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(saddlv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddlv_s16(a: int16x4_t) -> i32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7595,6 +8269,7 @@ pub unsafe fn vaddlv_s16(a: int16x4_t) -> i32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(saddlv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddlvq_s16(a: int16x8_t) -> i32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7608,6 +8283,7 @@ pub unsafe fn vaddlvq_s16(a: int16x8_t) -> i32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(saddlp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddlv_s32(a: int32x2_t) -> i64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7621,6 +8297,7 @@ pub unsafe fn vaddlv_s32(a: int32x2_t) -> i64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(saddlv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddlvq_s32(a: int32x4_t) -> i64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7634,6 +8311,7 @@ pub unsafe fn vaddlvq_s32(a: int32x4_t) -> i64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uaddlv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddlv_u16(a: uint16x4_t) -> u32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7647,6 +8325,7 @@ pub unsafe fn vaddlv_u16(a: uint16x4_t) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uaddlv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddlvq_u16(a: uint16x8_t) -> u32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7660,6 +8339,7 @@ pub unsafe fn vaddlvq_u16(a: uint16x8_t) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uaddlp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddlv_u32(a: uint32x2_t) -> u64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7673,6 +8353,7 @@ pub unsafe fn vaddlv_u32(a: uint32x2_t) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uaddlv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddlvq_u32(a: uint32x4_t) -> u64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7686,6 +8367,7 @@ pub unsafe fn vaddlvq_u32(a: uint32x4_t) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ssubw))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsubw_high_s8(a: int16x8_t, b: int8x16_t) -> int16x8_t { let c: int8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); simd_sub(a, simd_cast(c)) @@ -7695,6 +8377,7 @@ pub unsafe fn vsubw_high_s8(a: int16x8_t, b: int8x16_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ssubw))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsubw_high_s16(a: int32x4_t, b: int16x8_t) -> int32x4_t { let c: int16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); simd_sub(a, simd_cast(c)) @@ -7704,6 +8387,7 @@ pub unsafe fn vsubw_high_s16(a: int32x4_t, b: int16x8_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ssubw))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsubw_high_s32(a: int64x2_t, b: int32x4_t) -> int64x2_t { let c: int32x2_t = simd_shuffle2!(b, b, [2, 3]); simd_sub(a, simd_cast(c)) @@ -7713,6 +8397,7 @@ pub unsafe fn vsubw_high_s32(a: int64x2_t, b: int32x4_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(usubw))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsubw_high_u8(a: uint16x8_t, b: uint8x16_t) -> uint16x8_t { let c: uint8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); simd_sub(a, simd_cast(c)) @@ -7722,6 +8407,7 @@ pub unsafe fn vsubw_high_u8(a: uint16x8_t, b: uint8x16_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(usubw))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsubw_high_u16(a: uint32x4_t, b: uint16x8_t) -> uint32x4_t { let c: uint16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); simd_sub(a, simd_cast(c)) @@ -7731,6 +8417,7 @@ pub unsafe fn vsubw_high_u16(a: uint32x4_t, b: uint16x8_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(usubw))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsubw_high_u32(a: uint64x2_t, b: uint32x4_t) -> uint64x2_t { let c: uint32x2_t = simd_shuffle2!(b, b, [2, 3]); simd_sub(a, simd_cast(c)) @@ -7740,6 +8427,7 @@ pub unsafe fn vsubw_high_u32(a: uint64x2_t, b: uint32x4_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ssubl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsubl_high_s8(a: int8x16_t, b: int8x16_t) -> int16x8_t { let c: int8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); let d: int16x8_t = simd_cast(c); @@ -7752,6 +8440,7 @@ pub unsafe fn vsubl_high_s8(a: int8x16_t, b: int8x16_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ssubl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsubl_high_s16(a: int16x8_t, b: int16x8_t) -> int32x4_t { let c: int16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); let d: int32x4_t = simd_cast(c); @@ -7764,6 +8453,7 @@ pub unsafe fn vsubl_high_s16(a: int16x8_t, b: int16x8_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ssubl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsubl_high_s32(a: int32x4_t, b: int32x4_t) -> int64x2_t { let c: int32x2_t = simd_shuffle2!(a, a, [2, 3]); let d: int64x2_t = simd_cast(c); @@ -7776,6 +8466,7 @@ pub unsafe fn vsubl_high_s32(a: int32x4_t, b: int32x4_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(usubl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsubl_high_u8(a: uint8x16_t, b: uint8x16_t) -> uint16x8_t { let c: uint8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); let d: uint16x8_t = simd_cast(c); @@ -7788,6 +8479,7 @@ pub unsafe fn vsubl_high_u8(a: uint8x16_t, b: uint8x16_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(usubl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsubl_high_u16(a: uint16x8_t, b: uint16x8_t) -> uint32x4_t { let c: uint16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); let d: uint32x4_t = simd_cast(c); @@ -7800,6 +8492,7 @@ pub unsafe fn vsubl_high_u16(a: uint16x8_t, b: uint16x8_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(usubl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsubl_high_u32(a: uint32x4_t, b: uint32x4_t) -> uint64x2_t { let c: uint32x2_t = simd_shuffle2!(a, a, [2, 3]); let d: uint64x2_t = simd_cast(c); @@ -8466,6 +9159,7 @@ pub unsafe fn vdotq_laneq_u32(a: uint32x4_t, b: uint8x16_t, c: #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmax))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmax_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8479,6 +9173,7 @@ pub unsafe fn vmax_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmax))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmaxq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8492,6 +9187,7 @@ pub unsafe fn vmaxq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmaxnm))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmaxnm_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8505,6 +9201,7 @@ pub unsafe fn vmaxnm_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmaxnm))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmaxnmq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8518,6 +9215,7 @@ pub unsafe fn vmaxnmq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmaxnmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmaxnmv_f32(a: float32x2_t) -> f32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8531,6 +9229,7 @@ pub unsafe fn vmaxnmv_f32(a: float32x2_t) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmaxnmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmaxnmvq_f64(a: float64x2_t) -> f64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8544,6 +9243,7 @@ pub unsafe fn vmaxnmvq_f64(a: float64x2_t) -> f64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmaxnmv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmaxnmvq_f32(a: float32x4_t) -> f32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8557,6 +9257,7 @@ pub unsafe fn vmaxnmvq_f32(a: float32x4_t) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmaxnmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpmaxnm_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8570,6 +9271,7 @@ pub unsafe fn vpmaxnm_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmaxnmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpmaxnmq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8583,6 +9285,7 @@ pub unsafe fn vpmaxnmq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmaxnmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpmaxnmq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8596,6 +9299,7 @@ pub unsafe fn vpmaxnmq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmaxnmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpmaxnms_f32(a: float32x2_t) -> f32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8609,6 +9313,7 @@ pub unsafe fn vpmaxnms_f32(a: float32x2_t) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmaxnmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpmaxnmqd_f64(a: float64x2_t) -> f64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8622,6 +9327,7 @@ pub unsafe fn vpmaxnmqd_f64(a: float64x2_t) -> f64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmaxp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpmaxs_f32(a: float32x2_t) -> f32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8635,6 +9341,7 @@ pub unsafe fn vpmaxs_f32(a: float32x2_t) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmaxp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpmaxqd_f64(a: float64x2_t) -> f64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8648,6 +9355,7 @@ pub unsafe fn vpmaxqd_f64(a: float64x2_t) -> f64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmin))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmin_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8661,6 +9369,7 @@ pub unsafe fn vmin_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmin))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vminq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8674,6 +9383,7 @@ pub unsafe fn vminq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fminnm))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vminnm_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8687,6 +9397,7 @@ pub unsafe fn vminnm_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fminnm))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vminnmq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8700,6 +9411,7 @@ pub unsafe fn vminnmq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fminnmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vminnmv_f32(a: float32x2_t) -> f32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8713,6 +9425,7 @@ pub unsafe fn vminnmv_f32(a: float32x2_t) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fminnmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vminnmvq_f64(a: float64x2_t) -> f64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8726,6 +9439,7 @@ pub unsafe fn vminnmvq_f64(a: float64x2_t) -> f64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fminnmv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vminnmvq_f32(a: float32x4_t) -> f32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8739,6 +9453,7 @@ pub unsafe fn vminnmvq_f32(a: float32x4_t) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sxtl2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmovl_high_s8(a: int8x16_t) -> int16x8_t { let a: int8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); vmovl_s8(a) @@ -8748,6 +9463,7 @@ pub unsafe fn vmovl_high_s8(a: int8x16_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sxtl2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmovl_high_s16(a: int16x8_t) -> int32x4_t { let a: int16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); vmovl_s16(a) @@ -8757,6 +9473,7 @@ pub unsafe fn vmovl_high_s16(a: int16x8_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sxtl2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmovl_high_s32(a: int32x4_t) -> int64x2_t { let a: int32x2_t = simd_shuffle2!(a, a, [2, 3]); vmovl_s32(a) @@ -8766,6 +9483,7 @@ pub unsafe fn vmovl_high_s32(a: int32x4_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uxtl2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmovl_high_u8(a: uint8x16_t) -> uint16x8_t { let a: uint8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); vmovl_u8(a) @@ -8775,6 +9493,7 @@ pub unsafe fn vmovl_high_u8(a: uint8x16_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uxtl2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmovl_high_u16(a: uint16x8_t) -> uint32x4_t { let a: uint16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); vmovl_u16(a) @@ -8784,6 +9503,7 @@ pub unsafe fn vmovl_high_u16(a: uint16x8_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uxtl2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmovl_high_u32(a: uint32x4_t) -> uint64x2_t { let a: uint32x2_t = simd_shuffle2!(a, a, [2, 3]); vmovl_u32(a) @@ -8793,6 +9513,7 @@ pub unsafe fn vmovl_high_u32(a: uint32x4_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(faddp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpaddq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8806,6 +9527,7 @@ pub unsafe fn vpaddq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(faddp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpaddq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8819,6 +9541,7 @@ pub unsafe fn vpaddq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpadds_f32(a: float32x2_t) -> f32 { let a1: f32 = simd_extract(a, 0); let a2: f32 = simd_extract(a, 1); @@ -8829,6 +9552,7 @@ pub unsafe fn vpadds_f32(a: float32x2_t) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpaddd_f64(a: float64x2_t) -> f64 { let a1: f64 = simd_extract(a, 0); let a2: f64 = simd_extract(a, 1); @@ -8839,6 +9563,7 @@ pub unsafe fn vpaddd_f64(a: float64x2_t) -> f64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fminnmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpminnm_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8852,6 +9577,7 @@ pub unsafe fn vpminnm_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fminnmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpminnmq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8865,6 +9591,7 @@ pub unsafe fn vpminnmq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fminnmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpminnmq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8878,6 +9605,7 @@ pub unsafe fn vpminnmq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fminnmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpminnms_f32(a: float32x2_t) -> f32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8891,6 +9619,7 @@ pub unsafe fn vpminnms_f32(a: float32x2_t) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fminnmp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpminnmqd_f64(a: float64x2_t) -> f64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8904,6 +9633,7 @@ pub unsafe fn vpminnmqd_f64(a: float64x2_t) -> f64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fminp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpmins_f32(a: float32x2_t) -> f32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8917,6 +9647,7 @@ pub unsafe fn vpmins_f32(a: float32x2_t) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fminp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpminqd_f64(a: float64x2_t) -> f64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8930,6 +9661,7 @@ pub unsafe fn vpminqd_f64(a: float64x2_t) -> f64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmull))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmullh_s16(a: i16, b: i16) -> i32 { let a: int16x4_t = vdup_n_s16(a); let b: int16x4_t = vdup_n_s16(b); @@ -8940,6 +9672,7 @@ pub unsafe fn vqdmullh_s16(a: i16, b: i16) -> i32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmull))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmulls_s32(a: i32, b: i32) -> i64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8953,6 +9686,7 @@ pub unsafe fn vqdmulls_s32(a: i32, b: i32) -> i64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmull2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmull_high_s16(a: int16x8_t, b: int16x8_t) -> int32x4_t { let a: int16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); let b: int16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); @@ -8963,6 +9697,7 @@ pub unsafe fn vqdmull_high_s16(a: int16x8_t, b: int16x8_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmull2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmull_high_s32(a: int32x4_t, b: int32x4_t) -> int64x2_t { let a: int32x2_t = simd_shuffle2!(a, a, [2, 3]); let b: int32x2_t = simd_shuffle2!(b, b, [2, 3]); @@ -8973,6 +9708,7 @@ pub unsafe fn vqdmull_high_s32(a: int32x4_t, b: int32x4_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmull2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmull_high_n_s16(a: int16x8_t, b: i16) -> int32x4_t { let a: int16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); let b: int16x4_t = vdup_n_s16(b); @@ -8983,6 +9719,7 @@ pub unsafe fn vqdmull_high_n_s16(a: int16x8_t, b: i16) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmull2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmull_high_n_s32(a: int32x4_t, b: i32) -> int64x2_t { let a: int32x2_t = simd_shuffle2!(a, a, [2, 3]); let b: int32x2_t = vdup_n_s32(b); @@ -8994,6 +9731,7 @@ pub unsafe fn vqdmull_high_n_s32(a: int32x4_t, b: i32) -> int64x2_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmull, N = 4))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmull_laneq_s16(a: int16x4_t, b: int16x8_t) -> int32x4_t { static_assert_imm3!(N); let b: int16x4_t = simd_shuffle4!(b, b, [N as u32, N as u32, N as u32, N as u32]); @@ -9005,6 +9743,7 @@ pub unsafe fn vqdmull_laneq_s16(a: int16x4_t, b: int16x8_t) -> int #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmull, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmull_laneq_s32(a: int32x2_t, b: int32x4_t) -> int64x2_t { static_assert_imm2!(N); let b: int32x2_t = simd_shuffle2!(b, b, [N as u32, N as u32]); @@ -9016,6 +9755,7 @@ pub unsafe fn vqdmull_laneq_s32(a: int32x2_t, b: int32x4_t) -> int #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmull, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmullh_lane_s16(a: i16, b: int16x4_t) -> i32 { static_assert_imm2!(N); let b: i16 = simd_extract(b, N as u32); @@ -9027,6 +9767,7 @@ pub unsafe fn vqdmullh_lane_s16(a: i16, b: int16x4_t) -> i32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmull, N = 4))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmullh_laneq_s16(a: i16, b: int16x8_t) -> i32 { static_assert_imm3!(N); let b: i16 = simd_extract(b, N as u32); @@ -9038,6 +9779,7 @@ pub unsafe fn vqdmullh_laneq_s16(a: i16, b: int16x8_t) -> i32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmull, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmulls_lane_s32(a: i32, b: int32x2_t) -> i64 { static_assert_imm1!(N); let b: i32 = simd_extract(b, N as u32); @@ -9049,6 +9791,7 @@ pub unsafe fn vqdmulls_lane_s32(a: i32, b: int32x2_t) -> i64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmull, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmulls_laneq_s32(a: i32, b: int32x4_t) -> i64 { static_assert_imm2!(N); let b: i32 = simd_extract(b, N as u32); @@ -9060,6 +9803,7 @@ pub unsafe fn vqdmulls_laneq_s32(a: i32, b: int32x4_t) -> i64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmull2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmull_high_lane_s16(a: int16x8_t, b: int16x4_t) -> int32x4_t { static_assert_imm2!(N); let a: int16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); @@ -9072,6 +9816,7 @@ pub unsafe fn vqdmull_high_lane_s16(a: int16x8_t, b: int16x4_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmull2, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmull_high_lane_s32(a: int32x4_t, b: int32x2_t) -> int64x2_t { static_assert_imm1!(N); let a: int32x2_t = simd_shuffle2!(a, a, [2, 3]); @@ -9084,6 +9829,7 @@ pub unsafe fn vqdmull_high_lane_s32(a: int32x4_t, b: int32x2_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmull2, N = 4))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmull_high_laneq_s16(a: int16x8_t, b: int16x8_t) -> int32x4_t { static_assert_imm3!(N); let a: int16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); @@ -9096,6 +9842,7 @@ pub unsafe fn vqdmull_high_laneq_s16(a: int16x8_t, b: int16x8_t) - #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmull2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmull_high_laneq_s32(a: int32x4_t, b: int32x4_t) -> int64x2_t { static_assert_imm2!(N); let a: int32x2_t = simd_shuffle2!(a, a, [2, 3]); @@ -9107,6 +9854,7 @@ pub unsafe fn vqdmull_high_laneq_s32(a: int32x4_t, b: int32x4_t) - #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmlal2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlal_high_s16(a: int32x4_t, b: int16x8_t, c: int16x8_t) -> int32x4_t { vqaddq_s32(a, vqdmull_high_s16(b, c)) } @@ -9115,6 +9863,7 @@ pub unsafe fn vqdmlal_high_s16(a: int32x4_t, b: int16x8_t, c: int16x8_t) -> int3 #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmlal2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlal_high_s32(a: int64x2_t, b: int32x4_t, c: int32x4_t) -> int64x2_t { vqaddq_s64(a, vqdmull_high_s32(b, c)) } @@ -9123,6 +9872,7 @@ pub unsafe fn vqdmlal_high_s32(a: int64x2_t, b: int32x4_t, c: int32x4_t) -> int6 #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmlal2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlal_high_n_s16(a: int32x4_t, b: int16x8_t, c: i16) -> int32x4_t { vqaddq_s32(a, vqdmull_high_n_s16(b, c)) } @@ -9131,6 +9881,7 @@ pub unsafe fn vqdmlal_high_n_s16(a: int32x4_t, b: int16x8_t, c: i16) -> int32x4_ #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmlal2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlal_high_n_s32(a: int64x2_t, b: int32x4_t, c: i32) -> int64x2_t { vqaddq_s64(a, vqdmull_high_n_s32(b, c)) } @@ -9140,6 +9891,7 @@ pub unsafe fn vqdmlal_high_n_s32(a: int64x2_t, b: int32x4_t, c: i32) -> int64x2_ #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmlal, N = 2))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlal_laneq_s16(a: int32x4_t, b: int16x4_t, c: int16x8_t) -> int32x4_t { static_assert_imm3!(N); vqaddq_s32(a, vqdmull_laneq_s16::(b, c)) @@ -9150,6 +9902,7 @@ pub unsafe fn vqdmlal_laneq_s16(a: int32x4_t, b: int16x4_t, c: int #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmlal, N = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlal_laneq_s32(a: int64x2_t, b: int32x2_t, c: int32x4_t) -> int64x2_t { static_assert_imm2!(N); vqaddq_s64(a, vqdmull_laneq_s32::(b, c)) @@ -9160,6 +9913,7 @@ pub unsafe fn vqdmlal_laneq_s32(a: int64x2_t, b: int32x2_t, c: int #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmlal2, N = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlal_high_lane_s16(a: int32x4_t, b: int16x8_t, c: int16x4_t) -> int32x4_t { static_assert_imm2!(N); vqaddq_s32(a, vqdmull_high_lane_s16::(b, c)) @@ -9170,6 +9924,7 @@ pub unsafe fn vqdmlal_high_lane_s16(a: int32x4_t, b: int16x8_t, c: #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmlal2, N = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlal_high_laneq_s16(a: int32x4_t, b: int16x8_t, c: int16x8_t) -> int32x4_t { static_assert_imm3!(N); vqaddq_s32(a, vqdmull_high_laneq_s16::(b, c)) @@ -9180,6 +9935,7 @@ pub unsafe fn vqdmlal_high_laneq_s16(a: int32x4_t, b: int16x8_t, c #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmlal2, N = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlal_high_lane_s32(a: int64x2_t, b: int32x4_t, c: int32x2_t) -> int64x2_t { static_assert_imm1!(N); vqaddq_s64(a, vqdmull_high_lane_s32::(b, c)) @@ -9190,6 +9946,7 @@ pub unsafe fn vqdmlal_high_lane_s32(a: int64x2_t, b: int32x4_t, c: #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmlal2, N = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlal_high_laneq_s32(a: int64x2_t, b: int32x4_t, c: int32x4_t) -> int64x2_t { static_assert_imm2!(N); vqaddq_s64(a, vqdmull_high_laneq_s32::(b, c)) @@ -9199,6 +9956,7 @@ pub unsafe fn vqdmlal_high_laneq_s32(a: int64x2_t, b: int32x4_t, c #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmull))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlalh_s16(a: i32, b: i16, c: i16) -> i32 { let x: int32x4_t = vqdmull_s16(vdup_n_s16(b), vdup_n_s16(c)); vqadds_s32(a, simd_extract(x, 0)) @@ -9208,6 +9966,7 @@ pub unsafe fn vqdmlalh_s16(a: i32, b: i16, c: i16) -> i32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmull))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlals_s32(a: i64, b: i32, c: i32) -> i64 { let x: int64x2_t = vqdmull_s32(vdup_n_s32(b), vdup_n_s32(c)); vqaddd_s64(a, simd_extract(x, 0)) @@ -9218,6 +9977,7 @@ pub unsafe fn vqdmlals_s32(a: i64, b: i32, c: i32) -> i64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmlal, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlalh_lane_s16(a: i32, b: i16, c: int16x4_t) -> i32 { static_assert_imm2!(LANE); vqdmlalh_s16(a, b, simd_extract(c, LANE as u32)) @@ -9228,6 +9988,7 @@ pub unsafe fn vqdmlalh_lane_s16(a: i32, b: i16, c: int16x4_t) - #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmlal, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlalh_laneq_s16(a: i32, b: i16, c: int16x8_t) -> i32 { static_assert_imm3!(LANE); vqdmlalh_s16(a, b, simd_extract(c, LANE as u32)) @@ -9238,6 +9999,7 @@ pub unsafe fn vqdmlalh_laneq_s16(a: i32, b: i16, c: int16x8_t) #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmull, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlals_lane_s32(a: i64, b: i32, c: int32x2_t) -> i64 { static_assert_imm1!(LANE); vqdmlals_s32(a, b, simd_extract(c, LANE as u32)) @@ -9248,6 +10010,7 @@ pub unsafe fn vqdmlals_lane_s32(a: i64, b: i32, c: int32x2_t) - #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmull, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlals_laneq_s32(a: i64, b: i32, c: int32x4_t) -> i64 { static_assert_imm2!(LANE); vqdmlals_s32(a, b, simd_extract(c, LANE as u32)) @@ -9257,6 +10020,7 @@ pub unsafe fn vqdmlals_laneq_s32(a: i64, b: i32, c: int32x4_t) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmlsl2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlsl_high_s16(a: int32x4_t, b: int16x8_t, c: int16x8_t) -> int32x4_t { vqsubq_s32(a, vqdmull_high_s16(b, c)) } @@ -9265,6 +10029,7 @@ pub unsafe fn vqdmlsl_high_s16(a: int32x4_t, b: int16x8_t, c: int16x8_t) -> int3 #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmlsl2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlsl_high_s32(a: int64x2_t, b: int32x4_t, c: int32x4_t) -> int64x2_t { vqsubq_s64(a, vqdmull_high_s32(b, c)) } @@ -9273,6 +10038,7 @@ pub unsafe fn vqdmlsl_high_s32(a: int64x2_t, b: int32x4_t, c: int32x4_t) -> int6 #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmlsl2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlsl_high_n_s16(a: int32x4_t, b: int16x8_t, c: i16) -> int32x4_t { vqsubq_s32(a, vqdmull_high_n_s16(b, c)) } @@ -9281,6 +10047,7 @@ pub unsafe fn vqdmlsl_high_n_s16(a: int32x4_t, b: int16x8_t, c: i16) -> int32x4_ #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmlsl2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlsl_high_n_s32(a: int64x2_t, b: int32x4_t, c: i32) -> int64x2_t { vqsubq_s64(a, vqdmull_high_n_s32(b, c)) } @@ -9290,6 +10057,7 @@ pub unsafe fn vqdmlsl_high_n_s32(a: int64x2_t, b: int32x4_t, c: i32) -> int64x2_ #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmlsl, N = 2))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlsl_laneq_s16(a: int32x4_t, b: int16x4_t, c: int16x8_t) -> int32x4_t { static_assert_imm3!(N); vqsubq_s32(a, vqdmull_laneq_s16::(b, c)) @@ -9300,6 +10068,7 @@ pub unsafe fn vqdmlsl_laneq_s16(a: int32x4_t, b: int16x4_t, c: int #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmlsl, N = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlsl_laneq_s32(a: int64x2_t, b: int32x2_t, c: int32x4_t) -> int64x2_t { static_assert_imm2!(N); vqsubq_s64(a, vqdmull_laneq_s32::(b, c)) @@ -9310,6 +10079,7 @@ pub unsafe fn vqdmlsl_laneq_s32(a: int64x2_t, b: int32x2_t, c: int #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmlsl2, N = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlsl_high_lane_s16(a: int32x4_t, b: int16x8_t, c: int16x4_t) -> int32x4_t { static_assert_imm2!(N); vqsubq_s32(a, vqdmull_high_lane_s16::(b, c)) @@ -9320,6 +10090,7 @@ pub unsafe fn vqdmlsl_high_lane_s16(a: int32x4_t, b: int16x8_t, c: #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmlsl2, N = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlsl_high_laneq_s16(a: int32x4_t, b: int16x8_t, c: int16x8_t) -> int32x4_t { static_assert_imm3!(N); vqsubq_s32(a, vqdmull_high_laneq_s16::(b, c)) @@ -9330,6 +10101,7 @@ pub unsafe fn vqdmlsl_high_laneq_s16(a: int32x4_t, b: int16x8_t, c #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmlsl2, N = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlsl_high_lane_s32(a: int64x2_t, b: int32x4_t, c: int32x2_t) -> int64x2_t { static_assert_imm1!(N); vqsubq_s64(a, vqdmull_high_lane_s32::(b, c)) @@ -9340,6 +10112,7 @@ pub unsafe fn vqdmlsl_high_lane_s32(a: int64x2_t, b: int32x4_t, c: #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmlsl2, N = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlsl_high_laneq_s32(a: int64x2_t, b: int32x4_t, c: int32x4_t) -> int64x2_t { static_assert_imm2!(N); vqsubq_s64(a, vqdmull_high_laneq_s32::(b, c)) @@ -9349,6 +10122,7 @@ pub unsafe fn vqdmlsl_high_laneq_s32(a: int64x2_t, b: int32x4_t, c #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmull))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlslh_s16(a: i32, b: i16, c: i16) -> i32 { let x: int32x4_t = vqdmull_s16(vdup_n_s16(b), vdup_n_s16(c)); vqsubs_s32(a, simd_extract(x, 0)) @@ -9358,6 +10132,7 @@ pub unsafe fn vqdmlslh_s16(a: i32, b: i16, c: i16) -> i32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmull))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlsls_s32(a: i64, b: i32, c: i32) -> i64 { let x: int64x2_t = vqdmull_s32(vdup_n_s32(b), vdup_n_s32(c)); vqsubd_s64(a, simd_extract(x, 0)) @@ -9368,6 +10143,7 @@ pub unsafe fn vqdmlsls_s32(a: i64, b: i32, c: i32) -> i64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmlsl, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlslh_lane_s16(a: i32, b: i16, c: int16x4_t) -> i32 { static_assert_imm2!(LANE); vqdmlslh_s16(a, b, simd_extract(c, LANE as u32)) @@ -9378,6 +10154,7 @@ pub unsafe fn vqdmlslh_lane_s16(a: i32, b: i16, c: int16x4_t) - #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmlsl, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlslh_laneq_s16(a: i32, b: i16, c: int16x8_t) -> i32 { static_assert_imm3!(LANE); vqdmlslh_s16(a, b, simd_extract(c, LANE as u32)) @@ -9388,6 +10165,7 @@ pub unsafe fn vqdmlslh_laneq_s16(a: i32, b: i16, c: int16x8_t) #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmull, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlsls_lane_s32(a: i64, b: i32, c: int32x2_t) -> i64 { static_assert_imm1!(LANE); vqdmlsls_s32(a, b, simd_extract(c, LANE as u32)) @@ -9398,6 +10176,7 @@ pub unsafe fn vqdmlsls_lane_s32(a: i64, b: i32, c: int32x2_t) - #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmull, LANE = 0))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmlsls_laneq_s32(a: i64, b: i32, c: int32x4_t) -> i64 { static_assert_imm2!(LANE); vqdmlsls_s32(a, b, simd_extract(c, LANE as u32)) @@ -9407,6 +10186,7 @@ pub unsafe fn vqdmlsls_laneq_s32(a: i64, b: i32, c: int32x4_t) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmulh))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmulhh_s16(a: i16, b: i16) -> i16 { let a: int16x4_t = vdup_n_s16(a); let b: int16x4_t = vdup_n_s16(b); @@ -9417,6 +10197,7 @@ pub unsafe fn vqdmulhh_s16(a: i16, b: i16) -> i16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmulh))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmulhs_s32(a: i32, b: i32) -> i32 { let a: int32x2_t = vdup_n_s32(a); let b: int32x2_t = vdup_n_s32(b); @@ -9428,6 +10209,7 @@ pub unsafe fn vqdmulhs_s32(a: i32, b: i32) -> i32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmulh, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmulhh_lane_s16(a: i16, b: int16x4_t) -> i16 { static_assert_imm2!(N); let b: i16 = simd_extract(b, N as u32); @@ -9439,6 +10221,7 @@ pub unsafe fn vqdmulhh_lane_s16(a: i16, b: int16x4_t) -> i16 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmulh, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmulhh_laneq_s16(a: i16, b: int16x8_t) -> i16 { static_assert_imm3!(N); let b: i16 = simd_extract(b, N as u32); @@ -9450,6 +10233,7 @@ pub unsafe fn vqdmulhh_laneq_s16(a: i16, b: int16x8_t) -> i16 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmulh, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmulhs_lane_s32(a: i32, b: int32x2_t) -> i32 { static_assert_imm1!(N); let b: i32 = simd_extract(b, N as u32); @@ -9461,6 +10245,7 @@ pub unsafe fn vqdmulhs_lane_s32(a: i32, b: int32x2_t) -> i32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmulh, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmulhs_laneq_s32(a: i32, b: int32x4_t) -> i32 { static_assert_imm2!(N); let b: i32 = simd_extract(b, N as u32); @@ -9472,6 +10257,7 @@ pub unsafe fn vqdmulhs_laneq_s32(a: i32, b: int32x4_t) -> i32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmulh, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmulh_lane_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { static_assert_imm2!(LANE); vqdmulh_s16(a, vdup_n_s16(simd_extract(b, LANE as u32))) @@ -9482,6 +10268,7 @@ pub unsafe fn vqdmulh_lane_s16(a: int16x4_t, b: int16x4_t) -> i #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmulh, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmulhq_lane_s16(a: int16x8_t, b: int16x4_t) -> int16x8_t { static_assert_imm2!(LANE); vqdmulhq_s16(a, vdupq_n_s16(simd_extract(b, LANE as u32))) @@ -9492,6 +10279,7 @@ pub unsafe fn vqdmulhq_lane_s16(a: int16x8_t, b: int16x4_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmulh, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmulh_lane_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { static_assert_imm1!(LANE); vqdmulh_s32(a, vdup_n_s32(simd_extract(b, LANE as u32))) @@ -9502,6 +10290,7 @@ pub unsafe fn vqdmulh_lane_s32(a: int32x2_t, b: int32x2_t) -> i #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqdmulh, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqdmulhq_lane_s32(a: int32x4_t, b: int32x2_t) -> int32x4_t { static_assert_imm1!(LANE); vqdmulhq_s32(a, vdupq_n_s32(simd_extract(b, LANE as u32))) @@ -9511,6 +10300,7 @@ pub unsafe fn vqdmulhq_lane_s32(a: int32x4_t, b: int32x2_t) -> #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqxtn))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqmovnh_s16(a: i16) -> i8 { simd_extract(vqmovn_s16(vdupq_n_s16(a)), 0) } @@ -9519,6 +10309,7 @@ pub unsafe fn vqmovnh_s16(a: i16) -> i8 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqxtn))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqmovns_s32(a: i32) -> i16 { simd_extract(vqmovn_s32(vdupq_n_s32(a)), 0) } @@ -9527,6 +10318,7 @@ pub unsafe fn vqmovns_s32(a: i32) -> i16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqxtn))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqmovnh_u16(a: u16) -> u8 { simd_extract(vqmovn_u16(vdupq_n_u16(a)), 0) } @@ -9535,6 +10327,7 @@ pub unsafe fn vqmovnh_u16(a: u16) -> u8 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqxtn))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqmovns_u32(a: u32) -> u16 { simd_extract(vqmovn_u32(vdupq_n_u32(a)), 0) } @@ -9543,6 +10336,7 @@ pub unsafe fn vqmovns_u32(a: u32) -> u16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqxtn))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqmovnd_s64(a: i64) -> i32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -9556,6 +10350,7 @@ pub unsafe fn vqmovnd_s64(a: i64) -> i32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqxtn))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqmovnd_u64(a: u64) -> u32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -9569,6 +10364,7 @@ pub unsafe fn vqmovnd_u64(a: u64) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqxtn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqmovn_high_s16(a: int8x8_t, b: int16x8_t) -> int8x16_t { simd_shuffle16!(a, vqmovn_s16(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) } @@ -9577,6 +10373,7 @@ pub unsafe fn vqmovn_high_s16(a: int8x8_t, b: int16x8_t) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqxtn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqmovn_high_s32(a: int16x4_t, b: int32x4_t) -> int16x8_t { simd_shuffle8!(a, vqmovn_s32(b), [0, 1, 2, 3, 4, 5, 6, 7]) } @@ -9585,6 +10382,7 @@ pub unsafe fn vqmovn_high_s32(a: int16x4_t, b: int32x4_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqxtn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqmovn_high_s64(a: int32x2_t, b: int64x2_t) -> int32x4_t { simd_shuffle4!(a, vqmovn_s64(b), [0, 1, 2, 3]) } @@ -9593,6 +10391,7 @@ pub unsafe fn vqmovn_high_s64(a: int32x2_t, b: int64x2_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqxtn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqmovn_high_u16(a: uint8x8_t, b: uint16x8_t) -> uint8x16_t { simd_shuffle16!(a, vqmovn_u16(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) } @@ -9601,6 +10400,7 @@ pub unsafe fn vqmovn_high_u16(a: uint8x8_t, b: uint16x8_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqxtn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqmovn_high_u32(a: uint16x4_t, b: uint32x4_t) -> uint16x8_t { simd_shuffle8!(a, vqmovn_u32(b), [0, 1, 2, 3, 4, 5, 6, 7]) } @@ -9609,6 +10409,7 @@ pub unsafe fn vqmovn_high_u32(a: uint16x4_t, b: uint32x4_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqxtn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqmovn_high_u64(a: uint32x2_t, b: uint64x2_t) -> uint32x4_t { simd_shuffle4!(a, vqmovn_u64(b), [0, 1, 2, 3]) } @@ -9617,6 +10418,7 @@ pub unsafe fn vqmovn_high_u64(a: uint32x2_t, b: uint64x2_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqxtun))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqmovunh_s16(a: i16) -> u8 { simd_extract(vqmovun_s16(vdupq_n_s16(a)), 0) } @@ -9625,6 +10427,7 @@ pub unsafe fn vqmovunh_s16(a: i16) -> u8 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqxtun))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqmovuns_s32(a: i32) -> u16 { simd_extract(vqmovun_s32(vdupq_n_s32(a)), 0) } @@ -9633,6 +10436,7 @@ pub unsafe fn vqmovuns_s32(a: i32) -> u16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqxtun))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqmovund_s64(a: i64) -> u32 { simd_extract(vqmovun_s64(vdupq_n_s64(a)), 0) } @@ -9641,6 +10445,7 @@ pub unsafe fn vqmovund_s64(a: i64) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqxtun2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqmovun_high_s16(a: uint8x8_t, b: int16x8_t) -> uint8x16_t { simd_shuffle16!(a, vqmovun_s16(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) } @@ -9649,6 +10454,7 @@ pub unsafe fn vqmovun_high_s16(a: uint8x8_t, b: int16x8_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqxtun2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqmovun_high_s32(a: uint16x4_t, b: int32x4_t) -> uint16x8_t { simd_shuffle8!(a, vqmovun_s32(b), [0, 1, 2, 3, 4, 5, 6, 7]) } @@ -9657,6 +10463,7 @@ pub unsafe fn vqmovun_high_s32(a: uint16x4_t, b: int32x4_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqxtun2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqmovun_high_s64(a: uint32x2_t, b: int64x2_t) -> uint32x4_t { simd_shuffle4!(a, vqmovun_s64(b), [0, 1, 2, 3]) } @@ -9665,6 +10472,7 @@ pub unsafe fn vqmovun_high_s64(a: uint32x2_t, b: int64x2_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrdmulh))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrdmulhh_s16(a: i16, b: i16) -> i16 { simd_extract(vqrdmulh_s16(vdup_n_s16(a), vdup_n_s16(b)), 0) } @@ -9673,6 +10481,7 @@ pub unsafe fn vqrdmulhh_s16(a: i16, b: i16) -> i16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrdmulh))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrdmulhs_s32(a: i32, b: i32) -> i32 { simd_extract(vqrdmulh_s32(vdup_n_s32(a), vdup_n_s32(b)), 0) } @@ -9682,6 +10491,7 @@ pub unsafe fn vqrdmulhs_s32(a: i32, b: i32) -> i32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrdmulhh_lane_s16(a: i16, b: int16x4_t) -> i16 { static_assert_imm2!(LANE); vqrdmulhh_s16(a, simd_extract(b, LANE as u32)) @@ -9692,6 +10502,7 @@ pub unsafe fn vqrdmulhh_lane_s16(a: i16, b: int16x4_t) -> i16 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrdmulhh_laneq_s16(a: i16, b: int16x8_t) -> i16 { static_assert_imm3!(LANE); vqrdmulhh_s16(a, simd_extract(b, LANE as u32)) @@ -9702,6 +10513,7 @@ pub unsafe fn vqrdmulhh_laneq_s16(a: i16, b: int16x8_t) -> i16 #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrdmulhs_lane_s32(a: i32, b: int32x2_t) -> i32 { static_assert_imm1!(LANE); vqrdmulhs_s32(a, simd_extract(b, LANE as u32)) @@ -9712,6 +10524,7 @@ pub unsafe fn vqrdmulhs_lane_s32(a: i32, b: int32x2_t) -> i32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrdmulhs_laneq_s32(a: i32, b: int32x4_t) -> i32 { static_assert_imm2!(LANE); vqrdmulhs_s32(a, simd_extract(b, LANE as u32)) @@ -9895,6 +10708,7 @@ pub unsafe fn vqrdmlahs_laneq_s32(a: i32, b: i32, c: int32x4_t) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrdmulh))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrdmlshh_s16(a: i16, b: i16, c: i16) -> i16 { vqsubh_s16(a, vqrdmulhh_s16(b, c)) } @@ -9903,6 +10717,7 @@ pub unsafe fn vqrdmlshh_s16(a: i16, b: i16, c: i16) -> i16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrdmulh))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrdmlshs_s32(a: i32, b: i32, c: i32) -> i32 { vqsubs_s32(a, vqrdmulhs_s32(b, c)) } @@ -9912,6 +10727,7 @@ pub unsafe fn vqrdmlshs_s32(a: i32, b: i32, c: i32) -> i32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrdmlshh_lane_s16(a: i16, b: i16, c: int16x4_t) -> i16 { static_assert_imm2!(LANE); vqsubh_s16(a, vqrdmulhh_lane_s16::(b, c)) @@ -9922,6 +10738,7 @@ pub unsafe fn vqrdmlshh_lane_s16(a: i16, b: i16, c: int16x4_t) #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrdmlshh_laneq_s16(a: i16, b: i16, c: int16x8_t) -> i16 { static_assert_imm3!(LANE); vqsubh_s16(a, vqrdmulhh_laneq_s16::(b, c)) @@ -9932,6 +10749,7 @@ pub unsafe fn vqrdmlshh_laneq_s16(a: i16, b: i16, c: int16x8_t) #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrdmlshs_lane_s32(a: i32, b: i32, c: int32x2_t) -> i32 { static_assert_imm1!(LANE); vqsubs_s32(a, vqrdmulhs_lane_s32::(b, c)) @@ -9942,6 +10760,7 @@ pub unsafe fn vqrdmlshs_lane_s32(a: i32, b: i32, c: int32x2_t) #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrdmlshs_laneq_s32(a: i32, b: i32, c: int32x4_t) -> i32 { static_assert_imm2!(LANE); vqsubs_s32(a, vqrdmulhs_laneq_s32::(b, c)) @@ -9951,6 +10770,7 @@ pub unsafe fn vqrdmlshs_laneq_s32(a: i32, b: i32, c: int32x4_t) #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrshl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshls_s32(a: i32, b: i32) -> i32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -9964,6 +10784,7 @@ pub unsafe fn vqrshls_s32(a: i32, b: i32) -> i32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrshl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshld_s64(a: i64, b: i64) -> i64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -9977,6 +10798,7 @@ pub unsafe fn vqrshld_s64(a: i64, b: i64) -> i64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrshl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshlb_s8(a: i8, b: i8) -> i8 { let a: int8x8_t = vdup_n_s8(a); let b: int8x8_t = vdup_n_s8(b); @@ -9987,6 +10809,7 @@ pub unsafe fn vqrshlb_s8(a: i8, b: i8) -> i8 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrshl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshlh_s16(a: i16, b: i16) -> i16 { let a: int16x4_t = vdup_n_s16(a); let b: int16x4_t = vdup_n_s16(b); @@ -9997,6 +10820,7 @@ pub unsafe fn vqrshlh_s16(a: i16, b: i16) -> i16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqrshl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshls_u32(a: u32, b: i32) -> u32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10010,6 +10834,7 @@ pub unsafe fn vqrshls_u32(a: u32, b: i32) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqrshl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshld_u64(a: u64, b: i64) -> u64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10023,6 +10848,7 @@ pub unsafe fn vqrshld_u64(a: u64, b: i64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqrshl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshlb_u8(a: u8, b: i8) -> u8 { let a: uint8x8_t = vdup_n_u8(a); let b: int8x8_t = vdup_n_s8(b); @@ -10033,6 +10859,7 @@ pub unsafe fn vqrshlb_u8(a: u8, b: i8) -> u8 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqrshl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshlh_u16(a: u16, b: i16) -> u16 { let a: uint16x4_t = vdup_n_u16(a); let b: int16x4_t = vdup_n_s16(b); @@ -10044,6 +10871,7 @@ pub unsafe fn vqrshlh_u16(a: u16, b: i16) -> u16 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrnh_n_s16(a: i16) -> i8 { static_assert!(N : i32 where N >= 1 && N <= 8); let a: int16x8_t = vdupq_n_s16(a); @@ -10055,6 +10883,7 @@ pub unsafe fn vqrshrnh_n_s16(a: i16) -> i8 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrns_n_s32(a: i32) -> i16 { static_assert!(N : i32 where N >= 1 && N <= 16); let a: int32x4_t = vdupq_n_s32(a); @@ -10066,6 +10895,7 @@ pub unsafe fn vqrshrns_n_s32(a: i32) -> i16 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrnd_n_s64(a: i64) -> i32 { static_assert!(N : i32 where N >= 1 && N <= 32); let a: int64x2_t = vdupq_n_s64(a); @@ -10077,6 +10907,7 @@ pub unsafe fn vqrshrnd_n_s64(a: i64) -> i32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrshrn2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrn_high_n_s16(a: int8x8_t, b: int16x8_t) -> int8x16_t { static_assert!(N : i32 where N >= 1 && N <= 8); simd_shuffle16!(a, vqrshrn_n_s16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) @@ -10087,6 +10918,7 @@ pub unsafe fn vqrshrn_high_n_s16(a: int8x8_t, b: int16x8_t) -> int #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrshrn2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrn_high_n_s32(a: int16x4_t, b: int32x4_t) -> int16x8_t { static_assert!(N : i32 where N >= 1 && N <= 16); simd_shuffle8!(a, vqrshrn_n_s32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) @@ -10097,6 +10929,7 @@ pub unsafe fn vqrshrn_high_n_s32(a: int16x4_t, b: int32x4_t) -> in #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrshrn2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrn_high_n_s64(a: int32x2_t, b: int64x2_t) -> int32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); simd_shuffle4!(a, vqrshrn_n_s64::(b), [0, 1, 2, 3]) @@ -10107,6 +10940,7 @@ pub unsafe fn vqrshrn_high_n_s64(a: int32x2_t, b: int64x2_t) -> in #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqrshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrnh_n_u16(a: u16) -> u8 { static_assert!(N : i32 where N >= 1 && N <= 8); let a: uint16x8_t = vdupq_n_u16(a); @@ -10118,6 +10952,7 @@ pub unsafe fn vqrshrnh_n_u16(a: u16) -> u8 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqrshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrns_n_u32(a: u32) -> u16 { static_assert!(N : i32 where N >= 1 && N <= 16); let a: uint32x4_t = vdupq_n_u32(a); @@ -10129,6 +10964,7 @@ pub unsafe fn vqrshrns_n_u32(a: u32) -> u16 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqrshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrnd_n_u64(a: u64) -> u32 { static_assert!(N : i32 where N >= 1 && N <= 32); let a: uint64x2_t = vdupq_n_u64(a); @@ -10140,6 +10976,7 @@ pub unsafe fn vqrshrnd_n_u64(a: u64) -> u32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqrshrn2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrn_high_n_u16(a: uint8x8_t, b: uint16x8_t) -> uint8x16_t { static_assert!(N : i32 where N >= 1 && N <= 8); simd_shuffle16!(a, vqrshrn_n_u16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) @@ -10150,6 +10987,7 @@ pub unsafe fn vqrshrn_high_n_u16(a: uint8x8_t, b: uint16x8_t) -> u #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqrshrn2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrn_high_n_u32(a: uint16x4_t, b: uint32x4_t) -> uint16x8_t { static_assert!(N : i32 where N >= 1 && N <= 16); simd_shuffle8!(a, vqrshrn_n_u32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) @@ -10160,6 +10998,7 @@ pub unsafe fn vqrshrn_high_n_u32(a: uint16x4_t, b: uint32x4_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqrshrn2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrn_high_n_u64(a: uint32x2_t, b: uint64x2_t) -> uint32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); simd_shuffle4!(a, vqrshrn_n_u64::(b), [0, 1, 2, 3]) @@ -10170,6 +11009,7 @@ pub unsafe fn vqrshrn_high_n_u64(a: uint32x2_t, b: uint64x2_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrshrun, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrunh_n_s16(a: i16) -> u8 { static_assert!(N : i32 where N >= 1 && N <= 8); let a: int16x8_t = vdupq_n_s16(a); @@ -10181,6 +11021,7 @@ pub unsafe fn vqrshrunh_n_s16(a: i16) -> u8 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrshrun, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshruns_n_s32(a: i32) -> u16 { static_assert!(N : i32 where N >= 1 && N <= 16); let a: int32x4_t = vdupq_n_s32(a); @@ -10192,6 +11033,7 @@ pub unsafe fn vqrshruns_n_s32(a: i32) -> u16 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrshrun, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrund_n_s64(a: i64) -> u32 { static_assert!(N : i32 where N >= 1 && N <= 32); let a: int64x2_t = vdupq_n_s64(a); @@ -10203,6 +11045,7 @@ pub unsafe fn vqrshrund_n_s64(a: i64) -> u32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrshrun2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrun_high_n_s16(a: uint8x8_t, b: int16x8_t) -> uint8x16_t { static_assert!(N : i32 where N >= 1 && N <= 8); simd_shuffle16!(a, vqrshrun_n_s16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) @@ -10213,6 +11056,7 @@ pub unsafe fn vqrshrun_high_n_s16(a: uint8x8_t, b: int16x8_t) -> u #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrshrun2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrun_high_n_s32(a: uint16x4_t, b: int32x4_t) -> uint16x8_t { static_assert!(N : i32 where N >= 1 && N <= 16); simd_shuffle8!(a, vqrshrun_n_s32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) @@ -10223,6 +11067,7 @@ pub unsafe fn vqrshrun_high_n_s32(a: uint16x4_t, b: int32x4_t) -> #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqrshrun2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrun_high_n_s64(a: uint32x2_t, b: int64x2_t) -> uint32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); simd_shuffle4!(a, vqrshrun_n_s64::(b), [0, 1, 2, 3]) @@ -10232,6 +11077,7 @@ pub unsafe fn vqrshrun_high_n_s64(a: uint32x2_t, b: int64x2_t) -> #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqshl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshld_s64(a: i64, b: i64) -> i64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10245,6 +11091,7 @@ pub unsafe fn vqshld_s64(a: i64, b: i64) -> i64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqshl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshlb_s8(a: i8, b: i8) -> i8 { let c: int8x8_t = vqshl_s8(vdup_n_s8(a), vdup_n_s8(b)); simd_extract(c, 0) @@ -10254,6 +11101,7 @@ pub unsafe fn vqshlb_s8(a: i8, b: i8) -> i8 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqshl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshlh_s16(a: i16, b: i16) -> i16 { let c: int16x4_t = vqshl_s16(vdup_n_s16(a), vdup_n_s16(b)); simd_extract(c, 0) @@ -10263,6 +11111,7 @@ pub unsafe fn vqshlh_s16(a: i16, b: i16) -> i16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqshl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshls_s32(a: i32, b: i32) -> i32 { let c: int32x2_t = vqshl_s32(vdup_n_s32(a), vdup_n_s32(b)); simd_extract(c, 0) @@ -10272,6 +11121,7 @@ pub unsafe fn vqshls_s32(a: i32, b: i32) -> i32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqshl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshld_u64(a: u64, b: i64) -> u64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10285,6 +11135,7 @@ pub unsafe fn vqshld_u64(a: u64, b: i64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqshl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshlb_u8(a: u8, b: i8) -> u8 { let c: uint8x8_t = vqshl_u8(vdup_n_u8(a), vdup_n_s8(b)); simd_extract(c, 0) @@ -10294,6 +11145,7 @@ pub unsafe fn vqshlb_u8(a: u8, b: i8) -> u8 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqshl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshlh_u16(a: u16, b: i16) -> u16 { let c: uint16x4_t = vqshl_u16(vdup_n_u16(a), vdup_n_s16(b)); simd_extract(c, 0) @@ -10303,6 +11155,7 @@ pub unsafe fn vqshlh_u16(a: u16, b: i16) -> u16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqshl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshls_u32(a: u32, b: i32) -> u32 { let c: uint32x2_t = vqshl_u32(vdup_n_u32(a), vdup_n_s32(b)); simd_extract(c, 0) @@ -10313,6 +11166,7 @@ pub unsafe fn vqshls_u32(a: u32, b: i32) -> u32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqshl, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshlb_n_s8(a: i8) -> i8 { static_assert_imm3!(N); simd_extract(vqshl_n_s8::(vdup_n_s8(a)), 0) @@ -10323,6 +11177,7 @@ pub unsafe fn vqshlb_n_s8(a: i8) -> i8 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqshl, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshlh_n_s16(a: i16) -> i16 { static_assert_imm4!(N); simd_extract(vqshl_n_s16::(vdup_n_s16(a)), 0) @@ -10333,6 +11188,7 @@ pub unsafe fn vqshlh_n_s16(a: i16) -> i16 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqshl, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshls_n_s32(a: i32) -> i32 { static_assert_imm5!(N); simd_extract(vqshl_n_s32::(vdup_n_s32(a)), 0) @@ -10343,6 +11199,7 @@ pub unsafe fn vqshls_n_s32(a: i32) -> i32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqshl, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshld_n_s64(a: i64) -> i64 { static_assert_imm6!(N); simd_extract(vqshl_n_s64::(vdup_n_s64(a)), 0) @@ -10353,6 +11210,7 @@ pub unsafe fn vqshld_n_s64(a: i64) -> i64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqshl, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshlb_n_u8(a: u8) -> u8 { static_assert_imm3!(N); simd_extract(vqshl_n_u8::(vdup_n_u8(a)), 0) @@ -10363,6 +11221,7 @@ pub unsafe fn vqshlb_n_u8(a: u8) -> u8 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqshl, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshlh_n_u16(a: u16) -> u16 { static_assert_imm4!(N); simd_extract(vqshl_n_u16::(vdup_n_u16(a)), 0) @@ -10373,6 +11232,7 @@ pub unsafe fn vqshlh_n_u16(a: u16) -> u16 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqshl, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshls_n_u32(a: u32) -> u32 { static_assert_imm5!(N); simd_extract(vqshl_n_u32::(vdup_n_u32(a)), 0) @@ -10383,6 +11243,7 @@ pub unsafe fn vqshls_n_u32(a: u32) -> u32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqshl, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshld_n_u64(a: u64) -> u64 { static_assert_imm6!(N); simd_extract(vqshl_n_u64::(vdup_n_u64(a)), 0) @@ -10393,6 +11254,7 @@ pub unsafe fn vqshld_n_u64(a: u64) -> u64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqshlu, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshlub_n_s8(a: i8) -> u8 { static_assert_imm3!(N); simd_extract(vqshlu_n_s8::(vdup_n_s8(a)), 0) @@ -10403,6 +11265,7 @@ pub unsafe fn vqshlub_n_s8(a: i8) -> u8 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqshlu, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshluh_n_s16(a: i16) -> u16 { static_assert_imm4!(N); simd_extract(vqshlu_n_s16::(vdup_n_s16(a)), 0) @@ -10413,6 +11276,7 @@ pub unsafe fn vqshluh_n_s16(a: i16) -> u16 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqshlu, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshlus_n_s32(a: i32) -> u32 { static_assert_imm5!(N); simd_extract(vqshlu_n_s32::(vdup_n_s32(a)), 0) @@ -10423,6 +11287,7 @@ pub unsafe fn vqshlus_n_s32(a: i32) -> u32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqshlu, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshlud_n_s64(a: i64) -> u64 { static_assert_imm6!(N); simd_extract(vqshlu_n_s64::(vdup_n_s64(a)), 0) @@ -10433,6 +11298,7 @@ pub unsafe fn vqshlud_n_s64(a: i64) -> u64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrnd_n_s64(a: i64) -> i32 { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] @@ -10448,6 +11314,7 @@ pub unsafe fn vqshrnd_n_s64(a: i64) -> i32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrnh_n_s16(a: i16) -> i8 { static_assert!(N : i32 where N >= 1 && N <= 8); simd_extract(vqshrn_n_s16::(vdupq_n_s16(a)), 0) @@ -10458,6 +11325,7 @@ pub unsafe fn vqshrnh_n_s16(a: i16) -> i8 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrns_n_s32(a: i32) -> i16 { static_assert!(N : i32 where N >= 1 && N <= 16); simd_extract(vqshrn_n_s32::(vdupq_n_s32(a)), 0) @@ -10468,6 +11336,7 @@ pub unsafe fn vqshrns_n_s32(a: i32) -> i16 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqshrn2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrn_high_n_s16(a: int8x8_t, b: int16x8_t) -> int8x16_t { static_assert!(N : i32 where N >= 1 && N <= 8); simd_shuffle16!(a, vqshrn_n_s16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) @@ -10478,6 +11347,7 @@ pub unsafe fn vqshrn_high_n_s16(a: int8x8_t, b: int16x8_t) -> int8 #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqshrn2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrn_high_n_s32(a: int16x4_t, b: int32x4_t) -> int16x8_t { static_assert!(N : i32 where N >= 1 && N <= 16); simd_shuffle8!(a, vqshrn_n_s32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) @@ -10488,6 +11358,7 @@ pub unsafe fn vqshrn_high_n_s32(a: int16x4_t, b: int32x4_t) -> int #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqshrn2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrn_high_n_s64(a: int32x2_t, b: int64x2_t) -> int32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); simd_shuffle4!(a, vqshrn_n_s64::(b), [0, 1, 2, 3]) @@ -10498,6 +11369,7 @@ pub unsafe fn vqshrn_high_n_s64(a: int32x2_t, b: int64x2_t) -> int #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrnd_n_u64(a: u64) -> u32 { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] @@ -10513,6 +11385,7 @@ pub unsafe fn vqshrnd_n_u64(a: u64) -> u32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrnh_n_u16(a: u16) -> u8 { static_assert!(N : i32 where N >= 1 && N <= 8); simd_extract(vqshrn_n_u16::(vdupq_n_u16(a)), 0) @@ -10523,6 +11396,7 @@ pub unsafe fn vqshrnh_n_u16(a: u16) -> u8 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrns_n_u32(a: u32) -> u16 { static_assert!(N : i32 where N >= 1 && N <= 16); simd_extract(vqshrn_n_u32::(vdupq_n_u32(a)), 0) @@ -10533,6 +11407,7 @@ pub unsafe fn vqshrns_n_u32(a: u32) -> u16 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqshrn2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrn_high_n_u16(a: uint8x8_t, b: uint16x8_t) -> uint8x16_t { static_assert!(N : i32 where N >= 1 && N <= 8); simd_shuffle16!(a, vqshrn_n_u16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) @@ -10543,6 +11418,7 @@ pub unsafe fn vqshrn_high_n_u16(a: uint8x8_t, b: uint16x8_t) -> ui #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqshrn2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrn_high_n_u32(a: uint16x4_t, b: uint32x4_t) -> uint16x8_t { static_assert!(N : i32 where N >= 1 && N <= 16); simd_shuffle8!(a, vqshrn_n_u32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) @@ -10553,6 +11429,7 @@ pub unsafe fn vqshrn_high_n_u32(a: uint16x4_t, b: uint32x4_t) -> u #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uqshrn2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrn_high_n_u64(a: uint32x2_t, b: uint64x2_t) -> uint32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); simd_shuffle4!(a, vqshrn_n_u64::(b), [0, 1, 2, 3]) @@ -10563,6 +11440,7 @@ pub unsafe fn vqshrn_high_n_u64(a: uint32x2_t, b: uint64x2_t) -> u #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqshrun, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrunh_n_s16(a: i16) -> u8 { static_assert!(N : i32 where N >= 1 && N <= 8); simd_extract(vqshrun_n_s16::(vdupq_n_s16(a)), 0) @@ -10573,6 +11451,7 @@ pub unsafe fn vqshrunh_n_s16(a: i16) -> u8 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqshrun, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshruns_n_s32(a: i32) -> u16 { static_assert!(N : i32 where N >= 1 && N <= 16); simd_extract(vqshrun_n_s32::(vdupq_n_s32(a)), 0) @@ -10583,6 +11462,7 @@ pub unsafe fn vqshruns_n_s32(a: i32) -> u16 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqshrun, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrund_n_s64(a: i64) -> u32 { static_assert!(N : i32 where N >= 1 && N <= 32); simd_extract(vqshrun_n_s64::(vdupq_n_s64(a)), 0) @@ -10593,6 +11473,7 @@ pub unsafe fn vqshrund_n_s64(a: i64) -> u32 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqshrun2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrun_high_n_s16(a: uint8x8_t, b: int16x8_t) -> uint8x16_t { static_assert!(N : i32 where N >= 1 && N <= 8); simd_shuffle16!(a, vqshrun_n_s16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) @@ -10603,6 +11484,7 @@ pub unsafe fn vqshrun_high_n_s16(a: uint8x8_t, b: int16x8_t) -> ui #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqshrun2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrun_high_n_s32(a: uint16x4_t, b: int32x4_t) -> uint16x8_t { static_assert!(N : i32 where N >= 1 && N <= 16); simd_shuffle8!(a, vqshrun_n_s32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) @@ -10613,6 +11495,7 @@ pub unsafe fn vqshrun_high_n_s32(a: uint16x4_t, b: int32x4_t) -> u #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqshrun2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrun_high_n_s64(a: uint32x2_t, b: int64x2_t) -> uint32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); simd_shuffle4!(a, vqshrun_n_s64::(b), [0, 1, 2, 3]) @@ -10622,6 +11505,7 @@ pub unsafe fn vqshrun_high_n_s64(a: uint32x2_t, b: int64x2_t) -> u #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(usqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsqaddb_u8(a: u8, b: i8) -> u8 { simd_extract(vsqadd_u8(vdup_n_u8(a), vdup_n_s8(b)), 0) } @@ -10630,6 +11514,7 @@ pub unsafe fn vsqaddb_u8(a: u8, b: i8) -> u8 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(usqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsqaddh_u16(a: u16, b: i16) -> u16 { simd_extract(vsqadd_u16(vdup_n_u16(a), vdup_n_s16(b)), 0) } @@ -10638,6 +11523,7 @@ pub unsafe fn vsqaddh_u16(a: u16, b: i16) -> u16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(usqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsqadds_u32(a: u32, b: i32) -> u32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10651,6 +11537,7 @@ pub unsafe fn vsqadds_u32(a: u32, b: i32) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(usqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsqaddd_u64(a: u64, b: i64) -> u64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10664,6 +11551,7 @@ pub unsafe fn vsqaddd_u64(a: u64, b: i64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fsqrt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsqrt_f32(a: float32x2_t) -> float32x2_t { simd_fsqrt(a) } @@ -10672,6 +11560,7 @@ pub unsafe fn vsqrt_f32(a: float32x2_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fsqrt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsqrtq_f32(a: float32x4_t) -> float32x4_t { simd_fsqrt(a) } @@ -10680,6 +11569,7 @@ pub unsafe fn vsqrtq_f32(a: float32x4_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fsqrt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsqrt_f64(a: float64x1_t) -> float64x1_t { simd_fsqrt(a) } @@ -10688,6 +11578,7 @@ pub unsafe fn vsqrt_f64(a: float64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fsqrt))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsqrtq_f64(a: float64x2_t) -> float64x2_t { simd_fsqrt(a) } @@ -10696,6 +11587,7 @@ pub unsafe fn vsqrtq_f64(a: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frsqrte))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrsqrte_f64(a: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10709,6 +11601,7 @@ pub unsafe fn vrsqrte_f64(a: float64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frsqrte))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrsqrteq_f64(a: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10722,6 +11615,7 @@ pub unsafe fn vrsqrteq_f64(a: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frsqrte))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrsqrtes_f32(a: f32) -> f32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10735,6 +11629,7 @@ pub unsafe fn vrsqrtes_f32(a: f32) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frsqrte))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrsqrted_f64(a: f64) -> f64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10748,6 +11643,7 @@ pub unsafe fn vrsqrted_f64(a: f64) -> f64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frsqrts))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrsqrts_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10761,6 +11657,7 @@ pub unsafe fn vrsqrts_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frsqrts))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrsqrtsq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10774,6 +11671,7 @@ pub unsafe fn vrsqrtsq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frsqrts))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrsqrtss_f32(a: f32, b: f32) -> f32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10787,6 +11685,7 @@ pub unsafe fn vrsqrtss_f32(a: f32, b: f32) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frsqrts))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrsqrtsd_f64(a: f64, b: f64) -> f64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10800,6 +11699,7 @@ pub unsafe fn vrsqrtsd_f64(a: f64, b: f64) -> f64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frecpe))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrecpe_f64(a: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10813,6 +11713,7 @@ pub unsafe fn vrecpe_f64(a: float64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frecpe))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrecpeq_f64(a: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10826,6 +11727,7 @@ pub unsafe fn vrecpeq_f64(a: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frecpe))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrecpes_f32(a: f32) -> f32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10839,6 +11741,7 @@ pub unsafe fn vrecpes_f32(a: f32) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frecpe))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrecped_f64(a: f64) -> f64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10852,6 +11755,7 @@ pub unsafe fn vrecped_f64(a: f64) -> f64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frecps))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrecps_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10865,6 +11769,7 @@ pub unsafe fn vrecps_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frecps))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrecpsq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10878,6 +11783,7 @@ pub unsafe fn vrecpsq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frecps))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrecpss_f32(a: f32, b: f32) -> f32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10891,6 +11797,7 @@ pub unsafe fn vrecpss_f32(a: f32, b: f32) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frecps))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrecpsd_f64(a: f64, b: f64) -> f64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10904,6 +11811,7 @@ pub unsafe fn vrecpsd_f64(a: f64, b: f64) -> f64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frecpx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrecpxs_f32(a: f32) -> f32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10917,6 +11825,7 @@ pub unsafe fn vrecpxs_f32(a: f32) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(frecpx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrecpxd_f64(a: f64) -> f64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10930,6 +11839,7 @@ pub unsafe fn vrecpxd_f64(a: f64) -> f64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_s64_p64(a: poly64x1_t) -> int64x1_t { transmute(a) } @@ -10938,6 +11848,7 @@ pub unsafe fn vreinterpret_s64_p64(a: poly64x1_t) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_u64_p64(a: poly64x1_t) -> uint64x1_t { transmute(a) } @@ -10946,6 +11857,7 @@ pub unsafe fn vreinterpret_u64_p64(a: poly64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_p64_s64(a: int64x1_t) -> poly64x1_t { transmute(a) } @@ -10954,6 +11866,7 @@ pub unsafe fn vreinterpret_p64_s64(a: int64x1_t) -> poly64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_p64_u64(a: uint64x1_t) -> poly64x1_t { transmute(a) } @@ -10962,6 +11875,7 @@ pub unsafe fn vreinterpret_p64_u64(a: uint64x1_t) -> poly64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_s64_p64(a: poly64x2_t) -> int64x2_t { transmute(a) } @@ -10970,6 +11884,7 @@ pub unsafe fn vreinterpretq_s64_p64(a: poly64x2_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_u64_p64(a: poly64x2_t) -> uint64x2_t { transmute(a) } @@ -10978,6 +11893,7 @@ pub unsafe fn vreinterpretq_u64_p64(a: poly64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_p64_s64(a: int64x2_t) -> poly64x2_t { transmute(a) } @@ -10986,6 +11902,7 @@ pub unsafe fn vreinterpretq_p64_s64(a: int64x2_t) -> poly64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_p64_u64(a: uint64x2_t) -> poly64x2_t { transmute(a) } @@ -10994,6 +11911,7 @@ pub unsafe fn vreinterpretq_p64_u64(a: uint64x2_t) -> poly64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_s8_f64(a: float64x1_t) -> int8x8_t { transmute(a) } @@ -11002,6 +11920,7 @@ pub unsafe fn vreinterpret_s8_f64(a: float64x1_t) -> int8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_s16_f64(a: float64x1_t) -> int16x4_t { transmute(a) } @@ -11010,6 +11929,7 @@ pub unsafe fn vreinterpret_s16_f64(a: float64x1_t) -> int16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_s32_f64(a: float64x1_t) -> int32x2_t { transmute(a) } @@ -11018,6 +11938,7 @@ pub unsafe fn vreinterpret_s32_f64(a: float64x1_t) -> int32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_s64_f64(a: float64x1_t) -> int64x1_t { transmute(a) } @@ -11026,6 +11947,7 @@ pub unsafe fn vreinterpret_s64_f64(a: float64x1_t) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_s8_f64(a: float64x2_t) -> int8x16_t { transmute(a) } @@ -11034,6 +11956,7 @@ pub unsafe fn vreinterpretq_s8_f64(a: float64x2_t) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_s16_f64(a: float64x2_t) -> int16x8_t { transmute(a) } @@ -11042,6 +11965,7 @@ pub unsafe fn vreinterpretq_s16_f64(a: float64x2_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_s32_f64(a: float64x2_t) -> int32x4_t { transmute(a) } @@ -11050,6 +11974,7 @@ pub unsafe fn vreinterpretq_s32_f64(a: float64x2_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_s64_f64(a: float64x2_t) -> int64x2_t { transmute(a) } @@ -11058,6 +11983,7 @@ pub unsafe fn vreinterpretq_s64_f64(a: float64x2_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_u8_f64(a: float64x1_t) -> uint8x8_t { transmute(a) } @@ -11066,6 +11992,7 @@ pub unsafe fn vreinterpret_u8_f64(a: float64x1_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_u16_f64(a: float64x1_t) -> uint16x4_t { transmute(a) } @@ -11074,6 +12001,7 @@ pub unsafe fn vreinterpret_u16_f64(a: float64x1_t) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_u32_f64(a: float64x1_t) -> uint32x2_t { transmute(a) } @@ -11082,6 +12010,7 @@ pub unsafe fn vreinterpret_u32_f64(a: float64x1_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_u64_f64(a: float64x1_t) -> uint64x1_t { transmute(a) } @@ -11090,6 +12019,7 @@ pub unsafe fn vreinterpret_u64_f64(a: float64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_u8_f64(a: float64x2_t) -> uint8x16_t { transmute(a) } @@ -11098,6 +12028,7 @@ pub unsafe fn vreinterpretq_u8_f64(a: float64x2_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_u16_f64(a: float64x2_t) -> uint16x8_t { transmute(a) } @@ -11106,6 +12037,7 @@ pub unsafe fn vreinterpretq_u16_f64(a: float64x2_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_u32_f64(a: float64x2_t) -> uint32x4_t { transmute(a) } @@ -11114,6 +12046,7 @@ pub unsafe fn vreinterpretq_u32_f64(a: float64x2_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_u64_f64(a: float64x2_t) -> uint64x2_t { transmute(a) } @@ -11122,6 +12055,7 @@ pub unsafe fn vreinterpretq_u64_f64(a: float64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_p8_f64(a: float64x1_t) -> poly8x8_t { transmute(a) } @@ -11130,6 +12064,7 @@ pub unsafe fn vreinterpret_p8_f64(a: float64x1_t) -> poly8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_p16_f64(a: float64x1_t) -> poly16x4_t { transmute(a) } @@ -11138,6 +12073,7 @@ pub unsafe fn vreinterpret_p16_f64(a: float64x1_t) -> poly16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_p64_f32(a: float32x2_t) -> poly64x1_t { transmute(a) } @@ -11146,6 +12082,7 @@ pub unsafe fn vreinterpret_p64_f32(a: float32x2_t) -> poly64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_p64_f64(a: float64x1_t) -> poly64x1_t { transmute(a) } @@ -11154,6 +12091,7 @@ pub unsafe fn vreinterpret_p64_f64(a: float64x1_t) -> poly64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_p8_f64(a: float64x2_t) -> poly8x16_t { transmute(a) } @@ -11162,6 +12100,7 @@ pub unsafe fn vreinterpretq_p8_f64(a: float64x2_t) -> poly8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_p16_f64(a: float64x2_t) -> poly16x8_t { transmute(a) } @@ -11170,6 +12109,7 @@ pub unsafe fn vreinterpretq_p16_f64(a: float64x2_t) -> poly16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_p64_f32(a: float32x4_t) -> poly64x2_t { transmute(a) } @@ -11178,6 +12118,7 @@ pub unsafe fn vreinterpretq_p64_f32(a: float32x4_t) -> poly64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_p64_f64(a: float64x2_t) -> poly64x2_t { transmute(a) } @@ -11186,6 +12127,7 @@ pub unsafe fn vreinterpretq_p64_f64(a: float64x2_t) -> poly64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_p128_f64(a: float64x2_t) -> p128 { transmute(a) } @@ -11194,6 +12136,7 @@ pub unsafe fn vreinterpretq_p128_f64(a: float64x2_t) -> p128 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_f64_s8(a: int8x8_t) -> float64x1_t { transmute(a) } @@ -11202,6 +12145,7 @@ pub unsafe fn vreinterpret_f64_s8(a: int8x8_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_f64_s16(a: int16x4_t) -> float64x1_t { transmute(a) } @@ -11210,6 +12154,7 @@ pub unsafe fn vreinterpret_f64_s16(a: int16x4_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_f64_s32(a: int32x2_t) -> float64x1_t { transmute(a) } @@ -11218,6 +12163,7 @@ pub unsafe fn vreinterpret_f64_s32(a: int32x2_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_f64_s64(a: int64x1_t) -> float64x1_t { transmute(a) } @@ -11226,6 +12172,7 @@ pub unsafe fn vreinterpret_f64_s64(a: int64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_f64_s8(a: int8x16_t) -> float64x2_t { transmute(a) } @@ -11234,6 +12181,7 @@ pub unsafe fn vreinterpretq_f64_s8(a: int8x16_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_f64_s16(a: int16x8_t) -> float64x2_t { transmute(a) } @@ -11242,6 +12190,7 @@ pub unsafe fn vreinterpretq_f64_s16(a: int16x8_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_f64_s32(a: int32x4_t) -> float64x2_t { transmute(a) } @@ -11250,6 +12199,7 @@ pub unsafe fn vreinterpretq_f64_s32(a: int32x4_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_f64_s64(a: int64x2_t) -> float64x2_t { transmute(a) } @@ -11258,6 +12208,7 @@ pub unsafe fn vreinterpretq_f64_s64(a: int64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_f64_p8(a: poly8x8_t) -> float64x1_t { transmute(a) } @@ -11266,6 +12217,7 @@ pub unsafe fn vreinterpret_f64_p8(a: poly8x8_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_f64_u16(a: uint16x4_t) -> float64x1_t { transmute(a) } @@ -11274,6 +12226,7 @@ pub unsafe fn vreinterpret_f64_u16(a: uint16x4_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_f64_u32(a: uint32x2_t) -> float64x1_t { transmute(a) } @@ -11282,6 +12235,7 @@ pub unsafe fn vreinterpret_f64_u32(a: uint32x2_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_f64_u64(a: uint64x1_t) -> float64x1_t { transmute(a) } @@ -11290,6 +12244,7 @@ pub unsafe fn vreinterpret_f64_u64(a: uint64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_f64_p8(a: poly8x16_t) -> float64x2_t { transmute(a) } @@ -11298,6 +12253,7 @@ pub unsafe fn vreinterpretq_f64_p8(a: poly8x16_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_f64_u16(a: uint16x8_t) -> float64x2_t { transmute(a) } @@ -11306,6 +12262,7 @@ pub unsafe fn vreinterpretq_f64_u16(a: uint16x8_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_f64_u32(a: uint32x4_t) -> float64x2_t { transmute(a) } @@ -11314,6 +12271,7 @@ pub unsafe fn vreinterpretq_f64_u32(a: uint32x4_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_f64_u64(a: uint64x2_t) -> float64x2_t { transmute(a) } @@ -11322,6 +12280,7 @@ pub unsafe fn vreinterpretq_f64_u64(a: uint64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_f64_u8(a: uint8x8_t) -> float64x1_t { transmute(a) } @@ -11330,6 +12289,7 @@ pub unsafe fn vreinterpret_f64_u8(a: uint8x8_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_f64_p16(a: poly16x4_t) -> float64x1_t { transmute(a) } @@ -11338,6 +12298,7 @@ pub unsafe fn vreinterpret_f64_p16(a: poly16x4_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_f64_p64(a: poly64x1_t) -> float64x1_t { transmute(a) } @@ -11346,6 +12307,7 @@ pub unsafe fn vreinterpret_f64_p64(a: poly64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_f32_p64(a: poly64x1_t) -> float32x2_t { transmute(a) } @@ -11354,6 +12316,7 @@ pub unsafe fn vreinterpret_f32_p64(a: poly64x1_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_f64_u8(a: uint8x16_t) -> float64x2_t { transmute(a) } @@ -11362,6 +12325,7 @@ pub unsafe fn vreinterpretq_f64_u8(a: uint8x16_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_f64_p16(a: poly16x8_t) -> float64x2_t { transmute(a) } @@ -11370,6 +12334,7 @@ pub unsafe fn vreinterpretq_f64_p16(a: poly16x8_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_f64_p64(a: poly64x2_t) -> float64x2_t { transmute(a) } @@ -11378,6 +12343,7 @@ pub unsafe fn vreinterpretq_f64_p64(a: poly64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_f32_p64(a: poly64x2_t) -> float32x4_t { transmute(a) } @@ -11386,6 +12352,7 @@ pub unsafe fn vreinterpretq_f32_p64(a: poly64x2_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_f64_p128(a: p128) -> float64x2_t { transmute(a) } @@ -11394,6 +12361,7 @@ pub unsafe fn vreinterpretq_f64_p128(a: p128) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_f64_f32(a: float32x2_t) -> float64x1_t { transmute(a) } @@ -11402,6 +12370,7 @@ pub unsafe fn vreinterpret_f64_f32(a: float32x2_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpret_f32_f64(a: float64x1_t) -> float32x2_t { transmute(a) } @@ -11410,6 +12379,7 @@ pub unsafe fn vreinterpret_f32_f64(a: float64x1_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_f64_f32(a: float32x4_t) -> float64x2_t { transmute(a) } @@ -11418,6 +12388,7 @@ pub unsafe fn vreinterpretq_f64_f32(a: float32x4_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vreinterpretq_f32_f64(a: float64x2_t) -> float32x4_t { transmute(a) } @@ -11426,6 +12397,7 @@ pub unsafe fn vreinterpretq_f32_f64(a: float64x2_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(srshl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrshld_s64(a: i64, b: i64) -> i64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -11439,6 +12411,7 @@ pub unsafe fn vrshld_s64(a: i64, b: i64) -> i64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(urshl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrshld_u64(a: u64, b: i64) -> u64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -11453,6 +12426,7 @@ pub unsafe fn vrshld_u64(a: u64, b: i64) -> u64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(srshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrshrd_n_s64(a: i64) -> i64 { static_assert!(N : i32 where N >= 1 && N <= 64); vrshld_s64(a, -N as i64) @@ -11463,6 +12437,7 @@ pub unsafe fn vrshrd_n_s64(a: i64) -> i64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(urshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrshrd_n_u64(a: u64) -> u64 { static_assert!(N : i32 where N >= 1 && N <= 64); vrshld_u64(a, -N as i64) @@ -11473,6 +12448,7 @@ pub unsafe fn vrshrd_n_u64(a: u64) -> u64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(rshrn2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrshrn_high_n_s16(a: int8x8_t, b: int16x8_t) -> int8x16_t { static_assert!(N : i32 where N >= 1 && N <= 8); simd_shuffle16!(a, vrshrn_n_s16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) @@ -11483,6 +12459,7 @@ pub unsafe fn vrshrn_high_n_s16(a: int8x8_t, b: int16x8_t) -> int8 #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(rshrn2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrshrn_high_n_s32(a: int16x4_t, b: int32x4_t) -> int16x8_t { static_assert!(N : i32 where N >= 1 && N <= 16); simd_shuffle8!(a, vrshrn_n_s32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) @@ -11493,6 +12470,7 @@ pub unsafe fn vrshrn_high_n_s32(a: int16x4_t, b: int32x4_t) -> int #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(rshrn2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrshrn_high_n_s64(a: int32x2_t, b: int64x2_t) -> int32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); simd_shuffle4!(a, vrshrn_n_s64::(b), [0, 1, 2, 3]) @@ -11503,6 +12481,7 @@ pub unsafe fn vrshrn_high_n_s64(a: int32x2_t, b: int64x2_t) -> int #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(rshrn2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrshrn_high_n_u16(a: uint8x8_t, b: uint16x8_t) -> uint8x16_t { static_assert!(N : i32 where N >= 1 && N <= 8); simd_shuffle16!(a, vrshrn_n_u16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) @@ -11513,6 +12492,7 @@ pub unsafe fn vrshrn_high_n_u16(a: uint8x8_t, b: uint16x8_t) -> ui #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(rshrn2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrshrn_high_n_u32(a: uint16x4_t, b: uint32x4_t) -> uint16x8_t { static_assert!(N : i32 where N >= 1 && N <= 16); simd_shuffle8!(a, vrshrn_n_u32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) @@ -11523,6 +12503,7 @@ pub unsafe fn vrshrn_high_n_u32(a: uint16x4_t, b: uint32x4_t) -> u #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(rshrn2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrshrn_high_n_u64(a: uint32x2_t, b: uint64x2_t) -> uint32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); simd_shuffle4!(a, vrshrn_n_u64::(b), [0, 1, 2, 3]) @@ -11533,10 +12514,11 @@ pub unsafe fn vrshrn_high_n_u64(a: uint32x2_t, b: uint64x2_t) -> u #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(srsra, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrsrad_n_s64(a: i64, b: i64) -> i64 { static_assert!(N : i32 where N >= 1 && N <= 64); let b: i64 = vrshrd_n_s64::(b); - a + b + a.wrapping_add(b) } /// Ungisned rounding shift right and accumulate. @@ -11544,16 +12526,18 @@ pub unsafe fn vrsrad_n_s64(a: i64, b: i64) -> i64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ursra, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrsrad_n_u64(a: u64, b: u64) -> u64 { static_assert!(N : i32 where N >= 1 && N <= 64); let b: u64 = vrshrd_n_u64::(b); - a + b + a.wrapping_add(b) } /// Rounding subtract returning high narrow #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(rsubhn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrsubhn_high_s16(a: int8x8_t, b: int16x8_t, c: int16x8_t) -> int8x16_t { let x: int8x8_t = vrsubhn_s16(b, c); simd_shuffle16!(a, x, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) @@ -11563,6 +12547,7 @@ pub unsafe fn vrsubhn_high_s16(a: int8x8_t, b: int16x8_t, c: int16x8_t) -> int8x #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(rsubhn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrsubhn_high_s32(a: int16x4_t, b: int32x4_t, c: int32x4_t) -> int16x8_t { let x: int16x4_t = vrsubhn_s32(b, c); simd_shuffle8!(a, x, [0, 1, 2, 3, 4, 5, 6, 7]) @@ -11572,6 +12557,7 @@ pub unsafe fn vrsubhn_high_s32(a: int16x4_t, b: int32x4_t, c: int32x4_t) -> int1 #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(rsubhn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrsubhn_high_s64(a: int32x2_t, b: int64x2_t, c: int64x2_t) -> int32x4_t { let x: int32x2_t = vrsubhn_s64(b, c); simd_shuffle4!(a, x, [0, 1, 2, 3]) @@ -11581,6 +12567,7 @@ pub unsafe fn vrsubhn_high_s64(a: int32x2_t, b: int64x2_t, c: int64x2_t) -> int3 #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(rsubhn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrsubhn_high_u16(a: uint8x8_t, b: uint16x8_t, c: uint16x8_t) -> uint8x16_t { let x: uint8x8_t = vrsubhn_u16(b, c); simd_shuffle16!(a, x, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) @@ -11590,6 +12577,7 @@ pub unsafe fn vrsubhn_high_u16(a: uint8x8_t, b: uint16x8_t, c: uint16x8_t) -> ui #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(rsubhn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrsubhn_high_u32(a: uint16x4_t, b: uint32x4_t, c: uint32x4_t) -> uint16x8_t { let x: uint16x4_t = vrsubhn_u32(b, c); simd_shuffle8!(a, x, [0, 1, 2, 3, 4, 5, 6, 7]) @@ -11599,6 +12587,7 @@ pub unsafe fn vrsubhn_high_u32(a: uint16x4_t, b: uint32x4_t, c: uint32x4_t) -> u #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(rsubhn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrsubhn_high_u64(a: uint32x2_t, b: uint64x2_t, c: uint64x2_t) -> uint32x4_t { let x: uint32x2_t = vrsubhn_u64(b, c); simd_shuffle4!(a, x, [0, 1, 2, 3]) @@ -11609,6 +12598,7 @@ pub unsafe fn vrsubhn_high_u64(a: uint32x2_t, b: uint64x2_t, c: uint64x2_t) -> u #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vset_lane_f64(a: f64, b: float64x1_t) -> float64x1_t { static_assert!(LANE : i32 where LANE == 0); simd_insert(b, LANE as u32, a) @@ -11619,6 +12609,7 @@ pub unsafe fn vset_lane_f64(a: f64, b: float64x1_t) -> float64x #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsetq_lane_f64(a: f64, b: float64x2_t) -> float64x2_t { static_assert_imm1!(LANE); simd_insert(b, LANE as u32, a) @@ -11628,6 +12619,7 @@ pub unsafe fn vsetq_lane_f64(a: f64, b: float64x2_t) -> float64 #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sshl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vshld_s64(a: i64, b: i64) -> i64 { transmute(vshl_s64(transmute(a), transmute(b))) } @@ -11636,6 +12628,7 @@ pub unsafe fn vshld_s64(a: i64, b: i64) -> i64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ushl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vshld_u64(a: u64, b: i64) -> u64 { transmute(vshl_u64(transmute(a), transmute(b))) } @@ -11645,6 +12638,7 @@ pub unsafe fn vshld_u64(a: u64, b: i64) -> u64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sshll2, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vshll_high_n_s8(a: int8x16_t) -> int16x8_t { static_assert!(N : i32 where N >= 0 && N <= 8); let b: int8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); @@ -11656,6 +12650,7 @@ pub unsafe fn vshll_high_n_s8(a: int8x16_t) -> int16x8_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sshll2, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vshll_high_n_s16(a: int16x8_t) -> int32x4_t { static_assert!(N : i32 where N >= 0 && N <= 16); let b: int16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); @@ -11667,6 +12662,7 @@ pub unsafe fn vshll_high_n_s16(a: int16x8_t) -> int32x4_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sshll2, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vshll_high_n_s32(a: int32x4_t) -> int64x2_t { static_assert!(N : i32 where N >= 0 && N <= 32); let b: int32x2_t = simd_shuffle2!(a, a, [2, 3]); @@ -11678,6 +12674,7 @@ pub unsafe fn vshll_high_n_s32(a: int32x4_t) -> int64x2_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ushll2, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vshll_high_n_u8(a: uint8x16_t) -> uint16x8_t { static_assert!(N : i32 where N >= 0 && N <= 8); let b: uint8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); @@ -11689,6 +12686,7 @@ pub unsafe fn vshll_high_n_u8(a: uint8x16_t) -> uint16x8_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ushll2, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vshll_high_n_u16(a: uint16x8_t) -> uint32x4_t { static_assert!(N : i32 where N >= 0 && N <= 16); let b: uint16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); @@ -11700,6 +12698,7 @@ pub unsafe fn vshll_high_n_u16(a: uint16x8_t) -> uint32x4_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ushll2, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vshll_high_n_u32(a: uint32x4_t) -> uint64x2_t { static_assert!(N : i32 where N >= 0 && N <= 32); let b: uint32x2_t = simd_shuffle2!(a, a, [2, 3]); @@ -11711,6 +12710,7 @@ pub unsafe fn vshll_high_n_u32(a: uint32x4_t) -> uint64x2_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(shrn2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vshrn_high_n_s16(a: int8x8_t, b: int16x8_t) -> int8x16_t { static_assert!(N : i32 where N >= 1 && N <= 8); simd_shuffle16!(a, vshrn_n_s16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) @@ -11721,6 +12721,7 @@ pub unsafe fn vshrn_high_n_s16(a: int8x8_t, b: int16x8_t) -> int8x #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(shrn2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vshrn_high_n_s32(a: int16x4_t, b: int32x4_t) -> int16x8_t { static_assert!(N : i32 where N >= 1 && N <= 16); simd_shuffle8!(a, vshrn_n_s32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) @@ -11731,6 +12732,7 @@ pub unsafe fn vshrn_high_n_s32(a: int16x4_t, b: int32x4_t) -> int1 #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(shrn2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vshrn_high_n_s64(a: int32x2_t, b: int64x2_t) -> int32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); simd_shuffle4!(a, vshrn_n_s64::(b), [0, 1, 2, 3]) @@ -11741,6 +12743,7 @@ pub unsafe fn vshrn_high_n_s64(a: int32x2_t, b: int64x2_t) -> int3 #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(shrn2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vshrn_high_n_u16(a: uint8x8_t, b: uint16x8_t) -> uint8x16_t { static_assert!(N : i32 where N >= 1 && N <= 8); simd_shuffle16!(a, vshrn_n_u16::(b), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) @@ -11751,6 +12754,7 @@ pub unsafe fn vshrn_high_n_u16(a: uint8x8_t, b: uint16x8_t) -> uin #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(shrn2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vshrn_high_n_u32(a: uint16x4_t, b: uint32x4_t) -> uint16x8_t { static_assert!(N : i32 where N >= 1 && N <= 16); simd_shuffle8!(a, vshrn_n_u32::(b), [0, 1, 2, 3, 4, 5, 6, 7]) @@ -11761,6 +12765,7 @@ pub unsafe fn vshrn_high_n_u32(a: uint16x4_t, b: uint32x4_t) -> ui #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(shrn2, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vshrn_high_n_u64(a: uint32x2_t, b: uint64x2_t) -> uint32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); simd_shuffle4!(a, vshrn_n_u64::(b), [0, 1, 2, 3]) @@ -12004,6 +13009,7 @@ pub unsafe fn vrnd64zq_f32(a: float32x4_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn1_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]) } @@ -12012,6 +13018,7 @@ pub unsafe fn vtrn1_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn1q_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { simd_shuffle16!(a, b, [0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30]) } @@ -12020,6 +13027,7 @@ pub unsafe fn vtrn1q_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn1_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { simd_shuffle4!(a, b, [0, 4, 2, 6]) } @@ -12028,6 +13036,7 @@ pub unsafe fn vtrn1_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn1q_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]) } @@ -12036,6 +13045,7 @@ pub unsafe fn vtrn1q_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn1q_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { simd_shuffle4!(a, b, [0, 4, 2, 6]) } @@ -12044,6 +13054,7 @@ pub unsafe fn vtrn1q_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn1_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]) } @@ -12052,6 +13063,7 @@ pub unsafe fn vtrn1_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn1q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { simd_shuffle16!(a, b, [0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30]) } @@ -12060,6 +13072,7 @@ pub unsafe fn vtrn1q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn1_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { simd_shuffle4!(a, b, [0, 4, 2, 6]) } @@ -12068,6 +13081,7 @@ pub unsafe fn vtrn1_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn1q_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]) } @@ -12076,6 +13090,7 @@ pub unsafe fn vtrn1q_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn1q_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { simd_shuffle4!(a, b, [0, 4, 2, 6]) } @@ -12084,6 +13099,7 @@ pub unsafe fn vtrn1q_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn1_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]) } @@ -12092,6 +13108,7 @@ pub unsafe fn vtrn1_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn1q_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { simd_shuffle16!(a, b, [0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30]) } @@ -12100,6 +13117,7 @@ pub unsafe fn vtrn1q_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn1_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { simd_shuffle4!(a, b, [0, 4, 2, 6]) } @@ -12108,6 +13126,7 @@ pub unsafe fn vtrn1_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn1q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]) } @@ -12116,6 +13135,7 @@ pub unsafe fn vtrn1q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn1_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { simd_shuffle2!(a, b, [0, 2]) } @@ -12124,6 +13144,7 @@ pub unsafe fn vtrn1_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn1q_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { simd_shuffle2!(a, b, [0, 2]) } @@ -12132,6 +13153,7 @@ pub unsafe fn vtrn1q_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn1_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { simd_shuffle2!(a, b, [0, 2]) } @@ -12140,6 +13162,7 @@ pub unsafe fn vtrn1_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn1q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { simd_shuffle2!(a, b, [0, 2]) } @@ -12148,6 +13171,7 @@ pub unsafe fn vtrn1q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn1q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { simd_shuffle2!(a, b, [0, 2]) } @@ -12156,6 +13180,7 @@ pub unsafe fn vtrn1q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn1q_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { simd_shuffle4!(a, b, [0, 4, 2, 6]) } @@ -12164,6 +13189,7 @@ pub unsafe fn vtrn1q_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn1_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { simd_shuffle2!(a, b, [0, 2]) } @@ -12172,6 +13198,7 @@ pub unsafe fn vtrn1_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn1q_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { simd_shuffle2!(a, b, [0, 2]) } @@ -12180,6 +13207,7 @@ pub unsafe fn vtrn1q_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn2_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]) } @@ -12188,6 +13216,7 @@ pub unsafe fn vtrn2_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn2q_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { simd_shuffle16!(a, b, [1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31]) } @@ -12196,6 +13225,7 @@ pub unsafe fn vtrn2q_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn2_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { simd_shuffle4!(a, b, [1, 5, 3, 7]) } @@ -12204,6 +13234,7 @@ pub unsafe fn vtrn2_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn2q_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]) } @@ -12212,6 +13243,7 @@ pub unsafe fn vtrn2q_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn2q_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { simd_shuffle4!(a, b, [1, 5, 3, 7]) } @@ -12220,6 +13252,7 @@ pub unsafe fn vtrn2q_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn2_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]) } @@ -12228,6 +13261,7 @@ pub unsafe fn vtrn2_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn2q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { simd_shuffle16!(a, b, [1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31]) } @@ -12236,6 +13270,7 @@ pub unsafe fn vtrn2q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn2_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { simd_shuffle4!(a, b, [1, 5, 3, 7]) } @@ -12244,6 +13279,7 @@ pub unsafe fn vtrn2_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn2q_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]) } @@ -12252,6 +13288,7 @@ pub unsafe fn vtrn2q_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn2q_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { simd_shuffle4!(a, b, [1, 5, 3, 7]) } @@ -12260,6 +13297,7 @@ pub unsafe fn vtrn2q_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn2_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]) } @@ -12268,6 +13306,7 @@ pub unsafe fn vtrn2_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn2q_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { simd_shuffle16!(a, b, [1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31]) } @@ -12276,6 +13315,7 @@ pub unsafe fn vtrn2q_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn2_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { simd_shuffle4!(a, b, [1, 5, 3, 7]) } @@ -12284,6 +13324,7 @@ pub unsafe fn vtrn2_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn2q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]) } @@ -12292,6 +13333,7 @@ pub unsafe fn vtrn2q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn2_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { simd_shuffle2!(a, b, [1, 3]) } @@ -12300,6 +13342,7 @@ pub unsafe fn vtrn2_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn2q_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { simd_shuffle2!(a, b, [1, 3]) } @@ -12308,6 +13351,7 @@ pub unsafe fn vtrn2q_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn2_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { simd_shuffle2!(a, b, [1, 3]) } @@ -12316,6 +13360,7 @@ pub unsafe fn vtrn2_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn2q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { simd_shuffle2!(a, b, [1, 3]) } @@ -12324,6 +13369,7 @@ pub unsafe fn vtrn2q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn2q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { simd_shuffle2!(a, b, [1, 3]) } @@ -12332,6 +13378,7 @@ pub unsafe fn vtrn2q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(trn2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn2q_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { simd_shuffle4!(a, b, [1, 5, 3, 7]) } @@ -12340,6 +13387,7 @@ pub unsafe fn vtrn2q_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn2_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { simd_shuffle2!(a, b, [1, 3]) } @@ -12348,6 +13396,7 @@ pub unsafe fn vtrn2_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtrn2q_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { simd_shuffle2!(a, b, [1, 3]) } @@ -12356,6 +13405,7 @@ pub unsafe fn vtrn2q_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip1_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]) } @@ -12364,6 +13414,7 @@ pub unsafe fn vzip1_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip1q_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { simd_shuffle16!(a, b, [0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23]) } @@ -12372,6 +13423,7 @@ pub unsafe fn vzip1q_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip1_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { simd_shuffle4!(a, b, [0, 4, 1, 5]) } @@ -12380,6 +13432,7 @@ pub unsafe fn vzip1_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip1q_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]) } @@ -12388,6 +13441,7 @@ pub unsafe fn vzip1q_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip1_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { simd_shuffle2!(a, b, [0, 2]) } @@ -12396,6 +13450,7 @@ pub unsafe fn vzip1_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip1q_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { simd_shuffle4!(a, b, [0, 4, 1, 5]) } @@ -12404,6 +13459,7 @@ pub unsafe fn vzip1q_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip1q_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { simd_shuffle2!(a, b, [0, 2]) } @@ -12412,6 +13468,7 @@ pub unsafe fn vzip1q_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip1_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]) } @@ -12420,6 +13477,7 @@ pub unsafe fn vzip1_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip1q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { simd_shuffle16!(a, b, [0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23]) } @@ -12428,6 +13486,7 @@ pub unsafe fn vzip1q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip1_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { simd_shuffle4!(a, b, [0, 4, 1, 5]) } @@ -12436,6 +13495,7 @@ pub unsafe fn vzip1_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip1q_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]) } @@ -12444,6 +13504,7 @@ pub unsafe fn vzip1q_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip1_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { simd_shuffle2!(a, b, [0, 2]) } @@ -12452,6 +13513,7 @@ pub unsafe fn vzip1_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip1q_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { simd_shuffle4!(a, b, [0, 4, 1, 5]) } @@ -12460,6 +13522,7 @@ pub unsafe fn vzip1q_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip1q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { simd_shuffle2!(a, b, [0, 2]) } @@ -12468,6 +13531,7 @@ pub unsafe fn vzip1q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip1_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]) } @@ -12476,6 +13540,7 @@ pub unsafe fn vzip1_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip1q_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { simd_shuffle16!(a, b, [0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23]) } @@ -12484,6 +13549,7 @@ pub unsafe fn vzip1q_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip1_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { simd_shuffle4!(a, b, [0, 4, 1, 5]) } @@ -12492,6 +13558,7 @@ pub unsafe fn vzip1_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip1q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]) } @@ -12500,6 +13567,7 @@ pub unsafe fn vzip1q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip1q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { simd_shuffle2!(a, b, [0, 2]) } @@ -12508,6 +13576,7 @@ pub unsafe fn vzip1q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip1_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { simd_shuffle2!(a, b, [0, 2]) } @@ -12516,6 +13585,7 @@ pub unsafe fn vzip1_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip1q_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { simd_shuffle4!(a, b, [0, 4, 1, 5]) } @@ -12524,6 +13594,7 @@ pub unsafe fn vzip1q_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip1q_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { simd_shuffle2!(a, b, [0, 2]) } @@ -12532,6 +13603,7 @@ pub unsafe fn vzip1q_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip2_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]) } @@ -12540,6 +13612,7 @@ pub unsafe fn vzip2_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip2q_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { simd_shuffle16!(a, b, [8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31]) } @@ -12548,6 +13621,7 @@ pub unsafe fn vzip2q_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip2_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { simd_shuffle4!(a, b, [2, 6, 3, 7]) } @@ -12556,6 +13630,7 @@ pub unsafe fn vzip2_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip2q_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]) } @@ -12564,6 +13639,7 @@ pub unsafe fn vzip2q_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip2_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { simd_shuffle2!(a, b, [1, 3]) } @@ -12572,6 +13648,7 @@ pub unsafe fn vzip2_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip2q_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { simd_shuffle4!(a, b, [2, 6, 3, 7]) } @@ -12580,6 +13657,7 @@ pub unsafe fn vzip2q_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip2q_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { simd_shuffle2!(a, b, [1, 3]) } @@ -12588,6 +13666,7 @@ pub unsafe fn vzip2q_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip2_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]) } @@ -12596,6 +13675,7 @@ pub unsafe fn vzip2_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip2q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { simd_shuffle16!(a, b, [8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31]) } @@ -12604,6 +13684,7 @@ pub unsafe fn vzip2q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip2_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { simd_shuffle4!(a, b, [2, 6, 3, 7]) } @@ -12612,6 +13693,7 @@ pub unsafe fn vzip2_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip2q_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]) } @@ -12620,6 +13702,7 @@ pub unsafe fn vzip2q_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip2_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { simd_shuffle2!(a, b, [1, 3]) } @@ -12628,6 +13711,7 @@ pub unsafe fn vzip2_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip2q_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { simd_shuffle4!(a, b, [2, 6, 3, 7]) } @@ -12636,6 +13720,7 @@ pub unsafe fn vzip2q_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip2q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { simd_shuffle2!(a, b, [1, 3]) } @@ -12644,6 +13729,7 @@ pub unsafe fn vzip2q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip2_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]) } @@ -12652,6 +13738,7 @@ pub unsafe fn vzip2_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip2q_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { simd_shuffle16!(a, b, [8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31]) } @@ -12660,6 +13747,7 @@ pub unsafe fn vzip2q_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip2_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { simd_shuffle4!(a, b, [2, 6, 3, 7]) } @@ -12668,6 +13756,7 @@ pub unsafe fn vzip2_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip2q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]) } @@ -12676,6 +13765,7 @@ pub unsafe fn vzip2q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip2q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { simd_shuffle2!(a, b, [1, 3]) } @@ -12684,6 +13774,7 @@ pub unsafe fn vzip2q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip2_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { simd_shuffle2!(a, b, [1, 3]) } @@ -12692,6 +13783,7 @@ pub unsafe fn vzip2_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip2q_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { simd_shuffle4!(a, b, [2, 6, 3, 7]) } @@ -12700,6 +13792,7 @@ pub unsafe fn vzip2q_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vzip2q_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { simd_shuffle2!(a, b, [1, 3]) } @@ -12708,6 +13801,7 @@ pub unsafe fn vzip2q_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp1_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]) } @@ -12716,6 +13810,7 @@ pub unsafe fn vuzp1_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp1q_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { simd_shuffle16!(a, b, [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]) } @@ -12724,6 +13819,7 @@ pub unsafe fn vuzp1q_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp1_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { simd_shuffle4!(a, b, [0, 2, 4, 6]) } @@ -12732,6 +13828,7 @@ pub unsafe fn vuzp1_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp1q_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]) } @@ -12740,6 +13837,7 @@ pub unsafe fn vuzp1q_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp1q_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { simd_shuffle4!(a, b, [0, 2, 4, 6]) } @@ -12748,6 +13846,7 @@ pub unsafe fn vuzp1q_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp1_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]) } @@ -12756,6 +13855,7 @@ pub unsafe fn vuzp1_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp1q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { simd_shuffle16!(a, b, [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]) } @@ -12764,6 +13864,7 @@ pub unsafe fn vuzp1q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp1_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { simd_shuffle4!(a, b, [0, 2, 4, 6]) } @@ -12772,6 +13873,7 @@ pub unsafe fn vuzp1_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp1q_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]) } @@ -12780,6 +13882,7 @@ pub unsafe fn vuzp1q_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp1q_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { simd_shuffle4!(a, b, [0, 2, 4, 6]) } @@ -12788,6 +13891,7 @@ pub unsafe fn vuzp1q_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp1_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]) } @@ -12796,6 +13900,7 @@ pub unsafe fn vuzp1_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp1q_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { simd_shuffle16!(a, b, [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]) } @@ -12804,6 +13909,7 @@ pub unsafe fn vuzp1q_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp1_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { simd_shuffle4!(a, b, [0, 2, 4, 6]) } @@ -12812,6 +13918,7 @@ pub unsafe fn vuzp1_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp1q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]) } @@ -12820,6 +13927,7 @@ pub unsafe fn vuzp1q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp1_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { simd_shuffle2!(a, b, [0, 2]) } @@ -12828,6 +13936,7 @@ pub unsafe fn vuzp1_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp1q_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { simd_shuffle2!(a, b, [0, 2]) } @@ -12836,6 +13945,7 @@ pub unsafe fn vuzp1q_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp1_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { simd_shuffle2!(a, b, [0, 2]) } @@ -12844,6 +13954,7 @@ pub unsafe fn vuzp1_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp1q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { simd_shuffle2!(a, b, [0, 2]) } @@ -12852,6 +13963,7 @@ pub unsafe fn vuzp1q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp1q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { simd_shuffle2!(a, b, [0, 2]) } @@ -12860,6 +13972,7 @@ pub unsafe fn vuzp1q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp1q_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { simd_shuffle4!(a, b, [0, 2, 4, 6]) } @@ -12868,6 +13981,7 @@ pub unsafe fn vuzp1q_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp1_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { simd_shuffle2!(a, b, [0, 2]) } @@ -12876,6 +13990,7 @@ pub unsafe fn vuzp1_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp1q_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { simd_shuffle2!(a, b, [0, 2]) } @@ -12884,6 +13999,7 @@ pub unsafe fn vuzp1q_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp2_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]) } @@ -12892,6 +14008,7 @@ pub unsafe fn vuzp2_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp2q_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { simd_shuffle16!(a, b, [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]) } @@ -12900,6 +14017,7 @@ pub unsafe fn vuzp2q_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp2_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { simd_shuffle4!(a, b, [1, 3, 5, 7]) } @@ -12908,6 +14026,7 @@ pub unsafe fn vuzp2_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp2q_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]) } @@ -12916,6 +14035,7 @@ pub unsafe fn vuzp2q_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp2q_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { simd_shuffle4!(a, b, [1, 3, 5, 7]) } @@ -12924,6 +14044,7 @@ pub unsafe fn vuzp2q_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp2_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]) } @@ -12932,6 +14053,7 @@ pub unsafe fn vuzp2_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp2q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { simd_shuffle16!(a, b, [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]) } @@ -12940,6 +14062,7 @@ pub unsafe fn vuzp2q_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp2_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { simd_shuffle4!(a, b, [1, 3, 5, 7]) } @@ -12948,6 +14071,7 @@ pub unsafe fn vuzp2_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp2q_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]) } @@ -12956,6 +14080,7 @@ pub unsafe fn vuzp2q_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp2q_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { simd_shuffle4!(a, b, [1, 3, 5, 7]) } @@ -12964,6 +14089,7 @@ pub unsafe fn vuzp2q_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp2_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]) } @@ -12972,6 +14098,7 @@ pub unsafe fn vuzp2_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp2q_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { simd_shuffle16!(a, b, [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]) } @@ -12980,6 +14107,7 @@ pub unsafe fn vuzp2q_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp2_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { simd_shuffle4!(a, b, [1, 3, 5, 7]) } @@ -12988,6 +14116,7 @@ pub unsafe fn vuzp2_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp2q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]) } @@ -12996,6 +14125,7 @@ pub unsafe fn vuzp2q_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp2_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { simd_shuffle2!(a, b, [1, 3]) } @@ -13004,6 +14134,7 @@ pub unsafe fn vuzp2_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp2q_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { simd_shuffle2!(a, b, [1, 3]) } @@ -13012,6 +14143,7 @@ pub unsafe fn vuzp2q_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp2_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { simd_shuffle2!(a, b, [1, 3]) } @@ -13020,6 +14152,7 @@ pub unsafe fn vuzp2_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp2q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { simd_shuffle2!(a, b, [1, 3]) } @@ -13028,6 +14161,7 @@ pub unsafe fn vuzp2q_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp2q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { simd_shuffle2!(a, b, [1, 3]) } @@ -13036,6 +14170,7 @@ pub unsafe fn vuzp2q_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uzp2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp2q_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { simd_shuffle4!(a, b, [1, 3, 5, 7]) } @@ -13044,6 +14179,7 @@ pub unsafe fn vuzp2q_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp2_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { simd_shuffle2!(a, b, [1, 3]) } @@ -13052,6 +14188,7 @@ pub unsafe fn vuzp2_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(zip2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuzp2q_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { simd_shuffle2!(a, b, [1, 3]) } @@ -13060,6 +14197,7 @@ pub unsafe fn vuzp2q_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uabal))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vabal_high_u8(a: uint16x8_t, b: uint8x16_t, c: uint8x16_t) -> uint16x8_t { let d: uint8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); let e: uint8x8_t = simd_shuffle8!(c, c, [8, 9, 10, 11, 12, 13, 14, 15]); @@ -13071,6 +14209,7 @@ pub unsafe fn vabal_high_u8(a: uint16x8_t, b: uint8x16_t, c: uint8x16_t) -> uint #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uabal))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vabal_high_u16(a: uint32x4_t, b: uint16x8_t, c: uint16x8_t) -> uint32x4_t { let d: uint16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); let e: uint16x4_t = simd_shuffle4!(c, c, [4, 5, 6, 7]); @@ -13082,6 +14221,7 @@ pub unsafe fn vabal_high_u16(a: uint32x4_t, b: uint16x8_t, c: uint16x8_t) -> uin #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uabal))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vabal_high_u32(a: uint64x2_t, b: uint32x4_t, c: uint32x4_t) -> uint64x2_t { let d: uint32x2_t = simd_shuffle2!(b, b, [2, 3]); let e: uint32x2_t = simd_shuffle2!(c, c, [2, 3]); @@ -13093,6 +14233,7 @@ pub unsafe fn vabal_high_u32(a: uint64x2_t, b: uint32x4_t, c: uint32x4_t) -> uin #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sabal))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vabal_high_s8(a: int16x8_t, b: int8x16_t, c: int8x16_t) -> int16x8_t { let d: int8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); let e: int8x8_t = simd_shuffle8!(c, c, [8, 9, 10, 11, 12, 13, 14, 15]); @@ -13105,6 +14246,7 @@ pub unsafe fn vabal_high_s8(a: int16x8_t, b: int8x16_t, c: int8x16_t) -> int16x8 #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sabal))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vabal_high_s16(a: int32x4_t, b: int16x8_t, c: int16x8_t) -> int32x4_t { let d: int16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); let e: int16x4_t = simd_shuffle4!(c, c, [4, 5, 6, 7]); @@ -13117,6 +14259,7 @@ pub unsafe fn vabal_high_s16(a: int32x4_t, b: int16x8_t, c: int16x8_t) -> int32x #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sabal))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vabal_high_s32(a: int64x2_t, b: int32x4_t, c: int32x4_t) -> int64x2_t { let d: int32x2_t = simd_shuffle2!(b, b, [2, 3]); let e: int32x2_t = simd_shuffle2!(c, c, [2, 3]); @@ -13129,6 +14272,7 @@ pub unsafe fn vabal_high_s32(a: int64x2_t, b: int32x4_t, c: int32x4_t) -> int64x #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqabs))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqabs_s64(a: int64x1_t) -> int64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -13142,6 +14286,7 @@ pub unsafe fn vqabs_s64(a: int64x1_t) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqabs))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqabsq_s64(a: int64x2_t) -> int64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -13155,6 +14300,7 @@ pub unsafe fn vqabsq_s64(a: int64x2_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqabs))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqabsb_s8(a: i8) -> i8 { simd_extract(vqabs_s8(vdup_n_s8(a)), 0) } @@ -13163,6 +14309,7 @@ pub unsafe fn vqabsb_s8(a: i8) -> i8 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqabs))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqabsh_s16(a: i16) -> i16 { simd_extract(vqabs_s16(vdup_n_s16(a)), 0) } @@ -13171,6 +14318,7 @@ pub unsafe fn vqabsh_s16(a: i16) -> i16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqabs))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqabss_s32(a: i32) -> i32 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -13184,6 +14332,7 @@ pub unsafe fn vqabss_s32(a: i32) -> i32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sqabs))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqabsd_s64(a: i64) -> i64 { #[allow(improper_ctypes)] extern "unadjusted" { @@ -13198,6 +14347,7 @@ pub unsafe fn vqabsd_s64(a: i64) -> i64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sli, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vslid_n_s64(a: i64, b: i64) -> i64 { static_assert!(N : i32 where N >= 0 && N <= 63); transmute(vsli_n_s64::(transmute(a), transmute(b))) @@ -13208,6 +14358,7 @@ pub unsafe fn vslid_n_s64(a: i64, b: i64) -> i64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sli, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vslid_n_u64(a: u64, b: u64) -> u64 { static_assert!(N : i32 where N >= 0 && N <= 63); transmute(vsli_n_u64::(transmute(a), transmute(b))) @@ -13218,6 +14369,7 @@ pub unsafe fn vslid_n_u64(a: u64, b: u64) -> u64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sri, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsrid_n_s64(a: i64, b: i64) -> i64 { static_assert!(N : i32 where N >= 1 && N <= 64); transmute(vsri_n_s64::(transmute(a), transmute(b))) @@ -13228,6 +14380,7 @@ pub unsafe fn vsrid_n_s64(a: i64, b: i64) -> i64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sri, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsrid_n_u64(a: u64, b: u64) -> u64 { static_assert!(N : i32 where N >= 1 && N <= 64); transmute(vsri_n_u64::(transmute(a), transmute(b))) @@ -17802,7 +18955,7 @@ mod test { let a: [f64; 2] = [0., 1.]; let e: [f64; 1] = [1.]; let mut r: [f64; 1] = [0f64; 1]; - vst1_lane_f64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_lane_f64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -17811,7 +18964,7 @@ mod test { let a: [f64; 3] = [0., 1., 2.]; let e: [f64; 2] = [1., 0.]; let mut r: [f64; 2] = [0f64; 2]; - vst1q_lane_f64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_lane_f64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -17820,7 +18973,7 @@ mod test { let a: [f64; 3] = [0., 1., 2.]; let e: [f64; 2] = [1., 2.]; let mut r: [f64; 2] = [0f64; 2]; - vst1_f64_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_f64_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -17829,7 +18982,7 @@ mod test { let a: [f64; 5] = [0., 1., 2., 3., 4.]; let e: [f64; 4] = [1., 2., 3., 4.]; let mut r: [f64; 4] = [0f64; 4]; - vst1q_f64_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_f64_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -17838,7 +18991,7 @@ mod test { let a: [f64; 4] = [0., 1., 2., 3.]; let e: [f64; 3] = [1., 2., 3.]; let mut r: [f64; 3] = [0f64; 3]; - vst1_f64_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_f64_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -17847,7 +19000,7 @@ mod test { let a: [f64; 7] = [0., 1., 2., 3., 4., 5., 6.]; let e: [f64; 6] = [1., 2., 3., 4., 5., 6.]; let mut r: [f64; 6] = [0f64; 6]; - vst1q_f64_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_f64_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -17856,7 +19009,7 @@ mod test { let a: [f64; 5] = [0., 1., 2., 3., 4.]; let e: [f64; 4] = [1., 2., 3., 4.]; let mut r: [f64; 4] = [0f64; 4]; - vst1_f64_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_f64_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -17865,7 +19018,7 @@ mod test { let a: [f64; 9] = [0., 1., 2., 3., 4., 5., 6., 7., 8.]; let e: [f64; 8] = [1., 2., 3., 4., 5., 6., 7., 8.]; let mut r: [f64; 8] = [0f64; 8]; - vst1q_f64_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_f64_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -17874,7 +19027,7 @@ mod test { let a: [i64; 5] = [0, 1, 2, 2, 3]; let e: [i64; 4] = [1, 2, 2, 3]; let mut r: [i64; 4] = [0i64; 4]; - vst2q_s64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_s64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -17883,7 +19036,7 @@ mod test { let a: [u64; 5] = [0, 1, 2, 2, 3]; let e: [u64; 4] = [1, 2, 2, 3]; let mut r: [u64; 4] = [0u64; 4]; - vst2q_u64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_u64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -17892,7 +19045,7 @@ mod test { let a: [u64; 5] = [0, 1, 2, 2, 3]; let e: [u64; 4] = [1, 2, 2, 3]; let mut r: [u64; 4] = [0u64; 4]; - vst2q_p64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_p64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -17901,7 +19054,7 @@ mod test { let a: [f64; 3] = [0., 1., 2.]; let e: [f64; 2] = [1., 2.]; let mut r: [f64; 2] = [0f64; 2]; - vst2_f64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_f64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -17910,7 +19063,7 @@ mod test { let a: [f64; 5] = [0., 1., 2., 2., 3.]; let e: [f64; 4] = [1., 2., 2., 3.]; let mut r: [f64; 4] = [0f64; 4]; - vst2q_f64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_f64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -17919,7 +19072,7 @@ mod test { let a: [i8; 33] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]; let e: [i8; 32] = [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [i8; 32] = [0i8; 32]; - vst2q_lane_s8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_lane_s8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -17928,7 +19081,7 @@ mod test { let a: [i64; 3] = [0, 1, 2]; let e: [i64; 2] = [1, 2]; let mut r: [i64; 2] = [0i64; 2]; - vst2_lane_s64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_lane_s64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -17937,7 +19090,7 @@ mod test { let a: [i64; 5] = [0, 1, 2, 2, 3]; let e: [i64; 4] = [1, 2, 0, 0]; let mut r: [i64; 4] = [0i64; 4]; - vst2q_lane_s64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_lane_s64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -17946,7 +19099,7 @@ mod test { let a: [u8; 33] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]; let e: [u8; 32] = [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u8; 32] = [0u8; 32]; - vst2q_lane_u8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_lane_u8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -17955,7 +19108,7 @@ mod test { let a: [u64; 3] = [0, 1, 2]; let e: [u64; 2] = [1, 2]; let mut r: [u64; 2] = [0u64; 2]; - vst2_lane_u64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_lane_u64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -17964,7 +19117,7 @@ mod test { let a: [u64; 5] = [0, 1, 2, 2, 3]; let e: [u64; 4] = [1, 2, 0, 0]; let mut r: [u64; 4] = [0u64; 4]; - vst2q_lane_u64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_lane_u64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -17973,7 +19126,7 @@ mod test { let a: [u8; 33] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]; let e: [u8; 32] = [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u8; 32] = [0u8; 32]; - vst2q_lane_p8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_lane_p8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -17982,7 +19135,7 @@ mod test { let a: [u64; 3] = [0, 1, 2]; let e: [u64; 2] = [1, 2]; let mut r: [u64; 2] = [0u64; 2]; - vst2_lane_p64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_lane_p64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -17991,7 +19144,7 @@ mod test { let a: [u64; 5] = [0, 1, 2, 2, 3]; let e: [u64; 4] = [1, 2, 0, 0]; let mut r: [u64; 4] = [0u64; 4]; - vst2q_lane_p64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_lane_p64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18000,7 +19153,7 @@ mod test { let a: [f64; 3] = [0., 1., 2.]; let e: [f64; 2] = [1., 2.]; let mut r: [f64; 2] = [0f64; 2]; - vst2_lane_f64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_lane_f64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18009,7 +19162,7 @@ mod test { let a: [f64; 5] = [0., 1., 2., 2., 3.]; let e: [f64; 4] = [1., 2., 0., 0.]; let mut r: [f64; 4] = [0f64; 4]; - vst2q_lane_f64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_lane_f64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18018,7 +19171,7 @@ mod test { let a: [i64; 7] = [0, 1, 2, 2, 4, 2, 4]; let e: [i64; 6] = [1, 2, 2, 2, 4, 4]; let mut r: [i64; 6] = [0i64; 6]; - vst3q_s64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_s64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18027,7 +19180,7 @@ mod test { let a: [u64; 7] = [0, 1, 2, 2, 4, 2, 4]; let e: [u64; 6] = [1, 2, 2, 2, 4, 4]; let mut r: [u64; 6] = [0u64; 6]; - vst3q_u64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_u64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18036,7 +19189,7 @@ mod test { let a: [u64; 7] = [0, 1, 2, 2, 4, 2, 4]; let e: [u64; 6] = [1, 2, 2, 2, 4, 4]; let mut r: [u64; 6] = [0u64; 6]; - vst3q_p64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_p64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18045,7 +19198,7 @@ mod test { let a: [f64; 4] = [0., 1., 2., 2.]; let e: [f64; 3] = [1., 2., 2.]; let mut r: [f64; 3] = [0f64; 3]; - vst3_f64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_f64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18054,7 +19207,7 @@ mod test { let a: [f64; 7] = [0., 1., 2., 2., 4., 2., 4.]; let e: [f64; 6] = [1., 2., 2., 2., 4., 4.]; let mut r: [f64; 6] = [0f64; 6]; - vst3q_f64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_f64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18063,7 +19216,7 @@ mod test { let a: [i8; 49] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16, 25, 26, 27, 28, 29, 30, 31, 32, 2, 4, 7, 8, 13, 14, 15, 16, 41, 42, 43, 44, 45, 46, 47, 48]; let e: [i8; 48] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [i8; 48] = [0i8; 48]; - vst3q_lane_s8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_lane_s8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18072,7 +19225,7 @@ mod test { let a: [i64; 4] = [0, 1, 2, 2]; let e: [i64; 3] = [1, 2, 2]; let mut r: [i64; 3] = [0i64; 3]; - vst3_lane_s64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_lane_s64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18081,7 +19234,7 @@ mod test { let a: [i64; 7] = [0, 1, 2, 2, 4, 2, 4]; let e: [i64; 6] = [1, 2, 2, 0, 0, 0]; let mut r: [i64; 6] = [0i64; 6]; - vst3q_lane_s64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_lane_s64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18090,7 +19243,7 @@ mod test { let a: [u8; 49] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16, 25, 26, 27, 28, 29, 30, 31, 32, 2, 4, 7, 8, 13, 14, 15, 16, 41, 42, 43, 44, 45, 46, 47, 48]; let e: [u8; 48] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u8; 48] = [0u8; 48]; - vst3q_lane_u8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_lane_u8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18099,7 +19252,7 @@ mod test { let a: [u64; 4] = [0, 1, 2, 2]; let e: [u64; 3] = [1, 2, 2]; let mut r: [u64; 3] = [0u64; 3]; - vst3_lane_u64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_lane_u64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18108,7 +19261,7 @@ mod test { let a: [u64; 7] = [0, 1, 2, 2, 4, 2, 4]; let e: [u64; 6] = [1, 2, 2, 0, 0, 0]; let mut r: [u64; 6] = [0u64; 6]; - vst3q_lane_u64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_lane_u64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18117,7 +19270,7 @@ mod test { let a: [u8; 49] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16, 25, 26, 27, 28, 29, 30, 31, 32, 2, 4, 7, 8, 13, 14, 15, 16, 41, 42, 43, 44, 45, 46, 47, 48]; let e: [u8; 48] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u8; 48] = [0u8; 48]; - vst3q_lane_p8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_lane_p8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18126,7 +19279,7 @@ mod test { let a: [u64; 4] = [0, 1, 2, 2]; let e: [u64; 3] = [1, 2, 2]; let mut r: [u64; 3] = [0u64; 3]; - vst3_lane_p64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_lane_p64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18135,7 +19288,7 @@ mod test { let a: [u64; 7] = [0, 1, 2, 2, 4, 2, 4]; let e: [u64; 6] = [1, 2, 2, 0, 0, 0]; let mut r: [u64; 6] = [0u64; 6]; - vst3q_lane_p64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_lane_p64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18144,7 +19297,7 @@ mod test { let a: [f64; 4] = [0., 1., 2., 2.]; let e: [f64; 3] = [1., 2., 2.]; let mut r: [f64; 3] = [0f64; 3]; - vst3_lane_f64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_lane_f64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18153,7 +19306,7 @@ mod test { let a: [f64; 7] = [0., 1., 2., 2., 3., 2., 3.]; let e: [f64; 6] = [1., 2., 2., 0., 0., 0.]; let mut r: [f64; 6] = [0f64; 6]; - vst3q_lane_f64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_lane_f64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18162,7 +19315,7 @@ mod test { let a: [i64; 9] = [0, 1, 2, 2, 6, 2, 6, 6, 8]; let e: [i64; 8] = [1, 2, 2, 6, 2, 6, 6, 8]; let mut r: [i64; 8] = [0i64; 8]; - vst4q_s64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_s64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18171,7 +19324,7 @@ mod test { let a: [u64; 9] = [0, 1, 2, 2, 6, 2, 6, 6, 8]; let e: [u64; 8] = [1, 2, 2, 6, 2, 6, 6, 8]; let mut r: [u64; 8] = [0u64; 8]; - vst4q_u64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_u64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18180,7 +19333,7 @@ mod test { let a: [u64; 9] = [0, 1, 2, 2, 6, 2, 6, 6, 8]; let e: [u64; 8] = [1, 2, 2, 6, 2, 6, 6, 8]; let mut r: [u64; 8] = [0u64; 8]; - vst4q_p64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_p64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18189,7 +19342,7 @@ mod test { let a: [f64; 5] = [0., 1., 2., 2., 6.]; let e: [f64; 4] = [1., 2., 2., 6.]; let mut r: [f64; 4] = [0f64; 4]; - vst4_f64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_f64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18198,7 +19351,7 @@ mod test { let a: [f64; 9] = [0., 1., 2., 2., 6., 2., 6., 6., 8.]; let e: [f64; 8] = [1., 2., 2., 6., 2., 6., 6., 8.]; let mut r: [f64; 8] = [0f64; 8]; - vst4q_f64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_f64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18207,7 +19360,7 @@ mod test { let a: [i8; 65] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64]; let e: [i8; 64] = [1, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [i8; 64] = [0i8; 64]; - vst4q_lane_s8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_lane_s8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18216,7 +19369,7 @@ mod test { let a: [i64; 5] = [0, 1, 2, 2, 6]; let e: [i64; 4] = [1, 2, 2, 6]; let mut r: [i64; 4] = [0i64; 4]; - vst4_lane_s64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_lane_s64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18225,7 +19378,7 @@ mod test { let a: [i64; 9] = [0, 1, 2, 2, 6, 2, 6, 6, 8]; let e: [i64; 8] = [1, 2, 2, 6, 0, 0, 0, 0]; let mut r: [i64; 8] = [0i64; 8]; - vst4q_lane_s64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_lane_s64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18234,7 +19387,7 @@ mod test { let a: [u8; 65] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64]; let e: [u8; 64] = [1, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u8; 64] = [0u8; 64]; - vst4q_lane_u8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_lane_u8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18243,7 +19396,7 @@ mod test { let a: [u64; 5] = [0, 1, 2, 2, 6]; let e: [u64; 4] = [1, 2, 2, 6]; let mut r: [u64; 4] = [0u64; 4]; - vst4_lane_u64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_lane_u64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18252,7 +19405,7 @@ mod test { let a: [u64; 9] = [0, 1, 2, 2, 6, 2, 6, 6, 8]; let e: [u64; 8] = [1, 2, 2, 6, 0, 0, 0, 0]; let mut r: [u64; 8] = [0u64; 8]; - vst4q_lane_u64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_lane_u64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18261,7 +19414,7 @@ mod test { let a: [u8; 65] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64]; let e: [u8; 64] = [1, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u8; 64] = [0u8; 64]; - vst4q_lane_p8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_lane_p8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18270,7 +19423,7 @@ mod test { let a: [u64; 5] = [0, 1, 2, 2, 6]; let e: [u64; 4] = [1, 2, 2, 6]; let mut r: [u64; 4] = [0u64; 4]; - vst4_lane_p64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_lane_p64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18279,7 +19432,7 @@ mod test { let a: [u64; 9] = [0, 1, 2, 2, 6, 2, 6, 6, 8]; let e: [u64; 8] = [1, 2, 2, 6, 0, 0, 0, 0]; let mut r: [u64; 8] = [0u64; 8]; - vst4q_lane_p64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_lane_p64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18288,7 +19441,7 @@ mod test { let a: [f64; 5] = [0., 1., 2., 2., 6.]; let e: [f64; 4] = [1., 2., 2., 6.]; let mut r: [f64; 4] = [0f64; 4]; - vst4_lane_f64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_lane_f64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -18297,7 +19450,7 @@ mod test { let a: [f64; 9] = [0., 1., 2., 2., 6., 2., 6., 6., 8.]; let e: [f64; 8] = [1., 2., 2., 6., 0., 0., 0., 0.]; let mut r: [f64; 8] = [0f64; 8]; - vst4q_lane_f64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_lane_f64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs index ff895f9875..65ba527ee0 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs @@ -20,19 +20,24 @@ use stdarch_test::assert_instr; types! { /// ARM-specific 64-bit wide vector of one packed `f64`. + #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub struct float64x1_t(f64); // FIXME: check this! /// ARM-specific 128-bit wide vector of two packed `f64`. + #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub struct float64x2_t(f64, f64); } /// ARM-specific type containing two `float64x1_t` vectors. #[derive(Copy, Clone, Debug)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub struct float64x1x2_t(pub float64x1_t, pub float64x1_t); /// ARM-specific type containing three `float64x1_t` vectors. #[derive(Copy, Clone, Debug)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub struct float64x1x3_t(pub float64x1_t, pub float64x1_t, pub float64x1_t); /// ARM-specific type containing four `float64x1_t` vectors. #[derive(Copy, Clone, Debug)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub struct float64x1x4_t( pub float64x1_t, pub float64x1_t, @@ -42,12 +47,15 @@ pub struct float64x1x4_t( /// ARM-specific type containing two `float64x2_t` vectors. #[derive(Copy, Clone, Debug)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub struct float64x2x2_t(pub float64x2_t, pub float64x2_t); /// ARM-specific type containing three `float64x2_t` vectors. #[derive(Copy, Clone, Debug)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub struct float64x2x3_t(pub float64x2_t, pub float64x2_t, pub float64x2_t); /// ARM-specific type containing four `float64x2_t` vectors. #[derive(Copy, Clone, Debug)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub struct float64x2x4_t( pub float64x2_t, pub float64x2_t, @@ -354,6 +362,7 @@ extern "unadjusted" { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N1 = 0, N2 = 0))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_lane_s64( _a: int64x1_t, b: int64x1_t, @@ -368,6 +377,7 @@ pub unsafe fn vcopy_lane_s64( #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N1 = 0, N2 = 0))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_lane_u64( _a: uint64x1_t, b: uint64x1_t, @@ -382,6 +392,7 @@ pub unsafe fn vcopy_lane_u64( #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N1 = 0, N2 = 0))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_lane_p64( _a: poly64x1_t, b: poly64x1_t, @@ -396,6 +407,7 @@ pub unsafe fn vcopy_lane_p64( #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N1 = 0, N2 = 0))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_lane_f64( _a: float64x1_t, b: float64x1_t, @@ -410,6 +422,7 @@ pub unsafe fn vcopy_lane_f64( #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_laneq_s64( _a: int64x1_t, b: int64x2_t, @@ -424,6 +437,7 @@ pub unsafe fn vcopy_laneq_s64( #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_laneq_u64( _a: uint64x1_t, b: uint64x2_t, @@ -438,6 +452,7 @@ pub unsafe fn vcopy_laneq_u64( #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_laneq_p64( _a: poly64x1_t, b: poly64x2_t, @@ -452,6 +467,7 @@ pub unsafe fn vcopy_laneq_p64( #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, LANE1 = 0, LANE2 = 1))] #[rustc_legacy_const_generics(1, 3)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcopy_laneq_f64( _a: float64x1_t, b: float64x2_t, @@ -465,6 +481,7 @@ pub unsafe fn vcopy_laneq_f64( #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1_s8(ptr: *const i8) -> int8x8_t { read_unaligned(ptr.cast()) } @@ -473,6 +490,7 @@ pub unsafe fn vld1_s8(ptr: *const i8) -> int8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1q_s8(ptr: *const i8) -> int8x16_t { read_unaligned(ptr.cast()) } @@ -481,6 +499,7 @@ pub unsafe fn vld1q_s8(ptr: *const i8) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1_s16(ptr: *const i16) -> int16x4_t { read_unaligned(ptr.cast()) } @@ -489,6 +508,7 @@ pub unsafe fn vld1_s16(ptr: *const i16) -> int16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1q_s16(ptr: *const i16) -> int16x8_t { read_unaligned(ptr.cast()) } @@ -497,6 +517,7 @@ pub unsafe fn vld1q_s16(ptr: *const i16) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1_s32(ptr: *const i32) -> int32x2_t { read_unaligned(ptr.cast()) } @@ -505,6 +526,7 @@ pub unsafe fn vld1_s32(ptr: *const i32) -> int32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1q_s32(ptr: *const i32) -> int32x4_t { read_unaligned(ptr.cast()) } @@ -513,6 +535,7 @@ pub unsafe fn vld1q_s32(ptr: *const i32) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1_s64(ptr: *const i64) -> int64x1_t { read_unaligned(ptr.cast()) } @@ -521,6 +544,7 @@ pub unsafe fn vld1_s64(ptr: *const i64) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1q_s64(ptr: *const i64) -> int64x2_t { read_unaligned(ptr.cast()) } @@ -529,6 +553,7 @@ pub unsafe fn vld1q_s64(ptr: *const i64) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1_u8(ptr: *const u8) -> uint8x8_t { read_unaligned(ptr.cast()) } @@ -537,6 +562,7 @@ pub unsafe fn vld1_u8(ptr: *const u8) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1q_u8(ptr: *const u8) -> uint8x16_t { read_unaligned(ptr.cast()) } @@ -545,6 +571,7 @@ pub unsafe fn vld1q_u8(ptr: *const u8) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1_u16(ptr: *const u16) -> uint16x4_t { read_unaligned(ptr.cast()) } @@ -553,6 +580,7 @@ pub unsafe fn vld1_u16(ptr: *const u16) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1q_u16(ptr: *const u16) -> uint16x8_t { read_unaligned(ptr.cast()) } @@ -561,6 +589,7 @@ pub unsafe fn vld1q_u16(ptr: *const u16) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1_u32(ptr: *const u32) -> uint32x2_t { read_unaligned(ptr.cast()) } @@ -569,6 +598,7 @@ pub unsafe fn vld1_u32(ptr: *const u32) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1q_u32(ptr: *const u32) -> uint32x4_t { read_unaligned(ptr.cast()) } @@ -577,6 +607,7 @@ pub unsafe fn vld1q_u32(ptr: *const u32) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1_u64(ptr: *const u64) -> uint64x1_t { read_unaligned(ptr.cast()) } @@ -585,6 +616,7 @@ pub unsafe fn vld1_u64(ptr: *const u64) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1q_u64(ptr: *const u64) -> uint64x2_t { read_unaligned(ptr.cast()) } @@ -593,6 +625,7 @@ pub unsafe fn vld1q_u64(ptr: *const u64) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1_p8(ptr: *const p8) -> poly8x8_t { read_unaligned(ptr.cast()) } @@ -601,6 +634,7 @@ pub unsafe fn vld1_p8(ptr: *const p8) -> poly8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1q_p8(ptr: *const p8) -> poly8x16_t { read_unaligned(ptr.cast()) } @@ -609,6 +643,7 @@ pub unsafe fn vld1q_p8(ptr: *const p8) -> poly8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1_p16(ptr: *const p16) -> poly16x4_t { read_unaligned(ptr.cast()) } @@ -617,6 +652,7 @@ pub unsafe fn vld1_p16(ptr: *const p16) -> poly16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1q_p16(ptr: *const p16) -> poly16x8_t { read_unaligned(ptr.cast()) } @@ -625,6 +661,7 @@ pub unsafe fn vld1q_p16(ptr: *const p16) -> poly16x8_t { #[inline] #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1_p64(ptr: *const p64) -> poly64x1_t { read_unaligned(ptr.cast()) } @@ -633,6 +670,7 @@ pub unsafe fn vld1_p64(ptr: *const p64) -> poly64x1_t { #[inline] #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1q_p64(ptr: *const p64) -> poly64x2_t { read_unaligned(ptr.cast()) } @@ -641,6 +679,7 @@ pub unsafe fn vld1q_p64(ptr: *const p64) -> poly64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1_f32(ptr: *const f32) -> float32x2_t { read_unaligned(ptr.cast()) } @@ -649,6 +688,7 @@ pub unsafe fn vld1_f32(ptr: *const f32) -> float32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1q_f32(ptr: *const f32) -> float32x4_t { read_unaligned(ptr.cast()) } @@ -657,6 +697,7 @@ pub unsafe fn vld1q_f32(ptr: *const f32) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1_f64(ptr: *const f64) -> float64x1_t { read_unaligned(ptr.cast()) } @@ -665,6 +706,7 @@ pub unsafe fn vld1_f64(ptr: *const f64) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1q_f64(ptr: *const f64) -> float64x2_t { read_unaligned(ptr.cast()) } @@ -673,6 +715,7 @@ pub unsafe fn vld1q_f64(ptr: *const f64) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ldr))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1_dup_f64(ptr: *const f64) -> float64x1_t { vld1_f64(ptr) } @@ -681,6 +724,7 @@ pub unsafe fn vld1_dup_f64(ptr: *const f64) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ld1r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1q_dup_f64(ptr: *const f64) -> float64x2_t { let x = vld1q_lane_f64::<0>(ptr, transmute(f64x2::splat(0.))); simd_shuffle2!(x, x, [0, 0]) @@ -691,6 +735,7 @@ pub unsafe fn vld1q_dup_f64(ptr: *const f64) -> float64x2_t { #[target_feature(enable = "neon")] #[rustc_legacy_const_generics(2)] #[cfg_attr(test, assert_instr(ldr, LANE = 0))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1_lane_f64(ptr: *const f64, src: float64x1_t) -> float64x1_t { static_assert!(LANE : i32 where LANE == 0); simd_insert(src, LANE as u32, *ptr) @@ -701,6 +746,7 @@ pub unsafe fn vld1_lane_f64(ptr: *const f64, src: float64x1_t) #[target_feature(enable = "neon")] #[rustc_legacy_const_generics(2)] #[cfg_attr(test, assert_instr(ld1, LANE = 1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1q_lane_f64(ptr: *const f64, src: float64x2_t) -> float64x2_t { static_assert_imm1!(LANE); simd_insert(src, LANE as u32, *ptr) @@ -711,6 +757,7 @@ pub unsafe fn vld1q_lane_f64(ptr: *const f64, src: float64x2_t) #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_s8(ptr: *mut i8, a: int8x8_t) { write_unaligned(ptr.cast(), a); } @@ -720,6 +767,7 @@ pub unsafe fn vst1_s8(ptr: *mut i8, a: int8x8_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_s8(ptr: *mut i8, a: int8x16_t) { write_unaligned(ptr.cast(), a); } @@ -729,6 +777,7 @@ pub unsafe fn vst1q_s8(ptr: *mut i8, a: int8x16_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_s16(ptr: *mut i16, a: int16x4_t) { write_unaligned(ptr.cast(), a); } @@ -738,6 +787,7 @@ pub unsafe fn vst1_s16(ptr: *mut i16, a: int16x4_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_s16(ptr: *mut i16, a: int16x8_t) { write_unaligned(ptr.cast(), a); } @@ -747,6 +797,7 @@ pub unsafe fn vst1q_s16(ptr: *mut i16, a: int16x8_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_s32(ptr: *mut i32, a: int32x2_t) { write_unaligned(ptr.cast(), a); } @@ -756,6 +807,7 @@ pub unsafe fn vst1_s32(ptr: *mut i32, a: int32x2_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_s32(ptr: *mut i32, a: int32x4_t) { write_unaligned(ptr.cast(), a); } @@ -765,6 +817,7 @@ pub unsafe fn vst1q_s32(ptr: *mut i32, a: int32x4_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_s64(ptr: *mut i64, a: int64x1_t) { write_unaligned(ptr.cast(), a); } @@ -774,6 +827,7 @@ pub unsafe fn vst1_s64(ptr: *mut i64, a: int64x1_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_s64(ptr: *mut i64, a: int64x2_t) { write_unaligned(ptr.cast(), a); } @@ -783,6 +837,7 @@ pub unsafe fn vst1q_s64(ptr: *mut i64, a: int64x2_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_u8(ptr: *mut u8, a: uint8x8_t) { write_unaligned(ptr.cast(), a); } @@ -792,6 +847,7 @@ pub unsafe fn vst1_u8(ptr: *mut u8, a: uint8x8_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_u8(ptr: *mut u8, a: uint8x16_t) { write_unaligned(ptr.cast(), a); } @@ -801,6 +857,7 @@ pub unsafe fn vst1q_u8(ptr: *mut u8, a: uint8x16_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_u16(ptr: *mut u16, a: uint16x4_t) { write_unaligned(ptr.cast(), a); } @@ -810,6 +867,7 @@ pub unsafe fn vst1_u16(ptr: *mut u16, a: uint16x4_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_u16(ptr: *mut u16, a: uint16x8_t) { write_unaligned(ptr.cast(), a); } @@ -819,6 +877,7 @@ pub unsafe fn vst1q_u16(ptr: *mut u16, a: uint16x8_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_u32(ptr: *mut u32, a: uint32x2_t) { write_unaligned(ptr.cast(), a); } @@ -828,6 +887,7 @@ pub unsafe fn vst1_u32(ptr: *mut u32, a: uint32x2_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_u32(ptr: *mut u32, a: uint32x4_t) { write_unaligned(ptr.cast(), a); } @@ -837,6 +897,7 @@ pub unsafe fn vst1q_u32(ptr: *mut u32, a: uint32x4_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_u64(ptr: *mut u64, a: uint64x1_t) { write_unaligned(ptr.cast(), a); } @@ -846,6 +907,7 @@ pub unsafe fn vst1_u64(ptr: *mut u64, a: uint64x1_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_u64(ptr: *mut u64, a: uint64x2_t) { write_unaligned(ptr.cast(), a); } @@ -855,6 +917,7 @@ pub unsafe fn vst1q_u64(ptr: *mut u64, a: uint64x2_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_p8(ptr: *mut p8, a: poly8x8_t) { write_unaligned(ptr.cast(), a); } @@ -864,6 +927,7 @@ pub unsafe fn vst1_p8(ptr: *mut p8, a: poly8x8_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_p8(ptr: *mut p8, a: poly8x16_t) { write_unaligned(ptr.cast(), a); } @@ -873,6 +937,7 @@ pub unsafe fn vst1q_p8(ptr: *mut p8, a: poly8x16_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_p16(ptr: *mut p16, a: poly16x4_t) { write_unaligned(ptr.cast(), a); } @@ -882,6 +947,7 @@ pub unsafe fn vst1_p16(ptr: *mut p16, a: poly16x4_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_p16(ptr: *mut p16, a: poly16x8_t) { write_unaligned(ptr.cast(), a); } @@ -891,6 +957,7 @@ pub unsafe fn vst1q_p16(ptr: *mut p16, a: poly16x8_t) { #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_p64(ptr: *mut p64, a: poly64x1_t) { write_unaligned(ptr.cast(), a); } @@ -900,6 +967,7 @@ pub unsafe fn vst1_p64(ptr: *mut p64, a: poly64x1_t) { #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_p64(ptr: *mut p64, a: poly64x2_t) { write_unaligned(ptr.cast(), a); } @@ -909,6 +977,7 @@ pub unsafe fn vst1q_p64(ptr: *mut p64, a: poly64x2_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_f32(ptr: *mut f32, a: float32x2_t) { write_unaligned(ptr.cast(), a); } @@ -918,6 +987,7 @@ pub unsafe fn vst1_f32(ptr: *mut f32, a: float32x2_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_f32(ptr: *mut f32, a: float32x4_t) { write_unaligned(ptr.cast(), a); } @@ -927,6 +997,7 @@ pub unsafe fn vst1q_f32(ptr: *mut f32, a: float32x4_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_f64(ptr: *mut f64, a: float64x1_t) { write_unaligned(ptr.cast(), a); } @@ -936,6 +1007,7 @@ pub unsafe fn vst1_f64(ptr: *mut f64, a: float64x1_t) { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(str))] #[allow(clippy::cast_ptr_alignment)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_f64(ptr: *mut f64, a: float64x2_t) { write_unaligned(ptr.cast(), a); } @@ -944,6 +1016,7 @@ pub unsafe fn vst1q_f64(ptr: *mut f64, a: float64x2_t) { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(abs))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vabsd_s64(a: i64) -> i64 { vabsd_s64_(a) } @@ -951,6 +1024,7 @@ pub unsafe fn vabsd_s64(a: i64) -> i64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(abs))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vabs_s64(a: int64x1_t) -> int64x1_t { vabs_s64_(a) } @@ -958,6 +1032,7 @@ pub unsafe fn vabs_s64(a: int64x1_t) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(abs))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vabsq_s64(a: int64x2_t) -> int64x2_t { vabsq_s64_(a) } @@ -968,6 +1043,7 @@ pub unsafe fn vabsq_s64(a: int64x2_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(bsl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vbsl_f64(a: uint64x1_t, b: float64x1_t, c: float64x1_t) -> float64x1_t { simd_select(transmute::<_, int64x1_t>(a), b, c) } @@ -975,6 +1051,7 @@ pub unsafe fn vbsl_f64(a: uint64x1_t, b: float64x1_t, c: float64x1_t) -> float64 #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(bsl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vbsl_p64(a: poly64x1_t, b: poly64x1_t, c: poly64x1_t) -> poly64x1_t { simd_select(transmute::<_, int64x1_t>(a), b, c) } @@ -982,6 +1059,7 @@ pub unsafe fn vbsl_p64(a: poly64x1_t, b: poly64x1_t, c: poly64x1_t) -> poly64x1_ #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(bsl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vbslq_f64(a: uint64x2_t, b: float64x2_t, c: float64x2_t) -> float64x2_t { simd_select(transmute::<_, int64x2_t>(a), b, c) } @@ -989,6 +1067,7 @@ pub unsafe fn vbslq_f64(a: uint64x2_t, b: float64x2_t, c: float64x2_t) -> float6 #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(bsl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vbslq_p64(a: poly64x2_t, b: poly64x2_t, c: poly64x2_t) -> poly64x2_t { simd_select(transmute::<_, int64x2_t>(a), b, c) } @@ -997,6 +1076,7 @@ pub unsafe fn vbslq_p64(a: poly64x2_t, b: poly64x2_t, c: poly64x2_t) -> poly64x2 #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(suqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuqadd_s8(a: int8x8_t, b: uint8x8_t) -> int8x8_t { vuqadd_s8_(a, b) } @@ -1004,6 +1084,7 @@ pub unsafe fn vuqadd_s8(a: int8x8_t, b: uint8x8_t) -> int8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(suqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuqaddq_s8(a: int8x16_t, b: uint8x16_t) -> int8x16_t { vuqaddq_s8_(a, b) } @@ -1011,6 +1092,7 @@ pub unsafe fn vuqaddq_s8(a: int8x16_t, b: uint8x16_t) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(suqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuqadd_s16(a: int16x4_t, b: uint16x4_t) -> int16x4_t { vuqadd_s16_(a, b) } @@ -1018,6 +1100,7 @@ pub unsafe fn vuqadd_s16(a: int16x4_t, b: uint16x4_t) -> int16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(suqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuqaddq_s16(a: int16x8_t, b: uint16x8_t) -> int16x8_t { vuqaddq_s16_(a, b) } @@ -1025,6 +1108,7 @@ pub unsafe fn vuqaddq_s16(a: int16x8_t, b: uint16x8_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(suqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuqadd_s32(a: int32x2_t, b: uint32x2_t) -> int32x2_t { vuqadd_s32_(a, b) } @@ -1032,6 +1116,7 @@ pub unsafe fn vuqadd_s32(a: int32x2_t, b: uint32x2_t) -> int32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(suqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuqaddq_s32(a: int32x4_t, b: uint32x4_t) -> int32x4_t { vuqaddq_s32_(a, b) } @@ -1039,6 +1124,7 @@ pub unsafe fn vuqaddq_s32(a: int32x4_t, b: uint32x4_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(suqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuqadd_s64(a: int64x1_t, b: uint64x1_t) -> int64x1_t { vuqadd_s64_(a, b) } @@ -1046,6 +1132,7 @@ pub unsafe fn vuqadd_s64(a: int64x1_t, b: uint64x1_t) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(suqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vuqaddq_s64(a: int64x2_t, b: uint64x2_t) -> int64x2_t { vuqaddq_s64_(a, b) } @@ -1054,6 +1141,7 @@ pub unsafe fn vuqaddq_s64(a: int64x2_t, b: uint64x2_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(usqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsqadd_u8(a: uint8x8_t, b: int8x8_t) -> uint8x8_t { vsqadd_u8_(a, b) } @@ -1061,6 +1149,7 @@ pub unsafe fn vsqadd_u8(a: uint8x8_t, b: int8x8_t) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(usqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsqaddq_u8(a: uint8x16_t, b: int8x16_t) -> uint8x16_t { vsqaddq_u8_(a, b) } @@ -1068,6 +1157,7 @@ pub unsafe fn vsqaddq_u8(a: uint8x16_t, b: int8x16_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(usqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsqadd_u16(a: uint16x4_t, b: int16x4_t) -> uint16x4_t { vsqadd_u16_(a, b) } @@ -1075,6 +1165,7 @@ pub unsafe fn vsqadd_u16(a: uint16x4_t, b: int16x4_t) -> uint16x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(usqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsqaddq_u16(a: uint16x8_t, b: int16x8_t) -> uint16x8_t { vsqaddq_u16_(a, b) } @@ -1082,6 +1173,7 @@ pub unsafe fn vsqaddq_u16(a: uint16x8_t, b: int16x8_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(usqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsqadd_u32(a: uint32x2_t, b: int32x2_t) -> uint32x2_t { vsqadd_u32_(a, b) } @@ -1089,6 +1181,7 @@ pub unsafe fn vsqadd_u32(a: uint32x2_t, b: int32x2_t) -> uint32x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(usqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsqaddq_u32(a: uint32x4_t, b: int32x4_t) -> uint32x4_t { vsqaddq_u32_(a, b) } @@ -1096,6 +1189,7 @@ pub unsafe fn vsqaddq_u32(a: uint32x4_t, b: int32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(usqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsqadd_u64(a: uint64x1_t, b: int64x1_t) -> uint64x1_t { vsqadd_u64_(a, b) } @@ -1103,6 +1197,7 @@ pub unsafe fn vsqadd_u64(a: uint64x1_t, b: int64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(usqadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsqaddq_u64(a: uint64x2_t, b: int64x2_t) -> uint64x2_t { vsqaddq_u64_(a, b) } @@ -1111,6 +1206,7 @@ pub unsafe fn vsqaddq_u64(a: uint64x2_t, b: int64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(addp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpaddq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { vpaddq_s16_(a, b) } @@ -1118,6 +1214,7 @@ pub unsafe fn vpaddq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(addp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpaddq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { transmute(vpaddq_s16_(transmute(a), transmute(b))) } @@ -1125,6 +1222,7 @@ pub unsafe fn vpaddq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(addp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpaddq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { vpaddq_s32_(a, b) } @@ -1132,6 +1230,7 @@ pub unsafe fn vpaddq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(addp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpaddq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { transmute(vpaddq_s32_(transmute(a), transmute(b))) } @@ -1139,6 +1238,7 @@ pub unsafe fn vpaddq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(addp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpaddq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { vpaddq_s64_(a, b) } @@ -1146,6 +1246,7 @@ pub unsafe fn vpaddq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(addp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpaddq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { transmute(vpaddq_s64_(transmute(a), transmute(b))) } @@ -1153,6 +1254,7 @@ pub unsafe fn vpaddq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(addp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpaddq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { vpaddq_s8_(a, b) } @@ -1160,6 +1262,7 @@ pub unsafe fn vpaddq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(addp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpaddq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { transmute(vpaddq_s8_(transmute(a), transmute(b))) } @@ -1167,6 +1270,7 @@ pub unsafe fn vpaddq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(addp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpaddd_s64(a: int64x2_t) -> i64 { transmute(vaddvq_u64_(transmute(a))) } @@ -1174,6 +1278,7 @@ pub unsafe fn vpaddd_s64(a: int64x2_t) -> i64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(addp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpaddd_u64(a: uint64x2_t) -> u64 { transmute(vaddvq_u64_(transmute(a))) } @@ -1182,97 +1287,124 @@ pub unsafe fn vpaddd_u64(a: uint64x2_t) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(addv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddv_s16(a: int16x4_t) -> i16 { vaddv_s16_(a) } + /// Add across vector #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(addp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddv_s32(a: int32x2_t) -> i32 { vaddv_s32_(a) } + /// Add across vector #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(addv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddv_s8(a: int8x8_t) -> i8 { vaddv_s8_(a) } + /// Add across vector #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(addv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddv_u16(a: uint16x4_t) -> u16 { vaddv_u16_(a) } + /// Add across vector #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(addp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddv_u32(a: uint32x2_t) -> u32 { vaddv_u32_(a) } + /// Add across vector #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(addv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddv_u8(a: uint8x8_t) -> u8 { vaddv_u8_(a) } + /// Add across vector #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(addv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddvq_s16(a: int16x8_t) -> i16 { vaddvq_s16_(a) } + /// Add across vector #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(addv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddvq_s32(a: int32x4_t) -> i32 { vaddvq_s32_(a) } + /// Add across vector #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(addv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddvq_s8(a: int8x16_t) -> i8 { vaddvq_s8_(a) } + /// Add across vector #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(addv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddvq_u16(a: uint16x8_t) -> u16 { vaddvq_u16_(a) } + /// Add across vector #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(addv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddvq_u32(a: uint32x4_t) -> u32 { vaddvq_u32_(a) } + /// Add across vector #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(addv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddvq_u8(a: uint8x16_t) -> u8 { vaddvq_u8_(a) } + /// Add across vector #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(addp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddvq_s64(a: int64x2_t) -> i64 { vaddvq_s64_(a) } + /// Add across vector #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(addp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddvq_u64(a: uint64x2_t) -> u64 { vaddvq_u64_(a) } @@ -1281,27 +1413,34 @@ pub unsafe fn vaddvq_u64(a: uint64x2_t) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(saddlv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddlv_s8(a: int8x8_t) -> i16 { vaddlv_s8_(a) as i16 } + /// Signed Add Long across Vector #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(saddlv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddlvq_s8(a: int8x16_t) -> i16 { vaddlvq_s8_(a) as i16 } + /// Unsigned Add Long across Vector #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uaddlv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddlv_u8(a: uint8x8_t) -> u16 { vaddlv_u8_(a) as u16 } + /// Unsigned Add Long across Vector #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uaddlv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddlvq_u8(a: uint8x16_t) -> u16 { vaddlvq_u8_(a) as u16 } @@ -1310,6 +1449,7 @@ pub unsafe fn vaddlvq_u8(a: uint8x16_t) -> u16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vadd_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { simd_add(a, b) } @@ -1318,6 +1458,7 @@ pub unsafe fn vadd_f64(a: float64x1_t, b: float64x1_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fadd))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { simd_add(a, b) } @@ -1326,6 +1467,7 @@ pub unsafe fn vaddq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(add))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vadd_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { simd_add(a, b) } @@ -1334,6 +1476,7 @@ pub unsafe fn vadd_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(add))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vadd_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { simd_add(a, b) } @@ -1342,6 +1485,7 @@ pub unsafe fn vadd_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(add))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddd_s64(a: i64, b: i64) -> i64 { a.wrapping_add(b) } @@ -1350,6 +1494,7 @@ pub unsafe fn vaddd_s64(a: i64, b: i64) -> i64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(add))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vaddd_u64(a: u64, b: u64) -> u64 { a.wrapping_add(b) } @@ -1358,6 +1503,7 @@ pub unsafe fn vaddd_u64(a: u64, b: u64) -> u64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smaxv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmaxv_s8(a: int8x8_t) -> i8 { vmaxv_s8_(a) } @@ -1366,6 +1512,7 @@ pub unsafe fn vmaxv_s8(a: int8x8_t) -> i8 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smaxv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmaxvq_s8(a: int8x16_t) -> i8 { vmaxvq_s8_(a) } @@ -1374,6 +1521,7 @@ pub unsafe fn vmaxvq_s8(a: int8x16_t) -> i8 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smaxv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmaxv_s16(a: int16x4_t) -> i16 { vmaxv_s16_(a) } @@ -1382,6 +1530,7 @@ pub unsafe fn vmaxv_s16(a: int16x4_t) -> i16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smaxv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmaxvq_s16(a: int16x8_t) -> i16 { vmaxvq_s16_(a) } @@ -1390,6 +1539,7 @@ pub unsafe fn vmaxvq_s16(a: int16x8_t) -> i16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smaxp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmaxv_s32(a: int32x2_t) -> i32 { vmaxv_s32_(a) } @@ -1398,6 +1548,7 @@ pub unsafe fn vmaxv_s32(a: int32x2_t) -> i32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smaxv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmaxvq_s32(a: int32x4_t) -> i32 { vmaxvq_s32_(a) } @@ -1406,6 +1557,7 @@ pub unsafe fn vmaxvq_s32(a: int32x4_t) -> i32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umaxv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmaxv_u8(a: uint8x8_t) -> u8 { vmaxv_u8_(a) } @@ -1414,6 +1566,7 @@ pub unsafe fn vmaxv_u8(a: uint8x8_t) -> u8 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umaxv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmaxvq_u8(a: uint8x16_t) -> u8 { vmaxvq_u8_(a) } @@ -1422,6 +1575,7 @@ pub unsafe fn vmaxvq_u8(a: uint8x16_t) -> u8 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umaxv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmaxv_u16(a: uint16x4_t) -> u16 { vmaxv_u16_(a) } @@ -1430,6 +1584,7 @@ pub unsafe fn vmaxv_u16(a: uint16x4_t) -> u16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umaxv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmaxvq_u16(a: uint16x8_t) -> u16 { vmaxvq_u16_(a) } @@ -1438,6 +1593,7 @@ pub unsafe fn vmaxvq_u16(a: uint16x8_t) -> u16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umaxp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmaxv_u32(a: uint32x2_t) -> u32 { vmaxv_u32_(a) } @@ -1446,6 +1602,7 @@ pub unsafe fn vmaxv_u32(a: uint32x2_t) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umaxv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmaxvq_u32(a: uint32x4_t) -> u32 { vmaxvq_u32_(a) } @@ -1454,6 +1611,7 @@ pub unsafe fn vmaxvq_u32(a: uint32x4_t) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmaxp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmaxv_f32(a: float32x2_t) -> f32 { vmaxv_f32_(a) } @@ -1462,6 +1620,7 @@ pub unsafe fn vmaxv_f32(a: float32x2_t) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmaxv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmaxvq_f32(a: float32x4_t) -> f32 { vmaxvq_f32_(a) } @@ -1470,6 +1629,7 @@ pub unsafe fn vmaxvq_f32(a: float32x4_t) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmaxp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmaxvq_f64(a: float64x2_t) -> f64 { vmaxvq_f64_(a) } @@ -1478,6 +1638,7 @@ pub unsafe fn vmaxvq_f64(a: float64x2_t) -> f64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sminv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vminv_s8(a: int8x8_t) -> i8 { vminv_s8_(a) } @@ -1486,6 +1647,7 @@ pub unsafe fn vminv_s8(a: int8x8_t) -> i8 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sminv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vminvq_s8(a: int8x16_t) -> i8 { vminvq_s8_(a) } @@ -1494,6 +1656,7 @@ pub unsafe fn vminvq_s8(a: int8x16_t) -> i8 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sminv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vminv_s16(a: int16x4_t) -> i16 { vminv_s16_(a) } @@ -1502,6 +1665,7 @@ pub unsafe fn vminv_s16(a: int16x4_t) -> i16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sminv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vminvq_s16(a: int16x8_t) -> i16 { vminvq_s16_(a) } @@ -1510,6 +1674,7 @@ pub unsafe fn vminvq_s16(a: int16x8_t) -> i16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sminp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vminv_s32(a: int32x2_t) -> i32 { vminv_s32_(a) } @@ -1518,6 +1683,7 @@ pub unsafe fn vminv_s32(a: int32x2_t) -> i32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sminv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vminvq_s32(a: int32x4_t) -> i32 { vminvq_s32_(a) } @@ -1526,6 +1692,7 @@ pub unsafe fn vminvq_s32(a: int32x4_t) -> i32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uminv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vminv_u8(a: uint8x8_t) -> u8 { vminv_u8_(a) } @@ -1534,6 +1701,7 @@ pub unsafe fn vminv_u8(a: uint8x8_t) -> u8 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uminv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vminvq_u8(a: uint8x16_t) -> u8 { vminvq_u8_(a) } @@ -1542,6 +1710,7 @@ pub unsafe fn vminvq_u8(a: uint8x16_t) -> u8 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uminv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vminv_u16(a: uint16x4_t) -> u16 { vminv_u16_(a) } @@ -1550,6 +1719,7 @@ pub unsafe fn vminv_u16(a: uint16x4_t) -> u16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uminv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vminvq_u16(a: uint16x8_t) -> u16 { vminvq_u16_(a) } @@ -1558,6 +1728,7 @@ pub unsafe fn vminvq_u16(a: uint16x8_t) -> u16 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uminp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vminv_u32(a: uint32x2_t) -> u32 { vminv_u32_(a) } @@ -1566,6 +1737,7 @@ pub unsafe fn vminv_u32(a: uint32x2_t) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uminv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vminvq_u32(a: uint32x4_t) -> u32 { vminvq_u32_(a) } @@ -1574,6 +1746,7 @@ pub unsafe fn vminvq_u32(a: uint32x4_t) -> u32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fminp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vminv_f32(a: float32x2_t) -> f32 { vminv_f32_(a) } @@ -1582,6 +1755,7 @@ pub unsafe fn vminv_f32(a: float32x2_t) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fminv))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vminvq_f32(a: float32x4_t) -> f32 { vminvq_f32_(a) } @@ -1590,6 +1764,7 @@ pub unsafe fn vminvq_f32(a: float32x4_t) -> f32 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fminp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vminvq_f64(a: float64x2_t) -> f64 { vminvq_f64_(a) } @@ -1598,6 +1773,7 @@ pub unsafe fn vminvq_f64(a: float64x2_t) -> f64 { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sminp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpminq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { vpminq_s8_(a, b) } @@ -1606,6 +1782,7 @@ pub unsafe fn vpminq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sminp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpminq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { vpminq_s16_(a, b) } @@ -1614,6 +1791,7 @@ pub unsafe fn vpminq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sminp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpminq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { vpminq_s32_(a, b) } @@ -1622,6 +1800,7 @@ pub unsafe fn vpminq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uminp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpminq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { vpminq_u8_(a, b) } @@ -1630,6 +1809,7 @@ pub unsafe fn vpminq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uminp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpminq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { vpminq_u16_(a, b) } @@ -1638,6 +1818,7 @@ pub unsafe fn vpminq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(uminp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpminq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { vpminq_u32_(a, b) } @@ -1646,6 +1827,7 @@ pub unsafe fn vpminq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fminp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpminq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { vpminq_f32_(a, b) } @@ -1654,6 +1836,7 @@ pub unsafe fn vpminq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fminp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpminq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { vpminq_f64_(a, b) } @@ -1662,6 +1845,7 @@ pub unsafe fn vpminq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smaxp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpmaxq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { vpmaxq_s8_(a, b) } @@ -1670,6 +1854,7 @@ pub unsafe fn vpmaxq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smaxp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpmaxq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { vpmaxq_s16_(a, b) } @@ -1678,6 +1863,7 @@ pub unsafe fn vpmaxq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(smaxp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpmaxq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { vpmaxq_s32_(a, b) } @@ -1686,6 +1872,7 @@ pub unsafe fn vpmaxq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umaxp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpmaxq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { vpmaxq_u8_(a, b) } @@ -1694,6 +1881,7 @@ pub unsafe fn vpmaxq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umaxp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpmaxq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { vpmaxq_u16_(a, b) } @@ -1702,6 +1890,7 @@ pub unsafe fn vpmaxq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(umaxp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpmaxq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { vpmaxq_u32_(a, b) } @@ -1710,6 +1899,7 @@ pub unsafe fn vpmaxq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmaxp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpmaxq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { vpmaxq_f32_(a, b) } @@ -1718,6 +1908,7 @@ pub unsafe fn vpmaxq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmaxp))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vpmaxq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { vpmaxq_f64_(a, b) } @@ -1727,10 +1918,9 @@ pub unsafe fn vpmaxq_f64(a: float64x2_t, b: float64x2_t) -> float64x2_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vext_p64(a: poly64x1_t, _b: poly64x1_t) -> poly64x1_t { - if N != 0 { - unreachable_unchecked() - } + static_assert!(N : i32 where N == 0); a } @@ -1739,16 +1929,16 @@ pub unsafe fn vext_p64(a: poly64x1_t, _b: poly64x1_t) -> poly64x1_ #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vext_f64(a: float64x1_t, _b: float64x1_t) -> float64x1_t { - if N != 0 { - unreachable_unchecked() - } + static_assert!(N : i32 where N == 0); a } /// Vector combine #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcombine_s8(low: int8x8_t, high: int8x8_t) -> int8x16_t { simd_shuffle16!( low, @@ -1761,6 +1951,7 @@ pub unsafe fn vcombine_s8(low: int8x8_t, high: int8x8_t) -> int8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcombine_s16(low: int16x4_t, high: int16x4_t) -> int16x8_t { simd_shuffle8!(low, high, [0, 1, 2, 3, 4, 5, 6, 7]) } @@ -1769,6 +1960,7 @@ pub unsafe fn vcombine_s16(low: int16x4_t, high: int16x4_t) -> int16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcombine_s32(low: int32x2_t, high: int32x2_t) -> int32x4_t { simd_shuffle4!(low, high, [0, 1, 2, 3]) } @@ -1777,6 +1969,7 @@ pub unsafe fn vcombine_s32(low: int32x2_t, high: int32x2_t) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcombine_s64(low: int64x1_t, high: int64x1_t) -> int64x2_t { simd_shuffle2!(low, high, [0, 1]) } @@ -1785,6 +1978,7 @@ pub unsafe fn vcombine_s64(low: int64x1_t, high: int64x1_t) -> int64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcombine_u8(low: uint8x8_t, high: uint8x8_t) -> uint8x16_t { simd_shuffle16!( low, @@ -1797,6 +1991,7 @@ pub unsafe fn vcombine_u8(low: uint8x8_t, high: uint8x8_t) -> uint8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcombine_u16(low: uint16x4_t, high: uint16x4_t) -> uint16x8_t { simd_shuffle8!(low, high, [0, 1, 2, 3, 4, 5, 6, 7]) } @@ -1805,6 +2000,7 @@ pub unsafe fn vcombine_u16(low: uint16x4_t, high: uint16x4_t) -> uint16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcombine_u32(low: uint32x2_t, high: uint32x2_t) -> uint32x4_t { simd_shuffle4!(low, high, [0, 1, 2, 3]) } @@ -1813,6 +2009,7 @@ pub unsafe fn vcombine_u32(low: uint32x2_t, high: uint32x2_t) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcombine_u64(low: uint64x1_t, high: uint64x1_t) -> uint64x2_t { simd_shuffle2!(low, high, [0, 1]) } @@ -1821,6 +2018,7 @@ pub unsafe fn vcombine_u64(low: uint64x1_t, high: uint64x1_t) -> uint64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcombine_p64(low: poly64x1_t, high: poly64x1_t) -> poly64x2_t { simd_shuffle2!(low, high, [0, 1]) } @@ -1829,6 +2027,7 @@ pub unsafe fn vcombine_p64(low: poly64x1_t, high: poly64x1_t) -> poly64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmov))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdup_n_p64(value: p64) -> poly64x1_t { transmute(u64x1::new(value)) } @@ -1837,6 +2036,7 @@ pub unsafe fn vdup_n_p64(value: p64) -> poly64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdup_n_f64(value: f64) -> float64x1_t { float64x1_t(value) } @@ -1845,6 +2045,7 @@ pub unsafe fn vdup_n_f64(value: f64) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(dup))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdupq_n_p64(value: p64) -> poly64x2_t { transmute(u64x2::new(value, value)) } @@ -1853,6 +2054,7 @@ pub unsafe fn vdupq_n_p64(value: p64) -> poly64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(dup))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vdupq_n_f64(value: f64) -> float64x2_t { float64x2_t(value, value) } @@ -1861,6 +2063,7 @@ pub unsafe fn vdupq_n_f64(value: f64) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(fmov))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmov_n_p64(value: p64) -> poly64x1_t { vdup_n_p64(value) } @@ -1869,6 +2072,7 @@ pub unsafe fn vmov_n_p64(value: p64) -> poly64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmov_n_f64(value: f64) -> float64x1_t { vdup_n_f64(value) } @@ -1877,6 +2081,7 @@ pub unsafe fn vmov_n_f64(value: f64) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(dup))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmovq_n_p64(value: p64) -> poly64x2_t { vdupq_n_p64(value) } @@ -1885,6 +2090,7 @@ pub unsafe fn vmovq_n_p64(value: p64) -> poly64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(dup))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vmovq_n_f64(value: f64) -> float64x2_t { vdupq_n_f64(value) } @@ -1893,6 +2099,7 @@ pub unsafe fn vmovq_n_f64(value: f64) -> float64x2_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vget_high_f64(a: float64x2_t) -> float64x1_t { float64x1_t(simd_extract(a, 1)) } @@ -1901,6 +2108,7 @@ pub unsafe fn vget_high_f64(a: float64x2_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(ext))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vget_high_p64(a: poly64x2_t) -> poly64x1_t { transmute(u64x1::new(simd_extract(a, 1))) } @@ -1909,6 +2117,7 @@ pub unsafe fn vget_high_p64(a: poly64x2_t) -> poly64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vget_low_f64(a: float64x2_t) -> float64x1_t { float64x1_t(simd_extract(a, 0)) } @@ -1917,6 +2126,7 @@ pub unsafe fn vget_low_f64(a: float64x2_t) -> float64x1_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vget_low_p64(a: poly64x2_t) -> poly64x1_t { transmute(u64x1::new(simd_extract(a, 0))) } @@ -1925,6 +2135,7 @@ pub unsafe fn vget_low_p64(a: poly64x2_t) -> poly64x1_t { #[inline] #[target_feature(enable = "neon")] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, IMM5 = 0))] pub unsafe fn vget_lane_f64(v: float64x1_t) -> f64 { static_assert!(IMM5 : i32 where IMM5 == 0); @@ -1935,6 +2146,7 @@ pub unsafe fn vget_lane_f64(v: float64x1_t) -> f64 { #[inline] #[target_feature(enable = "neon")] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, IMM5 = 0))] pub unsafe fn vgetq_lane_f64(v: float64x2_t) -> f64 { static_assert_imm1!(IMM5); @@ -1955,6 +2167,7 @@ pub unsafe fn vcombine_f16 ( low: float16x4_t, high: float16x4_t) -> float16x8_ #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcombine_f32(low: float32x2_t, high: float32x2_t) -> float32x4_t { simd_shuffle4!(low, high, [0, 1, 2, 3]) } @@ -1963,6 +2176,7 @@ pub unsafe fn vcombine_f32(low: float32x2_t, high: float32x2_t) -> float32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcombine_p8(low: poly8x8_t, high: poly8x8_t) -> poly8x16_t { simd_shuffle16!( low, @@ -1975,6 +2189,7 @@ pub unsafe fn vcombine_p8(low: poly8x8_t, high: poly8x8_t) -> poly8x16_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcombine_p16(low: poly16x4_t, high: poly16x4_t) -> poly16x8_t { simd_shuffle8!(low, high, [0, 1, 2, 3, 4, 5, 6, 7]) } @@ -1983,6 +2198,7 @@ pub unsafe fn vcombine_p16(low: poly16x4_t, high: poly16x4_t) -> poly16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(mov))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcombine_f64(low: float64x1_t, high: float64x1_t) -> float64x2_t { simd_shuffle2!(low, high, [0, 1]) } @@ -1992,6 +2208,7 @@ pub unsafe fn vcombine_f64(low: float64x1_t, high: float64x1_t) -> float64x2_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtbl1_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { vqtbl1_s8(vcombine_s8(a, zeroed()), transmute(b)) } @@ -2001,6 +2218,7 @@ pub unsafe fn vtbl1_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtbl1_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { vqtbl1_u8(vcombine_u8(a, zeroed()), b) } @@ -2010,6 +2228,7 @@ pub unsafe fn vtbl1_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtbl1_p8(a: poly8x8_t, b: uint8x8_t) -> poly8x8_t { vqtbl1_p8(vcombine_p8(a, zeroed()), b) } @@ -2019,6 +2238,7 @@ pub unsafe fn vtbl1_p8(a: poly8x8_t, b: uint8x8_t) -> poly8x8_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtbl2_s8(a: int8x8x2_t, b: int8x8_t) -> int8x8_t { vqtbl1_s8(vcombine_s8(a.0, a.1), transmute(b)) } @@ -2028,6 +2248,7 @@ pub unsafe fn vtbl2_s8(a: int8x8x2_t, b: int8x8_t) -> int8x8_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtbl2_u8(a: uint8x8x2_t, b: uint8x8_t) -> uint8x8_t { vqtbl1_u8(vcombine_u8(a.0, a.1), b) } @@ -2037,6 +2258,7 @@ pub unsafe fn vtbl2_u8(a: uint8x8x2_t, b: uint8x8_t) -> uint8x8_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtbl2_p8(a: poly8x8x2_t, b: uint8x8_t) -> poly8x8_t { vqtbl1_p8(vcombine_p8(a.0, a.1), b) } @@ -2046,6 +2268,7 @@ pub unsafe fn vtbl2_p8(a: poly8x8x2_t, b: uint8x8_t) -> poly8x8_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtbl3_s8(a: int8x8x3_t, b: int8x8_t) -> int8x8_t { vqtbl2_s8( int8x16x2_t(vcombine_s8(a.0, a.1), vcombine_s8(a.2, zeroed())), @@ -2058,6 +2281,7 @@ pub unsafe fn vtbl3_s8(a: int8x8x3_t, b: int8x8_t) -> int8x8_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtbl3_u8(a: uint8x8x3_t, b: uint8x8_t) -> uint8x8_t { vqtbl2_u8( uint8x16x2_t(vcombine_u8(a.0, a.1), vcombine_u8(a.2, zeroed())), @@ -2070,6 +2294,7 @@ pub unsafe fn vtbl3_u8(a: uint8x8x3_t, b: uint8x8_t) -> uint8x8_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtbl3_p8(a: poly8x8x3_t, b: uint8x8_t) -> poly8x8_t { vqtbl2_p8( poly8x16x2_t(vcombine_p8(a.0, a.1), vcombine_p8(a.2, zeroed())), @@ -2082,6 +2307,7 @@ pub unsafe fn vtbl3_p8(a: poly8x8x3_t, b: uint8x8_t) -> poly8x8_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtbl4_s8(a: int8x8x4_t, b: int8x8_t) -> int8x8_t { vqtbl2_s8( int8x16x2_t(vcombine_s8(a.0, a.1), vcombine_s8(a.2, a.3)), @@ -2094,6 +2320,7 @@ pub unsafe fn vtbl4_s8(a: int8x8x4_t, b: int8x8_t) -> int8x8_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtbl4_u8(a: uint8x8x4_t, b: uint8x8_t) -> uint8x8_t { vqtbl2_u8( uint8x16x2_t(vcombine_u8(a.0, a.1), vcombine_u8(a.2, a.3)), @@ -2106,6 +2333,7 @@ pub unsafe fn vtbl4_u8(a: uint8x8x4_t, b: uint8x8_t) -> uint8x8_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtbl4_p8(a: poly8x8x4_t, b: uint8x8_t) -> poly8x8_t { vqtbl2_p8( poly8x16x2_t(vcombine_p8(a.0, a.1), vcombine_p8(a.2, a.3)), @@ -2118,6 +2346,7 @@ pub unsafe fn vtbl4_p8(a: poly8x8x4_t, b: uint8x8_t) -> poly8x8_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtbx1_s8(a: int8x8_t, b: int8x8_t, c: int8x8_t) -> int8x8_t { let r = vqtbx1_s8(a, vcombine_s8(b, zeroed()), transmute(c)); let m: int8x8_t = simd_lt(c, transmute(i8x8::splat(8))); @@ -2129,6 +2358,7 @@ pub unsafe fn vtbx1_s8(a: int8x8_t, b: int8x8_t, c: int8x8_t) -> int8x8_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtbx1_u8(a: uint8x8_t, b: uint8x8_t, c: uint8x8_t) -> uint8x8_t { let r = vqtbx1_u8(a, vcombine_u8(b, zeroed()), c); let m: int8x8_t = simd_lt(c, transmute(u8x8::splat(8))); @@ -2140,6 +2370,7 @@ pub unsafe fn vtbx1_u8(a: uint8x8_t, b: uint8x8_t, c: uint8x8_t) -> uint8x8_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtbx1_p8(a: poly8x8_t, b: poly8x8_t, c: uint8x8_t) -> poly8x8_t { let r = vqtbx1_p8(a, vcombine_p8(b, zeroed()), c); let m: int8x8_t = simd_lt(c, transmute(u8x8::splat(8))); @@ -2151,6 +2382,7 @@ pub unsafe fn vtbx1_p8(a: poly8x8_t, b: poly8x8_t, c: uint8x8_t) -> poly8x8_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtbx2_s8(a: int8x8_t, b: int8x8x2_t, c: int8x8_t) -> int8x8_t { vqtbx1_s8(a, vcombine_s8(b.0, b.1), transmute(c)) } @@ -2160,6 +2392,7 @@ pub unsafe fn vtbx2_s8(a: int8x8_t, b: int8x8x2_t, c: int8x8_t) -> int8x8_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtbx2_u8(a: uint8x8_t, b: uint8x8x2_t, c: uint8x8_t) -> uint8x8_t { vqtbx1_u8(a, vcombine_u8(b.0, b.1), c) } @@ -2169,6 +2402,7 @@ pub unsafe fn vtbx2_u8(a: uint8x8_t, b: uint8x8x2_t, c: uint8x8_t) -> uint8x8_t #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtbx2_p8(a: poly8x8_t, b: poly8x8x2_t, c: uint8x8_t) -> poly8x8_t { vqtbx1_p8(a, vcombine_p8(b.0, b.1), c) } @@ -2178,6 +2412,7 @@ pub unsafe fn vtbx2_p8(a: poly8x8_t, b: poly8x8x2_t, c: uint8x8_t) -> poly8x8_t #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtbx3_s8(a: int8x8_t, b: int8x8x3_t, c: int8x8_t) -> int8x8_t { let r = vqtbx2_s8( a, @@ -2193,6 +2428,7 @@ pub unsafe fn vtbx3_s8(a: int8x8_t, b: int8x8x3_t, c: int8x8_t) -> int8x8_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtbx3_u8(a: uint8x8_t, b: uint8x8x3_t, c: uint8x8_t) -> uint8x8_t { let r = vqtbx2_u8( a, @@ -2208,6 +2444,7 @@ pub unsafe fn vtbx3_u8(a: uint8x8_t, b: uint8x8x3_t, c: uint8x8_t) -> uint8x8_t #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtbx3_p8(a: poly8x8_t, b: poly8x8x3_t, c: uint8x8_t) -> poly8x8_t { let r = vqtbx2_p8( a, @@ -2223,6 +2460,7 @@ pub unsafe fn vtbx3_p8(a: poly8x8_t, b: poly8x8x3_t, c: uint8x8_t) -> poly8x8_t #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtbx4_s8(a: int8x8_t, b: int8x8x4_t, c: int8x8_t) -> int8x8_t { vqtbx2_s8( a, @@ -2236,6 +2474,7 @@ pub unsafe fn vtbx4_s8(a: int8x8_t, b: int8x8x4_t, c: int8x8_t) -> int8x8_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtbx4_u8(a: uint8x8_t, b: uint8x8x4_t, c: uint8x8_t) -> uint8x8_t { vqtbx2_u8( a, @@ -2249,6 +2488,7 @@ pub unsafe fn vtbx4_u8(a: uint8x8_t, b: uint8x8x4_t, c: uint8x8_t) -> uint8x8_t #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vtbx4_p8(a: poly8x8_t, b: poly8x8x4_t, c: uint8x8_t) -> poly8x8_t { vqtbx2_p8( a, @@ -2262,94 +2502,117 @@ pub unsafe fn vtbx4_p8(a: poly8x8_t, b: poly8x8x4_t, c: uint8x8_t) -> poly8x8_t #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbl1_s8(t: int8x16_t, idx: uint8x8_t) -> int8x8_t { vqtbl1(t, idx) } + /// Table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbl1q_s8(t: int8x16_t, idx: uint8x16_t) -> int8x16_t { vqtbl1q(t, idx) } + /// Table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbl1_u8(t: uint8x16_t, idx: uint8x8_t) -> uint8x8_t { transmute(vqtbl1(transmute(t), transmute(idx))) } + /// Table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbl1q_u8(t: uint8x16_t, idx: uint8x16_t) -> uint8x16_t { transmute(vqtbl1q(transmute(t), transmute(idx))) } + /// Table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbl1_p8(t: poly8x16_t, idx: uint8x8_t) -> poly8x8_t { transmute(vqtbl1(transmute(t), transmute(idx))) } + /// Table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbl1q_p8(t: poly8x16_t, idx: uint8x16_t) -> poly8x16_t { transmute(vqtbl1q(transmute(t), transmute(idx))) } + /// Extended table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbx1_s8(a: int8x8_t, t: int8x16_t, idx: uint8x8_t) -> int8x8_t { vqtbx1(a, t, idx) } + /// Extended table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbx1q_s8(a: int8x16_t, t: int8x16_t, idx: uint8x16_t) -> int8x16_t { vqtbx1q(a, t, idx) } + /// Extended table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbx1_u8(a: uint8x8_t, t: uint8x16_t, idx: uint8x8_t) -> uint8x8_t { transmute(vqtbx1(transmute(a), transmute(t), transmute(idx))) } + /// Extended table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbx1q_u8(a: uint8x16_t, t: uint8x16_t, idx: uint8x16_t) -> uint8x16_t { transmute(vqtbx1q(transmute(a), transmute(t), transmute(idx))) } + /// Extended table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbx1_p8(a: poly8x8_t, t: poly8x16_t, idx: uint8x8_t) -> poly8x8_t { transmute(vqtbx1(transmute(a), transmute(t), transmute(idx))) } + /// Extended table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbx1q_p8(a: poly8x16_t, t: poly8x16_t, idx: uint8x16_t) -> poly8x16_t { transmute(vqtbx1q(transmute(a), transmute(t), transmute(idx))) } @@ -2359,70 +2622,87 @@ pub unsafe fn vqtbx1q_p8(a: poly8x16_t, t: poly8x16_t, idx: uint8x16_t) -> poly8 #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbl2_s8(t: int8x16x2_t, idx: uint8x8_t) -> int8x8_t { vqtbl2(t.0, t.1, idx) } + /// Table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbl2q_s8(t: int8x16x2_t, idx: uint8x16_t) -> int8x16_t { vqtbl2q(t.0, t.1, idx) } + /// Table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbl2_u8(t: uint8x16x2_t, idx: uint8x8_t) -> uint8x8_t { transmute(vqtbl2(transmute(t.0), transmute(t.1), transmute(idx))) } + /// Table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbl2q_u8(t: uint8x16x2_t, idx: uint8x16_t) -> uint8x16_t { transmute(vqtbl2q(transmute(t.0), transmute(t.1), transmute(idx))) } + /// Table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbl2_p8(t: poly8x16x2_t, idx: uint8x8_t) -> poly8x8_t { transmute(vqtbl2(transmute(t.0), transmute(t.1), transmute(idx))) } + /// Table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbl2q_p8(t: poly8x16x2_t, idx: uint8x16_t) -> poly8x16_t { transmute(vqtbl2q(transmute(t.0), transmute(t.1), transmute(idx))) } + /// Extended table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbx2_s8(a: int8x8_t, t: int8x16x2_t, idx: uint8x8_t) -> int8x8_t { vqtbx2(a, t.0, t.1, idx) } + /// Extended table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbx2q_s8(a: int8x16_t, t: int8x16x2_t, idx: uint8x16_t) -> int8x16_t { vqtbx2q(a, t.0, t.1, idx) } + /// Extended table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbx2_u8(a: uint8x8_t, t: uint8x16x2_t, idx: uint8x8_t) -> uint8x8_t { transmute(vqtbx2( transmute(a), @@ -2431,11 +2711,13 @@ pub unsafe fn vqtbx2_u8(a: uint8x8_t, t: uint8x16x2_t, idx: uint8x8_t) -> uint8x transmute(idx), )) } + /// Extended table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbx2q_u8(a: uint8x16_t, t: uint8x16x2_t, idx: uint8x16_t) -> uint8x16_t { transmute(vqtbx2q( transmute(a), @@ -2444,11 +2726,13 @@ pub unsafe fn vqtbx2q_u8(a: uint8x16_t, t: uint8x16x2_t, idx: uint8x16_t) -> uin transmute(idx), )) } + /// Extended table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbx2_p8(a: poly8x8_t, t: poly8x16x2_t, idx: uint8x8_t) -> poly8x8_t { transmute(vqtbx2( transmute(a), @@ -2457,11 +2741,13 @@ pub unsafe fn vqtbx2_p8(a: poly8x8_t, t: poly8x16x2_t, idx: uint8x8_t) -> poly8x transmute(idx), )) } + /// Extended table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbx2q_p8(a: poly8x16_t, t: poly8x16x2_t, idx: uint8x16_t) -> poly8x16_t { transmute(vqtbx2q( transmute(a), @@ -2476,22 +2762,27 @@ pub unsafe fn vqtbx2q_p8(a: poly8x16_t, t: poly8x16x2_t, idx: uint8x16_t) -> pol #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbl3_s8(t: int8x16x3_t, idx: uint8x8_t) -> int8x8_t { vqtbl3(t.0, t.1, t.2, idx) } + /// Table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbl3q_s8(t: int8x16x3_t, idx: uint8x16_t) -> int8x16_t { vqtbl3q(t.0, t.1, t.2, idx) } + /// Table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbl3_u8(t: uint8x16x3_t, idx: uint8x8_t) -> uint8x8_t { transmute(vqtbl3( transmute(t.0), @@ -2500,11 +2791,13 @@ pub unsafe fn vqtbl3_u8(t: uint8x16x3_t, idx: uint8x8_t) -> uint8x8_t { transmute(idx), )) } + /// Table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbl3q_u8(t: uint8x16x3_t, idx: uint8x16_t) -> uint8x16_t { transmute(vqtbl3q( transmute(t.0), @@ -2513,11 +2806,13 @@ pub unsafe fn vqtbl3q_u8(t: uint8x16x3_t, idx: uint8x16_t) -> uint8x16_t { transmute(idx), )) } + /// Table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbl3_p8(t: poly8x16x3_t, idx: uint8x8_t) -> poly8x8_t { transmute(vqtbl3( transmute(t.0), @@ -2526,11 +2821,13 @@ pub unsafe fn vqtbl3_p8(t: poly8x16x3_t, idx: uint8x8_t) -> poly8x8_t { transmute(idx), )) } + /// Table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbl3q_p8(t: poly8x16x3_t, idx: uint8x16_t) -> poly8x16_t { transmute(vqtbl3q( transmute(t.0), @@ -2539,27 +2836,33 @@ pub unsafe fn vqtbl3q_p8(t: poly8x16x3_t, idx: uint8x16_t) -> poly8x16_t { transmute(idx), )) } + /// Extended table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbx3_s8(a: int8x8_t, t: int8x16x3_t, idx: uint8x8_t) -> int8x8_t { vqtbx3(a, t.0, t.1, t.2, idx) } + /// Extended table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbx3q_s8(a: int8x16_t, t: int8x16x3_t, idx: uint8x16_t) -> int8x16_t { vqtbx3q(a, t.0, t.1, t.2, idx) } + /// Extended table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbx3_u8(a: uint8x8_t, t: uint8x16x3_t, idx: uint8x8_t) -> uint8x8_t { transmute(vqtbx3( transmute(a), @@ -2569,11 +2872,13 @@ pub unsafe fn vqtbx3_u8(a: uint8x8_t, t: uint8x16x3_t, idx: uint8x8_t) -> uint8x transmute(idx), )) } + /// Extended table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbx3q_u8(a: uint8x16_t, t: uint8x16x3_t, idx: uint8x16_t) -> uint8x16_t { transmute(vqtbx3q( transmute(a), @@ -2583,11 +2888,13 @@ pub unsafe fn vqtbx3q_u8(a: uint8x16_t, t: uint8x16x3_t, idx: uint8x16_t) -> uin transmute(idx), )) } + /// Extended table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbx3_p8(a: poly8x8_t, t: poly8x16x3_t, idx: uint8x8_t) -> poly8x8_t { transmute(vqtbx3( transmute(a), @@ -2597,11 +2904,13 @@ pub unsafe fn vqtbx3_p8(a: poly8x8_t, t: poly8x16x3_t, idx: uint8x8_t) -> poly8x transmute(idx), )) } + /// Extended table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbx3q_p8(a: poly8x16_t, t: poly8x16x3_t, idx: uint8x16_t) -> poly8x16_t { transmute(vqtbx3q( transmute(a), @@ -2617,22 +2926,27 @@ pub unsafe fn vqtbx3q_p8(a: poly8x16_t, t: poly8x16x3_t, idx: uint8x16_t) -> pol #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbl4_s8(t: int8x16x4_t, idx: uint8x8_t) -> int8x8_t { vqtbl4(t.0, t.1, t.2, t.3, idx) } + /// Table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbl4q_s8(t: int8x16x4_t, idx: uint8x16_t) -> int8x16_t { vqtbl4q(t.0, t.1, t.2, t.3, idx) } + /// Table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbl4_u8(t: uint8x16x4_t, idx: uint8x8_t) -> uint8x8_t { transmute(vqtbl4( transmute(t.0), @@ -2642,11 +2956,13 @@ pub unsafe fn vqtbl4_u8(t: uint8x16x4_t, idx: uint8x8_t) -> uint8x8_t { transmute(idx), )) } + /// Table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbl4q_u8(t: uint8x16x4_t, idx: uint8x16_t) -> uint8x16_t { transmute(vqtbl4q( transmute(t.0), @@ -2656,11 +2972,13 @@ pub unsafe fn vqtbl4q_u8(t: uint8x16x4_t, idx: uint8x16_t) -> uint8x16_t { transmute(idx), )) } + /// Table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbl4_p8(t: poly8x16x4_t, idx: uint8x8_t) -> poly8x8_t { transmute(vqtbl4( transmute(t.0), @@ -2670,11 +2988,13 @@ pub unsafe fn vqtbl4_p8(t: poly8x16x4_t, idx: uint8x8_t) -> poly8x8_t { transmute(idx), )) } + /// Table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbl))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbl4q_p8(t: poly8x16x4_t, idx: uint8x16_t) -> poly8x16_t { transmute(vqtbl4q( transmute(t.0), @@ -2684,27 +3004,33 @@ pub unsafe fn vqtbl4q_p8(t: poly8x16x4_t, idx: uint8x16_t) -> poly8x16_t { transmute(idx), )) } + /// Extended table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbx4_s8(a: int8x8_t, t: int8x16x4_t, idx: uint8x8_t) -> int8x8_t { vqtbx4(a, t.0, t.1, t.2, t.3, idx) } + /// Extended table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbx4q_s8(a: int8x16_t, t: int8x16x4_t, idx: uint8x16_t) -> int8x16_t { vqtbx4q(a, t.0, t.1, t.2, t.3, idx) } + /// Extended table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbx4_u8(a: uint8x8_t, t: uint8x16x4_t, idx: uint8x8_t) -> uint8x8_t { transmute(vqtbx4( transmute(a), @@ -2715,11 +3041,13 @@ pub unsafe fn vqtbx4_u8(a: uint8x8_t, t: uint8x16x4_t, idx: uint8x8_t) -> uint8x transmute(idx), )) } + /// Extended table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbx4q_u8(a: uint8x16_t, t: uint8x16x4_t, idx: uint8x16_t) -> uint8x16_t { transmute(vqtbx4q( transmute(a), @@ -2730,11 +3058,13 @@ pub unsafe fn vqtbx4q_u8(a: uint8x16_t, t: uint8x16x4_t, idx: uint8x16_t) -> uin transmute(idx), )) } + /// Extended table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbx4_p8(a: poly8x8_t, t: poly8x16x4_t, idx: uint8x8_t) -> poly8x8_t { transmute(vqtbx4( transmute(a), @@ -2745,11 +3075,13 @@ pub unsafe fn vqtbx4_p8(a: poly8x8_t, t: poly8x16x4_t, idx: uint8x8_t) -> poly8x transmute(idx), )) } + /// Extended table look-up #[inline] #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(tbx))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqtbx4q_p8(a: poly8x16_t, t: poly8x16x4_t, idx: uint8x16_t) -> poly8x16_t { transmute(vqtbx4q( transmute(a), @@ -2766,6 +3098,7 @@ pub unsafe fn vqtbx4q_p8(a: poly8x16_t, t: poly8x16x4_t, idx: uint8x16_t) -> pol #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vshld_n_s64(a: i64) -> i64 { static_assert_imm6!(N); a << N @@ -2776,6 +3109,7 @@ pub unsafe fn vshld_n_s64(a: i64) -> i64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vshld_n_u64(a: u64) -> u64 { static_assert_imm6!(N); a << N @@ -2786,6 +3120,7 @@ pub unsafe fn vshld_n_u64(a: u64) -> u64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vshrd_n_s64(a: i64) -> i64 { static_assert!(N : i32 where N >= 1 && N <= 64); let n: i32 = if N == 64 { 63 } else { N }; @@ -2797,6 +3132,7 @@ pub unsafe fn vshrd_n_s64(a: i64) -> i64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vshrd_n_u64(a: u64) -> u64 { static_assert!(N : i32 where N >= 1 && N <= 64); let n: i32 = if N == 64 { @@ -2812,9 +3148,10 @@ pub unsafe fn vshrd_n_u64(a: u64) -> u64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsrad_n_s64(a: i64, b: i64) -> i64 { static_assert!(N : i32 where N >= 1 && N <= 64); - a + vshrd_n_s64::(b) + a.wrapping_add(vshrd_n_s64::(b)) } /// Unsigned shift right and accumulate @@ -2822,9 +3159,10 @@ pub unsafe fn vsrad_n_s64(a: i64, b: i64) -> i64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(nop, N = 2))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsrad_n_u64(a: u64, b: u64) -> u64 { static_assert!(N : i32 where N >= 1 && N <= 64); - a + vshrd_n_u64::(b) + a.wrapping_add(vshrd_n_u64::(b)) } /// Shift Left and Insert (immediate) @@ -2832,6 +3170,7 @@ pub unsafe fn vsrad_n_u64(a: u64, b: u64) -> u64 { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sli, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsli_n_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { static_assert_imm3!(N); vsli_n_s8_(a, b, N) @@ -2841,6 +3180,7 @@ pub unsafe fn vsli_n_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sli, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsliq_n_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { static_assert_imm3!(N); vsliq_n_s8_(a, b, N) @@ -2850,6 +3190,7 @@ pub unsafe fn vsliq_n_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sli, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsli_n_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { static_assert_imm4!(N); vsli_n_s16_(a, b, N) @@ -2859,6 +3200,7 @@ pub unsafe fn vsli_n_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sli, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsliq_n_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { static_assert_imm4!(N); vsliq_n_s16_(a, b, N) @@ -2868,6 +3210,7 @@ pub unsafe fn vsliq_n_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sli, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsli_n_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { static_assert!(N: i32 where N >= 0 && N <= 31); vsli_n_s32_(a, b, N) @@ -2877,6 +3220,7 @@ pub unsafe fn vsli_n_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sli, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsliq_n_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { static_assert!(N: i32 where N >= 0 && N <= 31); vsliq_n_s32_(a, b, N) @@ -2886,6 +3230,7 @@ pub unsafe fn vsliq_n_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sli, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsli_n_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { static_assert!(N: i32 where N >= 0 && N <= 63); vsli_n_s64_(a, b, N) @@ -2895,6 +3240,7 @@ pub unsafe fn vsli_n_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sli, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsliq_n_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { static_assert!(N: i32 where N >= 0 && N <= 63); vsliq_n_s64_(a, b, N) @@ -2904,6 +3250,7 @@ pub unsafe fn vsliq_n_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sli, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsli_n_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { static_assert_imm3!(N); transmute(vsli_n_s8_(transmute(a), transmute(b), N)) @@ -2913,6 +3260,7 @@ pub unsafe fn vsli_n_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sli, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsliq_n_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { static_assert_imm3!(N); transmute(vsliq_n_s8_(transmute(a), transmute(b), N)) @@ -2922,6 +3270,7 @@ pub unsafe fn vsliq_n_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16 #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sli, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsli_n_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { static_assert_imm4!(N); transmute(vsli_n_s16_(transmute(a), transmute(b), N)) @@ -2931,6 +3280,7 @@ pub unsafe fn vsli_n_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4 #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sli, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsliq_n_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { static_assert_imm4!(N); transmute(vsliq_n_s16_(transmute(a), transmute(b), N)) @@ -2940,6 +3290,7 @@ pub unsafe fn vsliq_n_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sli, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsli_n_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { static_assert!(N: i32 where N >= 0 && N <= 31); transmute(vsli_n_s32_(transmute(a), transmute(b), N)) @@ -2949,6 +3300,7 @@ pub unsafe fn vsli_n_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2 #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sli, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsliq_n_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { static_assert!(N: i32 where N >= 0 && N <= 31); transmute(vsliq_n_s32_(transmute(a), transmute(b), N)) @@ -2958,6 +3310,7 @@ pub unsafe fn vsliq_n_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sli, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsli_n_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { static_assert!(N: i32 where N >= 0 && N <= 63); transmute(vsli_n_s64_(transmute(a), transmute(b), N)) @@ -2967,6 +3320,7 @@ pub unsafe fn vsli_n_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1 #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sli, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsliq_n_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { static_assert!(N: i32 where N >= 0 && N <= 63); transmute(vsliq_n_s64_(transmute(a), transmute(b), N)) @@ -2976,6 +3330,7 @@ pub unsafe fn vsliq_n_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sli, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsli_n_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { static_assert_imm3!(N); transmute(vsli_n_s8_(transmute(a), transmute(b), N)) @@ -2985,6 +3340,7 @@ pub unsafe fn vsli_n_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sli, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsliq_n_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { static_assert_imm3!(N); transmute(vsliq_n_s8_(transmute(a), transmute(b), N)) @@ -2994,6 +3350,7 @@ pub unsafe fn vsliq_n_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16 #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sli, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsli_n_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { static_assert_imm4!(N); transmute(vsli_n_s16_(transmute(a), transmute(b), N)) @@ -3003,6 +3360,7 @@ pub unsafe fn vsli_n_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4 #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sli, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsliq_n_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { static_assert_imm4!(N); transmute(vsliq_n_s16_(transmute(a), transmute(b), N)) @@ -3012,6 +3370,7 @@ pub unsafe fn vsliq_n_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(sli, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsli_n_p64(a: poly64x1_t, b: poly64x1_t) -> poly64x1_t { static_assert!(N: i32 where N >= 0 && N <= 63); transmute(vsli_n_s64_(transmute(a), transmute(b), N)) @@ -3021,6 +3380,7 @@ pub unsafe fn vsli_n_p64(a: poly64x1_t, b: poly64x1_t) -> poly64x1 #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(sli, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsliq_n_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { static_assert!(N: i32 where N >= 0 && N <= 63); transmute(vsliq_n_s64_(transmute(a), transmute(b), N)) @@ -3030,6 +3390,7 @@ pub unsafe fn vsliq_n_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sri, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsri_n_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { static_assert!(N: i32 where N >= 1 && N <= 8); vsri_n_s8_(a, b, N) @@ -3039,6 +3400,7 @@ pub unsafe fn vsri_n_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sri, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsriq_n_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { static_assert!(N: i32 where N >= 1 && N <= 8); vsriq_n_s8_(a, b, N) @@ -3048,6 +3410,7 @@ pub unsafe fn vsriq_n_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sri, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsri_n_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { static_assert!(N: i32 where N >= 1 && N <= 16); vsri_n_s16_(a, b, N) @@ -3057,6 +3420,7 @@ pub unsafe fn vsri_n_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sri, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsriq_n_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { static_assert!(N: i32 where N >= 1 && N <= 16); vsriq_n_s16_(a, b, N) @@ -3066,6 +3430,7 @@ pub unsafe fn vsriq_n_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sri, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsri_n_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { static_assert!(N: i32 where N >= 1 && N <= 32); vsri_n_s32_(a, b, N) @@ -3075,6 +3440,7 @@ pub unsafe fn vsri_n_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sri, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsriq_n_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { static_assert!(N: i32 where N >= 1 && N <= 32); vsriq_n_s32_(a, b, N) @@ -3084,6 +3450,7 @@ pub unsafe fn vsriq_n_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sri, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsri_n_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { static_assert!(N: i32 where N >= 1 && N <= 64); vsri_n_s64_(a, b, N) @@ -3093,6 +3460,7 @@ pub unsafe fn vsri_n_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sri, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsriq_n_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { static_assert!(N: i32 where N >= 1 && N <= 64); vsriq_n_s64_(a, b, N) @@ -3102,6 +3470,7 @@ pub unsafe fn vsriq_n_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sri, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsri_n_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { static_assert!(N: i32 where N >= 1 && N <= 8); transmute(vsri_n_s8_(transmute(a), transmute(b), N)) @@ -3111,6 +3480,7 @@ pub unsafe fn vsri_n_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sri, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsriq_n_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { static_assert!(N: i32 where N >= 1 && N <= 8); transmute(vsriq_n_s8_(transmute(a), transmute(b), N)) @@ -3120,6 +3490,7 @@ pub unsafe fn vsriq_n_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16 #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sri, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsri_n_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { static_assert!(N: i32 where N >= 1 && N <= 16); transmute(vsri_n_s16_(transmute(a), transmute(b), N)) @@ -3129,6 +3500,7 @@ pub unsafe fn vsri_n_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4 #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sri, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsriq_n_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { static_assert!(N: i32 where N >= 1 && N <= 16); transmute(vsriq_n_s16_(transmute(a), transmute(b), N)) @@ -3138,6 +3510,7 @@ pub unsafe fn vsriq_n_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sri, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsri_n_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { static_assert!(N: i32 where N >= 1 && N <= 32); transmute(vsri_n_s32_(transmute(a), transmute(b), N)) @@ -3147,6 +3520,7 @@ pub unsafe fn vsri_n_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2 #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sri, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsriq_n_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { static_assert!(N: i32 where N >= 1 && N <= 32); transmute(vsriq_n_s32_(transmute(a), transmute(b), N)) @@ -3156,6 +3530,7 @@ pub unsafe fn vsriq_n_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sri, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsri_n_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { static_assert!(N: i32 where N >= 1 && N <= 64); transmute(vsri_n_s64_(transmute(a), transmute(b), N)) @@ -3165,6 +3540,7 @@ pub unsafe fn vsri_n_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1 #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sri, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsriq_n_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { static_assert!(N: i32 where N >= 1 && N <= 64); transmute(vsriq_n_s64_(transmute(a), transmute(b), N)) @@ -3174,6 +3550,7 @@ pub unsafe fn vsriq_n_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sri, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsri_n_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { static_assert!(N: i32 where N >= 1 && N <= 8); transmute(vsri_n_s8_(transmute(a), transmute(b), N)) @@ -3183,6 +3560,7 @@ pub unsafe fn vsri_n_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sri, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsriq_n_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { static_assert!(N: i32 where N >= 1 && N <= 8); transmute(vsriq_n_s8_(transmute(a), transmute(b), N)) @@ -3192,6 +3570,7 @@ pub unsafe fn vsriq_n_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16 #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sri, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsri_n_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { static_assert!(N: i32 where N >= 1 && N <= 16); transmute(vsri_n_s16_(transmute(a), transmute(b), N)) @@ -3201,6 +3580,7 @@ pub unsafe fn vsri_n_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4 #[target_feature(enable = "neon")] #[cfg_attr(test, assert_instr(sri, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsriq_n_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { static_assert!(N: i32 where N >= 1 && N <= 16); transmute(vsriq_n_s16_(transmute(a), transmute(b), N)) @@ -3210,6 +3590,7 @@ pub unsafe fn vsriq_n_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(sri, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsri_n_p64(a: poly64x1_t, b: poly64x1_t) -> poly64x1_t { static_assert!(N: i32 where N >= 1 && N <= 64); transmute(vsri_n_s64_(transmute(a), transmute(b), N)) @@ -3219,6 +3600,7 @@ pub unsafe fn vsri_n_p64(a: poly64x1_t, b: poly64x1_t) -> poly64x1 #[target_feature(enable = "neon,aes")] #[cfg_attr(test, assert_instr(sri, N = 1))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vsriq_n_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { static_assert!(N: i32 where N >= 1 && N <= 64); transmute(vsriq_n_s64_(transmute(a), transmute(b), N)) diff --git a/library/stdarch/crates/core_arch/src/aarch64/prefetch.rs b/library/stdarch/crates/core_arch/src/aarch64/prefetch.rs index 687c3f39a0..3ae0ef506b 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/prefetch.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/prefetch.rs @@ -66,7 +66,7 @@ pub const _PREFETCH_LOCALITY3: i32 = 3; #[rustc_legacy_const_generics(1, 2)] // FIXME: Replace this with the standard ACLE __pld/__pldx/__pli/__plix intrinsics pub unsafe fn _prefetch(p: *const i8) { - // We use the `llvm.prefetch` instrinsic with `cache type` = 1 (data cache). + // We use the `llvm.prefetch` intrinsic with `cache type` = 1 (data cache). static_assert_imm1!(RW); static_assert_imm2!(LOCALITY); prefetch(p, RW, LOCALITY, 1); diff --git a/library/stdarch/crates/core_arch/src/arm/armclang.rs b/library/stdarch/crates/core_arch/src/arm/armclang.rs index 6b332e82c0..e68c02d027 100644 --- a/library/stdarch/crates/core_arch/src/arm/armclang.rs +++ b/library/stdarch/crates/core_arch/src/arm/armclang.rs @@ -31,5 +31,5 @@ use stdarch_test::assert_instr; #[rustc_legacy_const_generics(0)] pub unsafe fn __breakpoint() { static_assert_imm8!(VAL); - asm!("bkpt #{}", const VAL); + crate::arch::asm!("bkpt #{}", const VAL); } diff --git a/library/stdarch/crates/core_arch/src/arm/mod.rs b/library/stdarch/crates/core_arch/src/arm/mod.rs index 3c56ec7b1e..efe0068d40 100644 --- a/library/stdarch/crates/core_arch/src/arm/mod.rs +++ b/library/stdarch/crates/core_arch/src/arm/mod.rs @@ -93,7 +93,7 @@ pub unsafe fn udf() -> ! { /// This provides a hint to debugging and related systems. The argument must be /// a constant integer from 0 to 15 inclusive. See implementation documentation /// for the effect (if any) of this instruction and the meaning of the -/// argument. This is available only when compliling for AArch32. +/// argument. This is available only when compiling for AArch32. // Section 10.1 of ACLE says that the supported arches are: 7, 7-M // "The DBG hint instruction is added in ARMv7. It is UNDEFINED in the ARMv6 base architecture, and // executes as a NOP instruction in ARMv6K and ARMv6T2." - ARM Architecture Reference Manual ARMv7-A diff --git a/library/stdarch/crates/core_arch/src/arm_shared/barrier/cp15.rs b/library/stdarch/crates/core_arch/src/arm_shared/barrier/cp15.rs index 25d4c3c8cb..6faae0fee0 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/barrier/cp15.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/barrier/cp15.rs @@ -1,6 +1,8 @@ // Reference: ARM11 MPCore Processor Technical Reference Manual (ARM DDI 0360E) Section 3.5 "Summary // of CP15 instructions" +use crate::arch::asm; + /// Full system is the required shareability domain, reads and writes are the /// required access types pub struct SY; diff --git a/library/stdarch/crates/core_arch/src/arm_shared/barrier/v8.rs b/library/stdarch/crates/core_arch/src/arm_shared/barrier/v8.rs index 2951a5a670..db15da805d 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/barrier/v8.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/barrier/v8.rs @@ -16,7 +16,7 @@ pub struct NSHLD; dmb_dsb!(NSHLD); -/// Outher Shareable is the required shareability domain, reads are the required +/// Outer Shareable is the required shareability domain, reads are the required /// access type pub struct OSHLD; diff --git a/library/stdarch/crates/core_arch/src/arm_shared/hints.rs b/library/stdarch/crates/core_arch/src/arm_shared/hints.rs index 1d6551e5e7..d7e43f5517 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/hints.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/hints.rs @@ -77,7 +77,7 @@ pub unsafe fn __yield() { /// will increase execution time. #[inline(always)] pub unsafe fn __nop() { - asm!("nop", options(nomem, nostack, preserves_flags)); + crate::arch::asm!("nop", options(nomem, nostack, preserves_flags)); } extern "unadjusted" { diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs index 2f93c65262..7837307e44 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs @@ -15,6 +15,7 @@ use stdarch_test::assert_instr; #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vand_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { simd_and(a, b) } @@ -25,6 +26,7 @@ pub unsafe fn vand_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vandq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { simd_and(a, b) } @@ -35,6 +37,7 @@ pub unsafe fn vandq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vand_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { simd_and(a, b) } @@ -45,6 +48,7 @@ pub unsafe fn vand_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vandq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { simd_and(a, b) } @@ -55,6 +59,7 @@ pub unsafe fn vandq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vand_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { simd_and(a, b) } @@ -65,6 +70,7 @@ pub unsafe fn vand_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vandq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { simd_and(a, b) } @@ -75,6 +81,7 @@ pub unsafe fn vandq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vand_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { simd_and(a, b) } @@ -85,6 +92,7 @@ pub unsafe fn vand_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vandq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { simd_and(a, b) } @@ -95,6 +103,7 @@ pub unsafe fn vandq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vand_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { simd_and(a, b) } @@ -105,6 +114,7 @@ pub unsafe fn vand_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vandq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { simd_and(a, b) } @@ -115,6 +125,7 @@ pub unsafe fn vandq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vand_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { simd_and(a, b) } @@ -125,6 +136,7 @@ pub unsafe fn vand_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vandq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { simd_and(a, b) } @@ -135,6 +147,7 @@ pub unsafe fn vandq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vand_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { simd_and(a, b) } @@ -145,6 +158,7 @@ pub unsafe fn vand_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vandq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { simd_and(a, b) } @@ -155,6 +169,7 @@ pub unsafe fn vandq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vand_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { simd_and(a, b) } @@ -165,6 +180,7 @@ pub unsafe fn vand_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vand))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(and))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vandq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { simd_and(a, b) } @@ -175,6 +191,7 @@ pub unsafe fn vandq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vorr_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { simd_or(a, b) } @@ -185,6 +202,7 @@ pub unsafe fn vorr_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vorrq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { simd_or(a, b) } @@ -195,6 +213,7 @@ pub unsafe fn vorrq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vorr_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { simd_or(a, b) } @@ -205,6 +224,7 @@ pub unsafe fn vorr_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vorrq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { simd_or(a, b) } @@ -215,6 +235,7 @@ pub unsafe fn vorrq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vorr_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { simd_or(a, b) } @@ -225,6 +246,7 @@ pub unsafe fn vorr_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vorrq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { simd_or(a, b) } @@ -235,6 +257,7 @@ pub unsafe fn vorrq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vorr_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { simd_or(a, b) } @@ -245,6 +268,7 @@ pub unsafe fn vorr_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vorrq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { simd_or(a, b) } @@ -255,6 +279,7 @@ pub unsafe fn vorrq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vorr_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { simd_or(a, b) } @@ -265,6 +290,7 @@ pub unsafe fn vorr_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vorrq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { simd_or(a, b) } @@ -275,6 +301,7 @@ pub unsafe fn vorrq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vorr_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { simd_or(a, b) } @@ -285,6 +312,7 @@ pub unsafe fn vorr_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vorrq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { simd_or(a, b) } @@ -295,6 +323,7 @@ pub unsafe fn vorrq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vorr_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { simd_or(a, b) } @@ -305,6 +334,7 @@ pub unsafe fn vorr_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vorrq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { simd_or(a, b) } @@ -315,6 +345,7 @@ pub unsafe fn vorrq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vorr_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { simd_or(a, b) } @@ -325,6 +356,7 @@ pub unsafe fn vorr_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orr))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vorrq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { simd_or(a, b) } @@ -335,6 +367,7 @@ pub unsafe fn vorrq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn veor_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { simd_xor(a, b) } @@ -345,6 +378,7 @@ pub unsafe fn veor_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn veorq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { simd_xor(a, b) } @@ -355,6 +389,7 @@ pub unsafe fn veorq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn veor_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { simd_xor(a, b) } @@ -365,6 +400,7 @@ pub unsafe fn veor_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn veorq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { simd_xor(a, b) } @@ -375,6 +411,7 @@ pub unsafe fn veorq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn veor_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { simd_xor(a, b) } @@ -385,6 +422,7 @@ pub unsafe fn veor_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn veorq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { simd_xor(a, b) } @@ -395,6 +433,7 @@ pub unsafe fn veorq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn veor_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { simd_xor(a, b) } @@ -405,6 +444,7 @@ pub unsafe fn veor_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn veorq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { simd_xor(a, b) } @@ -415,6 +455,7 @@ pub unsafe fn veorq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn veor_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { simd_xor(a, b) } @@ -425,6 +466,7 @@ pub unsafe fn veor_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn veorq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { simd_xor(a, b) } @@ -435,6 +477,7 @@ pub unsafe fn veorq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn veor_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { simd_xor(a, b) } @@ -445,6 +488,7 @@ pub unsafe fn veor_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn veorq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { simd_xor(a, b) } @@ -455,6 +499,7 @@ pub unsafe fn veorq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn veor_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { simd_xor(a, b) } @@ -465,6 +510,7 @@ pub unsafe fn veor_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn veorq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { simd_xor(a, b) } @@ -475,6 +521,7 @@ pub unsafe fn veorq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn veor_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { simd_xor(a, b) } @@ -485,6 +532,7 @@ pub unsafe fn veor_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(veor))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(eor))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn veorq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { simd_xor(a, b) } @@ -495,6 +543,7 @@ pub unsafe fn veorq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabd_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -511,6 +560,7 @@ vabd_s8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabdq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -527,6 +577,7 @@ vabdq_s8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabd_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -543,6 +594,7 @@ vabd_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabdq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -559,6 +611,7 @@ vabdq_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabd_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -575,6 +628,7 @@ vabd_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabdq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -591,6 +645,7 @@ vabdq_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabd_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -607,6 +662,7 @@ vabd_u8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabdq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -623,6 +679,7 @@ vabdq_u8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabd_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -639,6 +696,7 @@ vabd_u16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabdq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -655,6 +713,7 @@ vabdq_u16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabd_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -671,6 +730,7 @@ vabd_u32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabdq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -687,6 +747,7 @@ vabdq_u32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fabd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabd_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -703,6 +764,7 @@ vabd_f32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabd.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fabd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabdq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -719,6 +781,7 @@ vabdq_f32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabdl.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabdl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabdl_u8(a: uint8x8_t, b: uint8x8_t) -> uint16x8_t { simd_cast(vabd_u8(a, b)) } @@ -729,6 +792,7 @@ pub unsafe fn vabdl_u8(a: uint8x8_t, b: uint8x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabdl.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabdl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabdl_u16(a: uint16x4_t, b: uint16x4_t) -> uint32x4_t { simd_cast(vabd_u16(a, b)) } @@ -739,6 +803,7 @@ pub unsafe fn vabdl_u16(a: uint16x4_t, b: uint16x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabdl.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabdl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabdl_u32(a: uint32x2_t, b: uint32x2_t) -> uint64x2_t { simd_cast(vabd_u32(a, b)) } @@ -749,6 +814,7 @@ pub unsafe fn vabdl_u32(a: uint32x2_t, b: uint32x2_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabdl.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabdl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabdl_s8(a: int8x8_t, b: int8x8_t) -> int16x8_t { let c: uint8x8_t = simd_cast(vabd_s8(a, b)); simd_cast(c) @@ -760,6 +826,7 @@ pub unsafe fn vabdl_s8(a: int8x8_t, b: int8x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabdl.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabdl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabdl_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t { let c: uint16x4_t = simd_cast(vabd_s16(a, b)); simd_cast(c) @@ -771,6 +838,7 @@ pub unsafe fn vabdl_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabdl.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabdl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabdl_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t { let c: uint32x2_t = simd_cast(vabd_s32(a, b)); simd_cast(c) @@ -782,6 +850,7 @@ pub unsafe fn vabdl_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vceq_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { simd_eq(a, b) } @@ -792,6 +861,7 @@ pub unsafe fn vceq_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vceqq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { simd_eq(a, b) } @@ -802,6 +872,7 @@ pub unsafe fn vceqq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vceq_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { simd_eq(a, b) } @@ -812,6 +883,7 @@ pub unsafe fn vceq_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vceqq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { simd_eq(a, b) } @@ -822,6 +894,7 @@ pub unsafe fn vceqq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vceq_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { simd_eq(a, b) } @@ -832,6 +905,7 @@ pub unsafe fn vceq_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vceqq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { simd_eq(a, b) } @@ -842,6 +916,7 @@ pub unsafe fn vceqq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vceq_s8(a: int8x8_t, b: int8x8_t) -> uint8x8_t { simd_eq(a, b) } @@ -852,6 +927,7 @@ pub unsafe fn vceq_s8(a: int8x8_t, b: int8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vceqq_s8(a: int8x16_t, b: int8x16_t) -> uint8x16_t { simd_eq(a, b) } @@ -862,6 +938,7 @@ pub unsafe fn vceqq_s8(a: int8x16_t, b: int8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vceq_s16(a: int16x4_t, b: int16x4_t) -> uint16x4_t { simd_eq(a, b) } @@ -872,6 +949,7 @@ pub unsafe fn vceq_s16(a: int16x4_t, b: int16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vceqq_s16(a: int16x8_t, b: int16x8_t) -> uint16x8_t { simd_eq(a, b) } @@ -882,6 +960,7 @@ pub unsafe fn vceqq_s16(a: int16x8_t, b: int16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vceq_s32(a: int32x2_t, b: int32x2_t) -> uint32x2_t { simd_eq(a, b) } @@ -892,6 +971,7 @@ pub unsafe fn vceq_s32(a: int32x2_t, b: int32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vceqq_s32(a: int32x4_t, b: int32x4_t) -> uint32x4_t { simd_eq(a, b) } @@ -902,6 +982,7 @@ pub unsafe fn vceqq_s32(a: int32x4_t, b: int32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vceq_p8(a: poly8x8_t, b: poly8x8_t) -> uint8x8_t { simd_eq(a, b) } @@ -912,6 +993,7 @@ pub unsafe fn vceq_p8(a: poly8x8_t, b: poly8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmeq))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vceqq_p8(a: poly8x16_t, b: poly8x16_t) -> uint8x16_t { simd_eq(a, b) } @@ -922,6 +1004,7 @@ pub unsafe fn vceqq_p8(a: poly8x16_t, b: poly8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcmeq))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vceq_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t { simd_eq(a, b) } @@ -932,6 +1015,7 @@ pub unsafe fn vceq_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vceq.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcmeq))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vceqq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { simd_eq(a, b) } @@ -942,6 +1026,7 @@ pub unsafe fn vceqq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtst_s8(a: int8x8_t, b: int8x8_t) -> uint8x8_t { let c: int8x8_t = simd_and(a, b); let d: i8x8 = i8x8::new(0, 0, 0, 0, 0, 0, 0, 0); @@ -954,6 +1039,7 @@ pub unsafe fn vtst_s8(a: int8x8_t, b: int8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtstq_s8(a: int8x16_t, b: int8x16_t) -> uint8x16_t { let c: int8x16_t = simd_and(a, b); let d: i8x16 = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); @@ -966,6 +1052,7 @@ pub unsafe fn vtstq_s8(a: int8x16_t, b: int8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtst_s16(a: int16x4_t, b: int16x4_t) -> uint16x4_t { let c: int16x4_t = simd_and(a, b); let d: i16x4 = i16x4::new(0, 0, 0, 0); @@ -978,6 +1065,7 @@ pub unsafe fn vtst_s16(a: int16x4_t, b: int16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtstq_s16(a: int16x8_t, b: int16x8_t) -> uint16x8_t { let c: int16x8_t = simd_and(a, b); let d: i16x8 = i16x8::new(0, 0, 0, 0, 0, 0, 0, 0); @@ -990,6 +1078,7 @@ pub unsafe fn vtstq_s16(a: int16x8_t, b: int16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtst_s32(a: int32x2_t, b: int32x2_t) -> uint32x2_t { let c: int32x2_t = simd_and(a, b); let d: i32x2 = i32x2::new(0, 0); @@ -1002,6 +1091,7 @@ pub unsafe fn vtst_s32(a: int32x2_t, b: int32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtstq_s32(a: int32x4_t, b: int32x4_t) -> uint32x4_t { let c: int32x4_t = simd_and(a, b); let d: i32x4 = i32x4::new(0, 0, 0, 0); @@ -1014,6 +1104,7 @@ pub unsafe fn vtstq_s32(a: int32x4_t, b: int32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtst_p8(a: poly8x8_t, b: poly8x8_t) -> uint8x8_t { let c: poly8x8_t = simd_and(a, b); let d: i8x8 = i8x8::new(0, 0, 0, 0, 0, 0, 0, 0); @@ -1026,18 +1117,46 @@ pub unsafe fn vtst_p8(a: poly8x8_t, b: poly8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtstq_p8(a: poly8x16_t, b: poly8x16_t) -> uint8x16_t { let c: poly8x16_t = simd_and(a, b); let d: i8x16 = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); simd_ne(c, transmute(d)) } +/// Signed compare bitwise Test bits nonzero +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] +pub unsafe fn vtst_p16(a: poly16x4_t, b: poly16x4_t) -> uint16x4_t { + let c: poly16x4_t = simd_and(a, b); + let d: i16x4 = i16x4::new(0, 0, 0, 0); + simd_ne(c, transmute(d)) +} + +/// Signed compare bitwise Test bits nonzero +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] +pub unsafe fn vtstq_p16(a: poly16x8_t, b: poly16x8_t) -> uint16x8_t { + let c: poly16x8_t = simd_and(a, b); + let d: i16x8 = i16x8::new(0, 0, 0, 0, 0, 0, 0, 0); + simd_ne(c, transmute(d)) +} + /// Unsigned compare bitwise Test bits nonzero #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtst_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { let c: uint8x8_t = simd_and(a, b); let d: u8x8 = u8x8::new(0, 0, 0, 0, 0, 0, 0, 0); @@ -1050,6 +1169,7 @@ pub unsafe fn vtst_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtstq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { let c: uint8x16_t = simd_and(a, b); let d: u8x16 = u8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); @@ -1062,6 +1182,7 @@ pub unsafe fn vtstq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtst_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { let c: uint16x4_t = simd_and(a, b); let d: u16x4 = u16x4::new(0, 0, 0, 0); @@ -1074,6 +1195,7 @@ pub unsafe fn vtst_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtstq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { let c: uint16x8_t = simd_and(a, b); let d: u16x8 = u16x8::new(0, 0, 0, 0, 0, 0, 0, 0); @@ -1086,6 +1208,7 @@ pub unsafe fn vtstq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtst_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { let c: uint32x2_t = simd_and(a, b); let d: u32x2 = u32x2::new(0, 0); @@ -1098,6 +1221,7 @@ pub unsafe fn vtst_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtst))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmtst))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtstq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { let c: uint32x4_t = simd_and(a, b); let d: u32x4 = u32x4::new(0, 0, 0, 0); @@ -1110,6 +1234,7 @@ pub unsafe fn vtstq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vabs))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fabs))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabs_f32(a: float32x2_t) -> float32x2_t { simd_fabs(a) } @@ -1120,6 +1245,7 @@ pub unsafe fn vabs_f32(a: float32x2_t) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vabs))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fabs))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabsq_f32(a: float32x4_t) -> float32x4_t { simd_fabs(a) } @@ -1130,6 +1256,7 @@ pub unsafe fn vabsq_f32(a: float32x4_t) -> float32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmgt))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcgt_s8(a: int8x8_t, b: int8x8_t) -> uint8x8_t { simd_gt(a, b) } @@ -1140,6 +1267,7 @@ pub unsafe fn vcgt_s8(a: int8x8_t, b: int8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmgt))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcgtq_s8(a: int8x16_t, b: int8x16_t) -> uint8x16_t { simd_gt(a, b) } @@ -1150,6 +1278,7 @@ pub unsafe fn vcgtq_s8(a: int8x16_t, b: int8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmgt))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcgt_s16(a: int16x4_t, b: int16x4_t) -> uint16x4_t { simd_gt(a, b) } @@ -1160,6 +1289,7 @@ pub unsafe fn vcgt_s16(a: int16x4_t, b: int16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmgt))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcgtq_s16(a: int16x8_t, b: int16x8_t) -> uint16x8_t { simd_gt(a, b) } @@ -1170,6 +1300,7 @@ pub unsafe fn vcgtq_s16(a: int16x8_t, b: int16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmgt))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcgt_s32(a: int32x2_t, b: int32x2_t) -> uint32x2_t { simd_gt(a, b) } @@ -1180,6 +1311,7 @@ pub unsafe fn vcgt_s32(a: int32x2_t, b: int32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmgt))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcgtq_s32(a: int32x4_t, b: int32x4_t) -> uint32x4_t { simd_gt(a, b) } @@ -1190,6 +1322,7 @@ pub unsafe fn vcgtq_s32(a: int32x4_t, b: int32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhi))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcgt_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { simd_gt(a, b) } @@ -1200,6 +1333,7 @@ pub unsafe fn vcgt_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhi))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcgtq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { simd_gt(a, b) } @@ -1210,6 +1344,7 @@ pub unsafe fn vcgtq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhi))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcgt_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { simd_gt(a, b) } @@ -1220,6 +1355,7 @@ pub unsafe fn vcgt_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhi))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcgtq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { simd_gt(a, b) } @@ -1230,6 +1366,7 @@ pub unsafe fn vcgtq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhi))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcgt_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { simd_gt(a, b) } @@ -1240,6 +1377,7 @@ pub unsafe fn vcgt_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhi))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcgtq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { simd_gt(a, b) } @@ -1250,6 +1388,7 @@ pub unsafe fn vcgtq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcmgt))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcgt_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t { simd_gt(a, b) } @@ -1260,6 +1399,7 @@ pub unsafe fn vcgt_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcmgt))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcgtq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { simd_gt(a, b) } @@ -1270,6 +1410,7 @@ pub unsafe fn vcgtq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmgt))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vclt_s8(a: int8x8_t, b: int8x8_t) -> uint8x8_t { simd_lt(a, b) } @@ -1280,6 +1421,7 @@ pub unsafe fn vclt_s8(a: int8x8_t, b: int8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmgt))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcltq_s8(a: int8x16_t, b: int8x16_t) -> uint8x16_t { simd_lt(a, b) } @@ -1290,6 +1432,7 @@ pub unsafe fn vcltq_s8(a: int8x16_t, b: int8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmgt))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vclt_s16(a: int16x4_t, b: int16x4_t) -> uint16x4_t { simd_lt(a, b) } @@ -1300,6 +1443,7 @@ pub unsafe fn vclt_s16(a: int16x4_t, b: int16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmgt))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcltq_s16(a: int16x8_t, b: int16x8_t) -> uint16x8_t { simd_lt(a, b) } @@ -1310,6 +1454,7 @@ pub unsafe fn vcltq_s16(a: int16x8_t, b: int16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmgt))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vclt_s32(a: int32x2_t, b: int32x2_t) -> uint32x2_t { simd_lt(a, b) } @@ -1320,6 +1465,7 @@ pub unsafe fn vclt_s32(a: int32x2_t, b: int32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmgt))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcltq_s32(a: int32x4_t, b: int32x4_t) -> uint32x4_t { simd_lt(a, b) } @@ -1330,6 +1476,7 @@ pub unsafe fn vcltq_s32(a: int32x4_t, b: int32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhi))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vclt_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { simd_lt(a, b) } @@ -1340,6 +1487,7 @@ pub unsafe fn vclt_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhi))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcltq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { simd_lt(a, b) } @@ -1350,6 +1498,7 @@ pub unsafe fn vcltq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhi))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vclt_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { simd_lt(a, b) } @@ -1360,6 +1509,7 @@ pub unsafe fn vclt_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhi))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcltq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { simd_lt(a, b) } @@ -1370,6 +1520,7 @@ pub unsafe fn vcltq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhi))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vclt_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { simd_lt(a, b) } @@ -1380,6 +1531,7 @@ pub unsafe fn vclt_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhi))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcltq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { simd_lt(a, b) } @@ -1390,6 +1542,7 @@ pub unsafe fn vcltq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcmgt))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vclt_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t { simd_lt(a, b) } @@ -1400,6 +1553,7 @@ pub unsafe fn vclt_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcgt.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcmgt))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcltq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { simd_lt(a, b) } @@ -1410,6 +1564,7 @@ pub unsafe fn vcltq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmge))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcle_s8(a: int8x8_t, b: int8x8_t) -> uint8x8_t { simd_le(a, b) } @@ -1420,6 +1575,7 @@ pub unsafe fn vcle_s8(a: int8x8_t, b: int8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmge))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcleq_s8(a: int8x16_t, b: int8x16_t) -> uint8x16_t { simd_le(a, b) } @@ -1430,6 +1586,7 @@ pub unsafe fn vcleq_s8(a: int8x16_t, b: int8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmge))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcle_s16(a: int16x4_t, b: int16x4_t) -> uint16x4_t { simd_le(a, b) } @@ -1440,6 +1597,7 @@ pub unsafe fn vcle_s16(a: int16x4_t, b: int16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmge))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcleq_s16(a: int16x8_t, b: int16x8_t) -> uint16x8_t { simd_le(a, b) } @@ -1450,6 +1608,7 @@ pub unsafe fn vcleq_s16(a: int16x8_t, b: int16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmge))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcle_s32(a: int32x2_t, b: int32x2_t) -> uint32x2_t { simd_le(a, b) } @@ -1460,6 +1619,7 @@ pub unsafe fn vcle_s32(a: int32x2_t, b: int32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmge))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcleq_s32(a: int32x4_t, b: int32x4_t) -> uint32x4_t { simd_le(a, b) } @@ -1470,6 +1630,7 @@ pub unsafe fn vcleq_s32(a: int32x4_t, b: int32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhs))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcle_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { simd_le(a, b) } @@ -1480,6 +1641,7 @@ pub unsafe fn vcle_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhs))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcleq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { simd_le(a, b) } @@ -1490,6 +1652,7 @@ pub unsafe fn vcleq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhs))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcle_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { simd_le(a, b) } @@ -1500,6 +1663,7 @@ pub unsafe fn vcle_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhs))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcleq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { simd_le(a, b) } @@ -1510,6 +1674,7 @@ pub unsafe fn vcleq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhs))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcle_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { simd_le(a, b) } @@ -1520,6 +1685,7 @@ pub unsafe fn vcle_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhs))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcleq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { simd_le(a, b) } @@ -1530,6 +1696,7 @@ pub unsafe fn vcleq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcmge))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcle_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t { simd_le(a, b) } @@ -1540,6 +1707,7 @@ pub unsafe fn vcle_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcmge))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcleq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { simd_le(a, b) } @@ -1550,6 +1718,7 @@ pub unsafe fn vcleq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmge))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcge_s8(a: int8x8_t, b: int8x8_t) -> uint8x8_t { simd_ge(a, b) } @@ -1560,6 +1729,7 @@ pub unsafe fn vcge_s8(a: int8x8_t, b: int8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmge))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcgeq_s8(a: int8x16_t, b: int8x16_t) -> uint8x16_t { simd_ge(a, b) } @@ -1570,6 +1740,7 @@ pub unsafe fn vcgeq_s8(a: int8x16_t, b: int8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmge))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcge_s16(a: int16x4_t, b: int16x4_t) -> uint16x4_t { simd_ge(a, b) } @@ -1580,6 +1751,7 @@ pub unsafe fn vcge_s16(a: int16x4_t, b: int16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmge))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcgeq_s16(a: int16x8_t, b: int16x8_t) -> uint16x8_t { simd_ge(a, b) } @@ -1590,6 +1762,7 @@ pub unsafe fn vcgeq_s16(a: int16x8_t, b: int16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmge))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcge_s32(a: int32x2_t, b: int32x2_t) -> uint32x2_t { simd_ge(a, b) } @@ -1600,6 +1773,7 @@ pub unsafe fn vcge_s32(a: int32x2_t, b: int32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmge))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcgeq_s32(a: int32x4_t, b: int32x4_t) -> uint32x4_t { simd_ge(a, b) } @@ -1610,6 +1784,7 @@ pub unsafe fn vcgeq_s32(a: int32x4_t, b: int32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhs))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcge_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { simd_ge(a, b) } @@ -1620,6 +1795,7 @@ pub unsafe fn vcge_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhs))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcgeq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { simd_ge(a, b) } @@ -1630,6 +1806,7 @@ pub unsafe fn vcgeq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhs))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcge_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { simd_ge(a, b) } @@ -1640,6 +1817,7 @@ pub unsafe fn vcge_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhs))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcgeq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { simd_ge(a, b) } @@ -1650,6 +1828,7 @@ pub unsafe fn vcgeq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhs))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcge_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { simd_ge(a, b) } @@ -1660,6 +1839,7 @@ pub unsafe fn vcge_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cmhs))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcgeq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { simd_ge(a, b) } @@ -1670,6 +1850,7 @@ pub unsafe fn vcgeq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcmge))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcge_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t { simd_ge(a, b) } @@ -1680,6 +1861,7 @@ pub unsafe fn vcge_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcge.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcmge))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcgeq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { simd_ge(a, b) } @@ -1690,6 +1872,7 @@ pub unsafe fn vcgeq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcls.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcls_s8(a: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -1706,6 +1889,7 @@ vcls_s8_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcls.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vclsq_s8(a: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -1722,6 +1906,7 @@ vclsq_s8_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcls.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcls_s16(a: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -1738,6 +1923,7 @@ vcls_s16_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcls.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vclsq_s16(a: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -1754,6 +1940,7 @@ vclsq_s16_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcls.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcls_s32(a: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -1770,6 +1957,7 @@ vcls_s32_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vcls.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vclsq_s32(a: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -1786,7 +1974,8 @@ vclsq_s32_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcls))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))] -pub unsafe fn vcls_u8(a: uint8x8_t) -> uint8x8_t { +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] +pub unsafe fn vcls_u8(a: uint8x8_t) -> int8x8_t { transmute(vcls_s8(transmute(a))) } @@ -1796,7 +1985,8 @@ pub unsafe fn vcls_u8(a: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcls))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))] -pub unsafe fn vclsq_u8(a: uint8x16_t) -> uint8x16_t { +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] +pub unsafe fn vclsq_u8(a: uint8x16_t) -> int8x16_t { transmute(vclsq_s8(transmute(a))) } @@ -1806,7 +1996,8 @@ pub unsafe fn vclsq_u8(a: uint8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcls))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))] -pub unsafe fn vcls_u16(a: uint16x4_t) -> uint16x4_t { +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] +pub unsafe fn vcls_u16(a: uint16x4_t) -> int16x4_t { transmute(vcls_s16(transmute(a))) } @@ -1816,7 +2007,8 @@ pub unsafe fn vcls_u16(a: uint16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcls))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))] -pub unsafe fn vclsq_u16(a: uint16x8_t) -> uint16x8_t { +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] +pub unsafe fn vclsq_u16(a: uint16x8_t) -> int16x8_t { transmute(vclsq_s16(transmute(a))) } @@ -1826,7 +2018,8 @@ pub unsafe fn vclsq_u16(a: uint16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcls))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))] -pub unsafe fn vcls_u32(a: uint32x2_t) -> uint32x2_t { +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] +pub unsafe fn vcls_u32(a: uint32x2_t) -> int32x2_t { transmute(vcls_s32(transmute(a))) } @@ -1836,7 +2029,8 @@ pub unsafe fn vcls_u32(a: uint32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcls))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cls))] -pub unsafe fn vclsq_u32(a: uint32x4_t) -> uint32x4_t { +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] +pub unsafe fn vclsq_u32(a: uint32x4_t) -> int32x4_t { transmute(vclsq_s32(transmute(a))) } @@ -1846,6 +2040,7 @@ pub unsafe fn vclsq_u32(a: uint32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vclz.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vclz_s8(a: int8x8_t) -> int8x8_t { vclz_s8_(a) } @@ -1856,6 +2051,7 @@ pub unsafe fn vclz_s8(a: int8x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vclz.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vclzq_s8(a: int8x16_t) -> int8x16_t { vclzq_s8_(a) } @@ -1866,6 +2062,7 @@ pub unsafe fn vclzq_s8(a: int8x16_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vclz.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vclz_s16(a: int16x4_t) -> int16x4_t { vclz_s16_(a) } @@ -1876,6 +2073,7 @@ pub unsafe fn vclz_s16(a: int16x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vclz.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vclzq_s16(a: int16x8_t) -> int16x8_t { vclzq_s16_(a) } @@ -1886,6 +2084,7 @@ pub unsafe fn vclzq_s16(a: int16x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vclz.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vclz_s32(a: int32x2_t) -> int32x2_t { vclz_s32_(a) } @@ -1896,6 +2095,7 @@ pub unsafe fn vclz_s32(a: int32x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vclz.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vclzq_s32(a: int32x4_t) -> int32x4_t { vclzq_s32_(a) } @@ -1906,6 +2106,7 @@ pub unsafe fn vclzq_s32(a: int32x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vclz.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vclz_u8(a: uint8x8_t) -> uint8x8_t { transmute(vclz_s8_(transmute(a))) } @@ -1916,6 +2117,7 @@ pub unsafe fn vclz_u8(a: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vclz.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vclzq_u8(a: uint8x16_t) -> uint8x16_t { transmute(vclzq_s8_(transmute(a))) } @@ -1926,6 +2128,7 @@ pub unsafe fn vclzq_u8(a: uint8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vclz.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vclz_u16(a: uint16x4_t) -> uint16x4_t { transmute(vclz_s16_(transmute(a))) } @@ -1936,6 +2139,7 @@ pub unsafe fn vclz_u16(a: uint16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vclz.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vclzq_u16(a: uint16x8_t) -> uint16x8_t { transmute(vclzq_s16_(transmute(a))) } @@ -1946,6 +2150,7 @@ pub unsafe fn vclzq_u16(a: uint16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vclz.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vclz_u32(a: uint32x2_t) -> uint32x2_t { transmute(vclz_s32_(transmute(a))) } @@ -1956,6 +2161,7 @@ pub unsafe fn vclz_u32(a: uint32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vclz.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vclzq_u32(a: uint32x4_t) -> uint32x4_t { transmute(vclzq_s32_(transmute(a))) } @@ -1966,6 +2172,7 @@ pub unsafe fn vclzq_u32(a: uint32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vacgt.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(facgt))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcagt_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -1982,6 +2189,7 @@ vcagt_f32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vacgt.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(facgt))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcagtq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -1998,6 +2206,7 @@ vcagtq_f32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vacge.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(facge))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcage_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -2014,6 +2223,7 @@ vcage_f32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vacge.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(facge))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcageq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -2030,6 +2240,7 @@ vcageq_f32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vacgt.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(facgt))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcalt_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t { vcagt_f32(b, a) } @@ -2040,6 +2251,7 @@ pub unsafe fn vcalt_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vacgt.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(facgt))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcaltq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { vcagtq_f32(b, a) } @@ -2050,6 +2262,7 @@ pub unsafe fn vcaltq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vacge.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(facge))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcale_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t { vcage_f32(b, a) } @@ -2060,6 +2273,7 @@ pub unsafe fn vcale_f32(a: float32x2_t, b: float32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vacge.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(facge))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcaleq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { vcageq_f32(b, a) } @@ -2070,6 +2284,7 @@ pub unsafe fn vcaleq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcreate_s8(a: u64) -> int8x8_t { transmute(a) } @@ -2080,6 +2295,7 @@ pub unsafe fn vcreate_s8(a: u64) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcreate_s16(a: u64) -> int16x4_t { transmute(a) } @@ -2090,6 +2306,7 @@ pub unsafe fn vcreate_s16(a: u64) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcreate_s32(a: u64) -> int32x2_t { transmute(a) } @@ -2100,6 +2317,7 @@ pub unsafe fn vcreate_s32(a: u64) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcreate_s64(a: u64) -> int64x1_t { transmute(a) } @@ -2110,6 +2328,7 @@ pub unsafe fn vcreate_s64(a: u64) -> int64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcreate_u8(a: u64) -> uint8x8_t { transmute(a) } @@ -2120,6 +2339,7 @@ pub unsafe fn vcreate_u8(a: u64) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcreate_u16(a: u64) -> uint16x4_t { transmute(a) } @@ -2130,6 +2350,7 @@ pub unsafe fn vcreate_u16(a: u64) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcreate_u32(a: u64) -> uint32x2_t { transmute(a) } @@ -2140,6 +2361,7 @@ pub unsafe fn vcreate_u32(a: u64) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcreate_u64(a: u64) -> uint64x1_t { transmute(a) } @@ -2150,6 +2372,7 @@ pub unsafe fn vcreate_u64(a: u64) -> uint64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcreate_p8(a: u64) -> poly8x8_t { transmute(a) } @@ -2160,6 +2383,7 @@ pub unsafe fn vcreate_p8(a: u64) -> poly8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcreate_p16(a: u64) -> poly16x4_t { transmute(a) } @@ -2170,6 +2394,7 @@ pub unsafe fn vcreate_p16(a: u64) -> poly16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcreate_p64(a: u64) -> poly64x1_t { transmute(a) } @@ -2180,6 +2405,7 @@ pub unsafe fn vcreate_p64(a: u64) -> poly64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcreate_f32(a: u64) -> float32x2_t { transmute(a) } @@ -2190,6 +2416,7 @@ pub unsafe fn vcreate_f32(a: u64) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcvt))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(scvtf))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcvt_f32_s32(a: int32x2_t) -> float32x2_t { simd_cast(a) } @@ -2200,6 +2427,7 @@ pub unsafe fn vcvt_f32_s32(a: int32x2_t) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcvt))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(scvtf))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcvtq_f32_s32(a: int32x4_t) -> float32x4_t { simd_cast(a) } @@ -2210,6 +2438,7 @@ pub unsafe fn vcvtq_f32_s32(a: int32x4_t) -> float32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcvt))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ucvtf))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcvt_f32_u32(a: uint32x2_t) -> float32x2_t { simd_cast(a) } @@ -2220,6 +2449,7 @@ pub unsafe fn vcvt_f32_u32(a: uint32x2_t) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcvt))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ucvtf))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcvtq_f32_u32(a: uint32x4_t) -> float32x4_t { simd_cast(a) } @@ -2228,7 +2458,7 @@ pub unsafe fn vcvtq_f32_u32(a: uint32x4_t) -> float32x4_t { #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcvt, N = 2))] +#[cfg_attr(test, assert_instr(vcvt, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vcvt_n_f32_s32(a: int32x2_t) -> float32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); @@ -2244,8 +2474,9 @@ vcvt_n_f32_s32_(a, N) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(scvtf, N = 2))] +#[cfg_attr(test, assert_instr(scvtf, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvt_n_f32_s32(a: int32x2_t) -> float32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] @@ -2260,7 +2491,7 @@ vcvt_n_f32_s32_(a, N) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcvt, N = 2))] +#[cfg_attr(test, assert_instr(vcvt, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vcvtq_n_f32_s32(a: int32x4_t) -> float32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); @@ -2276,8 +2507,9 @@ vcvtq_n_f32_s32_(a, N) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(scvtf, N = 2))] +#[cfg_attr(test, assert_instr(scvtf, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtq_n_f32_s32(a: int32x4_t) -> float32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] @@ -2292,7 +2524,7 @@ vcvtq_n_f32_s32_(a, N) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcvt, N = 2))] +#[cfg_attr(test, assert_instr(vcvt, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vcvt_n_f32_u32(a: uint32x2_t) -> float32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); @@ -2308,8 +2540,9 @@ vcvt_n_f32_u32_(a, N) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ucvtf, N = 2))] +#[cfg_attr(test, assert_instr(ucvtf, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvt_n_f32_u32(a: uint32x2_t) -> float32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] @@ -2324,7 +2557,7 @@ vcvt_n_f32_u32_(a, N) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcvt, N = 2))] +#[cfg_attr(test, assert_instr(vcvt, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vcvtq_n_f32_u32(a: uint32x4_t) -> float32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); @@ -2340,8 +2573,9 @@ vcvtq_n_f32_u32_(a, N) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ucvtf, N = 2))] +#[cfg_attr(test, assert_instr(ucvtf, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtq_n_f32_u32(a: uint32x4_t) -> float32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] @@ -2356,7 +2590,7 @@ vcvtq_n_f32_u32_(a, N) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcvt, N = 2))] +#[cfg_attr(test, assert_instr(vcvt, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vcvt_n_s32_f32(a: float32x2_t) -> int32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); @@ -2372,8 +2606,9 @@ vcvt_n_s32_f32_(a, N) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcvtzs, N = 2))] +#[cfg_attr(test, assert_instr(fcvtzs, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvt_n_s32_f32(a: float32x2_t) -> int32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] @@ -2388,7 +2623,7 @@ vcvt_n_s32_f32_(a, N) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcvt, N = 2))] +#[cfg_attr(test, assert_instr(vcvt, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vcvtq_n_s32_f32(a: float32x4_t) -> int32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); @@ -2404,8 +2639,9 @@ vcvtq_n_s32_f32_(a, N) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcvtzs, N = 2))] +#[cfg_attr(test, assert_instr(fcvtzs, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtq_n_s32_f32(a: float32x4_t) -> int32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] @@ -2420,7 +2656,7 @@ vcvtq_n_s32_f32_(a, N) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcvt, N = 2))] +#[cfg_attr(test, assert_instr(vcvt, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vcvt_n_u32_f32(a: float32x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); @@ -2436,8 +2672,9 @@ vcvt_n_u32_f32_(a, N) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcvtzu, N = 2))] +#[cfg_attr(test, assert_instr(fcvtzu, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvt_n_u32_f32(a: float32x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] @@ -2452,7 +2689,7 @@ vcvt_n_u32_f32_(a, N) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcvt, N = 2))] +#[cfg_attr(test, assert_instr(vcvt, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vcvtq_n_u32_f32(a: float32x4_t) -> uint32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); @@ -2468,8 +2705,9 @@ vcvtq_n_u32_f32_(a, N) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcvtzu, N = 2))] +#[cfg_attr(test, assert_instr(fcvtzu, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vcvtq_n_u32_f32(a: float32x4_t) -> uint32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] @@ -2486,6 +2724,7 @@ vcvtq_n_u32_f32_(a, N) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcvt))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcvtzs))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcvt_s32_f32(a: float32x2_t) -> int32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -2502,6 +2741,7 @@ vcvt_s32_f32_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcvt))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcvtzs))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcvtq_s32_f32(a: float32x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -2518,6 +2758,7 @@ vcvtq_s32_f32_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcvt))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcvtzu))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcvt_u32_f32(a: float32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -2534,6 +2775,7 @@ vcvt_u32_f32_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcvt))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fcvtzu))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vcvtq_u32_f32(a: float32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -2551,6 +2793,7 @@ vcvtq_u32_f32_(a) #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8", N = 4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 4))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdup_lane_s8(a: int8x8_t) -> int8x8_t { static_assert_imm3!(N); simd_shuffle8!(a, a, [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32]) @@ -2563,6 +2806,7 @@ pub unsafe fn vdup_lane_s8(a: int8x8_t) -> int8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8", N = 8))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 8))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdupq_laneq_s8(a: int8x16_t) -> int8x16_t { static_assert_imm4!(N); simd_shuffle16!(a, a, [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32]) @@ -2575,6 +2819,7 @@ pub unsafe fn vdupq_laneq_s8(a: int8x16_t) -> int8x16_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdup_lane_s16(a: int16x4_t) -> int16x4_t { static_assert_imm2!(N); simd_shuffle4!(a, a, [N as u32, N as u32, N as u32, N as u32]) @@ -2587,6 +2832,7 @@ pub unsafe fn vdup_lane_s16(a: int16x4_t) -> int16x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16", N = 4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 4))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdupq_laneq_s16(a: int16x8_t) -> int16x8_t { static_assert_imm3!(N); simd_shuffle8!(a, a, [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32]) @@ -2599,6 +2845,7 @@ pub unsafe fn vdupq_laneq_s16(a: int16x8_t) -> int16x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32", N = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 1))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdup_lane_s32(a: int32x2_t) -> int32x2_t { static_assert_imm1!(N); simd_shuffle2!(a, a, [N as u32, N as u32]) @@ -2611,6 +2858,7 @@ pub unsafe fn vdup_lane_s32(a: int32x2_t) -> int32x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdupq_laneq_s32(a: int32x4_t) -> int32x4_t { static_assert_imm2!(N); simd_shuffle4!(a, a, [N as u32, N as u32, N as u32, N as u32]) @@ -2623,6 +2871,7 @@ pub unsafe fn vdupq_laneq_s32(a: int32x4_t) -> int32x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8", N = 8))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 8))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdup_laneq_s8(a: int8x16_t) -> int8x8_t { static_assert_imm4!(N); simd_shuffle8!(a, a, [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32]) @@ -2635,6 +2884,7 @@ pub unsafe fn vdup_laneq_s8(a: int8x16_t) -> int8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16", N = 4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 4))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdup_laneq_s16(a: int16x8_t) -> int16x4_t { static_assert_imm3!(N); simd_shuffle4!(a, a, [N as u32, N as u32, N as u32, N as u32]) @@ -2647,6 +2897,7 @@ pub unsafe fn vdup_laneq_s16(a: int16x8_t) -> int16x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdup_laneq_s32(a: int32x4_t) -> int32x2_t { static_assert_imm2!(N); simd_shuffle2!(a, a, [N as u32, N as u32]) @@ -2659,6 +2910,7 @@ pub unsafe fn vdup_laneq_s32(a: int32x4_t) -> int32x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8", N = 4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 4))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdupq_lane_s8(a: int8x8_t) -> int8x16_t { static_assert_imm3!(N); simd_shuffle16!(a, a, [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32]) @@ -2671,6 +2923,7 @@ pub unsafe fn vdupq_lane_s8(a: int8x8_t) -> int8x16_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdupq_lane_s16(a: int16x4_t) -> int16x8_t { static_assert_imm2!(N); simd_shuffle8!(a, a, [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32]) @@ -2683,6 +2936,7 @@ pub unsafe fn vdupq_lane_s16(a: int16x4_t) -> int16x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32", N = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 1))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdupq_lane_s32(a: int32x2_t) -> int32x4_t { static_assert_imm1!(N); simd_shuffle4!(a, a, [N as u32, N as u32, N as u32, N as u32]) @@ -2695,6 +2949,7 @@ pub unsafe fn vdupq_lane_s32(a: int32x2_t) -> int32x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8", N = 4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 4))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdup_lane_u8(a: uint8x8_t) -> uint8x8_t { static_assert_imm3!(N); simd_shuffle8!(a, a, [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32]) @@ -2707,6 +2962,7 @@ pub unsafe fn vdup_lane_u8(a: uint8x8_t) -> uint8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8", N = 8))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 8))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdupq_laneq_u8(a: uint8x16_t) -> uint8x16_t { static_assert_imm4!(N); simd_shuffle16!(a, a, [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32]) @@ -2719,6 +2975,7 @@ pub unsafe fn vdupq_laneq_u8(a: uint8x16_t) -> uint8x16_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdup_lane_u16(a: uint16x4_t) -> uint16x4_t { static_assert_imm2!(N); simd_shuffle4!(a, a, [N as u32, N as u32, N as u32, N as u32]) @@ -2731,6 +2988,7 @@ pub unsafe fn vdup_lane_u16(a: uint16x4_t) -> uint16x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16", N = 4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 4))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdupq_laneq_u16(a: uint16x8_t) -> uint16x8_t { static_assert_imm3!(N); simd_shuffle8!(a, a, [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32]) @@ -2743,6 +3001,7 @@ pub unsafe fn vdupq_laneq_u16(a: uint16x8_t) -> uint16x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32", N = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 1))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdup_lane_u32(a: uint32x2_t) -> uint32x2_t { static_assert_imm1!(N); simd_shuffle2!(a, a, [N as u32, N as u32]) @@ -2755,6 +3014,7 @@ pub unsafe fn vdup_lane_u32(a: uint32x2_t) -> uint32x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdupq_laneq_u32(a: uint32x4_t) -> uint32x4_t { static_assert_imm2!(N); simd_shuffle4!(a, a, [N as u32, N as u32, N as u32, N as u32]) @@ -2767,6 +3027,7 @@ pub unsafe fn vdupq_laneq_u32(a: uint32x4_t) -> uint32x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8", N = 8))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 8))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdup_laneq_u8(a: uint8x16_t) -> uint8x8_t { static_assert_imm4!(N); simd_shuffle8!(a, a, [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32]) @@ -2779,6 +3040,7 @@ pub unsafe fn vdup_laneq_u8(a: uint8x16_t) -> uint8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16", N = 4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 4))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdup_laneq_u16(a: uint16x8_t) -> uint16x4_t { static_assert_imm3!(N); simd_shuffle4!(a, a, [N as u32, N as u32, N as u32, N as u32]) @@ -2791,6 +3053,7 @@ pub unsafe fn vdup_laneq_u16(a: uint16x8_t) -> uint16x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdup_laneq_u32(a: uint32x4_t) -> uint32x2_t { static_assert_imm2!(N); simd_shuffle2!(a, a, [N as u32, N as u32]) @@ -2803,6 +3066,7 @@ pub unsafe fn vdup_laneq_u32(a: uint32x4_t) -> uint32x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8", N = 4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 4))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdupq_lane_u8(a: uint8x8_t) -> uint8x16_t { static_assert_imm3!(N); simd_shuffle16!(a, a, [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32]) @@ -2815,6 +3079,7 @@ pub unsafe fn vdupq_lane_u8(a: uint8x8_t) -> uint8x16_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdupq_lane_u16(a: uint16x4_t) -> uint16x8_t { static_assert_imm2!(N); simd_shuffle8!(a, a, [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32]) @@ -2827,6 +3092,7 @@ pub unsafe fn vdupq_lane_u16(a: uint16x4_t) -> uint16x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32", N = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 1))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdupq_lane_u32(a: uint32x2_t) -> uint32x4_t { static_assert_imm1!(N); simd_shuffle4!(a, a, [N as u32, N as u32, N as u32, N as u32]) @@ -2839,6 +3105,7 @@ pub unsafe fn vdupq_lane_u32(a: uint32x2_t) -> uint32x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8", N = 4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 4))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdup_lane_p8(a: poly8x8_t) -> poly8x8_t { static_assert_imm3!(N); simd_shuffle8!(a, a, [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32]) @@ -2851,6 +3118,7 @@ pub unsafe fn vdup_lane_p8(a: poly8x8_t) -> poly8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8", N = 8))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 8))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdupq_laneq_p8(a: poly8x16_t) -> poly8x16_t { static_assert_imm4!(N); simd_shuffle16!(a, a, [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32]) @@ -2863,6 +3131,7 @@ pub unsafe fn vdupq_laneq_p8(a: poly8x16_t) -> poly8x16_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdup_lane_p16(a: poly16x4_t) -> poly16x4_t { static_assert_imm2!(N); simd_shuffle4!(a, a, [N as u32, N as u32, N as u32, N as u32]) @@ -2875,6 +3144,7 @@ pub unsafe fn vdup_lane_p16(a: poly16x4_t) -> poly16x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16", N = 4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 4))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdupq_laneq_p16(a: poly16x8_t) -> poly16x8_t { static_assert_imm3!(N); simd_shuffle8!(a, a, [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32]) @@ -2887,6 +3157,7 @@ pub unsafe fn vdupq_laneq_p16(a: poly16x8_t) -> poly16x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8", N = 8))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 8))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdup_laneq_p8(a: poly8x16_t) -> poly8x8_t { static_assert_imm4!(N); simd_shuffle8!(a, a, [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32]) @@ -2899,6 +3170,7 @@ pub unsafe fn vdup_laneq_p8(a: poly8x16_t) -> poly8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16", N = 4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 4))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdup_laneq_p16(a: poly16x8_t) -> poly16x4_t { static_assert_imm3!(N); simd_shuffle4!(a, a, [N as u32, N as u32, N as u32, N as u32]) @@ -2911,6 +3183,7 @@ pub unsafe fn vdup_laneq_p16(a: poly16x8_t) -> poly16x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8", N = 4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 4))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdupq_lane_p8(a: poly8x8_t) -> poly8x16_t { static_assert_imm3!(N); simd_shuffle16!(a, a, [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32]) @@ -2923,6 +3196,7 @@ pub unsafe fn vdupq_lane_p8(a: poly8x8_t) -> poly8x16_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdupq_lane_p16(a: poly16x4_t) -> poly16x8_t { static_assert_imm2!(N); simd_shuffle8!(a, a, [N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32, N as u32]) @@ -2935,6 +3209,7 @@ pub unsafe fn vdupq_lane_p16(a: poly16x4_t) -> poly16x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmov, N = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 1))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdupq_laneq_s64(a: int64x2_t) -> int64x2_t { static_assert_imm1!(N); simd_shuffle2!(a, a, [N as u32, N as u32]) @@ -2947,6 +3222,7 @@ pub unsafe fn vdupq_laneq_s64(a: int64x2_t) -> int64x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmov, N = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 0))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdupq_lane_s64(a: int64x1_t) -> int64x2_t { static_assert!(N : i32 where N == 0); simd_shuffle2!(a, a, [N as u32, N as u32]) @@ -2959,6 +3235,7 @@ pub unsafe fn vdupq_lane_s64(a: int64x1_t) -> int64x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmov, N = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 1))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdupq_laneq_u64(a: uint64x2_t) -> uint64x2_t { static_assert_imm1!(N); simd_shuffle2!(a, a, [N as u32, N as u32]) @@ -2971,6 +3248,7 @@ pub unsafe fn vdupq_laneq_u64(a: uint64x2_t) -> uint64x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmov, N = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 0))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdupq_lane_u64(a: uint64x1_t) -> uint64x2_t { static_assert!(N : i32 where N == 0); simd_shuffle2!(a, a, [N as u32, N as u32]) @@ -2983,6 +3261,7 @@ pub unsafe fn vdupq_lane_u64(a: uint64x1_t) -> uint64x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32", N = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 1))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdup_lane_f32(a: float32x2_t) -> float32x2_t { static_assert_imm1!(N); simd_shuffle2!(a, a, [N as u32, N as u32]) @@ -2995,6 +3274,7 @@ pub unsafe fn vdup_lane_f32(a: float32x2_t) -> float32x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdupq_laneq_f32(a: float32x4_t) -> float32x4_t { static_assert_imm2!(N); simd_shuffle4!(a, a, [N as u32, N as u32, N as u32, N as u32]) @@ -3007,6 +3287,7 @@ pub unsafe fn vdupq_laneq_f32(a: float32x4_t) -> float32x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdup_laneq_f32(a: float32x4_t) -> float32x2_t { static_assert_imm2!(N); simd_shuffle2!(a, a, [N as u32, N as u32]) @@ -3019,6 +3300,7 @@ pub unsafe fn vdup_laneq_f32(a: float32x4_t) -> float32x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32", N = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup, N = 1))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdupq_lane_f32(a: float32x2_t) -> float32x4_t { static_assert_imm1!(N); simd_shuffle4!(a, a, [N as u32, N as u32, N as u32, N as u32]) @@ -3031,6 +3313,7 @@ pub unsafe fn vdupq_lane_f32(a: float32x2_t) -> float32x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, N = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, N = 0))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdup_lane_s64(a: int64x1_t) -> int64x1_t { static_assert!(N : i32 where N == 0); a @@ -3043,6 +3326,7 @@ pub unsafe fn vdup_lane_s64(a: int64x1_t) -> int64x1_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, N = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, N = 0))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdup_lane_u64(a: uint64x1_t) -> uint64x1_t { static_assert!(N : i32 where N == 0); a @@ -3055,6 +3339,7 @@ pub unsafe fn vdup_lane_u64(a: uint64x1_t) -> uint64x1_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmov, N = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, N = 1))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdup_laneq_s64(a: int64x2_t) -> int64x1_t { static_assert_imm1!(N); transmute::(simd_extract(a, N as u32)) @@ -3067,6 +3352,7 @@ pub unsafe fn vdup_laneq_s64(a: int64x2_t) -> int64x1_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmov, N = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, N = 1))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vdup_laneq_u64(a: uint64x2_t) -> uint64x1_t { static_assert_imm1!(N); transmute::(simd_extract(a, N as u32)) @@ -3079,6 +3365,7 @@ pub unsafe fn vdup_laneq_u64(a: uint64x2_t) -> uint64x1_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 4))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vext_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { static_assert_imm3!(N); match N & 0b111 { @@ -3101,6 +3388,7 @@ pub unsafe fn vext_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 8))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 8))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vextq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { static_assert_imm4!(N); match N & 0b1111 { @@ -3131,6 +3419,7 @@ pub unsafe fn vextq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vext_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { static_assert_imm2!(N); match N & 0b11 { @@ -3149,6 +3438,7 @@ pub unsafe fn vext_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 4))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vextq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { static_assert_imm3!(N); match N & 0b111 { @@ -3171,6 +3461,7 @@ pub unsafe fn vextq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vext_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { static_assert_imm1!(N); match N & 0b1 { @@ -3187,6 +3478,7 @@ pub unsafe fn vext_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vextq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { static_assert_imm2!(N); match N & 0b11 { @@ -3205,6 +3497,7 @@ pub unsafe fn vextq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 4))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vext_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { static_assert_imm3!(N); match N & 0b111 { @@ -3227,6 +3520,7 @@ pub unsafe fn vext_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 8))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 8))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vextq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { static_assert_imm4!(N); match N & 0b1111 { @@ -3257,6 +3551,7 @@ pub unsafe fn vextq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vext_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { static_assert_imm2!(N); match N & 0b11 { @@ -3275,6 +3570,7 @@ pub unsafe fn vext_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 4))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vextq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { static_assert_imm3!(N); match N & 0b111 { @@ -3297,6 +3593,7 @@ pub unsafe fn vextq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_ #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vext_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { static_assert_imm1!(N); match N & 0b1 { @@ -3313,6 +3610,7 @@ pub unsafe fn vext_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vextq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { static_assert_imm2!(N); match N & 0b11 { @@ -3331,6 +3629,7 @@ pub unsafe fn vextq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_ #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 4))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vext_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { static_assert_imm3!(N); match N & 0b111 { @@ -3353,6 +3652,7 @@ pub unsafe fn vext_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 8))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 8))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vextq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { static_assert_imm4!(N); match N & 0b1111 { @@ -3383,6 +3683,7 @@ pub unsafe fn vextq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vext_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { static_assert_imm2!(N); match N & 0b11 { @@ -3401,6 +3702,7 @@ pub unsafe fn vext_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 4))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vextq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { static_assert_imm3!(N); match N & 0b111 { @@ -3423,6 +3725,7 @@ pub unsafe fn vextq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_ #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmov, N = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vextq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { static_assert_imm1!(N); match N & 0b1 { @@ -3439,6 +3742,7 @@ pub unsafe fn vextq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmov, N = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vextq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { static_assert_imm1!(N); match N & 0b1 { @@ -3455,6 +3759,7 @@ pub unsafe fn vextq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_ #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vext_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { static_assert_imm1!(N); match N & 0b1 { @@ -3471,6 +3776,7 @@ pub unsafe fn vext_f32(a: float32x2_t, b: float32x2_t) -> float32x #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vext.8", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vextq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { static_assert_imm2!(N); match N & 0b11 { @@ -3488,6 +3794,7 @@ pub unsafe fn vextq_f32(a: float32x4_t, b: float32x4_t) -> float32 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmla_s8(a: int8x8_t, b: int8x8_t, c: int8x8_t) -> int8x8_t { simd_add(a, simd_mul(b, c)) } @@ -3498,6 +3805,7 @@ pub unsafe fn vmla_s8(a: int8x8_t, b: int8x8_t, c: int8x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlaq_s8(a: int8x16_t, b: int8x16_t, c: int8x16_t) -> int8x16_t { simd_add(a, simd_mul(b, c)) } @@ -3508,6 +3816,7 @@ pub unsafe fn vmlaq_s8(a: int8x16_t, b: int8x16_t, c: int8x16_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmla_s16(a: int16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t { simd_add(a, simd_mul(b, c)) } @@ -3518,6 +3827,7 @@ pub unsafe fn vmla_s16(a: int16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlaq_s16(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t { simd_add(a, simd_mul(b, c)) } @@ -3528,6 +3838,7 @@ pub unsafe fn vmlaq_s16(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmla_s32(a: int32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t { simd_add(a, simd_mul(b, c)) } @@ -3538,6 +3849,7 @@ pub unsafe fn vmla_s32(a: int32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlaq_s32(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t { simd_add(a, simd_mul(b, c)) } @@ -3548,6 +3860,7 @@ pub unsafe fn vmlaq_s32(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmla_u8(a: uint8x8_t, b: uint8x8_t, c: uint8x8_t) -> uint8x8_t { simd_add(a, simd_mul(b, c)) } @@ -3558,6 +3871,7 @@ pub unsafe fn vmla_u8(a: uint8x8_t, b: uint8x8_t, c: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlaq_u8(a: uint8x16_t, b: uint8x16_t, c: uint8x16_t) -> uint8x16_t { simd_add(a, simd_mul(b, c)) } @@ -3568,6 +3882,7 @@ pub unsafe fn vmlaq_u8(a: uint8x16_t, b: uint8x16_t, c: uint8x16_t) -> uint8x16_ #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmla_u16(a: uint16x4_t, b: uint16x4_t, c: uint16x4_t) -> uint16x4_t { simd_add(a, simd_mul(b, c)) } @@ -3578,6 +3893,7 @@ pub unsafe fn vmla_u16(a: uint16x4_t, b: uint16x4_t, c: uint16x4_t) -> uint16x4_ #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlaq_u16(a: uint16x8_t, b: uint16x8_t, c: uint16x8_t) -> uint16x8_t { simd_add(a, simd_mul(b, c)) } @@ -3588,6 +3904,7 @@ pub unsafe fn vmlaq_u16(a: uint16x8_t, b: uint16x8_t, c: uint16x8_t) -> uint16x8 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmla_u32(a: uint32x2_t, b: uint32x2_t, c: uint32x2_t) -> uint32x2_t { simd_add(a, simd_mul(b, c)) } @@ -3598,6 +3915,7 @@ pub unsafe fn vmla_u32(a: uint32x2_t, b: uint32x2_t, c: uint32x2_t) -> uint32x2_ #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlaq_u32(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4_t { simd_add(a, simd_mul(b, c)) } @@ -3608,6 +3926,7 @@ pub unsafe fn vmlaq_u32(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmla_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t { simd_add(a, simd_mul(b, c)) } @@ -3618,6 +3937,7 @@ pub unsafe fn vmla_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float3 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlaq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t { simd_add(a, simd_mul(b, c)) } @@ -3628,6 +3948,7 @@ pub unsafe fn vmlaq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmla_n_s16(a: int16x4_t, b: int16x4_t, c: i16) -> int16x4_t { vmla_s16(a, b, vdup_n_s16(c)) } @@ -3638,6 +3959,7 @@ pub unsafe fn vmla_n_s16(a: int16x4_t, b: int16x4_t, c: i16) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlaq_n_s16(a: int16x8_t, b: int16x8_t, c: i16) -> int16x8_t { vmlaq_s16(a, b, vdupq_n_s16(c)) } @@ -3648,6 +3970,7 @@ pub unsafe fn vmlaq_n_s16(a: int16x8_t, b: int16x8_t, c: i16) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmla_n_s32(a: int32x2_t, b: int32x2_t, c: i32) -> int32x2_t { vmla_s32(a, b, vdup_n_s32(c)) } @@ -3658,6 +3981,7 @@ pub unsafe fn vmla_n_s32(a: int32x2_t, b: int32x2_t, c: i32) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlaq_n_s32(a: int32x4_t, b: int32x4_t, c: i32) -> int32x4_t { vmlaq_s32(a, b, vdupq_n_s32(c)) } @@ -3668,6 +3992,7 @@ pub unsafe fn vmlaq_n_s32(a: int32x4_t, b: int32x4_t, c: i32) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmla_n_u16(a: uint16x4_t, b: uint16x4_t, c: u16) -> uint16x4_t { vmla_u16(a, b, vdup_n_u16(c)) } @@ -3678,6 +4003,7 @@ pub unsafe fn vmla_n_u16(a: uint16x4_t, b: uint16x4_t, c: u16) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlaq_n_u16(a: uint16x8_t, b: uint16x8_t, c: u16) -> uint16x8_t { vmlaq_u16(a, b, vdupq_n_u16(c)) } @@ -3688,6 +4014,7 @@ pub unsafe fn vmlaq_n_u16(a: uint16x8_t, b: uint16x8_t, c: u16) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmla_n_u32(a: uint32x2_t, b: uint32x2_t, c: u32) -> uint32x2_t { vmla_u32(a, b, vdup_n_u32(c)) } @@ -3698,6 +4025,7 @@ pub unsafe fn vmla_n_u32(a: uint32x2_t, b: uint32x2_t, c: u32) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlaq_n_u32(a: uint32x4_t, b: uint32x4_t, c: u32) -> uint32x4_t { vmlaq_u32(a, b, vdupq_n_u32(c)) } @@ -3708,6 +4036,7 @@ pub unsafe fn vmlaq_n_u32(a: uint32x4_t, b: uint32x4_t, c: u32) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmla_n_f32(a: float32x2_t, b: float32x2_t, c: f32) -> float32x2_t { vmla_f32(a, b, vdup_n_f32(c)) } @@ -3718,6 +4047,7 @@ pub unsafe fn vmla_n_f32(a: float32x2_t, b: float32x2_t, c: f32) -> float32x2_t #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlaq_n_f32(a: float32x4_t, b: float32x4_t, c: f32) -> float32x4_t { vmlaq_f32(a, b, vdupq_n_f32(c)) } @@ -3729,6 +4059,7 @@ pub unsafe fn vmlaq_n_f32(a: float32x4_t, b: float32x4_t, c: f32) -> float32x4_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmla_lane_s16(a: int16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t { static_assert_imm2!(LANE); vmla_s16(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -3741,6 +4072,7 @@ pub unsafe fn vmla_lane_s16(a: int16x4_t, b: int16x4_t, c: int1 #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmla_laneq_s16(a: int16x4_t, b: int16x4_t, c: int16x8_t) -> int16x4_t { static_assert_imm3!(LANE); vmla_s16(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -3753,6 +4085,7 @@ pub unsafe fn vmla_laneq_s16(a: int16x4_t, b: int16x4_t, c: int #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlaq_lane_s16(a: int16x8_t, b: int16x8_t, c: int16x4_t) -> int16x8_t { static_assert_imm2!(LANE); vmlaq_s16(a, b, simd_shuffle8!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -3765,6 +4098,7 @@ pub unsafe fn vmlaq_lane_s16(a: int16x8_t, b: int16x8_t, c: int #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlaq_laneq_s16(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t { static_assert_imm3!(LANE); vmlaq_s16(a, b, simd_shuffle8!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -3777,6 +4111,7 @@ pub unsafe fn vmlaq_laneq_s16(a: int16x8_t, b: int16x8_t, c: in #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmla_lane_s32(a: int32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t { static_assert_imm1!(LANE); vmla_s32(a, b, simd_shuffle2!(c, c, [LANE as u32, LANE as u32])) @@ -3789,6 +4124,7 @@ pub unsafe fn vmla_lane_s32(a: int32x2_t, b: int32x2_t, c: int3 #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmla_laneq_s32(a: int32x2_t, b: int32x2_t, c: int32x4_t) -> int32x2_t { static_assert_imm2!(LANE); vmla_s32(a, b, simd_shuffle2!(c, c, [LANE as u32, LANE as u32])) @@ -3801,6 +4137,7 @@ pub unsafe fn vmla_laneq_s32(a: int32x2_t, b: int32x2_t, c: int #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlaq_lane_s32(a: int32x4_t, b: int32x4_t, c: int32x2_t) -> int32x4_t { static_assert_imm1!(LANE); vmlaq_s32(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -3813,6 +4150,7 @@ pub unsafe fn vmlaq_lane_s32(a: int32x4_t, b: int32x4_t, c: int #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlaq_laneq_s32(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t { static_assert_imm2!(LANE); vmlaq_s32(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -3825,6 +4163,7 @@ pub unsafe fn vmlaq_laneq_s32(a: int32x4_t, b: int32x4_t, c: in #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmla_lane_u16(a: uint16x4_t, b: uint16x4_t, c: uint16x4_t) -> uint16x4_t { static_assert_imm2!(LANE); vmla_u16(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -3837,6 +4176,7 @@ pub unsafe fn vmla_lane_u16(a: uint16x4_t, b: uint16x4_t, c: ui #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmla_laneq_u16(a: uint16x4_t, b: uint16x4_t, c: uint16x8_t) -> uint16x4_t { static_assert_imm3!(LANE); vmla_u16(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -3849,6 +4189,7 @@ pub unsafe fn vmla_laneq_u16(a: uint16x4_t, b: uint16x4_t, c: u #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlaq_lane_u16(a: uint16x8_t, b: uint16x8_t, c: uint16x4_t) -> uint16x8_t { static_assert_imm2!(LANE); vmlaq_u16(a, b, simd_shuffle8!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -3861,6 +4202,7 @@ pub unsafe fn vmlaq_lane_u16(a: uint16x8_t, b: uint16x8_t, c: u #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i16", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlaq_laneq_u16(a: uint16x8_t, b: uint16x8_t, c: uint16x8_t) -> uint16x8_t { static_assert_imm3!(LANE); vmlaq_u16(a, b, simd_shuffle8!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -3873,6 +4215,7 @@ pub unsafe fn vmlaq_laneq_u16(a: uint16x8_t, b: uint16x8_t, c: #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmla_lane_u32(a: uint32x2_t, b: uint32x2_t, c: uint32x2_t) -> uint32x2_t { static_assert_imm1!(LANE); vmla_u32(a, b, simd_shuffle2!(c, c, [LANE as u32, LANE as u32])) @@ -3885,6 +4228,7 @@ pub unsafe fn vmla_lane_u32(a: uint32x2_t, b: uint32x2_t, c: ui #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmla_laneq_u32(a: uint32x2_t, b: uint32x2_t, c: uint32x4_t) -> uint32x2_t { static_assert_imm2!(LANE); vmla_u32(a, b, simd_shuffle2!(c, c, [LANE as u32, LANE as u32])) @@ -3897,6 +4241,7 @@ pub unsafe fn vmla_laneq_u32(a: uint32x2_t, b: uint32x2_t, c: u #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlaq_lane_u32(a: uint32x4_t, b: uint32x4_t, c: uint32x2_t) -> uint32x4_t { static_assert_imm1!(LANE); vmlaq_u32(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -3909,6 +4254,7 @@ pub unsafe fn vmlaq_lane_u32(a: uint32x4_t, b: uint32x4_t, c: u #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.i32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mla, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlaq_laneq_u32(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4_t { static_assert_imm2!(LANE); vmlaq_u32(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -3921,6 +4267,7 @@ pub unsafe fn vmlaq_laneq_u32(a: uint32x4_t, b: uint32x4_t, c: #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.f32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmla_lane_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t { static_assert_imm1!(LANE); vmla_f32(a, b, simd_shuffle2!(c, c, [LANE as u32, LANE as u32])) @@ -3933,6 +4280,7 @@ pub unsafe fn vmla_lane_f32(a: float32x2_t, b: float32x2_t, c: #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.f32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmla_laneq_f32(a: float32x2_t, b: float32x2_t, c: float32x4_t) -> float32x2_t { static_assert_imm2!(LANE); vmla_f32(a, b, simd_shuffle2!(c, c, [LANE as u32, LANE as u32])) @@ -3945,6 +4293,7 @@ pub unsafe fn vmla_laneq_f32(a: float32x2_t, b: float32x2_t, c: #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.f32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlaq_lane_f32(a: float32x4_t, b: float32x4_t, c: float32x2_t) -> float32x4_t { static_assert_imm1!(LANE); vmlaq_f32(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -3957,6 +4306,7 @@ pub unsafe fn vmlaq_lane_f32(a: float32x4_t, b: float32x4_t, c: #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmla.f32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlaq_laneq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t { static_assert_imm2!(LANE); vmlaq_f32(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -3968,6 +4318,7 @@ pub unsafe fn vmlaq_laneq_f32(a: float32x4_t, b: float32x4_t, c #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlal))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlal_s8(a: int16x8_t, b: int8x8_t, c: int8x8_t) -> int16x8_t { simd_add(a, vmull_s8(b, c)) } @@ -3978,6 +4329,7 @@ pub unsafe fn vmlal_s8(a: int16x8_t, b: int8x8_t, c: int8x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlal))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlal_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t { simd_add(a, vmull_s16(b, c)) } @@ -3988,6 +4340,7 @@ pub unsafe fn vmlal_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlal))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlal_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t { simd_add(a, vmull_s32(b, c)) } @@ -3998,6 +4351,7 @@ pub unsafe fn vmlal_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlal))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlal_u8(a: uint16x8_t, b: uint8x8_t, c: uint8x8_t) -> uint16x8_t { simd_add(a, vmull_u8(b, c)) } @@ -4008,6 +4362,7 @@ pub unsafe fn vmlal_u8(a: uint16x8_t, b: uint8x8_t, c: uint8x8_t) -> uint16x8_t #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlal))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlal_u16(a: uint32x4_t, b: uint16x4_t, c: uint16x4_t) -> uint32x4_t { simd_add(a, vmull_u16(b, c)) } @@ -4018,6 +4373,7 @@ pub unsafe fn vmlal_u16(a: uint32x4_t, b: uint16x4_t, c: uint16x4_t) -> uint32x4 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlal))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlal_u32(a: uint64x2_t, b: uint32x2_t, c: uint32x2_t) -> uint64x2_t { simd_add(a, vmull_u32(b, c)) } @@ -4028,6 +4384,7 @@ pub unsafe fn vmlal_u32(a: uint64x2_t, b: uint32x2_t, c: uint32x2_t) -> uint64x2 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlal))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlal_n_s16(a: int32x4_t, b: int16x4_t, c: i16) -> int32x4_t { vmlal_s16(a, b, vdup_n_s16(c)) } @@ -4038,6 +4395,7 @@ pub unsafe fn vmlal_n_s16(a: int32x4_t, b: int16x4_t, c: i16) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlal))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlal_n_s32(a: int64x2_t, b: int32x2_t, c: i32) -> int64x2_t { vmlal_s32(a, b, vdup_n_s32(c)) } @@ -4048,6 +4406,7 @@ pub unsafe fn vmlal_n_s32(a: int64x2_t, b: int32x2_t, c: i32) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlal))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlal_n_u16(a: uint32x4_t, b: uint16x4_t, c: u16) -> uint32x4_t { vmlal_u16(a, b, vdup_n_u16(c)) } @@ -4058,6 +4417,7 @@ pub unsafe fn vmlal_n_u16(a: uint32x4_t, b: uint16x4_t, c: u16) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlal))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlal_n_u32(a: uint64x2_t, b: uint32x2_t, c: u32) -> uint64x2_t { vmlal_u32(a, b, vdup_n_u32(c)) } @@ -4069,6 +4429,7 @@ pub unsafe fn vmlal_n_u32(a: uint64x2_t, b: uint32x2_t, c: u32) -> uint64x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.s16", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlal, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlal_lane_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t { static_assert_imm2!(LANE); vmlal_s16(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4081,6 +4442,7 @@ pub unsafe fn vmlal_lane_s16(a: int32x4_t, b: int16x4_t, c: int #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.s16", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlal, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlal_laneq_s16(a: int32x4_t, b: int16x4_t, c: int16x8_t) -> int32x4_t { static_assert_imm3!(LANE); vmlal_s16(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4093,6 +4455,7 @@ pub unsafe fn vmlal_laneq_s16(a: int32x4_t, b: int16x4_t, c: in #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.s32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlal, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlal_lane_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t { static_assert_imm1!(LANE); vmlal_s32(a, b, simd_shuffle2!(c, c, [LANE as u32, LANE as u32])) @@ -4105,6 +4468,7 @@ pub unsafe fn vmlal_lane_s32(a: int64x2_t, b: int32x2_t, c: int #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.s32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlal, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlal_laneq_s32(a: int64x2_t, b: int32x2_t, c: int32x4_t) -> int64x2_t { static_assert_imm2!(LANE); vmlal_s32(a, b, simd_shuffle2!(c, c, [LANE as u32, LANE as u32])) @@ -4117,6 +4481,7 @@ pub unsafe fn vmlal_laneq_s32(a: int64x2_t, b: int32x2_t, c: in #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.u16", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlal, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlal_lane_u16(a: uint32x4_t, b: uint16x4_t, c: uint16x4_t) -> uint32x4_t { static_assert_imm2!(LANE); vmlal_u16(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4129,6 +4494,7 @@ pub unsafe fn vmlal_lane_u16(a: uint32x4_t, b: uint16x4_t, c: u #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.u16", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlal, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlal_laneq_u16(a: uint32x4_t, b: uint16x4_t, c: uint16x8_t) -> uint32x4_t { static_assert_imm3!(LANE); vmlal_u16(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4141,6 +4507,7 @@ pub unsafe fn vmlal_laneq_u16(a: uint32x4_t, b: uint16x4_t, c: #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.u32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlal, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlal_lane_u32(a: uint64x2_t, b: uint32x2_t, c: uint32x2_t) -> uint64x2_t { static_assert_imm1!(LANE); vmlal_u32(a, b, simd_shuffle2!(c, c, [LANE as u32, LANE as u32])) @@ -4153,6 +4520,7 @@ pub unsafe fn vmlal_lane_u32(a: uint64x2_t, b: uint32x2_t, c: u #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlal.u32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlal, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlal_laneq_u32(a: uint64x2_t, b: uint32x2_t, c: uint32x4_t) -> uint64x2_t { static_assert_imm2!(LANE); vmlal_u32(a, b, simd_shuffle2!(c, c, [LANE as u32, LANE as u32])) @@ -4164,6 +4532,7 @@ pub unsafe fn vmlal_laneq_u32(a: uint64x2_t, b: uint32x2_t, c: #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmls_s8(a: int8x8_t, b: int8x8_t, c: int8x8_t) -> int8x8_t { simd_sub(a, simd_mul(b, c)) } @@ -4174,6 +4543,7 @@ pub unsafe fn vmls_s8(a: int8x8_t, b: int8x8_t, c: int8x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsq_s8(a: int8x16_t, b: int8x16_t, c: int8x16_t) -> int8x16_t { simd_sub(a, simd_mul(b, c)) } @@ -4184,6 +4554,7 @@ pub unsafe fn vmlsq_s8(a: int8x16_t, b: int8x16_t, c: int8x16_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmls_s16(a: int16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t { simd_sub(a, simd_mul(b, c)) } @@ -4194,6 +4565,7 @@ pub unsafe fn vmls_s16(a: int16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsq_s16(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t { simd_sub(a, simd_mul(b, c)) } @@ -4204,6 +4576,7 @@ pub unsafe fn vmlsq_s16(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmls_s32(a: int32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t { simd_sub(a, simd_mul(b, c)) } @@ -4214,6 +4587,7 @@ pub unsafe fn vmls_s32(a: int32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsq_s32(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t { simd_sub(a, simd_mul(b, c)) } @@ -4224,6 +4598,7 @@ pub unsafe fn vmlsq_s32(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmls_u8(a: uint8x8_t, b: uint8x8_t, c: uint8x8_t) -> uint8x8_t { simd_sub(a, simd_mul(b, c)) } @@ -4234,6 +4609,7 @@ pub unsafe fn vmls_u8(a: uint8x8_t, b: uint8x8_t, c: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsq_u8(a: uint8x16_t, b: uint8x16_t, c: uint8x16_t) -> uint8x16_t { simd_sub(a, simd_mul(b, c)) } @@ -4244,6 +4620,7 @@ pub unsafe fn vmlsq_u8(a: uint8x16_t, b: uint8x16_t, c: uint8x16_t) -> uint8x16_ #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmls_u16(a: uint16x4_t, b: uint16x4_t, c: uint16x4_t) -> uint16x4_t { simd_sub(a, simd_mul(b, c)) } @@ -4254,6 +4631,7 @@ pub unsafe fn vmls_u16(a: uint16x4_t, b: uint16x4_t, c: uint16x4_t) -> uint16x4_ #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsq_u16(a: uint16x8_t, b: uint16x8_t, c: uint16x8_t) -> uint16x8_t { simd_sub(a, simd_mul(b, c)) } @@ -4264,6 +4642,7 @@ pub unsafe fn vmlsq_u16(a: uint16x8_t, b: uint16x8_t, c: uint16x8_t) -> uint16x8 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmls_u32(a: uint32x2_t, b: uint32x2_t, c: uint32x2_t) -> uint32x2_t { simd_sub(a, simd_mul(b, c)) } @@ -4274,6 +4653,7 @@ pub unsafe fn vmls_u32(a: uint32x2_t, b: uint32x2_t, c: uint32x2_t) -> uint32x2_ #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsq_u32(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4_t { simd_sub(a, simd_mul(b, c)) } @@ -4284,6 +4664,7 @@ pub unsafe fn vmlsq_u32(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmls_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t { simd_sub(a, simd_mul(b, c)) } @@ -4294,6 +4675,7 @@ pub unsafe fn vmls_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float3 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t { simd_sub(a, simd_mul(b, c)) } @@ -4304,6 +4686,7 @@ pub unsafe fn vmlsq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmls_n_s16(a: int16x4_t, b: int16x4_t, c: i16) -> int16x4_t { vmls_s16(a, b, vdup_n_s16(c)) } @@ -4314,6 +4697,7 @@ pub unsafe fn vmls_n_s16(a: int16x4_t, b: int16x4_t, c: i16) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsq_n_s16(a: int16x8_t, b: int16x8_t, c: i16) -> int16x8_t { vmlsq_s16(a, b, vdupq_n_s16(c)) } @@ -4324,6 +4708,7 @@ pub unsafe fn vmlsq_n_s16(a: int16x8_t, b: int16x8_t, c: i16) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmls_n_s32(a: int32x2_t, b: int32x2_t, c: i32) -> int32x2_t { vmls_s32(a, b, vdup_n_s32(c)) } @@ -4334,6 +4719,7 @@ pub unsafe fn vmls_n_s32(a: int32x2_t, b: int32x2_t, c: i32) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsq_n_s32(a: int32x4_t, b: int32x4_t, c: i32) -> int32x4_t { vmlsq_s32(a, b, vdupq_n_s32(c)) } @@ -4344,6 +4730,7 @@ pub unsafe fn vmlsq_n_s32(a: int32x4_t, b: int32x4_t, c: i32) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmls_n_u16(a: uint16x4_t, b: uint16x4_t, c: u16) -> uint16x4_t { vmls_u16(a, b, vdup_n_u16(c)) } @@ -4354,6 +4741,7 @@ pub unsafe fn vmls_n_u16(a: uint16x4_t, b: uint16x4_t, c: u16) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsq_n_u16(a: uint16x8_t, b: uint16x8_t, c: u16) -> uint16x8_t { vmlsq_u16(a, b, vdupq_n_u16(c)) } @@ -4364,6 +4752,7 @@ pub unsafe fn vmlsq_n_u16(a: uint16x8_t, b: uint16x8_t, c: u16) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmls_n_u32(a: uint32x2_t, b: uint32x2_t, c: u32) -> uint32x2_t { vmls_u32(a, b, vdup_n_u32(c)) } @@ -4374,6 +4763,7 @@ pub unsafe fn vmls_n_u32(a: uint32x2_t, b: uint32x2_t, c: u32) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsq_n_u32(a: uint32x4_t, b: uint32x4_t, c: u32) -> uint32x4_t { vmlsq_u32(a, b, vdupq_n_u32(c)) } @@ -4384,6 +4774,7 @@ pub unsafe fn vmlsq_n_u32(a: uint32x4_t, b: uint32x4_t, c: u32) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmls_n_f32(a: float32x2_t, b: float32x2_t, c: f32) -> float32x2_t { vmls_f32(a, b, vdup_n_f32(c)) } @@ -4394,6 +4785,7 @@ pub unsafe fn vmls_n_f32(a: float32x2_t, b: float32x2_t, c: f32) -> float32x2_t #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsq_n_f32(a: float32x4_t, b: float32x4_t, c: f32) -> float32x4_t { vmlsq_f32(a, b, vdupq_n_f32(c)) } @@ -4405,6 +4797,7 @@ pub unsafe fn vmlsq_n_f32(a: float32x4_t, b: float32x4_t, c: f32) -> float32x4_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmls_lane_s16(a: int16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t { static_assert_imm2!(LANE); vmls_s16(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4417,6 +4810,7 @@ pub unsafe fn vmls_lane_s16(a: int16x4_t, b: int16x4_t, c: int1 #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmls_laneq_s16(a: int16x4_t, b: int16x4_t, c: int16x8_t) -> int16x4_t { static_assert_imm3!(LANE); vmls_s16(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4429,6 +4823,7 @@ pub unsafe fn vmls_laneq_s16(a: int16x4_t, b: int16x4_t, c: int #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsq_lane_s16(a: int16x8_t, b: int16x8_t, c: int16x4_t) -> int16x8_t { static_assert_imm2!(LANE); vmlsq_s16(a, b, simd_shuffle8!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4441,6 +4836,7 @@ pub unsafe fn vmlsq_lane_s16(a: int16x8_t, b: int16x8_t, c: int #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsq_laneq_s16(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t { static_assert_imm3!(LANE); vmlsq_s16(a, b, simd_shuffle8!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4453,6 +4849,7 @@ pub unsafe fn vmlsq_laneq_s16(a: int16x8_t, b: int16x8_t, c: in #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmls_lane_s32(a: int32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t { static_assert_imm1!(LANE); vmls_s32(a, b, simd_shuffle2!(c, c, [LANE as u32, LANE as u32])) @@ -4465,6 +4862,7 @@ pub unsafe fn vmls_lane_s32(a: int32x2_t, b: int32x2_t, c: int3 #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmls_laneq_s32(a: int32x2_t, b: int32x2_t, c: int32x4_t) -> int32x2_t { static_assert_imm2!(LANE); vmls_s32(a, b, simd_shuffle2!(c, c, [LANE as u32, LANE as u32])) @@ -4477,6 +4875,7 @@ pub unsafe fn vmls_laneq_s32(a: int32x2_t, b: int32x2_t, c: int #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsq_lane_s32(a: int32x4_t, b: int32x4_t, c: int32x2_t) -> int32x4_t { static_assert_imm1!(LANE); vmlsq_s32(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4489,6 +4888,7 @@ pub unsafe fn vmlsq_lane_s32(a: int32x4_t, b: int32x4_t, c: int #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsq_laneq_s32(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t { static_assert_imm2!(LANE); vmlsq_s32(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4501,6 +4901,7 @@ pub unsafe fn vmlsq_laneq_s32(a: int32x4_t, b: int32x4_t, c: in #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmls_lane_u16(a: uint16x4_t, b: uint16x4_t, c: uint16x4_t) -> uint16x4_t { static_assert_imm2!(LANE); vmls_u16(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4513,6 +4914,7 @@ pub unsafe fn vmls_lane_u16(a: uint16x4_t, b: uint16x4_t, c: ui #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmls_laneq_u16(a: uint16x4_t, b: uint16x4_t, c: uint16x8_t) -> uint16x4_t { static_assert_imm3!(LANE); vmls_u16(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4525,6 +4927,7 @@ pub unsafe fn vmls_laneq_u16(a: uint16x4_t, b: uint16x4_t, c: u #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsq_lane_u16(a: uint16x8_t, b: uint16x8_t, c: uint16x4_t) -> uint16x8_t { static_assert_imm2!(LANE); vmlsq_u16(a, b, simd_shuffle8!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4537,6 +4940,7 @@ pub unsafe fn vmlsq_lane_u16(a: uint16x8_t, b: uint16x8_t, c: u #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i16", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsq_laneq_u16(a: uint16x8_t, b: uint16x8_t, c: uint16x8_t) -> uint16x8_t { static_assert_imm3!(LANE); vmlsq_u16(a, b, simd_shuffle8!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4549,6 +4953,7 @@ pub unsafe fn vmlsq_laneq_u16(a: uint16x8_t, b: uint16x8_t, c: #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmls_lane_u32(a: uint32x2_t, b: uint32x2_t, c: uint32x2_t) -> uint32x2_t { static_assert_imm1!(LANE); vmls_u32(a, b, simd_shuffle2!(c, c, [LANE as u32, LANE as u32])) @@ -4561,6 +4966,7 @@ pub unsafe fn vmls_lane_u32(a: uint32x2_t, b: uint32x2_t, c: ui #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmls_laneq_u32(a: uint32x2_t, b: uint32x2_t, c: uint32x4_t) -> uint32x2_t { static_assert_imm2!(LANE); vmls_u32(a, b, simd_shuffle2!(c, c, [LANE as u32, LANE as u32])) @@ -4573,6 +4979,7 @@ pub unsafe fn vmls_laneq_u32(a: uint32x2_t, b: uint32x2_t, c: u #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsq_lane_u32(a: uint32x4_t, b: uint32x4_t, c: uint32x2_t) -> uint32x4_t { static_assert_imm1!(LANE); vmlsq_u32(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4585,6 +4992,7 @@ pub unsafe fn vmlsq_lane_u32(a: uint32x4_t, b: uint32x4_t, c: u #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.i32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mls, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsq_laneq_u32(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4_t { static_assert_imm2!(LANE); vmlsq_u32(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4597,6 +5005,7 @@ pub unsafe fn vmlsq_laneq_u32(a: uint32x4_t, b: uint32x4_t, c: #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.f32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmls_lane_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t { static_assert_imm1!(LANE); vmls_f32(a, b, simd_shuffle2!(c, c, [LANE as u32, LANE as u32])) @@ -4609,6 +5018,7 @@ pub unsafe fn vmls_lane_f32(a: float32x2_t, b: float32x2_t, c: #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.f32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmls_laneq_f32(a: float32x2_t, b: float32x2_t, c: float32x4_t) -> float32x2_t { static_assert_imm2!(LANE); vmls_f32(a, b, simd_shuffle2!(c, c, [LANE as u32, LANE as u32])) @@ -4621,6 +5031,7 @@ pub unsafe fn vmls_laneq_f32(a: float32x2_t, b: float32x2_t, c: #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.f32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsq_lane_f32(a: float32x4_t, b: float32x4_t, c: float32x2_t) -> float32x4_t { static_assert_imm1!(LANE); vmlsq_f32(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4633,6 +5044,7 @@ pub unsafe fn vmlsq_lane_f32(a: float32x4_t, b: float32x4_t, c: #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmls.f32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsq_laneq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t { static_assert_imm2!(LANE); vmlsq_f32(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4644,6 +5056,7 @@ pub unsafe fn vmlsq_laneq_f32(a: float32x4_t, b: float32x4_t, c #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlsl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsl_s8(a: int16x8_t, b: int8x8_t, c: int8x8_t) -> int16x8_t { simd_sub(a, vmull_s8(b, c)) } @@ -4654,6 +5067,7 @@ pub unsafe fn vmlsl_s8(a: int16x8_t, b: int8x8_t, c: int8x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlsl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsl_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t { simd_sub(a, vmull_s16(b, c)) } @@ -4664,6 +5078,7 @@ pub unsafe fn vmlsl_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlsl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsl_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t { simd_sub(a, vmull_s32(b, c)) } @@ -4674,6 +5089,7 @@ pub unsafe fn vmlsl_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlsl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsl_u8(a: uint16x8_t, b: uint8x8_t, c: uint8x8_t) -> uint16x8_t { simd_sub(a, vmull_u8(b, c)) } @@ -4684,6 +5100,7 @@ pub unsafe fn vmlsl_u8(a: uint16x8_t, b: uint8x8_t, c: uint8x8_t) -> uint16x8_t #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlsl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsl_u16(a: uint32x4_t, b: uint16x4_t, c: uint16x4_t) -> uint32x4_t { simd_sub(a, vmull_u16(b, c)) } @@ -4694,6 +5111,7 @@ pub unsafe fn vmlsl_u16(a: uint32x4_t, b: uint16x4_t, c: uint16x4_t) -> uint32x4 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlsl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsl_u32(a: uint64x2_t, b: uint32x2_t, c: uint32x2_t) -> uint64x2_t { simd_sub(a, vmull_u32(b, c)) } @@ -4704,6 +5122,7 @@ pub unsafe fn vmlsl_u32(a: uint64x2_t, b: uint32x2_t, c: uint32x2_t) -> uint64x2 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlsl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsl_n_s16(a: int32x4_t, b: int16x4_t, c: i16) -> int32x4_t { vmlsl_s16(a, b, vdup_n_s16(c)) } @@ -4714,6 +5133,7 @@ pub unsafe fn vmlsl_n_s16(a: int32x4_t, b: int16x4_t, c: i16) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlsl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsl_n_s32(a: int64x2_t, b: int32x2_t, c: i32) -> int64x2_t { vmlsl_s32(a, b, vdup_n_s32(c)) } @@ -4724,6 +5144,7 @@ pub unsafe fn vmlsl_n_s32(a: int64x2_t, b: int32x2_t, c: i32) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlsl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsl_n_u16(a: uint32x4_t, b: uint16x4_t, c: u16) -> uint32x4_t { vmlsl_u16(a, b, vdup_n_u16(c)) } @@ -4734,6 +5155,7 @@ pub unsafe fn vmlsl_n_u16(a: uint32x4_t, b: uint16x4_t, c: u16) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlsl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsl_n_u32(a: uint64x2_t, b: uint32x2_t, c: u32) -> uint64x2_t { vmlsl_u32(a, b, vdup_n_u32(c)) } @@ -4745,6 +5167,7 @@ pub unsafe fn vmlsl_n_u32(a: uint64x2_t, b: uint32x2_t, c: u32) -> uint64x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.s16", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlsl, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsl_lane_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t { static_assert_imm2!(LANE); vmlsl_s16(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4757,6 +5180,7 @@ pub unsafe fn vmlsl_lane_s16(a: int32x4_t, b: int16x4_t, c: int #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.s16", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlsl, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsl_laneq_s16(a: int32x4_t, b: int16x4_t, c: int16x8_t) -> int32x4_t { static_assert_imm3!(LANE); vmlsl_s16(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4769,6 +5193,7 @@ pub unsafe fn vmlsl_laneq_s16(a: int32x4_t, b: int16x4_t, c: in #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.s32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlsl, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsl_lane_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t { static_assert_imm1!(LANE); vmlsl_s32(a, b, simd_shuffle2!(c, c, [LANE as u32, LANE as u32])) @@ -4781,6 +5206,7 @@ pub unsafe fn vmlsl_lane_s32(a: int64x2_t, b: int32x2_t, c: int #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.s32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smlsl, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsl_laneq_s32(a: int64x2_t, b: int32x2_t, c: int32x4_t) -> int64x2_t { static_assert_imm2!(LANE); vmlsl_s32(a, b, simd_shuffle2!(c, c, [LANE as u32, LANE as u32])) @@ -4793,6 +5219,7 @@ pub unsafe fn vmlsl_laneq_s32(a: int64x2_t, b: int32x2_t, c: in #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.u16", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlsl, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsl_lane_u16(a: uint32x4_t, b: uint16x4_t, c: uint16x4_t) -> uint32x4_t { static_assert_imm2!(LANE); vmlsl_u16(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4805,6 +5232,7 @@ pub unsafe fn vmlsl_lane_u16(a: uint32x4_t, b: uint16x4_t, c: u #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.u16", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlsl, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsl_laneq_u16(a: uint32x4_t, b: uint16x4_t, c: uint16x8_t) -> uint32x4_t { static_assert_imm3!(LANE); vmlsl_u16(a, b, simd_shuffle4!(c, c, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -4817,6 +5245,7 @@ pub unsafe fn vmlsl_laneq_u16(a: uint32x4_t, b: uint16x4_t, c: #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.u32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlsl, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsl_lane_u32(a: uint64x2_t, b: uint32x2_t, c: uint32x2_t) -> uint64x2_t { static_assert_imm1!(LANE); vmlsl_u32(a, b, simd_shuffle2!(c, c, [LANE as u32, LANE as u32])) @@ -4829,6 +5258,7 @@ pub unsafe fn vmlsl_lane_u32(a: uint64x2_t, b: uint32x2_t, c: u #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmlsl.u32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umlsl, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmlsl_laneq_u32(a: uint64x2_t, b: uint32x2_t, c: uint32x4_t) -> uint64x2_t { static_assert_imm2!(LANE); vmlsl_u32(a, b, simd_shuffle2!(c, c, [LANE as u32, LANE as u32])) @@ -4840,6 +5270,7 @@ pub unsafe fn vmlsl_laneq_u32(a: uint64x2_t, b: uint32x2_t, c: #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vneg.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(neg))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vneg_s8(a: int8x8_t) -> int8x8_t { simd_neg(a) } @@ -4850,6 +5281,7 @@ pub unsafe fn vneg_s8(a: int8x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vneg.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(neg))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vnegq_s8(a: int8x16_t) -> int8x16_t { simd_neg(a) } @@ -4860,6 +5292,7 @@ pub unsafe fn vnegq_s8(a: int8x16_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vneg.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(neg))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vneg_s16(a: int16x4_t) -> int16x4_t { simd_neg(a) } @@ -4870,6 +5303,7 @@ pub unsafe fn vneg_s16(a: int16x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vneg.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(neg))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vnegq_s16(a: int16x8_t) -> int16x8_t { simd_neg(a) } @@ -4880,6 +5314,7 @@ pub unsafe fn vnegq_s16(a: int16x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vneg.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(neg))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vneg_s32(a: int32x2_t) -> int32x2_t { simd_neg(a) } @@ -4890,6 +5325,7 @@ pub unsafe fn vneg_s32(a: int32x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vneg.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(neg))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vnegq_s32(a: int32x4_t) -> int32x4_t { simd_neg(a) } @@ -4900,6 +5336,7 @@ pub unsafe fn vnegq_s32(a: int32x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vneg.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fneg))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vneg_f32(a: float32x2_t) -> float32x2_t { simd_neg(a) } @@ -4910,6 +5347,7 @@ pub unsafe fn vneg_f32(a: float32x2_t) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vneg.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fneg))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vnegq_f32(a: float32x4_t) -> float32x4_t { simd_neg(a) } @@ -4920,6 +5358,7 @@ pub unsafe fn vnegq_f32(a: float32x4_t) -> float32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqneg.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqneg))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqneg_s8(a: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4936,6 +5375,7 @@ vqneg_s8_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqneg.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqneg))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqnegq_s8(a: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4952,6 +5392,7 @@ vqnegq_s8_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqneg.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqneg))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqneg_s16(a: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4968,6 +5409,7 @@ vqneg_s16_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqneg.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqneg))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqnegq_s16(a: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -4984,6 +5426,7 @@ vqnegq_s16_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqneg.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqneg))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqneg_s32(a: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5000,6 +5443,7 @@ vqneg_s32_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqneg.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqneg))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqnegq_s32(a: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5016,6 +5460,7 @@ vqnegq_s32_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqsub_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5032,6 +5477,7 @@ vqsub_u8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqsubq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5048,6 +5494,7 @@ vqsubq_u8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqsub_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5064,6 +5511,7 @@ vqsub_u16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqsubq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5080,6 +5528,7 @@ vqsubq_u16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqsub_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5096,6 +5545,7 @@ vqsub_u32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqsubq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5112,6 +5562,7 @@ vqsubq_u32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.u64"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqsub_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5128,6 +5579,7 @@ vqsub_u64_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.u64"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqsubq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5144,6 +5596,7 @@ vqsubq_u64_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqsub_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5160,6 +5613,7 @@ vqsub_s8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqsubq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5176,6 +5630,7 @@ vqsubq_s8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqsub_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5192,6 +5647,7 @@ vqsub_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqsubq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5208,6 +5664,7 @@ vqsubq_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqsub_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5224,6 +5681,7 @@ vqsub_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqsubq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5240,6 +5698,7 @@ vqsubq_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.s64"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqsub_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5256,6 +5715,7 @@ vqsub_s64_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqsub.s64"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqsubq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5272,6 +5732,7 @@ vqsubq_s64_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhadd.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vhadd_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5288,6 +5749,7 @@ vhadd_u8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhadd.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vhaddq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5304,6 +5766,7 @@ vhaddq_u8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhadd.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vhadd_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5320,6 +5783,7 @@ vhadd_u16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhadd.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vhaddq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5336,6 +5800,7 @@ vhaddq_u16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhadd.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vhadd_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5352,6 +5817,7 @@ vhadd_u32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhadd.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vhaddq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5368,6 +5834,7 @@ vhaddq_u32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhadd.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vhadd_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5384,6 +5851,7 @@ vhadd_s8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhadd.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vhaddq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5400,6 +5868,7 @@ vhaddq_s8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhadd.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vhadd_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5416,6 +5885,7 @@ vhadd_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhadd.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vhaddq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5432,6 +5902,7 @@ vhaddq_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhadd.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vhadd_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5448,6 +5919,7 @@ vhadd_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhadd.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vhaddq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5464,6 +5936,7 @@ vhaddq_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrhadd.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urhadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrhadd_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5480,6 +5953,7 @@ vrhadd_u8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrhadd.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urhadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrhaddq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5496,6 +5970,7 @@ vrhaddq_u8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrhadd.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urhadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrhadd_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5512,6 +5987,7 @@ vrhadd_u16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrhadd.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urhadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrhaddq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5528,6 +6004,7 @@ vrhaddq_u16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrhadd.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urhadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrhadd_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5544,6 +6021,7 @@ vrhadd_u32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrhadd.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urhadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrhaddq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5560,6 +6038,7 @@ vrhaddq_u32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrhadd.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srhadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrhadd_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5576,6 +6055,7 @@ vrhadd_s8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrhadd.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srhadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrhaddq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5592,6 +6072,7 @@ vrhaddq_s8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrhadd.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srhadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrhadd_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5608,6 +6089,7 @@ vrhadd_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrhadd.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srhadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrhaddq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5624,6 +6106,7 @@ vrhaddq_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrhadd.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srhadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrhadd_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5640,6 +6123,7 @@ vrhadd_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrhadd.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srhadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrhaddq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5656,6 +6140,7 @@ vrhaddq_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrintn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frintn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrndn_f32(a: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5672,6 +6157,7 @@ vrndn_f32_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrintn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frintn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrndnq_f32(a: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5688,6 +6174,7 @@ vrndnq_f32_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqadd_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5704,6 +6191,7 @@ vqadd_u8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqaddq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5720,6 +6208,7 @@ vqaddq_u8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqadd_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5736,6 +6225,7 @@ vqadd_u16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqaddq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5752,6 +6242,7 @@ vqaddq_u16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqadd_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5768,6 +6259,7 @@ vqadd_u32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqaddq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5784,6 +6276,7 @@ vqaddq_u32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.u64"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqadd_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5800,6 +6293,7 @@ vqadd_u64_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.u64"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqaddq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5816,6 +6310,7 @@ vqaddq_u64_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqadd_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5832,6 +6327,7 @@ vqadd_s8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqaddq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5848,6 +6344,7 @@ vqaddq_s8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqadd_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5864,6 +6361,7 @@ vqadd_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqaddq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5880,6 +6378,7 @@ vqaddq_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqadd_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5896,6 +6395,7 @@ vqadd_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqaddq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5912,6 +6412,7 @@ vqaddq_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.s64"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqadd_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5928,6 +6429,7 @@ vqadd_s64_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqadd.s64"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqadd))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqaddq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5944,6 +6446,7 @@ vqaddq_s64_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_s8_x2(a: *const i8) -> int8x8x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5960,6 +6463,7 @@ vld1_s8_x2_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_s16_x2(a: *const i16) -> int16x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5976,6 +6480,7 @@ vld1_s16_x2_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_s32_x2(a: *const i32) -> int32x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -5992,6 +6497,7 @@ vld1_s32_x2_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_s64_x2(a: *const i64) -> int64x1x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6008,6 +6514,7 @@ vld1_s64_x2_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_s8_x2(a: *const i8) -> int8x16x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6024,6 +6531,7 @@ vld1q_s8_x2_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_s16_x2(a: *const i16) -> int16x8x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6040,6 +6548,7 @@ vld1q_s16_x2_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_s32_x2(a: *const i32) -> int32x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6056,6 +6565,7 @@ vld1q_s32_x2_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_s64_x2(a: *const i64) -> int64x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6072,6 +6582,7 @@ vld1q_s64_x2_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_s8_x3(a: *const i8) -> int8x8x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6088,6 +6599,7 @@ vld1_s8_x3_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_s16_x3(a: *const i16) -> int16x4x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6104,6 +6616,7 @@ vld1_s16_x3_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_s32_x3(a: *const i32) -> int32x2x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6120,6 +6633,7 @@ vld1_s32_x3_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_s64_x3(a: *const i64) -> int64x1x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6136,6 +6650,7 @@ vld1_s64_x3_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_s8_x3(a: *const i8) -> int8x16x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6152,6 +6667,7 @@ vld1q_s8_x3_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_s16_x3(a: *const i16) -> int16x8x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6168,6 +6684,7 @@ vld1q_s16_x3_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_s32_x3(a: *const i32) -> int32x4x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6184,6 +6701,7 @@ vld1q_s32_x3_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_s64_x3(a: *const i64) -> int64x2x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6200,6 +6718,7 @@ vld1q_s64_x3_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_s8_x4(a: *const i8) -> int8x8x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6216,6 +6735,7 @@ vld1_s8_x4_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_s16_x4(a: *const i16) -> int16x4x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6232,6 +6752,7 @@ vld1_s16_x4_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_s32_x4(a: *const i32) -> int32x2x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6248,6 +6769,7 @@ vld1_s32_x4_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_s64_x4(a: *const i64) -> int64x1x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6264,6 +6786,7 @@ vld1_s64_x4_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_s8_x4(a: *const i8) -> int8x16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6280,6 +6803,7 @@ vld1q_s8_x4_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_s16_x4(a: *const i16) -> int16x8x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6296,6 +6820,7 @@ vld1q_s16_x4_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_s32_x4(a: *const i32) -> int32x4x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6312,6 +6837,7 @@ vld1q_s32_x4_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_s64_x4(a: *const i64) -> int64x2x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6328,6 +6854,7 @@ vld1q_s64_x4_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_u8_x2(a: *const u8) -> uint8x8x2_t { transmute(vld1_s8_x2(transmute(a))) } @@ -6338,6 +6865,7 @@ pub unsafe fn vld1_u8_x2(a: *const u8) -> uint8x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_u16_x2(a: *const u16) -> uint16x4x2_t { transmute(vld1_s16_x2(transmute(a))) } @@ -6348,6 +6876,7 @@ pub unsafe fn vld1_u16_x2(a: *const u16) -> uint16x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_u32_x2(a: *const u32) -> uint32x2x2_t { transmute(vld1_s32_x2(transmute(a))) } @@ -6358,6 +6887,7 @@ pub unsafe fn vld1_u32_x2(a: *const u32) -> uint32x2x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_u64_x2(a: *const u64) -> uint64x1x2_t { transmute(vld1_s64_x2(transmute(a))) } @@ -6368,6 +6898,7 @@ pub unsafe fn vld1_u64_x2(a: *const u64) -> uint64x1x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_u8_x2(a: *const u8) -> uint8x16x2_t { transmute(vld1q_s8_x2(transmute(a))) } @@ -6378,6 +6909,7 @@ pub unsafe fn vld1q_u8_x2(a: *const u8) -> uint8x16x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_u16_x2(a: *const u16) -> uint16x8x2_t { transmute(vld1q_s16_x2(transmute(a))) } @@ -6388,6 +6920,7 @@ pub unsafe fn vld1q_u16_x2(a: *const u16) -> uint16x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_u32_x2(a: *const u32) -> uint32x4x2_t { transmute(vld1q_s32_x2(transmute(a))) } @@ -6398,6 +6931,7 @@ pub unsafe fn vld1q_u32_x2(a: *const u32) -> uint32x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_u64_x2(a: *const u64) -> uint64x2x2_t { transmute(vld1q_s64_x2(transmute(a))) } @@ -6408,6 +6942,7 @@ pub unsafe fn vld1q_u64_x2(a: *const u64) -> uint64x2x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_u8_x3(a: *const u8) -> uint8x8x3_t { transmute(vld1_s8_x3(transmute(a))) } @@ -6418,6 +6953,7 @@ pub unsafe fn vld1_u8_x3(a: *const u8) -> uint8x8x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_u16_x3(a: *const u16) -> uint16x4x3_t { transmute(vld1_s16_x3(transmute(a))) } @@ -6428,6 +6964,7 @@ pub unsafe fn vld1_u16_x3(a: *const u16) -> uint16x4x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_u32_x3(a: *const u32) -> uint32x2x3_t { transmute(vld1_s32_x3(transmute(a))) } @@ -6438,6 +6975,7 @@ pub unsafe fn vld1_u32_x3(a: *const u32) -> uint32x2x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_u64_x3(a: *const u64) -> uint64x1x3_t { transmute(vld1_s64_x3(transmute(a))) } @@ -6448,6 +6986,7 @@ pub unsafe fn vld1_u64_x3(a: *const u64) -> uint64x1x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_u8_x3(a: *const u8) -> uint8x16x3_t { transmute(vld1q_s8_x3(transmute(a))) } @@ -6458,6 +6997,7 @@ pub unsafe fn vld1q_u8_x3(a: *const u8) -> uint8x16x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_u16_x3(a: *const u16) -> uint16x8x3_t { transmute(vld1q_s16_x3(transmute(a))) } @@ -6468,6 +7008,7 @@ pub unsafe fn vld1q_u16_x3(a: *const u16) -> uint16x8x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_u32_x3(a: *const u32) -> uint32x4x3_t { transmute(vld1q_s32_x3(transmute(a))) } @@ -6478,6 +7019,7 @@ pub unsafe fn vld1q_u32_x3(a: *const u32) -> uint32x4x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_u64_x3(a: *const u64) -> uint64x2x3_t { transmute(vld1q_s64_x3(transmute(a))) } @@ -6488,6 +7030,7 @@ pub unsafe fn vld1q_u64_x3(a: *const u64) -> uint64x2x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_u8_x4(a: *const u8) -> uint8x8x4_t { transmute(vld1_s8_x4(transmute(a))) } @@ -6498,6 +7041,7 @@ pub unsafe fn vld1_u8_x4(a: *const u8) -> uint8x8x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_u16_x4(a: *const u16) -> uint16x4x4_t { transmute(vld1_s16_x4(transmute(a))) } @@ -6508,6 +7052,7 @@ pub unsafe fn vld1_u16_x4(a: *const u16) -> uint16x4x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_u32_x4(a: *const u32) -> uint32x2x4_t { transmute(vld1_s32_x4(transmute(a))) } @@ -6518,6 +7063,7 @@ pub unsafe fn vld1_u32_x4(a: *const u32) -> uint32x2x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_u64_x4(a: *const u64) -> uint64x1x4_t { transmute(vld1_s64_x4(transmute(a))) } @@ -6528,6 +7074,7 @@ pub unsafe fn vld1_u64_x4(a: *const u64) -> uint64x1x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_u8_x4(a: *const u8) -> uint8x16x4_t { transmute(vld1q_s8_x4(transmute(a))) } @@ -6538,6 +7085,7 @@ pub unsafe fn vld1q_u8_x4(a: *const u8) -> uint8x16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_u16_x4(a: *const u16) -> uint16x8x4_t { transmute(vld1q_s16_x4(transmute(a))) } @@ -6548,6 +7096,7 @@ pub unsafe fn vld1q_u16_x4(a: *const u16) -> uint16x8x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_u32_x4(a: *const u32) -> uint32x4x4_t { transmute(vld1q_s32_x4(transmute(a))) } @@ -6558,6 +7107,7 @@ pub unsafe fn vld1q_u32_x4(a: *const u32) -> uint32x4x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_u64_x4(a: *const u64) -> uint64x2x4_t { transmute(vld1q_s64_x4(transmute(a))) } @@ -6568,6 +7118,7 @@ pub unsafe fn vld1q_u64_x4(a: *const u64) -> uint64x2x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_p8_x2(a: *const p8) -> poly8x8x2_t { transmute(vld1_s8_x2(transmute(a))) } @@ -6578,6 +7129,7 @@ pub unsafe fn vld1_p8_x2(a: *const p8) -> poly8x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_p8_x3(a: *const p8) -> poly8x8x3_t { transmute(vld1_s8_x3(transmute(a))) } @@ -6588,6 +7140,7 @@ pub unsafe fn vld1_p8_x3(a: *const p8) -> poly8x8x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_p8_x4(a: *const p8) -> poly8x8x4_t { transmute(vld1_s8_x4(transmute(a))) } @@ -6598,6 +7151,7 @@ pub unsafe fn vld1_p8_x4(a: *const p8) -> poly8x8x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_p8_x2(a: *const p8) -> poly8x16x2_t { transmute(vld1q_s8_x2(transmute(a))) } @@ -6608,6 +7162,7 @@ pub unsafe fn vld1q_p8_x2(a: *const p8) -> poly8x16x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_p8_x3(a: *const p8) -> poly8x16x3_t { transmute(vld1q_s8_x3(transmute(a))) } @@ -6618,6 +7173,7 @@ pub unsafe fn vld1q_p8_x3(a: *const p8) -> poly8x16x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_p8_x4(a: *const p8) -> poly8x16x4_t { transmute(vld1q_s8_x4(transmute(a))) } @@ -6628,6 +7184,7 @@ pub unsafe fn vld1q_p8_x4(a: *const p8) -> poly8x16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_p16_x2(a: *const p16) -> poly16x4x2_t { transmute(vld1_s16_x2(transmute(a))) } @@ -6638,6 +7195,7 @@ pub unsafe fn vld1_p16_x2(a: *const p16) -> poly16x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_p16_x3(a: *const p16) -> poly16x4x3_t { transmute(vld1_s16_x3(transmute(a))) } @@ -6648,6 +7206,7 @@ pub unsafe fn vld1_p16_x3(a: *const p16) -> poly16x4x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_p16_x4(a: *const p16) -> poly16x4x4_t { transmute(vld1_s16_x4(transmute(a))) } @@ -6658,6 +7217,7 @@ pub unsafe fn vld1_p16_x4(a: *const p16) -> poly16x4x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_p16_x2(a: *const p16) -> poly16x8x2_t { transmute(vld1q_s16_x2(transmute(a))) } @@ -6668,6 +7228,7 @@ pub unsafe fn vld1q_p16_x2(a: *const p16) -> poly16x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_p16_x3(a: *const p16) -> poly16x8x3_t { transmute(vld1q_s16_x3(transmute(a))) } @@ -6678,6 +7239,7 @@ pub unsafe fn vld1q_p16_x3(a: *const p16) -> poly16x8x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_p16_x4(a: *const p16) -> poly16x8x4_t { transmute(vld1q_s16_x4(transmute(a))) } @@ -6688,6 +7250,7 @@ pub unsafe fn vld1q_p16_x4(a: *const p16) -> poly16x8x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_p64_x2(a: *const p64) -> poly64x1x2_t { transmute(vld1_s64_x2(transmute(a))) } @@ -6698,6 +7261,7 @@ pub unsafe fn vld1_p64_x2(a: *const p64) -> poly64x1x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_p64_x3(a: *const p64) -> poly64x1x3_t { transmute(vld1_s64_x3(transmute(a))) } @@ -6708,6 +7272,7 @@ pub unsafe fn vld1_p64_x3(a: *const p64) -> poly64x1x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_p64_x4(a: *const p64) -> poly64x1x4_t { transmute(vld1_s64_x4(transmute(a))) } @@ -6718,6 +7283,7 @@ pub unsafe fn vld1_p64_x4(a: *const p64) -> poly64x1x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_p64_x2(a: *const p64) -> poly64x2x2_t { transmute(vld1q_s64_x2(transmute(a))) } @@ -6728,6 +7294,7 @@ pub unsafe fn vld1q_p64_x2(a: *const p64) -> poly64x2x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_p64_x3(a: *const p64) -> poly64x2x3_t { transmute(vld1q_s64_x3(transmute(a))) } @@ -6738,6 +7305,7 @@ pub unsafe fn vld1q_p64_x3(a: *const p64) -> poly64x2x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_p64_x4(a: *const p64) -> poly64x2x4_t { transmute(vld1q_s64_x4(transmute(a))) } @@ -6748,6 +7316,7 @@ pub unsafe fn vld1q_p64_x4(a: *const p64) -> poly64x2x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_f32_x2(a: *const f32) -> float32x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6764,6 +7333,7 @@ vld1_f32_x2_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_f32_x2(a: *const f32) -> float32x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6780,6 +7350,7 @@ vld1q_f32_x2_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_f32_x3(a: *const f32) -> float32x2x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6796,6 +7367,7 @@ vld1_f32_x3_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_f32_x3(a: *const f32) -> float32x4x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6812,6 +7384,7 @@ vld1q_f32_x3_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1_f32_x4(a: *const f32) -> float32x2x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6828,6 +7401,7 @@ vld1_f32_x4_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld1q_f32_x4(a: *const f32) -> float32x4x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6842,7 +7416,7 @@ vld1q_f32_x4_(a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(test, assert_instr(vld2))] pub unsafe fn vld2_s8(a: *const i8) -> int8x8x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6856,21 +7430,22 @@ vld2_s8_(a as *const i8, 1) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +#[cfg_attr(test, assert_instr(ld2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2_s8(a: *const i8) -> int8x8x2_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2.v8i8.p0v8i8")] fn vld2_s8_(ptr: *const int8x8_t) -> int8x8x2_t; } -vld2_s8_(a.cast()) +vld2_s8_(a as _) } /// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(test, assert_instr(vld2))] pub unsafe fn vld2_s16(a: *const i16) -> int16x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6884,21 +7459,22 @@ vld2_s16_(a as *const i8, 2) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +#[cfg_attr(test, assert_instr(ld2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2_s16(a: *const i16) -> int16x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2.v4i16.p0v4i16")] fn vld2_s16_(ptr: *const int16x4_t) -> int16x4x2_t; } -vld2_s16_(a.cast()) +vld2_s16_(a as _) } /// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(test, assert_instr(vld2))] pub unsafe fn vld2_s32(a: *const i32) -> int32x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6912,21 +7488,22 @@ vld2_s32_(a as *const i8, 4) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +#[cfg_attr(test, assert_instr(ld2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2_s32(a: *const i32) -> int32x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2.v2i32.p0v2i32")] fn vld2_s32_(ptr: *const int32x2_t) -> int32x2x2_t; } -vld2_s32_(a.cast()) +vld2_s32_(a as _) } /// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(test, assert_instr(vld2))] pub unsafe fn vld2q_s8(a: *const i8) -> int8x16x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6940,21 +7517,22 @@ vld2q_s8_(a as *const i8, 1) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +#[cfg_attr(test, assert_instr(ld2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_s8(a: *const i8) -> int8x16x2_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2.v16i8.p0v16i8")] fn vld2q_s8_(ptr: *const int8x16_t) -> int8x16x2_t; } -vld2q_s8_(a.cast()) +vld2q_s8_(a as _) } /// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(test, assert_instr(vld2))] pub unsafe fn vld2q_s16(a: *const i16) -> int16x8x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6968,21 +7546,22 @@ vld2q_s16_(a as *const i8, 2) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +#[cfg_attr(test, assert_instr(ld2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_s16(a: *const i16) -> int16x8x2_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2.v8i16.p0v8i16")] fn vld2q_s16_(ptr: *const int16x8_t) -> int16x8x2_t; } -vld2q_s16_(a.cast()) +vld2q_s16_(a as _) } /// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(test, assert_instr(vld2))] pub unsafe fn vld2q_s32(a: *const i32) -> int32x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -6996,21 +7575,22 @@ vld2q_s32_(a as *const i8, 4) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +#[cfg_attr(test, assert_instr(ld2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_s32(a: *const i32) -> int32x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2.v4i32.p0v4i32")] fn vld2q_s32_(ptr: *const int32x4_t) -> int32x4x2_t; } -vld2q_s32_(a.cast()) +vld2q_s32_(a as _) } /// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vld2_s64(a: *const i64) -> int64x1x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7024,14 +7604,15 @@ vld2_s64_(a as *const i8, 8) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2_s64(a: *const i64) -> int64x1x2_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2.v1i64.p0v1i64")] fn vld2_s64_(ptr: *const int64x1_t) -> int64x1x2_t; } -vld2_s64_(a.cast()) +vld2_s64_(a as _) } /// Load multiple 2-element structures to two registers @@ -7040,6 +7621,7 @@ vld2_s64_(a.cast()) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2_u8(a: *const u8) -> uint8x8x2_t { transmute(vld2_s8(transmute(a))) } @@ -7050,6 +7632,7 @@ pub unsafe fn vld2_u8(a: *const u8) -> uint8x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2_u16(a: *const u16) -> uint16x4x2_t { transmute(vld2_s16(transmute(a))) } @@ -7060,6 +7643,7 @@ pub unsafe fn vld2_u16(a: *const u16) -> uint16x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2_u32(a: *const u32) -> uint32x2x2_t { transmute(vld2_s32(transmute(a))) } @@ -7070,6 +7654,7 @@ pub unsafe fn vld2_u32(a: *const u32) -> uint32x2x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2q_u8(a: *const u8) -> uint8x16x2_t { transmute(vld2q_s8(transmute(a))) } @@ -7080,6 +7665,7 @@ pub unsafe fn vld2q_u8(a: *const u8) -> uint8x16x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2q_u16(a: *const u16) -> uint16x8x2_t { transmute(vld2q_s16(transmute(a))) } @@ -7090,6 +7676,7 @@ pub unsafe fn vld2q_u16(a: *const u16) -> uint16x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2q_u32(a: *const u32) -> uint32x4x2_t { transmute(vld2q_s32(transmute(a))) } @@ -7100,6 +7687,7 @@ pub unsafe fn vld2q_u32(a: *const u32) -> uint32x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2_p8(a: *const p8) -> poly8x8x2_t { transmute(vld2_s8(transmute(a))) } @@ -7110,6 +7698,7 @@ pub unsafe fn vld2_p8(a: *const p8) -> poly8x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2_p16(a: *const p16) -> poly16x4x2_t { transmute(vld2_s16(transmute(a))) } @@ -7120,6 +7709,7 @@ pub unsafe fn vld2_p16(a: *const p16) -> poly16x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2q_p8(a: *const p8) -> poly8x16x2_t { transmute(vld2q_s8(transmute(a))) } @@ -7130,6 +7720,7 @@ pub unsafe fn vld2q_p8(a: *const p8) -> poly8x16x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2q_p16(a: *const p16) -> poly16x8x2_t { transmute(vld2q_s16(transmute(a))) } @@ -7140,6 +7731,7 @@ pub unsafe fn vld2q_p16(a: *const p16) -> poly16x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2_u64(a: *const u64) -> uint64x1x2_t { transmute(vld2_s64(transmute(a))) } @@ -7150,6 +7742,7 @@ pub unsafe fn vld2_u64(a: *const u64) -> uint64x1x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2_p64(a: *const p64) -> poly64x1x2_t { transmute(vld2_s64(transmute(a))) } @@ -7158,7 +7751,7 @@ pub unsafe fn vld2_p64(a: *const p64) -> poly64x1x2_t { #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(test, assert_instr(vld2))] pub unsafe fn vld2_f32(a: *const f32) -> float32x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7172,21 +7765,22 @@ vld2_f32_(a as *const i8, 4) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +#[cfg_attr(test, assert_instr(ld2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2_f32(a: *const f32) -> float32x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2.v2f32.p0v2f32")] fn vld2_f32_(ptr: *const float32x2_t) -> float32x2x2_t; } -vld2_f32_(a.cast()) +vld2_f32_(a as _) } /// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(test, assert_instr(vld2))] pub unsafe fn vld2q_f32(a: *const f32) -> float32x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7200,21 +7794,22 @@ vld2q_f32_(a as *const i8, 4) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2))] +#[cfg_attr(test, assert_instr(ld2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_f32(a: *const f32) -> float32x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2.v4f32.p0v4f32")] fn vld2q_f32_(ptr: *const float32x4_t) -> float32x4x2_t; } -vld2q_f32_(a.cast()) +vld2q_f32_(a as _) } /// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(test, assert_instr(vld2))] pub unsafe fn vld2_dup_s8(a: *const i8) -> int8x8x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7228,21 +7823,22 @@ vld2_dup_s8_(a as *const i8, 1) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +#[cfg_attr(test, assert_instr(ld2r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2_dup_s8(a: *const i8) -> int8x8x2_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2r.v8i8.p0i8")] fn vld2_dup_s8_(ptr: *const i8) -> int8x8x2_t; } -vld2_dup_s8_(a.cast()) +vld2_dup_s8_(a as _) } /// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(test, assert_instr(vld2))] pub unsafe fn vld2_dup_s16(a: *const i16) -> int16x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7256,21 +7852,22 @@ vld2_dup_s16_(a as *const i8, 2) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +#[cfg_attr(test, assert_instr(ld2r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2_dup_s16(a: *const i16) -> int16x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2r.v4i16.p0i16")] fn vld2_dup_s16_(ptr: *const i16) -> int16x4x2_t; } -vld2_dup_s16_(a.cast()) +vld2_dup_s16_(a as _) } /// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(test, assert_instr(vld2))] pub unsafe fn vld2_dup_s32(a: *const i32) -> int32x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7284,21 +7881,22 @@ vld2_dup_s32_(a as *const i8, 4) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +#[cfg_attr(test, assert_instr(ld2r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2_dup_s32(a: *const i32) -> int32x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2r.v2i32.p0i32")] fn vld2_dup_s32_(ptr: *const i32) -> int32x2x2_t; } -vld2_dup_s32_(a.cast()) +vld2_dup_s32_(a as _) } /// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(test, assert_instr(vld2))] pub unsafe fn vld2q_dup_s8(a: *const i8) -> int8x16x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7312,21 +7910,22 @@ vld2q_dup_s8_(a as *const i8, 1) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +#[cfg_attr(test, assert_instr(ld2r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_dup_s8(a: *const i8) -> int8x16x2_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2r.v16i8.p0i8")] fn vld2q_dup_s8_(ptr: *const i8) -> int8x16x2_t; } -vld2q_dup_s8_(a.cast()) +vld2q_dup_s8_(a as _) } /// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(test, assert_instr(vld2))] pub unsafe fn vld2q_dup_s16(a: *const i16) -> int16x8x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7340,21 +7939,22 @@ vld2q_dup_s16_(a as *const i8, 2) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +#[cfg_attr(test, assert_instr(ld2r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_dup_s16(a: *const i16) -> int16x8x2_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2r.v8i16.p0i16")] fn vld2q_dup_s16_(ptr: *const i16) -> int16x8x2_t; } -vld2q_dup_s16_(a.cast()) +vld2q_dup_s16_(a as _) } /// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(test, assert_instr(vld2))] pub unsafe fn vld2q_dup_s32(a: *const i32) -> int32x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7368,21 +7968,22 @@ vld2q_dup_s32_(a as *const i8, 4) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +#[cfg_attr(test, assert_instr(ld2r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_dup_s32(a: *const i32) -> int32x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2r.v4i32.p0i32")] fn vld2q_dup_s32_(ptr: *const i32) -> int32x4x2_t; } -vld2q_dup_s32_(a.cast()) +vld2q_dup_s32_(a as _) } /// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vld2_dup_s64(a: *const i64) -> int64x1x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7396,14 +7997,15 @@ vld2_dup_s64_(a as *const i8, 8) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +#[cfg_attr(test, assert_instr(ld2r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2_dup_s64(a: *const i64) -> int64x1x2_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2r.v1i64.p0i64")] fn vld2_dup_s64_(ptr: *const i64) -> int64x1x2_t; } -vld2_dup_s64_(a.cast()) +vld2_dup_s64_(a as _) } /// Load single 2-element structure and replicate to all lanes of two registers @@ -7412,6 +8014,7 @@ vld2_dup_s64_(a.cast()) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2_dup_u8(a: *const u8) -> uint8x8x2_t { transmute(vld2_dup_s8(transmute(a))) } @@ -7422,6 +8025,7 @@ pub unsafe fn vld2_dup_u8(a: *const u8) -> uint8x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2_dup_u16(a: *const u16) -> uint16x4x2_t { transmute(vld2_dup_s16(transmute(a))) } @@ -7432,6 +8036,7 @@ pub unsafe fn vld2_dup_u16(a: *const u16) -> uint16x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2_dup_u32(a: *const u32) -> uint32x2x2_t { transmute(vld2_dup_s32(transmute(a))) } @@ -7442,6 +8047,7 @@ pub unsafe fn vld2_dup_u32(a: *const u32) -> uint32x2x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2q_dup_u8(a: *const u8) -> uint8x16x2_t { transmute(vld2q_dup_s8(transmute(a))) } @@ -7452,6 +8058,7 @@ pub unsafe fn vld2q_dup_u8(a: *const u8) -> uint8x16x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2q_dup_u16(a: *const u16) -> uint16x8x2_t { transmute(vld2q_dup_s16(transmute(a))) } @@ -7462,6 +8069,7 @@ pub unsafe fn vld2q_dup_u16(a: *const u16) -> uint16x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2q_dup_u32(a: *const u32) -> uint32x4x2_t { transmute(vld2q_dup_s32(transmute(a))) } @@ -7472,6 +8080,7 @@ pub unsafe fn vld2q_dup_u32(a: *const u32) -> uint32x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2_dup_p8(a: *const p8) -> poly8x8x2_t { transmute(vld2_dup_s8(transmute(a))) } @@ -7482,6 +8091,7 @@ pub unsafe fn vld2_dup_p8(a: *const p8) -> poly8x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2_dup_p16(a: *const p16) -> poly16x4x2_t { transmute(vld2_dup_s16(transmute(a))) } @@ -7492,6 +8102,7 @@ pub unsafe fn vld2_dup_p16(a: *const p16) -> poly16x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2q_dup_p8(a: *const p8) -> poly8x16x2_t { transmute(vld2q_dup_s8(transmute(a))) } @@ -7502,6 +8113,7 @@ pub unsafe fn vld2q_dup_p8(a: *const p8) -> poly8x16x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2q_dup_p16(a: *const p16) -> poly16x8x2_t { transmute(vld2q_dup_s16(transmute(a))) } @@ -7512,6 +8124,7 @@ pub unsafe fn vld2q_dup_p16(a: *const p16) -> poly16x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2_dup_u64(a: *const u64) -> uint64x1x2_t { transmute(vld2_dup_s64(transmute(a))) } @@ -7522,6 +8135,7 @@ pub unsafe fn vld2_dup_u64(a: *const u64) -> uint64x1x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2_dup_p64(a: *const p64) -> poly64x1x2_t { transmute(vld2_dup_s64(transmute(a))) } @@ -7530,7 +8144,7 @@ pub unsafe fn vld2_dup_p64(a: *const p64) -> poly64x1x2_t { #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(test, assert_instr(vld2))] pub unsafe fn vld2_dup_f32(a: *const f32) -> float32x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7544,21 +8158,22 @@ vld2_dup_f32_(a as *const i8, 4) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +#[cfg_attr(test, assert_instr(ld2r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2_dup_f32(a: *const f32) -> float32x2x2_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2r.v2f32.p0f32")] fn vld2_dup_f32_(ptr: *const f32) -> float32x2x2_t; } -vld2_dup_f32_(a.cast()) +vld2_dup_f32_(a as _) } /// Load single 2-element structure and replicate to all lanes of two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2))] +#[cfg_attr(test, assert_instr(vld2))] pub unsafe fn vld2q_dup_f32(a: *const f32) -> float32x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7572,21 +8187,22 @@ vld2q_dup_f32_(a as *const i8, 4) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2r))] +#[cfg_attr(test, assert_instr(ld2r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_dup_f32(a: *const f32) -> float32x4x2_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2r.v4f32.p0f32")] fn vld2q_dup_f32_(ptr: *const f32) -> float32x4x2_t; } -vld2q_dup_f32_(a.cast()) +vld2q_dup_f32_(a as _) } /// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] +#[cfg_attr(test, assert_instr(vld2, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vld2_lane_s8(a: *const i8, b: int8x8x2_t) -> int8x8x2_t { static_assert_imm3!(LANE); @@ -7595,15 +8211,16 @@ pub unsafe fn vld2_lane_s8(a: *const i8, b: int8x8x2_t) -> int8 #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2lane.v8i8.p0i8")] fn vld2_lane_s8_(ptr: *const i8, a: int8x8_t, b: int8x8_t, n: i32, size: i32) -> int8x8x2_t; } -vld2_lane_s8_(a.cast(), b.0, b.1, LANE, 1) +vld2_lane_s8_(a as _, b.0, b.1, LANE, 1) } /// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] +#[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2_lane_s8(a: *const i8, b: int8x8x2_t) -> int8x8x2_t { static_assert_imm3!(LANE); #[allow(improper_ctypes)] @@ -7611,14 +8228,14 @@ pub unsafe fn vld2_lane_s8(a: *const i8, b: int8x8x2_t) -> int8 #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2lane.v8i8.p0i8")] fn vld2_lane_s8_(a: int8x8_t, b: int8x8_t, n: i64, ptr: *const i8) -> int8x8x2_t; } -vld2_lane_s8_(b.0, b.1, LANE as i64, a.cast()) +vld2_lane_s8_(b.0, b.1, LANE as i64, a as _) } /// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] +#[cfg_attr(test, assert_instr(vld2, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vld2_lane_s16(a: *const i16, b: int16x4x2_t) -> int16x4x2_t { static_assert_imm2!(LANE); @@ -7627,15 +8244,16 @@ pub unsafe fn vld2_lane_s16(a: *const i16, b: int16x4x2_t) -> i #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2lane.v4i16.p0i8")] fn vld2_lane_s16_(ptr: *const i8, a: int16x4_t, b: int16x4_t, n: i32, size: i32) -> int16x4x2_t; } -vld2_lane_s16_(a.cast(), b.0, b.1, LANE, 2) +vld2_lane_s16_(a as _, b.0, b.1, LANE, 2) } /// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] +#[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2_lane_s16(a: *const i16, b: int16x4x2_t) -> int16x4x2_t { static_assert_imm2!(LANE); #[allow(improper_ctypes)] @@ -7643,14 +8261,14 @@ pub unsafe fn vld2_lane_s16(a: *const i16, b: int16x4x2_t) -> i #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2lane.v4i16.p0i8")] fn vld2_lane_s16_(a: int16x4_t, b: int16x4_t, n: i64, ptr: *const i8) -> int16x4x2_t; } -vld2_lane_s16_(b.0, b.1, LANE as i64, a.cast()) +vld2_lane_s16_(b.0, b.1, LANE as i64, a as _) } /// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] +#[cfg_attr(test, assert_instr(vld2, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vld2_lane_s32(a: *const i32, b: int32x2x2_t) -> int32x2x2_t { static_assert_imm1!(LANE); @@ -7659,15 +8277,16 @@ pub unsafe fn vld2_lane_s32(a: *const i32, b: int32x2x2_t) -> i #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2lane.v2i32.p0i8")] fn vld2_lane_s32_(ptr: *const i8, a: int32x2_t, b: int32x2_t, n: i32, size: i32) -> int32x2x2_t; } -vld2_lane_s32_(a.cast(), b.0, b.1, LANE, 4) +vld2_lane_s32_(a as _, b.0, b.1, LANE, 4) } /// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] +#[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2_lane_s32(a: *const i32, b: int32x2x2_t) -> int32x2x2_t { static_assert_imm1!(LANE); #[allow(improper_ctypes)] @@ -7675,14 +8294,14 @@ pub unsafe fn vld2_lane_s32(a: *const i32, b: int32x2x2_t) -> i #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2lane.v2i32.p0i8")] fn vld2_lane_s32_(a: int32x2_t, b: int32x2_t, n: i64, ptr: *const i8) -> int32x2x2_t; } -vld2_lane_s32_(b.0, b.1, LANE as i64, a.cast()) +vld2_lane_s32_(b.0, b.1, LANE as i64, a as _) } /// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] +#[cfg_attr(test, assert_instr(vld2, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vld2q_lane_s16(a: *const i16, b: int16x8x2_t) -> int16x8x2_t { static_assert_imm3!(LANE); @@ -7691,15 +8310,16 @@ pub unsafe fn vld2q_lane_s16(a: *const i16, b: int16x8x2_t) -> #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2lane.v8i16.p0i8")] fn vld2q_lane_s16_(ptr: *const i8, a: int16x8_t, b: int16x8_t, n: i32, size: i32) -> int16x8x2_t; } -vld2q_lane_s16_(a.cast(), b.0, b.1, LANE, 2) +vld2q_lane_s16_(a as _, b.0, b.1, LANE, 2) } /// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] +#[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_lane_s16(a: *const i16, b: int16x8x2_t) -> int16x8x2_t { static_assert_imm3!(LANE); #[allow(improper_ctypes)] @@ -7707,14 +8327,14 @@ pub unsafe fn vld2q_lane_s16(a: *const i16, b: int16x8x2_t) -> #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2lane.v8i16.p0i8")] fn vld2q_lane_s16_(a: int16x8_t, b: int16x8_t, n: i64, ptr: *const i8) -> int16x8x2_t; } -vld2q_lane_s16_(b.0, b.1, LANE as i64, a.cast()) +vld2q_lane_s16_(b.0, b.1, LANE as i64, a as _) } /// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] +#[cfg_attr(test, assert_instr(vld2, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vld2q_lane_s32(a: *const i32, b: int32x4x2_t) -> int32x4x2_t { static_assert_imm2!(LANE); @@ -7723,15 +8343,16 @@ pub unsafe fn vld2q_lane_s32(a: *const i32, b: int32x4x2_t) -> #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2lane.v4i32.p0i8")] fn vld2q_lane_s32_(ptr: *const i8, a: int32x4_t, b: int32x4_t, n: i32, size: i32) -> int32x4x2_t; } -vld2q_lane_s32_(a.cast(), b.0, b.1, LANE, 4) +vld2q_lane_s32_(a as _, b.0, b.1, LANE, 4) } /// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] +#[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_lane_s32(a: *const i32, b: int32x4x2_t) -> int32x4x2_t { static_assert_imm2!(LANE); #[allow(improper_ctypes)] @@ -7739,7 +8360,7 @@ pub unsafe fn vld2q_lane_s32(a: *const i32, b: int32x4x2_t) -> #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2lane.v4i32.p0i8")] fn vld2q_lane_s32_(a: int32x4_t, b: int32x4_t, n: i64, ptr: *const i8) -> int32x4x2_t; } -vld2q_lane_s32_(b.0, b.1, LANE as i64, a.cast()) +vld2q_lane_s32_(b.0, b.1, LANE as i64, a as _) } /// Load multiple 2-element structures to two registers @@ -7749,6 +8370,7 @@ vld2q_lane_s32_(b.0, b.1, LANE as i64, a.cast()) #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2_lane_u8(a: *const u8, b: uint8x8x2_t) -> uint8x8x2_t { static_assert_imm3!(LANE); transmute(vld2_lane_s8::(transmute(a), transmute(b))) @@ -7761,6 +8383,7 @@ pub unsafe fn vld2_lane_u8(a: *const u8, b: uint8x8x2_t) -> uin #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2_lane_u16(a: *const u16, b: uint16x4x2_t) -> uint16x4x2_t { static_assert_imm2!(LANE); transmute(vld2_lane_s16::(transmute(a), transmute(b))) @@ -7773,6 +8396,7 @@ pub unsafe fn vld2_lane_u16(a: *const u16, b: uint16x4x2_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2_lane_u32(a: *const u32, b: uint32x2x2_t) -> uint32x2x2_t { static_assert_imm1!(LANE); transmute(vld2_lane_s32::(transmute(a), transmute(b))) @@ -7785,6 +8409,7 @@ pub unsafe fn vld2_lane_u32(a: *const u32, b: uint32x2x2_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2q_lane_u16(a: *const u16, b: uint16x8x2_t) -> uint16x8x2_t { static_assert_imm3!(LANE); transmute(vld2q_lane_s16::(transmute(a), transmute(b))) @@ -7797,6 +8422,7 @@ pub unsafe fn vld2q_lane_u16(a: *const u16, b: uint16x8x2_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2q_lane_u32(a: *const u32, b: uint32x4x2_t) -> uint32x4x2_t { static_assert_imm2!(LANE); transmute(vld2q_lane_s32::(transmute(a), transmute(b))) @@ -7809,6 +8435,7 @@ pub unsafe fn vld2q_lane_u32(a: *const u32, b: uint32x4x2_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2_lane_p8(a: *const p8, b: poly8x8x2_t) -> poly8x8x2_t { static_assert_imm3!(LANE); transmute(vld2_lane_s8::(transmute(a), transmute(b))) @@ -7821,6 +8448,7 @@ pub unsafe fn vld2_lane_p8(a: *const p8, b: poly8x8x2_t) -> pol #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2_lane_p16(a: *const p16, b: poly16x4x2_t) -> poly16x4x2_t { static_assert_imm2!(LANE); transmute(vld2_lane_s16::(transmute(a), transmute(b))) @@ -7833,6 +8461,7 @@ pub unsafe fn vld2_lane_p16(a: *const p16, b: poly16x4x2_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld2q_lane_p16(a: *const p16, b: poly16x8x2_t) -> poly16x8x2_t { static_assert_imm3!(LANE); transmute(vld2q_lane_s16::(transmute(a), transmute(b))) @@ -7842,7 +8471,7 @@ pub unsafe fn vld2q_lane_p16(a: *const p16, b: poly16x8x2_t) -> #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] +#[cfg_attr(test, assert_instr(vld2, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vld2_lane_f32(a: *const f32, b: float32x2x2_t) -> float32x2x2_t { static_assert_imm1!(LANE); @@ -7851,15 +8480,16 @@ pub unsafe fn vld2_lane_f32(a: *const f32, b: float32x2x2_t) -> #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2lane.v2f32.p0i8")] fn vld2_lane_f32_(ptr: *const i8, a: float32x2_t, b: float32x2_t, n: i32, size: i32) -> float32x2x2_t; } -vld2_lane_f32_(a.cast(), b.0, b.1, LANE, 4) +vld2_lane_f32_(a as _, b.0, b.1, LANE, 4) } /// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] +#[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2_lane_f32(a: *const f32, b: float32x2x2_t) -> float32x2x2_t { static_assert_imm1!(LANE); #[allow(improper_ctypes)] @@ -7867,14 +8497,14 @@ pub unsafe fn vld2_lane_f32(a: *const f32, b: float32x2x2_t) -> #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2lane.v2f32.p0i8")] fn vld2_lane_f32_(a: float32x2_t, b: float32x2_t, n: i64, ptr: *const i8) -> float32x2x2_t; } -vld2_lane_f32_(b.0, b.1, LANE as i64, a.cast()) +vld2_lane_f32_(b.0, b.1, LANE as i64, a as _) } /// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld2, LANE = 0))] +#[cfg_attr(test, assert_instr(vld2, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vld2q_lane_f32(a: *const f32, b: float32x4x2_t) -> float32x4x2_t { static_assert_imm2!(LANE); @@ -7883,15 +8513,16 @@ pub unsafe fn vld2q_lane_f32(a: *const f32, b: float32x4x2_t) - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld2lane.v4f32.p0i8")] fn vld2q_lane_f32_(ptr: *const i8, a: float32x4_t, b: float32x4_t, n: i32, size: i32) -> float32x4x2_t; } -vld2q_lane_f32_(a.cast(), b.0, b.1, LANE, 4) +vld2q_lane_f32_(a as _, b.0, b.1, LANE, 4) } /// Load multiple 2-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld2, LANE = 0))] +#[cfg_attr(test, assert_instr(ld2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld2q_lane_f32(a: *const f32, b: float32x4x2_t) -> float32x4x2_t { static_assert_imm2!(LANE); #[allow(improper_ctypes)] @@ -7899,14 +8530,14 @@ pub unsafe fn vld2q_lane_f32(a: *const f32, b: float32x4x2_t) - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld2lane.v4f32.p0i8")] fn vld2q_lane_f32_(a: float32x4_t, b: float32x4_t, n: i64, ptr: *const i8) -> float32x4x2_t; } -vld2q_lane_f32_(b.0, b.1, LANE as i64, a.cast()) +vld2q_lane_f32_(b.0, b.1, LANE as i64, a as _) } /// Load multiple 3-element structures to three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(test, assert_instr(vld3))] pub unsafe fn vld3_s8(a: *const i8) -> int8x8x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7920,21 +8551,22 @@ vld3_s8_(a as *const i8, 1) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +#[cfg_attr(test, assert_instr(ld3))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3_s8(a: *const i8) -> int8x8x3_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3.v8i8.p0v8i8")] fn vld3_s8_(ptr: *const int8x8_t) -> int8x8x3_t; } -vld3_s8_(a.cast()) +vld3_s8_(a as _) } /// Load multiple 3-element structures to three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(test, assert_instr(vld3))] pub unsafe fn vld3_s16(a: *const i16) -> int16x4x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7948,21 +8580,22 @@ vld3_s16_(a as *const i8, 2) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +#[cfg_attr(test, assert_instr(ld3))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3_s16(a: *const i16) -> int16x4x3_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3.v4i16.p0v4i16")] fn vld3_s16_(ptr: *const int16x4_t) -> int16x4x3_t; } -vld3_s16_(a.cast()) +vld3_s16_(a as _) } /// Load multiple 3-element structures to three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(test, assert_instr(vld3))] pub unsafe fn vld3_s32(a: *const i32) -> int32x2x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -7976,21 +8609,22 @@ vld3_s32_(a as *const i8, 4) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +#[cfg_attr(test, assert_instr(ld3))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3_s32(a: *const i32) -> int32x2x3_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3.v2i32.p0v2i32")] fn vld3_s32_(ptr: *const int32x2_t) -> int32x2x3_t; } -vld3_s32_(a.cast()) +vld3_s32_(a as _) } /// Load multiple 3-element structures to three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(test, assert_instr(vld3))] pub unsafe fn vld3q_s8(a: *const i8) -> int8x16x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8004,21 +8638,22 @@ vld3q_s8_(a as *const i8, 1) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +#[cfg_attr(test, assert_instr(ld3))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_s8(a: *const i8) -> int8x16x3_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3.v16i8.p0v16i8")] fn vld3q_s8_(ptr: *const int8x16_t) -> int8x16x3_t; } -vld3q_s8_(a.cast()) +vld3q_s8_(a as _) } /// Load multiple 3-element structures to three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(test, assert_instr(vld3))] pub unsafe fn vld3q_s16(a: *const i16) -> int16x8x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8032,21 +8667,22 @@ vld3q_s16_(a as *const i8, 2) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +#[cfg_attr(test, assert_instr(ld3))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_s16(a: *const i16) -> int16x8x3_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3.v8i16.p0v8i16")] fn vld3q_s16_(ptr: *const int16x8_t) -> int16x8x3_t; } -vld3q_s16_(a.cast()) +vld3q_s16_(a as _) } /// Load multiple 3-element structures to three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(test, assert_instr(vld3))] pub unsafe fn vld3q_s32(a: *const i32) -> int32x4x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8060,21 +8696,22 @@ vld3q_s32_(a as *const i8, 4) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +#[cfg_attr(test, assert_instr(ld3))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_s32(a: *const i32) -> int32x4x3_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3.v4i32.p0v4i32")] fn vld3q_s32_(ptr: *const int32x4_t) -> int32x4x3_t; } -vld3q_s32_(a.cast()) +vld3q_s32_(a as _) } /// Load multiple 3-element structures to three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vld3_s64(a: *const i64) -> int64x1x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8088,14 +8725,15 @@ vld3_s64_(a as *const i8, 8) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3_s64(a: *const i64) -> int64x1x3_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3.v1i64.p0v1i64")] fn vld3_s64_(ptr: *const int64x1_t) -> int64x1x3_t; } -vld3_s64_(a.cast()) +vld3_s64_(a as _) } /// Load multiple 3-element structures to three registers @@ -8104,6 +8742,7 @@ vld3_s64_(a.cast()) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3_u8(a: *const u8) -> uint8x8x3_t { transmute(vld3_s8(transmute(a))) } @@ -8114,6 +8753,7 @@ pub unsafe fn vld3_u8(a: *const u8) -> uint8x8x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3_u16(a: *const u16) -> uint16x4x3_t { transmute(vld3_s16(transmute(a))) } @@ -8124,6 +8764,7 @@ pub unsafe fn vld3_u16(a: *const u16) -> uint16x4x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3_u32(a: *const u32) -> uint32x2x3_t { transmute(vld3_s32(transmute(a))) } @@ -8134,6 +8775,7 @@ pub unsafe fn vld3_u32(a: *const u32) -> uint32x2x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3q_u8(a: *const u8) -> uint8x16x3_t { transmute(vld3q_s8(transmute(a))) } @@ -8144,6 +8786,7 @@ pub unsafe fn vld3q_u8(a: *const u8) -> uint8x16x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3q_u16(a: *const u16) -> uint16x8x3_t { transmute(vld3q_s16(transmute(a))) } @@ -8154,6 +8797,7 @@ pub unsafe fn vld3q_u16(a: *const u16) -> uint16x8x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3q_u32(a: *const u32) -> uint32x4x3_t { transmute(vld3q_s32(transmute(a))) } @@ -8164,6 +8808,7 @@ pub unsafe fn vld3q_u32(a: *const u32) -> uint32x4x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3_p8(a: *const p8) -> poly8x8x3_t { transmute(vld3_s8(transmute(a))) } @@ -8174,6 +8819,7 @@ pub unsafe fn vld3_p8(a: *const p8) -> poly8x8x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3_p16(a: *const p16) -> poly16x4x3_t { transmute(vld3_s16(transmute(a))) } @@ -8184,6 +8830,7 @@ pub unsafe fn vld3_p16(a: *const p16) -> poly16x4x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3q_p8(a: *const p8) -> poly8x16x3_t { transmute(vld3q_s8(transmute(a))) } @@ -8194,6 +8841,7 @@ pub unsafe fn vld3q_p8(a: *const p8) -> poly8x16x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3q_p16(a: *const p16) -> poly16x8x3_t { transmute(vld3q_s16(transmute(a))) } @@ -8204,6 +8852,7 @@ pub unsafe fn vld3q_p16(a: *const p16) -> poly16x8x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3_u64(a: *const u64) -> uint64x1x3_t { transmute(vld3_s64(transmute(a))) } @@ -8214,6 +8863,7 @@ pub unsafe fn vld3_u64(a: *const u64) -> uint64x1x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3_p64(a: *const p64) -> poly64x1x3_t { transmute(vld3_s64(transmute(a))) } @@ -8222,7 +8872,7 @@ pub unsafe fn vld3_p64(a: *const p64) -> poly64x1x3_t { #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(test, assert_instr(vld3))] pub unsafe fn vld3_f32(a: *const f32) -> float32x2x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8236,21 +8886,22 @@ vld3_f32_(a as *const i8, 4) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +#[cfg_attr(test, assert_instr(ld3))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3_f32(a: *const f32) -> float32x2x3_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3.v2f32.p0v2f32")] fn vld3_f32_(ptr: *const float32x2_t) -> float32x2x3_t; } -vld3_f32_(a.cast()) +vld3_f32_(a as _) } /// Load multiple 3-element structures to three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(test, assert_instr(vld3))] pub unsafe fn vld3q_f32(a: *const f32) -> float32x4x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8264,21 +8915,22 @@ vld3q_f32_(a as *const i8, 4) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3))] +#[cfg_attr(test, assert_instr(ld3))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_f32(a: *const f32) -> float32x4x3_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3.v4f32.p0v4f32")] fn vld3q_f32_(ptr: *const float32x4_t) -> float32x4x3_t; } -vld3q_f32_(a.cast()) +vld3q_f32_(a as _) } /// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(test, assert_instr(vld3))] pub unsafe fn vld3_dup_s8(a: *const i8) -> int8x8x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8292,21 +8944,22 @@ vld3_dup_s8_(a as *const i8, 1) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +#[cfg_attr(test, assert_instr(ld3r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3_dup_s8(a: *const i8) -> int8x8x3_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3r.v8i8.p0i8")] fn vld3_dup_s8_(ptr: *const i8) -> int8x8x3_t; } -vld3_dup_s8_(a.cast()) +vld3_dup_s8_(a as _) } /// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(test, assert_instr(vld3))] pub unsafe fn vld3_dup_s16(a: *const i16) -> int16x4x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8320,21 +8973,22 @@ vld3_dup_s16_(a as *const i8, 2) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +#[cfg_attr(test, assert_instr(ld3r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3_dup_s16(a: *const i16) -> int16x4x3_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3r.v4i16.p0i16")] fn vld3_dup_s16_(ptr: *const i16) -> int16x4x3_t; } -vld3_dup_s16_(a.cast()) +vld3_dup_s16_(a as _) } /// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(test, assert_instr(vld3))] pub unsafe fn vld3_dup_s32(a: *const i32) -> int32x2x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8348,21 +9002,22 @@ vld3_dup_s32_(a as *const i8, 4) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +#[cfg_attr(test, assert_instr(ld3r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3_dup_s32(a: *const i32) -> int32x2x3_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3r.v2i32.p0i32")] fn vld3_dup_s32_(ptr: *const i32) -> int32x2x3_t; } -vld3_dup_s32_(a.cast()) +vld3_dup_s32_(a as _) } /// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(test, assert_instr(vld3))] pub unsafe fn vld3q_dup_s8(a: *const i8) -> int8x16x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8376,21 +9031,22 @@ vld3q_dup_s8_(a as *const i8, 1) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +#[cfg_attr(test, assert_instr(ld3r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_dup_s8(a: *const i8) -> int8x16x3_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3r.v16i8.p0i8")] fn vld3q_dup_s8_(ptr: *const i8) -> int8x16x3_t; } -vld3q_dup_s8_(a.cast()) +vld3q_dup_s8_(a as _) } /// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(test, assert_instr(vld3))] pub unsafe fn vld3q_dup_s16(a: *const i16) -> int16x8x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8404,21 +9060,22 @@ vld3q_dup_s16_(a as *const i8, 2) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +#[cfg_attr(test, assert_instr(ld3r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_dup_s16(a: *const i16) -> int16x8x3_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3r.v8i16.p0i16")] fn vld3q_dup_s16_(ptr: *const i16) -> int16x8x3_t; } -vld3q_dup_s16_(a.cast()) +vld3q_dup_s16_(a as _) } /// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(test, assert_instr(vld3))] pub unsafe fn vld3q_dup_s32(a: *const i32) -> int32x4x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8432,21 +9089,22 @@ vld3q_dup_s32_(a as *const i8, 4) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +#[cfg_attr(test, assert_instr(ld3r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_dup_s32(a: *const i32) -> int32x4x3_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3r.v4i32.p0i32")] fn vld3q_dup_s32_(ptr: *const i32) -> int32x4x3_t; } -vld3q_dup_s32_(a.cast()) +vld3q_dup_s32_(a as _) } /// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vld3_dup_s64(a: *const i64) -> int64x1x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8460,14 +9118,15 @@ vld3_dup_s64_(a as *const i8, 8) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +#[cfg_attr(test, assert_instr(ld3r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3_dup_s64(a: *const i64) -> int64x1x3_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3r.v1i64.p0i64")] fn vld3_dup_s64_(ptr: *const i64) -> int64x1x3_t; } -vld3_dup_s64_(a.cast()) +vld3_dup_s64_(a as _) } /// Load single 3-element structure and replicate to all lanes of three registers @@ -8476,6 +9135,7 @@ vld3_dup_s64_(a.cast()) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3_dup_u8(a: *const u8) -> uint8x8x3_t { transmute(vld3_dup_s8(transmute(a))) } @@ -8486,6 +9146,7 @@ pub unsafe fn vld3_dup_u8(a: *const u8) -> uint8x8x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3_dup_u16(a: *const u16) -> uint16x4x3_t { transmute(vld3_dup_s16(transmute(a))) } @@ -8496,6 +9157,7 @@ pub unsafe fn vld3_dup_u16(a: *const u16) -> uint16x4x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3_dup_u32(a: *const u32) -> uint32x2x3_t { transmute(vld3_dup_s32(transmute(a))) } @@ -8506,6 +9168,7 @@ pub unsafe fn vld3_dup_u32(a: *const u32) -> uint32x2x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3q_dup_u8(a: *const u8) -> uint8x16x3_t { transmute(vld3q_dup_s8(transmute(a))) } @@ -8516,6 +9179,7 @@ pub unsafe fn vld3q_dup_u8(a: *const u8) -> uint8x16x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3q_dup_u16(a: *const u16) -> uint16x8x3_t { transmute(vld3q_dup_s16(transmute(a))) } @@ -8526,6 +9190,7 @@ pub unsafe fn vld3q_dup_u16(a: *const u16) -> uint16x8x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3q_dup_u32(a: *const u32) -> uint32x4x3_t { transmute(vld3q_dup_s32(transmute(a))) } @@ -8536,6 +9201,7 @@ pub unsafe fn vld3q_dup_u32(a: *const u32) -> uint32x4x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3_dup_p8(a: *const p8) -> poly8x8x3_t { transmute(vld3_dup_s8(transmute(a))) } @@ -8546,6 +9212,7 @@ pub unsafe fn vld3_dup_p8(a: *const p8) -> poly8x8x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3_dup_p16(a: *const p16) -> poly16x4x3_t { transmute(vld3_dup_s16(transmute(a))) } @@ -8556,6 +9223,7 @@ pub unsafe fn vld3_dup_p16(a: *const p16) -> poly16x4x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3q_dup_p8(a: *const p8) -> poly8x16x3_t { transmute(vld3q_dup_s8(transmute(a))) } @@ -8566,6 +9234,7 @@ pub unsafe fn vld3q_dup_p8(a: *const p8) -> poly8x16x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3q_dup_p16(a: *const p16) -> poly16x8x3_t { transmute(vld3q_dup_s16(transmute(a))) } @@ -8576,6 +9245,7 @@ pub unsafe fn vld3q_dup_p16(a: *const p16) -> poly16x8x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3_dup_u64(a: *const u64) -> uint64x1x3_t { transmute(vld3_dup_s64(transmute(a))) } @@ -8586,6 +9256,7 @@ pub unsafe fn vld3_dup_u64(a: *const u64) -> uint64x1x3_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3_dup_p64(a: *const p64) -> poly64x1x3_t { transmute(vld3_dup_s64(transmute(a))) } @@ -8594,7 +9265,7 @@ pub unsafe fn vld3_dup_p64(a: *const p64) -> poly64x1x3_t { #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(test, assert_instr(vld3))] pub unsafe fn vld3_dup_f32(a: *const f32) -> float32x2x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8608,21 +9279,22 @@ vld3_dup_f32_(a as *const i8, 4) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +#[cfg_attr(test, assert_instr(ld3r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3_dup_f32(a: *const f32) -> float32x2x3_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3r.v2f32.p0f32")] fn vld3_dup_f32_(ptr: *const f32) -> float32x2x3_t; } -vld3_dup_f32_(a.cast()) +vld3_dup_f32_(a as _) } /// Load single 3-element structure and replicate to all lanes of three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3))] +#[cfg_attr(test, assert_instr(vld3))] pub unsafe fn vld3q_dup_f32(a: *const f32) -> float32x4x3_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8636,21 +9308,22 @@ vld3q_dup_f32_(a as *const i8, 4) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3r))] +#[cfg_attr(test, assert_instr(ld3r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_dup_f32(a: *const f32) -> float32x4x3_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3r.v4f32.p0f32")] fn vld3q_dup_f32_(ptr: *const f32) -> float32x4x3_t; } -vld3q_dup_f32_(a.cast()) +vld3q_dup_f32_(a as _) } /// Load multiple 3-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] +#[cfg_attr(test, assert_instr(vld3, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vld3_lane_s8(a: *const i8, b: int8x8x3_t) -> int8x8x3_t { static_assert_imm3!(LANE); @@ -8659,15 +9332,16 @@ pub unsafe fn vld3_lane_s8(a: *const i8, b: int8x8x3_t) -> int8 #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3lane.v8i8.p0i8")] fn vld3_lane_s8_(ptr: *const i8, a: int8x8_t, b: int8x8_t, c: int8x8_t, n: i32, size: i32) -> int8x8x3_t; } -vld3_lane_s8_(a.cast(), b.0, b.1, b.2, LANE, 1) +vld3_lane_s8_(a as _, b.0, b.1, b.2, LANE, 1) } /// Load multiple 3-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] +#[cfg_attr(test, assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3_lane_s8(a: *const i8, b: int8x8x3_t) -> int8x8x3_t { static_assert_imm3!(LANE); #[allow(improper_ctypes)] @@ -8675,14 +9349,14 @@ pub unsafe fn vld3_lane_s8(a: *const i8, b: int8x8x3_t) -> int8 #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3lane.v8i8.p0i8")] fn vld3_lane_s8_(a: int8x8_t, b: int8x8_t, c: int8x8_t, n: i64, ptr: *const i8) -> int8x8x3_t; } -vld3_lane_s8_(b.0, b.1, b.2, LANE as i64, a.cast()) +vld3_lane_s8_(b.0, b.1, b.2, LANE as i64, a as _) } /// Load multiple 3-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] +#[cfg_attr(test, assert_instr(vld3, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vld3_lane_s16(a: *const i16, b: int16x4x3_t) -> int16x4x3_t { static_assert_imm2!(LANE); @@ -8691,15 +9365,16 @@ pub unsafe fn vld3_lane_s16(a: *const i16, b: int16x4x3_t) -> i #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3lane.v4i16.p0i8")] fn vld3_lane_s16_(ptr: *const i8, a: int16x4_t, b: int16x4_t, c: int16x4_t, n: i32, size: i32) -> int16x4x3_t; } -vld3_lane_s16_(a.cast(), b.0, b.1, b.2, LANE, 2) +vld3_lane_s16_(a as _, b.0, b.1, b.2, LANE, 2) } /// Load multiple 3-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] +#[cfg_attr(test, assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3_lane_s16(a: *const i16, b: int16x4x3_t) -> int16x4x3_t { static_assert_imm2!(LANE); #[allow(improper_ctypes)] @@ -8707,14 +9382,14 @@ pub unsafe fn vld3_lane_s16(a: *const i16, b: int16x4x3_t) -> i #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3lane.v4i16.p0i8")] fn vld3_lane_s16_(a: int16x4_t, b: int16x4_t, c: int16x4_t, n: i64, ptr: *const i8) -> int16x4x3_t; } -vld3_lane_s16_(b.0, b.1, b.2, LANE as i64, a.cast()) +vld3_lane_s16_(b.0, b.1, b.2, LANE as i64, a as _) } /// Load multiple 3-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] +#[cfg_attr(test, assert_instr(vld3, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vld3_lane_s32(a: *const i32, b: int32x2x3_t) -> int32x2x3_t { static_assert_imm1!(LANE); @@ -8723,15 +9398,16 @@ pub unsafe fn vld3_lane_s32(a: *const i32, b: int32x2x3_t) -> i #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3lane.v2i32.p0i8")] fn vld3_lane_s32_(ptr: *const i8, a: int32x2_t, b: int32x2_t, c: int32x2_t, n: i32, size: i32) -> int32x2x3_t; } -vld3_lane_s32_(a.cast(), b.0, b.1, b.2, LANE, 4) +vld3_lane_s32_(a as _, b.0, b.1, b.2, LANE, 4) } /// Load multiple 3-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] +#[cfg_attr(test, assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3_lane_s32(a: *const i32, b: int32x2x3_t) -> int32x2x3_t { static_assert_imm1!(LANE); #[allow(improper_ctypes)] @@ -8739,14 +9415,14 @@ pub unsafe fn vld3_lane_s32(a: *const i32, b: int32x2x3_t) -> i #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3lane.v2i32.p0i8")] fn vld3_lane_s32_(a: int32x2_t, b: int32x2_t, c: int32x2_t, n: i64, ptr: *const i8) -> int32x2x3_t; } -vld3_lane_s32_(b.0, b.1, b.2, LANE as i64, a.cast()) +vld3_lane_s32_(b.0, b.1, b.2, LANE as i64, a as _) } /// Load multiple 3-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] +#[cfg_attr(test, assert_instr(vld3, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vld3q_lane_s16(a: *const i16, b: int16x8x3_t) -> int16x8x3_t { static_assert_imm3!(LANE); @@ -8755,15 +9431,16 @@ pub unsafe fn vld3q_lane_s16(a: *const i16, b: int16x8x3_t) -> #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3lane.v8i16.p0i8")] fn vld3q_lane_s16_(ptr: *const i8, a: int16x8_t, b: int16x8_t, c: int16x8_t, n: i32, size: i32) -> int16x8x3_t; } -vld3q_lane_s16_(a.cast(), b.0, b.1, b.2, LANE, 2) +vld3q_lane_s16_(a as _, b.0, b.1, b.2, LANE, 2) } /// Load multiple 3-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] +#[cfg_attr(test, assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_lane_s16(a: *const i16, b: int16x8x3_t) -> int16x8x3_t { static_assert_imm3!(LANE); #[allow(improper_ctypes)] @@ -8771,14 +9448,14 @@ pub unsafe fn vld3q_lane_s16(a: *const i16, b: int16x8x3_t) -> #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3lane.v8i16.p0i8")] fn vld3q_lane_s16_(a: int16x8_t, b: int16x8_t, c: int16x8_t, n: i64, ptr: *const i8) -> int16x8x3_t; } -vld3q_lane_s16_(b.0, b.1, b.2, LANE as i64, a.cast()) +vld3q_lane_s16_(b.0, b.1, b.2, LANE as i64, a as _) } /// Load multiple 3-element structures to two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] +#[cfg_attr(test, assert_instr(vld3, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vld3q_lane_s32(a: *const i32, b: int32x4x3_t) -> int32x4x3_t { static_assert_imm2!(LANE); @@ -8787,15 +9464,16 @@ pub unsafe fn vld3q_lane_s32(a: *const i32, b: int32x4x3_t) -> #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3lane.v4i32.p0i8")] fn vld3q_lane_s32_(ptr: *const i8, a: int32x4_t, b: int32x4_t, c: int32x4_t, n: i32, size: i32) -> int32x4x3_t; } -vld3q_lane_s32_(a.cast(), b.0, b.1, b.2, LANE, 4) +vld3q_lane_s32_(a as _, b.0, b.1, b.2, LANE, 4) } /// Load multiple 3-element structures to two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] +#[cfg_attr(test, assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_lane_s32(a: *const i32, b: int32x4x3_t) -> int32x4x3_t { static_assert_imm2!(LANE); #[allow(improper_ctypes)] @@ -8803,7 +9481,7 @@ pub unsafe fn vld3q_lane_s32(a: *const i32, b: int32x4x3_t) -> #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3lane.v4i32.p0i8")] fn vld3q_lane_s32_(a: int32x4_t, b: int32x4_t, c: int32x4_t, n: i64, ptr: *const i8) -> int32x4x3_t; } -vld3q_lane_s32_(b.0, b.1, b.2, LANE as i64, a.cast()) +vld3q_lane_s32_(b.0, b.1, b.2, LANE as i64, a as _) } /// Load multiple 3-element structures to three registers @@ -8813,6 +9491,7 @@ vld3q_lane_s32_(b.0, b.1, b.2, LANE as i64, a.cast()) #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3_lane_u8(a: *const u8, b: uint8x8x3_t) -> uint8x8x3_t { static_assert_imm3!(LANE); transmute(vld3_lane_s8::(transmute(a), transmute(b))) @@ -8825,6 +9504,7 @@ pub unsafe fn vld3_lane_u8(a: *const u8, b: uint8x8x3_t) -> uin #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3_lane_u16(a: *const u16, b: uint16x4x3_t) -> uint16x4x3_t { static_assert_imm2!(LANE); transmute(vld3_lane_s16::(transmute(a), transmute(b))) @@ -8837,6 +9517,7 @@ pub unsafe fn vld3_lane_u16(a: *const u16, b: uint16x4x3_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3_lane_u32(a: *const u32, b: uint32x2x3_t) -> uint32x2x3_t { static_assert_imm1!(LANE); transmute(vld3_lane_s32::(transmute(a), transmute(b))) @@ -8849,6 +9530,7 @@ pub unsafe fn vld3_lane_u32(a: *const u32, b: uint32x2x3_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3q_lane_u16(a: *const u16, b: uint16x8x3_t) -> uint16x8x3_t { static_assert_imm3!(LANE); transmute(vld3q_lane_s16::(transmute(a), transmute(b))) @@ -8861,6 +9543,7 @@ pub unsafe fn vld3q_lane_u16(a: *const u16, b: uint16x8x3_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3q_lane_u32(a: *const u32, b: uint32x4x3_t) -> uint32x4x3_t { static_assert_imm2!(LANE); transmute(vld3q_lane_s32::(transmute(a), transmute(b))) @@ -8873,6 +9556,7 @@ pub unsafe fn vld3q_lane_u32(a: *const u32, b: uint32x4x3_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3_lane_p8(a: *const p8, b: poly8x8x3_t) -> poly8x8x3_t { static_assert_imm3!(LANE); transmute(vld3_lane_s8::(transmute(a), transmute(b))) @@ -8885,6 +9569,7 @@ pub unsafe fn vld3_lane_p8(a: *const p8, b: poly8x8x3_t) -> pol #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3_lane_p16(a: *const p16, b: poly16x4x3_t) -> poly16x4x3_t { static_assert_imm2!(LANE); transmute(vld3_lane_s16::(transmute(a), transmute(b))) @@ -8897,6 +9582,7 @@ pub unsafe fn vld3_lane_p16(a: *const p16, b: poly16x4x3_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld3q_lane_p16(a: *const p16, b: poly16x8x3_t) -> poly16x8x3_t { static_assert_imm3!(LANE); transmute(vld3q_lane_s16::(transmute(a), transmute(b))) @@ -8906,7 +9592,7 @@ pub unsafe fn vld3q_lane_p16(a: *const p16, b: poly16x8x3_t) -> #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] +#[cfg_attr(test, assert_instr(vld3, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vld3_lane_f32(a: *const f32, b: float32x2x3_t) -> float32x2x3_t { static_assert_imm1!(LANE); @@ -8915,15 +9601,16 @@ pub unsafe fn vld3_lane_f32(a: *const f32, b: float32x2x3_t) -> #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3lane.v2f32.p0i8")] fn vld3_lane_f32_(ptr: *const i8, a: float32x2_t, b: float32x2_t, c: float32x2_t, n: i32, size: i32) -> float32x2x3_t; } -vld3_lane_f32_(a.cast(), b.0, b.1, b.2, LANE, 4) +vld3_lane_f32_(a as _, b.0, b.1, b.2, LANE, 4) } /// Load multiple 3-element structures to three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] +#[cfg_attr(test, assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3_lane_f32(a: *const f32, b: float32x2x3_t) -> float32x2x3_t { static_assert_imm1!(LANE); #[allow(improper_ctypes)] @@ -8931,14 +9618,14 @@ pub unsafe fn vld3_lane_f32(a: *const f32, b: float32x2x3_t) -> #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3lane.v2f32.p0i8")] fn vld3_lane_f32_(a: float32x2_t, b: float32x2_t, c: float32x2_t, n: i64, ptr: *const i8) -> float32x2x3_t; } -vld3_lane_f32_(b.0, b.1, b.2, LANE as i64, a.cast()) +vld3_lane_f32_(b.0, b.1, b.2, LANE as i64, a as _) } /// Load multiple 3-element structures to three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld3, LANE = 0))] +#[cfg_attr(test, assert_instr(vld3, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vld3q_lane_f32(a: *const f32, b: float32x4x3_t) -> float32x4x3_t { static_assert_imm2!(LANE); @@ -8947,15 +9634,16 @@ pub unsafe fn vld3q_lane_f32(a: *const f32, b: float32x4x3_t) - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld3lane.v4f32.p0i8")] fn vld3q_lane_f32_(ptr: *const i8, a: float32x4_t, b: float32x4_t, c: float32x4_t, n: i32, size: i32) -> float32x4x3_t; } -vld3q_lane_f32_(a.cast(), b.0, b.1, b.2, LANE, 4) +vld3q_lane_f32_(a as _, b.0, b.1, b.2, LANE, 4) } /// Load multiple 3-element structures to three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld3, LANE = 0))] +#[cfg_attr(test, assert_instr(ld3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld3q_lane_f32(a: *const f32, b: float32x4x3_t) -> float32x4x3_t { static_assert_imm2!(LANE); #[allow(improper_ctypes)] @@ -8963,14 +9651,14 @@ pub unsafe fn vld3q_lane_f32(a: *const f32, b: float32x4x3_t) - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld3lane.v4f32.p0i8")] fn vld3q_lane_f32_(a: float32x4_t, b: float32x4_t, c: float32x4_t, n: i64, ptr: *const i8) -> float32x4x3_t; } -vld3q_lane_f32_(b.0, b.1, b.2, LANE as i64, a.cast()) +vld3q_lane_f32_(b.0, b.1, b.2, LANE as i64, a as _) } /// Load multiple 4-element structures to four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(test, assert_instr(vld4))] pub unsafe fn vld4_s8(a: *const i8) -> int8x8x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -8984,21 +9672,22 @@ vld4_s8_(a as *const i8, 1) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +#[cfg_attr(test, assert_instr(ld4))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4_s8(a: *const i8) -> int8x8x4_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4.v8i8.p0v8i8")] fn vld4_s8_(ptr: *const int8x8_t) -> int8x8x4_t; } -vld4_s8_(a.cast()) +vld4_s8_(a as _) } /// Load multiple 4-element structures to four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(test, assert_instr(vld4))] pub unsafe fn vld4_s16(a: *const i16) -> int16x4x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -9012,21 +9701,22 @@ vld4_s16_(a as *const i8, 2) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +#[cfg_attr(test, assert_instr(ld4))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4_s16(a: *const i16) -> int16x4x4_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4.v4i16.p0v4i16")] fn vld4_s16_(ptr: *const int16x4_t) -> int16x4x4_t; } -vld4_s16_(a.cast()) +vld4_s16_(a as _) } /// Load multiple 4-element structures to four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(test, assert_instr(vld4))] pub unsafe fn vld4_s32(a: *const i32) -> int32x2x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -9040,21 +9730,22 @@ vld4_s32_(a as *const i8, 4) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +#[cfg_attr(test, assert_instr(ld4))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4_s32(a: *const i32) -> int32x2x4_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4.v2i32.p0v2i32")] fn vld4_s32_(ptr: *const int32x2_t) -> int32x2x4_t; } -vld4_s32_(a.cast()) +vld4_s32_(a as _) } /// Load multiple 4-element structures to four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(test, assert_instr(vld4))] pub unsafe fn vld4q_s8(a: *const i8) -> int8x16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -9068,21 +9759,22 @@ vld4q_s8_(a as *const i8, 1) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +#[cfg_attr(test, assert_instr(ld4))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_s8(a: *const i8) -> int8x16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4.v16i8.p0v16i8")] fn vld4q_s8_(ptr: *const int8x16_t) -> int8x16x4_t; } -vld4q_s8_(a.cast()) +vld4q_s8_(a as _) } /// Load multiple 4-element structures to four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(test, assert_instr(vld4))] pub unsafe fn vld4q_s16(a: *const i16) -> int16x8x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -9096,21 +9788,22 @@ vld4q_s16_(a as *const i8, 2) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +#[cfg_attr(test, assert_instr(ld4))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_s16(a: *const i16) -> int16x8x4_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4.v8i16.p0v8i16")] fn vld4q_s16_(ptr: *const int16x8_t) -> int16x8x4_t; } -vld4q_s16_(a.cast()) +vld4q_s16_(a as _) } /// Load multiple 4-element structures to four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(test, assert_instr(vld4))] pub unsafe fn vld4q_s32(a: *const i32) -> int32x4x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -9124,21 +9817,22 @@ vld4q_s32_(a as *const i8, 4) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +#[cfg_attr(test, assert_instr(ld4))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_s32(a: *const i32) -> int32x4x4_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4.v4i32.p0v4i32")] fn vld4q_s32_(ptr: *const int32x4_t) -> int32x4x4_t; } -vld4q_s32_(a.cast()) +vld4q_s32_(a as _) } /// Load multiple 4-element structures to four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vld4_s64(a: *const i64) -> int64x1x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -9152,14 +9846,15 @@ vld4_s64_(a as *const i8, 8) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4_s64(a: *const i64) -> int64x1x4_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4.v1i64.p0v1i64")] fn vld4_s64_(ptr: *const int64x1_t) -> int64x1x4_t; } -vld4_s64_(a.cast()) +vld4_s64_(a as _) } /// Load multiple 4-element structures to four registers @@ -9168,6 +9863,7 @@ vld4_s64_(a.cast()) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4_u8(a: *const u8) -> uint8x8x4_t { transmute(vld4_s8(transmute(a))) } @@ -9178,6 +9874,7 @@ pub unsafe fn vld4_u8(a: *const u8) -> uint8x8x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4_u16(a: *const u16) -> uint16x4x4_t { transmute(vld4_s16(transmute(a))) } @@ -9188,6 +9885,7 @@ pub unsafe fn vld4_u16(a: *const u16) -> uint16x4x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4_u32(a: *const u32) -> uint32x2x4_t { transmute(vld4_s32(transmute(a))) } @@ -9198,6 +9896,7 @@ pub unsafe fn vld4_u32(a: *const u32) -> uint32x2x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4q_u8(a: *const u8) -> uint8x16x4_t { transmute(vld4q_s8(transmute(a))) } @@ -9208,6 +9907,7 @@ pub unsafe fn vld4q_u8(a: *const u8) -> uint8x16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4q_u16(a: *const u16) -> uint16x8x4_t { transmute(vld4q_s16(transmute(a))) } @@ -9218,6 +9918,7 @@ pub unsafe fn vld4q_u16(a: *const u16) -> uint16x8x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4q_u32(a: *const u32) -> uint32x4x4_t { transmute(vld4q_s32(transmute(a))) } @@ -9228,6 +9929,7 @@ pub unsafe fn vld4q_u32(a: *const u32) -> uint32x4x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4_p8(a: *const p8) -> poly8x8x4_t { transmute(vld4_s8(transmute(a))) } @@ -9238,6 +9940,7 @@ pub unsafe fn vld4_p8(a: *const p8) -> poly8x8x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4_p16(a: *const p16) -> poly16x4x4_t { transmute(vld4_s16(transmute(a))) } @@ -9248,6 +9951,7 @@ pub unsafe fn vld4_p16(a: *const p16) -> poly16x4x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4q_p8(a: *const p8) -> poly8x16x4_t { transmute(vld4q_s8(transmute(a))) } @@ -9258,6 +9962,7 @@ pub unsafe fn vld4q_p8(a: *const p8) -> poly8x16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4q_p16(a: *const p16) -> poly16x8x4_t { transmute(vld4q_s16(transmute(a))) } @@ -9268,6 +9973,7 @@ pub unsafe fn vld4q_p16(a: *const p16) -> poly16x8x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4_u64(a: *const u64) -> uint64x1x4_t { transmute(vld4_s64(transmute(a))) } @@ -9278,6 +9984,7 @@ pub unsafe fn vld4_u64(a: *const u64) -> uint64x1x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4_p64(a: *const p64) -> poly64x1x4_t { transmute(vld4_s64(transmute(a))) } @@ -9286,7 +9993,7 @@ pub unsafe fn vld4_p64(a: *const p64) -> poly64x1x4_t { #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(test, assert_instr(vld4))] pub unsafe fn vld4_f32(a: *const f32) -> float32x2x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -9300,21 +10007,22 @@ vld4_f32_(a as *const i8, 4) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +#[cfg_attr(test, assert_instr(ld4))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4_f32(a: *const f32) -> float32x2x4_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4.v2f32.p0v2f32")] fn vld4_f32_(ptr: *const float32x2_t) -> float32x2x4_t; } -vld4_f32_(a.cast()) +vld4_f32_(a as _) } /// Load multiple 4-element structures to four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(test, assert_instr(vld4))] pub unsafe fn vld4q_f32(a: *const f32) -> float32x4x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -9328,21 +10036,22 @@ vld4q_f32_(a as *const i8, 4) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4))] +#[cfg_attr(test, assert_instr(ld4))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_f32(a: *const f32) -> float32x4x4_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4.v4f32.p0v4f32")] fn vld4q_f32_(ptr: *const float32x4_t) -> float32x4x4_t; } -vld4q_f32_(a.cast()) +vld4q_f32_(a as _) } /// Load single 4-element structure and replicate to all lanes of four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(test, assert_instr(vld4))] pub unsafe fn vld4_dup_s8(a: *const i8) -> int8x8x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -9356,21 +10065,22 @@ vld4_dup_s8_(a as *const i8, 1) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +#[cfg_attr(test, assert_instr(ld4r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4_dup_s8(a: *const i8) -> int8x8x4_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4r.v8i8.p0i8")] fn vld4_dup_s8_(ptr: *const i8) -> int8x8x4_t; } -vld4_dup_s8_(a.cast()) +vld4_dup_s8_(a as _) } /// Load single 4-element structure and replicate to all lanes of four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(test, assert_instr(vld4))] pub unsafe fn vld4_dup_s16(a: *const i16) -> int16x4x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -9384,21 +10094,22 @@ vld4_dup_s16_(a as *const i8, 2) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +#[cfg_attr(test, assert_instr(ld4r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4_dup_s16(a: *const i16) -> int16x4x4_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4r.v4i16.p0i16")] fn vld4_dup_s16_(ptr: *const i16) -> int16x4x4_t; } -vld4_dup_s16_(a.cast()) +vld4_dup_s16_(a as _) } /// Load single 4-element structure and replicate to all lanes of four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(test, assert_instr(vld4))] pub unsafe fn vld4_dup_s32(a: *const i32) -> int32x2x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -9412,21 +10123,22 @@ vld4_dup_s32_(a as *const i8, 4) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +#[cfg_attr(test, assert_instr(ld4r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4_dup_s32(a: *const i32) -> int32x2x4_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4r.v2i32.p0i32")] fn vld4_dup_s32_(ptr: *const i32) -> int32x2x4_t; } -vld4_dup_s32_(a.cast()) +vld4_dup_s32_(a as _) } /// Load single 4-element structure and replicate to all lanes of four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(test, assert_instr(vld4))] pub unsafe fn vld4q_dup_s8(a: *const i8) -> int8x16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -9440,21 +10152,22 @@ vld4q_dup_s8_(a as *const i8, 1) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +#[cfg_attr(test, assert_instr(ld4r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_dup_s8(a: *const i8) -> int8x16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4r.v16i8.p0i8")] fn vld4q_dup_s8_(ptr: *const i8) -> int8x16x4_t; } -vld4q_dup_s8_(a.cast()) +vld4q_dup_s8_(a as _) } /// Load single 4-element structure and replicate to all lanes of four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(test, assert_instr(vld4))] pub unsafe fn vld4q_dup_s16(a: *const i16) -> int16x8x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -9468,21 +10181,22 @@ vld4q_dup_s16_(a as *const i8, 2) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +#[cfg_attr(test, assert_instr(ld4r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_dup_s16(a: *const i16) -> int16x8x4_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4r.v8i16.p0i16")] fn vld4q_dup_s16_(ptr: *const i16) -> int16x8x4_t; } -vld4q_dup_s16_(a.cast()) +vld4q_dup_s16_(a as _) } /// Load single 4-element structure and replicate to all lanes of four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(test, assert_instr(vld4))] pub unsafe fn vld4q_dup_s32(a: *const i32) -> int32x4x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -9496,21 +10210,22 @@ vld4q_dup_s32_(a as *const i8, 4) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +#[cfg_attr(test, assert_instr(ld4r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_dup_s32(a: *const i32) -> int32x4x4_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4r.v4i32.p0i32")] fn vld4q_dup_s32_(ptr: *const i32) -> int32x4x4_t; } -vld4q_dup_s32_(a.cast()) +vld4q_dup_s32_(a as _) } /// Load single 4-element structure and replicate to all lanes of four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vld4_dup_s64(a: *const i64) -> int64x1x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -9524,14 +10239,15 @@ vld4_dup_s64_(a as *const i8, 8) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +#[cfg_attr(test, assert_instr(ld4r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4_dup_s64(a: *const i64) -> int64x1x4_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4r.v1i64.p0i64")] fn vld4_dup_s64_(ptr: *const i64) -> int64x1x4_t; } -vld4_dup_s64_(a.cast()) +vld4_dup_s64_(a as _) } /// Load single 4-element structure and replicate to all lanes of four registers @@ -9540,6 +10256,7 @@ vld4_dup_s64_(a.cast()) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4_dup_u8(a: *const u8) -> uint8x8x4_t { transmute(vld4_dup_s8(transmute(a))) } @@ -9550,6 +10267,7 @@ pub unsafe fn vld4_dup_u8(a: *const u8) -> uint8x8x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4_dup_u16(a: *const u16) -> uint16x4x4_t { transmute(vld4_dup_s16(transmute(a))) } @@ -9560,6 +10278,7 @@ pub unsafe fn vld4_dup_u16(a: *const u16) -> uint16x4x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4_dup_u32(a: *const u32) -> uint32x2x4_t { transmute(vld4_dup_s32(transmute(a))) } @@ -9570,6 +10289,7 @@ pub unsafe fn vld4_dup_u32(a: *const u32) -> uint32x2x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4q_dup_u8(a: *const u8) -> uint8x16x4_t { transmute(vld4q_dup_s8(transmute(a))) } @@ -9580,6 +10300,7 @@ pub unsafe fn vld4q_dup_u8(a: *const u8) -> uint8x16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4q_dup_u16(a: *const u16) -> uint16x8x4_t { transmute(vld4q_dup_s16(transmute(a))) } @@ -9590,6 +10311,7 @@ pub unsafe fn vld4q_dup_u16(a: *const u16) -> uint16x8x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4q_dup_u32(a: *const u32) -> uint32x4x4_t { transmute(vld4q_dup_s32(transmute(a))) } @@ -9600,6 +10322,7 @@ pub unsafe fn vld4q_dup_u32(a: *const u32) -> uint32x4x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4_dup_p8(a: *const p8) -> poly8x8x4_t { transmute(vld4_dup_s8(transmute(a))) } @@ -9610,6 +10333,7 @@ pub unsafe fn vld4_dup_p8(a: *const p8) -> poly8x8x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4_dup_p16(a: *const p16) -> poly16x4x4_t { transmute(vld4_dup_s16(transmute(a))) } @@ -9620,6 +10344,7 @@ pub unsafe fn vld4_dup_p16(a: *const p16) -> poly16x4x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4q_dup_p8(a: *const p8) -> poly8x16x4_t { transmute(vld4q_dup_s8(transmute(a))) } @@ -9630,6 +10355,7 @@ pub unsafe fn vld4q_dup_p8(a: *const p8) -> poly8x16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4q_dup_p16(a: *const p16) -> poly16x8x4_t { transmute(vld4q_dup_s16(transmute(a))) } @@ -9640,6 +10366,7 @@ pub unsafe fn vld4q_dup_p16(a: *const p16) -> poly16x8x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4_dup_u64(a: *const u64) -> uint64x1x4_t { transmute(vld4_dup_s64(transmute(a))) } @@ -9650,6 +10377,7 @@ pub unsafe fn vld4_dup_u64(a: *const u64) -> uint64x1x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4_dup_p64(a: *const p64) -> poly64x1x4_t { transmute(vld4_dup_s64(transmute(a))) } @@ -9658,7 +10386,7 @@ pub unsafe fn vld4_dup_p64(a: *const p64) -> poly64x1x4_t { #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(test, assert_instr(vld4))] pub unsafe fn vld4_dup_f32(a: *const f32) -> float32x2x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -9672,21 +10400,22 @@ vld4_dup_f32_(a as *const i8, 4) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +#[cfg_attr(test, assert_instr(ld4r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4_dup_f32(a: *const f32) -> float32x2x4_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4r.v2f32.p0f32")] fn vld4_dup_f32_(ptr: *const f32) -> float32x2x4_t; } -vld4_dup_f32_(a.cast()) +vld4_dup_f32_(a as _) } /// Load single 4-element structure and replicate to all lanes of four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4))] +#[cfg_attr(test, assert_instr(vld4))] pub unsafe fn vld4q_dup_f32(a: *const f32) -> float32x4x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -9700,21 +10429,22 @@ vld4q_dup_f32_(a as *const i8, 4) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4r))] +#[cfg_attr(test, assert_instr(ld4r))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_dup_f32(a: *const f32) -> float32x4x4_t { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4r.v4f32.p0f32")] fn vld4q_dup_f32_(ptr: *const f32) -> float32x4x4_t; } -vld4q_dup_f32_(a.cast()) +vld4q_dup_f32_(a as _) } /// Load multiple 4-element structures to four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] +#[cfg_attr(test, assert_instr(vld4, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vld4_lane_s8(a: *const i8, b: int8x8x4_t) -> int8x8x4_t { static_assert_imm3!(LANE); @@ -9723,15 +10453,16 @@ pub unsafe fn vld4_lane_s8(a: *const i8, b: int8x8x4_t) -> int8 #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4lane.v8i8.p0i8")] fn vld4_lane_s8_(ptr: *const i8, a: int8x8_t, b: int8x8_t, c: int8x8_t, d: int8x8_t, n: i32, size: i32) -> int8x8x4_t; } -vld4_lane_s8_(a.cast(), b.0, b.1, b.2, b.3, LANE, 1) +vld4_lane_s8_(a as _, b.0, b.1, b.2, b.3, LANE, 1) } /// Load multiple 4-element structures to four registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] +#[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4_lane_s8(a: *const i8, b: int8x8x4_t) -> int8x8x4_t { static_assert_imm3!(LANE); #[allow(improper_ctypes)] @@ -9739,14 +10470,14 @@ pub unsafe fn vld4_lane_s8(a: *const i8, b: int8x8x4_t) -> int8 #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4lane.v8i8.p0i8")] fn vld4_lane_s8_(a: int8x8_t, b: int8x8_t, c: int8x8_t, d: int8x8_t, n: i64, ptr: *const i8) -> int8x8x4_t; } -vld4_lane_s8_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) +vld4_lane_s8_(b.0, b.1, b.2, b.3, LANE as i64, a as _) } /// Load multiple 4-element structures to four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] +#[cfg_attr(test, assert_instr(vld4, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vld4_lane_s16(a: *const i16, b: int16x4x4_t) -> int16x4x4_t { static_assert_imm2!(LANE); @@ -9755,15 +10486,16 @@ pub unsafe fn vld4_lane_s16(a: *const i16, b: int16x4x4_t) -> i #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4lane.v4i16.p0i8")] fn vld4_lane_s16_(ptr: *const i8, a: int16x4_t, b: int16x4_t, c: int16x4_t, d: int16x4_t, n: i32, size: i32) -> int16x4x4_t; } -vld4_lane_s16_(a.cast(), b.0, b.1, b.2, b.3, LANE, 2) +vld4_lane_s16_(a as _, b.0, b.1, b.2, b.3, LANE, 2) } /// Load multiple 4-element structures to four registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] +#[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4_lane_s16(a: *const i16, b: int16x4x4_t) -> int16x4x4_t { static_assert_imm2!(LANE); #[allow(improper_ctypes)] @@ -9771,14 +10503,14 @@ pub unsafe fn vld4_lane_s16(a: *const i16, b: int16x4x4_t) -> i #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4lane.v4i16.p0i8")] fn vld4_lane_s16_(a: int16x4_t, b: int16x4_t, c: int16x4_t, d: int16x4_t, n: i64, ptr: *const i8) -> int16x4x4_t; } -vld4_lane_s16_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) +vld4_lane_s16_(b.0, b.1, b.2, b.3, LANE as i64, a as _) } /// Load multiple 4-element structures to four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] +#[cfg_attr(test, assert_instr(vld4, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vld4_lane_s32(a: *const i32, b: int32x2x4_t) -> int32x2x4_t { static_assert_imm1!(LANE); @@ -9787,15 +10519,16 @@ pub unsafe fn vld4_lane_s32(a: *const i32, b: int32x2x4_t) -> i #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4lane.v2i32.p0i8")] fn vld4_lane_s32_(ptr: *const i8, a: int32x2_t, b: int32x2_t, c: int32x2_t, d: int32x2_t, n: i32, size: i32) -> int32x2x4_t; } -vld4_lane_s32_(a.cast(), b.0, b.1, b.2, b.3, LANE, 4) +vld4_lane_s32_(a as _, b.0, b.1, b.2, b.3, LANE, 4) } /// Load multiple 4-element structures to four registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] +#[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4_lane_s32(a: *const i32, b: int32x2x4_t) -> int32x2x4_t { static_assert_imm1!(LANE); #[allow(improper_ctypes)] @@ -9803,14 +10536,14 @@ pub unsafe fn vld4_lane_s32(a: *const i32, b: int32x2x4_t) -> i #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4lane.v2i32.p0i8")] fn vld4_lane_s32_(a: int32x2_t, b: int32x2_t, c: int32x2_t, d: int32x2_t, n: i64, ptr: *const i8) -> int32x2x4_t; } -vld4_lane_s32_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) +vld4_lane_s32_(b.0, b.1, b.2, b.3, LANE as i64, a as _) } /// Load multiple 4-element structures to four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] +#[cfg_attr(test, assert_instr(vld4, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vld4q_lane_s16(a: *const i16, b: int16x8x4_t) -> int16x8x4_t { static_assert_imm3!(LANE); @@ -9819,15 +10552,16 @@ pub unsafe fn vld4q_lane_s16(a: *const i16, b: int16x8x4_t) -> #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4lane.v8i16.p0i8")] fn vld4q_lane_s16_(ptr: *const i8, a: int16x8_t, b: int16x8_t, c: int16x8_t, d: int16x8_t, n: i32, size: i32) -> int16x8x4_t; } -vld4q_lane_s16_(a.cast(), b.0, b.1, b.2, b.3, LANE, 2) +vld4q_lane_s16_(a as _, b.0, b.1, b.2, b.3, LANE, 2) } /// Load multiple 4-element structures to four registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] +#[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_lane_s16(a: *const i16, b: int16x8x4_t) -> int16x8x4_t { static_assert_imm3!(LANE); #[allow(improper_ctypes)] @@ -9835,14 +10569,14 @@ pub unsafe fn vld4q_lane_s16(a: *const i16, b: int16x8x4_t) -> #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4lane.v8i16.p0i8")] fn vld4q_lane_s16_(a: int16x8_t, b: int16x8_t, c: int16x8_t, d: int16x8_t, n: i64, ptr: *const i8) -> int16x8x4_t; } -vld4q_lane_s16_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) +vld4q_lane_s16_(b.0, b.1, b.2, b.3, LANE as i64, a as _) } /// Load multiple 4-element structures to four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] +#[cfg_attr(test, assert_instr(vld4, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vld4q_lane_s32(a: *const i32, b: int32x4x4_t) -> int32x4x4_t { static_assert_imm2!(LANE); @@ -9851,15 +10585,16 @@ pub unsafe fn vld4q_lane_s32(a: *const i32, b: int32x4x4_t) -> #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4lane.v4i32.p0i8")] fn vld4q_lane_s32_(ptr: *const i8, a: int32x4_t, b: int32x4_t, c: int32x4_t, d: int32x4_t, n: i32, size: i32) -> int32x4x4_t; } -vld4q_lane_s32_(a.cast(), b.0, b.1, b.2, b.3, LANE, 4) +vld4q_lane_s32_(a as _, b.0, b.1, b.2, b.3, LANE, 4) } /// Load multiple 4-element structures to four registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] +#[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_lane_s32(a: *const i32, b: int32x4x4_t) -> int32x4x4_t { static_assert_imm2!(LANE); #[allow(improper_ctypes)] @@ -9867,7 +10602,7 @@ pub unsafe fn vld4q_lane_s32(a: *const i32, b: int32x4x4_t) -> #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4lane.v4i32.p0i8")] fn vld4q_lane_s32_(a: int32x4_t, b: int32x4_t, c: int32x4_t, d: int32x4_t, n: i64, ptr: *const i8) -> int32x4x4_t; } -vld4q_lane_s32_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) +vld4q_lane_s32_(b.0, b.1, b.2, b.3, LANE as i64, a as _) } /// Load multiple 4-element structures to four registers @@ -9877,6 +10612,7 @@ vld4q_lane_s32_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4_lane_u8(a: *const u8, b: uint8x8x4_t) -> uint8x8x4_t { static_assert_imm3!(LANE); transmute(vld4_lane_s8::(transmute(a), transmute(b))) @@ -9889,6 +10625,7 @@ pub unsafe fn vld4_lane_u8(a: *const u8, b: uint8x8x4_t) -> uin #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4_lane_u16(a: *const u16, b: uint16x4x4_t) -> uint16x4x4_t { static_assert_imm2!(LANE); transmute(vld4_lane_s16::(transmute(a), transmute(b))) @@ -9901,6 +10638,7 @@ pub unsafe fn vld4_lane_u16(a: *const u16, b: uint16x4x4_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4_lane_u32(a: *const u32, b: uint32x2x4_t) -> uint32x2x4_t { static_assert_imm1!(LANE); transmute(vld4_lane_s32::(transmute(a), transmute(b))) @@ -9913,6 +10651,7 @@ pub unsafe fn vld4_lane_u32(a: *const u32, b: uint32x2x4_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4q_lane_u16(a: *const u16, b: uint16x8x4_t) -> uint16x8x4_t { static_assert_imm3!(LANE); transmute(vld4q_lane_s16::(transmute(a), transmute(b))) @@ -9925,6 +10664,7 @@ pub unsafe fn vld4q_lane_u16(a: *const u16, b: uint16x8x4_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4q_lane_u32(a: *const u32, b: uint32x4x4_t) -> uint32x4x4_t { static_assert_imm2!(LANE); transmute(vld4q_lane_s32::(transmute(a), transmute(b))) @@ -9937,6 +10677,7 @@ pub unsafe fn vld4q_lane_u32(a: *const u32, b: uint32x4x4_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4_lane_p8(a: *const p8, b: poly8x8x4_t) -> poly8x8x4_t { static_assert_imm3!(LANE); transmute(vld4_lane_s8::(transmute(a), transmute(b))) @@ -9949,6 +10690,7 @@ pub unsafe fn vld4_lane_p8(a: *const p8, b: poly8x8x4_t) -> pol #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4_lane_p16(a: *const p16, b: poly16x4x4_t) -> poly16x4x4_t { static_assert_imm2!(LANE); transmute(vld4_lane_s16::(transmute(a), transmute(b))) @@ -9961,6 +10703,7 @@ pub unsafe fn vld4_lane_p16(a: *const p16, b: poly16x4x4_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vld4q_lane_p16(a: *const p16, b: poly16x8x4_t) -> poly16x8x4_t { static_assert_imm3!(LANE); transmute(vld4q_lane_s16::(transmute(a), transmute(b))) @@ -9970,7 +10713,7 @@ pub unsafe fn vld4q_lane_p16(a: *const p16, b: poly16x8x4_t) -> #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] +#[cfg_attr(test, assert_instr(vld4, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vld4_lane_f32(a: *const f32, b: float32x2x4_t) -> float32x2x4_t { static_assert_imm1!(LANE); @@ -9979,15 +10722,16 @@ pub unsafe fn vld4_lane_f32(a: *const f32, b: float32x2x4_t) -> #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4lane.v2f32.p0i8")] fn vld4_lane_f32_(ptr: *const i8, a: float32x2_t, b: float32x2_t, c: float32x2_t, d: float32x2_t, n: i32, size: i32) -> float32x2x4_t; } -vld4_lane_f32_(a.cast(), b.0, b.1, b.2, b.3, LANE, 4) +vld4_lane_f32_(a as _, b.0, b.1, b.2, b.3, LANE, 4) } /// Load multiple 4-element structures to four registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] +#[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4_lane_f32(a: *const f32, b: float32x2x4_t) -> float32x2x4_t { static_assert_imm1!(LANE); #[allow(improper_ctypes)] @@ -9995,14 +10739,14 @@ pub unsafe fn vld4_lane_f32(a: *const f32, b: float32x2x4_t) -> #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4lane.v2f32.p0i8")] fn vld4_lane_f32_(a: float32x2_t, b: float32x2_t, c: float32x2_t, d: float32x2_t, n: i64, ptr: *const i8) -> float32x2x4_t; } -vld4_lane_f32_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) +vld4_lane_f32_(b.0, b.1, b.2, b.3, LANE as i64, a as _) } /// Load multiple 4-element structures to four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vld4, LANE = 0))] +#[cfg_attr(test, assert_instr(vld4, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vld4q_lane_f32(a: *const f32, b: float32x4x4_t) -> float32x4x4_t { static_assert_imm2!(LANE); @@ -10011,15 +10755,16 @@ pub unsafe fn vld4q_lane_f32(a: *const f32, b: float32x4x4_t) - #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld4lane.v4f32.p0i8")] fn vld4q_lane_f32_(ptr: *const i8, a: float32x4_t, b: float32x4_t, c: float32x4_t, d: float32x4_t, n: i32, size: i32) -> float32x4x4_t; } -vld4q_lane_f32_(a.cast(), b.0, b.1, b.2, b.3, LANE, 4) +vld4q_lane_f32_(a as _, b.0, b.1, b.2, b.3, LANE, 4) } /// Load multiple 4-element structures to four registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld4, LANE = 0))] +#[cfg_attr(test, assert_instr(ld4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld4q_lane_f32(a: *const f32, b: float32x4x4_t) -> float32x4x4_t { static_assert_imm2!(LANE); #[allow(improper_ctypes)] @@ -10027,7 +10772,7 @@ pub unsafe fn vld4q_lane_f32(a: *const f32, b: float32x4x4_t) - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld4lane.v4f32.p0i8")] fn vld4q_lane_f32_(a: float32x4_t, b: float32x4_t, c: float32x4_t, d: float32x4_t, n: i64, ptr: *const i8) -> float32x4x4_t; } -vld4q_lane_f32_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) +vld4q_lane_f32_(b.0, b.1, b.2, b.3, LANE as i64, a as _) } /// Store multiple single-element structures from one, two, three, or four registers @@ -10037,6 +10782,7 @@ vld4q_lane_f32_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_lane_s8(a: *mut i8, b: int8x8_t) { static_assert_imm3!(LANE); *a = simd_extract(b, LANE as u32); @@ -10049,6 +10795,7 @@ pub unsafe fn vst1_lane_s8(a: *mut i8, b: int8x8_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_lane_s16(a: *mut i16, b: int16x4_t) { static_assert_imm2!(LANE); *a = simd_extract(b, LANE as u32); @@ -10061,6 +10808,7 @@ pub unsafe fn vst1_lane_s16(a: *mut i16, b: int16x4_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_lane_s32(a: *mut i32, b: int32x2_t) { static_assert_imm1!(LANE); *a = simd_extract(b, LANE as u32); @@ -10073,6 +10821,7 @@ pub unsafe fn vst1_lane_s32(a: *mut i32, b: int32x2_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_lane_s64(a: *mut i64, b: int64x1_t) { static_assert!(LANE : i32 where LANE == 0); *a = simd_extract(b, LANE as u32); @@ -10085,6 +10834,7 @@ pub unsafe fn vst1_lane_s64(a: *mut i64, b: int64x1_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_lane_s8(a: *mut i8, b: int8x16_t) { static_assert_imm4!(LANE); *a = simd_extract(b, LANE as u32); @@ -10097,6 +10847,7 @@ pub unsafe fn vst1q_lane_s8(a: *mut i8, b: int8x16_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_lane_s16(a: *mut i16, b: int16x8_t) { static_assert_imm3!(LANE); *a = simd_extract(b, LANE as u32); @@ -10109,6 +10860,7 @@ pub unsafe fn vst1q_lane_s16(a: *mut i16, b: int16x8_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_lane_s32(a: *mut i32, b: int32x4_t) { static_assert_imm2!(LANE); *a = simd_extract(b, LANE as u32); @@ -10121,6 +10873,7 @@ pub unsafe fn vst1q_lane_s32(a: *mut i32, b: int32x4_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_lane_s64(a: *mut i64, b: int64x2_t) { static_assert_imm1!(LANE); *a = simd_extract(b, LANE as u32); @@ -10133,6 +10886,7 @@ pub unsafe fn vst1q_lane_s64(a: *mut i64, b: int64x2_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_lane_u8(a: *mut u8, b: uint8x8_t) { static_assert_imm3!(LANE); *a = simd_extract(b, LANE as u32); @@ -10145,6 +10899,7 @@ pub unsafe fn vst1_lane_u8(a: *mut u8, b: uint8x8_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_lane_u16(a: *mut u16, b: uint16x4_t) { static_assert_imm2!(LANE); *a = simd_extract(b, LANE as u32); @@ -10157,6 +10912,7 @@ pub unsafe fn vst1_lane_u16(a: *mut u16, b: uint16x4_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_lane_u32(a: *mut u32, b: uint32x2_t) { static_assert_imm1!(LANE); *a = simd_extract(b, LANE as u32); @@ -10169,6 +10925,7 @@ pub unsafe fn vst1_lane_u32(a: *mut u32, b: uint32x2_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_lane_u64(a: *mut u64, b: uint64x1_t) { static_assert!(LANE : i32 where LANE == 0); *a = simd_extract(b, LANE as u32); @@ -10181,6 +10938,7 @@ pub unsafe fn vst1_lane_u64(a: *mut u64, b: uint64x1_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_lane_u8(a: *mut u8, b: uint8x16_t) { static_assert_imm4!(LANE); *a = simd_extract(b, LANE as u32); @@ -10193,6 +10951,7 @@ pub unsafe fn vst1q_lane_u8(a: *mut u8, b: uint8x16_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_lane_u16(a: *mut u16, b: uint16x8_t) { static_assert_imm3!(LANE); *a = simd_extract(b, LANE as u32); @@ -10205,6 +10964,7 @@ pub unsafe fn vst1q_lane_u16(a: *mut u16, b: uint16x8_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_lane_u32(a: *mut u32, b: uint32x4_t) { static_assert_imm2!(LANE); *a = simd_extract(b, LANE as u32); @@ -10217,6 +10977,7 @@ pub unsafe fn vst1q_lane_u32(a: *mut u32, b: uint32x4_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_lane_u64(a: *mut u64, b: uint64x2_t) { static_assert_imm1!(LANE); *a = simd_extract(b, LANE as u32); @@ -10229,6 +10990,7 @@ pub unsafe fn vst1q_lane_u64(a: *mut u64, b: uint64x2_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_lane_p8(a: *mut p8, b: poly8x8_t) { static_assert_imm3!(LANE); *a = simd_extract(b, LANE as u32); @@ -10241,6 +11003,7 @@ pub unsafe fn vst1_lane_p8(a: *mut p8, b: poly8x8_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_lane_p16(a: *mut p16, b: poly16x4_t) { static_assert_imm2!(LANE); *a = simd_extract(b, LANE as u32); @@ -10253,6 +11016,7 @@ pub unsafe fn vst1_lane_p16(a: *mut p16, b: poly16x4_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_lane_p8(a: *mut p8, b: poly8x16_t) { static_assert_imm4!(LANE); *a = simd_extract(b, LANE as u32); @@ -10265,6 +11029,7 @@ pub unsafe fn vst1q_lane_p8(a: *mut p8, b: poly8x16_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_lane_p16(a: *mut p16, b: poly16x8_t) { static_assert_imm3!(LANE); *a = simd_extract(b, LANE as u32); @@ -10277,6 +11042,7 @@ pub unsafe fn vst1q_lane_p16(a: *mut p16, b: poly16x8_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_lane_p64(a: *mut p64, b: poly64x1_t) { static_assert!(LANE : i32 where LANE == 0); *a = simd_extract(b, LANE as u32); @@ -10289,6 +11055,7 @@ pub unsafe fn vst1_lane_p64(a: *mut p64, b: poly64x1_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_lane_p64(a: *mut p64, b: poly64x2_t) { static_assert_imm1!(LANE); *a = simd_extract(b, LANE as u32); @@ -10301,6 +11068,7 @@ pub unsafe fn vst1q_lane_p64(a: *mut p64, b: poly64x2_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_lane_f32(a: *mut f32, b: float32x2_t) { static_assert_imm1!(LANE); *a = simd_extract(b, LANE as u32); @@ -10313,6 +11081,7 @@ pub unsafe fn vst1_lane_f32(a: *mut f32, b: float32x2_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_lane_f32(a: *mut f32, b: float32x4_t) { static_assert_imm2!(LANE); *a = simd_extract(b, LANE as u32); @@ -10322,7 +11091,7 @@ pub unsafe fn vst1q_lane_f32(a: *mut f32, b: float32x4_t) { #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1_s8_x2(a: *mut i8, b: int8x8x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10336,7 +11105,8 @@ vst1_s8_x2_(a, b.0, b.1) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_s8_x2(a: *mut i8, b: int8x8x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10350,7 +11120,7 @@ vst1_s8_x2_(b.0, b.1, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1_s16_x2(a: *mut i16, b: int16x4x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10364,7 +11134,8 @@ vst1_s16_x2_(a, b.0, b.1) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_s16_x2(a: *mut i16, b: int16x4x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10378,7 +11149,7 @@ vst1_s16_x2_(b.0, b.1, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1_s32_x2(a: *mut i32, b: int32x2x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10392,7 +11163,8 @@ vst1_s32_x2_(a, b.0, b.1) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_s32_x2(a: *mut i32, b: int32x2x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10406,7 +11178,7 @@ vst1_s32_x2_(b.0, b.1, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1_s64_x2(a: *mut i64, b: int64x1x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10420,7 +11192,8 @@ vst1_s64_x2_(a, b.0, b.1) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_s64_x2(a: *mut i64, b: int64x1x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10434,7 +11207,7 @@ vst1_s64_x2_(b.0, b.1, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1q_s8_x2(a: *mut i8, b: int8x16x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10448,7 +11221,8 @@ vst1q_s8_x2_(a, b.0, b.1) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_s8_x2(a: *mut i8, b: int8x16x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10462,7 +11236,7 @@ vst1q_s8_x2_(b.0, b.1, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1q_s16_x2(a: *mut i16, b: int16x8x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10476,7 +11250,8 @@ vst1q_s16_x2_(a, b.0, b.1) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_s16_x2(a: *mut i16, b: int16x8x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10490,7 +11265,7 @@ vst1q_s16_x2_(b.0, b.1, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1q_s32_x2(a: *mut i32, b: int32x4x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10504,7 +11279,8 @@ vst1q_s32_x2_(a, b.0, b.1) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_s32_x2(a: *mut i32, b: int32x4x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10518,7 +11294,7 @@ vst1q_s32_x2_(b.0, b.1, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1q_s64_x2(a: *mut i64, b: int64x2x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10532,7 +11308,8 @@ vst1q_s64_x2_(a, b.0, b.1) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_s64_x2(a: *mut i64, b: int64x2x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10546,7 +11323,7 @@ vst1q_s64_x2_(b.0, b.1, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1_s8_x3(a: *mut i8, b: int8x8x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10560,7 +11337,8 @@ vst1_s8_x3_(a, b.0, b.1, b.2) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_s8_x3(a: *mut i8, b: int8x8x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10574,7 +11352,7 @@ vst1_s8_x3_(b.0, b.1, b.2, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1_s16_x3(a: *mut i16, b: int16x4x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10588,7 +11366,8 @@ vst1_s16_x3_(a, b.0, b.1, b.2) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_s16_x3(a: *mut i16, b: int16x4x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10602,7 +11381,7 @@ vst1_s16_x3_(b.0, b.1, b.2, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1_s32_x3(a: *mut i32, b: int32x2x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10616,7 +11395,8 @@ vst1_s32_x3_(a, b.0, b.1, b.2) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_s32_x3(a: *mut i32, b: int32x2x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10630,7 +11410,7 @@ vst1_s32_x3_(b.0, b.1, b.2, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1_s64_x3(a: *mut i64, b: int64x1x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10644,7 +11424,8 @@ vst1_s64_x3_(a, b.0, b.1, b.2) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_s64_x3(a: *mut i64, b: int64x1x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10658,7 +11439,7 @@ vst1_s64_x3_(b.0, b.1, b.2, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1q_s8_x3(a: *mut i8, b: int8x16x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10672,7 +11453,8 @@ vst1q_s8_x3_(a, b.0, b.1, b.2) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_s8_x3(a: *mut i8, b: int8x16x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10686,7 +11468,7 @@ vst1q_s8_x3_(b.0, b.1, b.2, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1q_s16_x3(a: *mut i16, b: int16x8x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10700,7 +11482,8 @@ vst1q_s16_x3_(a, b.0, b.1, b.2) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_s16_x3(a: *mut i16, b: int16x8x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10714,7 +11497,7 @@ vst1q_s16_x3_(b.0, b.1, b.2, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1q_s32_x3(a: *mut i32, b: int32x4x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10728,7 +11511,8 @@ vst1q_s32_x3_(a, b.0, b.1, b.2) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_s32_x3(a: *mut i32, b: int32x4x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10742,7 +11526,7 @@ vst1q_s32_x3_(b.0, b.1, b.2, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1q_s64_x3(a: *mut i64, b: int64x2x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10756,7 +11540,8 @@ vst1q_s64_x3_(a, b.0, b.1, b.2) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_s64_x3(a: *mut i64, b: int64x2x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10770,7 +11555,7 @@ vst1q_s64_x3_(b.0, b.1, b.2, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1_s8_x4(a: *mut i8, b: int8x8x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10784,7 +11569,8 @@ vst1_s8_x4_(a, b.0, b.1, b.2, b.3) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_s8_x4(a: *mut i8, b: int8x8x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10798,7 +11584,7 @@ vst1_s8_x4_(b.0, b.1, b.2, b.3, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1_s16_x4(a: *mut i16, b: int16x4x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10812,7 +11598,8 @@ vst1_s16_x4_(a, b.0, b.1, b.2, b.3) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_s16_x4(a: *mut i16, b: int16x4x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10826,7 +11613,7 @@ vst1_s16_x4_(b.0, b.1, b.2, b.3, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1_s32_x4(a: *mut i32, b: int32x2x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10840,7 +11627,8 @@ vst1_s32_x4_(a, b.0, b.1, b.2, b.3) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_s32_x4(a: *mut i32, b: int32x2x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10854,7 +11642,7 @@ vst1_s32_x4_(b.0, b.1, b.2, b.3, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1_s64_x4(a: *mut i64, b: int64x1x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10868,7 +11656,8 @@ vst1_s64_x4_(a, b.0, b.1, b.2, b.3) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_s64_x4(a: *mut i64, b: int64x1x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10882,7 +11671,7 @@ vst1_s64_x4_(b.0, b.1, b.2, b.3, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1q_s8_x4(a: *mut i8, b: int8x16x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10896,7 +11685,8 @@ vst1q_s8_x4_(a, b.0, b.1, b.2, b.3) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_s8_x4(a: *mut i8, b: int8x16x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10910,7 +11700,7 @@ vst1q_s8_x4_(b.0, b.1, b.2, b.3, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1q_s16_x4(a: *mut i16, b: int16x8x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10924,7 +11714,8 @@ vst1q_s16_x4_(a, b.0, b.1, b.2, b.3) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_s16_x4(a: *mut i16, b: int16x8x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10938,7 +11729,7 @@ vst1q_s16_x4_(b.0, b.1, b.2, b.3, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1q_s32_x4(a: *mut i32, b: int32x4x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10952,7 +11743,8 @@ vst1q_s32_x4_(a, b.0, b.1, b.2, b.3) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_s32_x4(a: *mut i32, b: int32x4x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10966,7 +11758,7 @@ vst1q_s32_x4_(b.0, b.1, b.2, b.3, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1q_s64_x4(a: *mut i64, b: int64x2x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10980,7 +11772,8 @@ vst1q_s64_x4_(a, b.0, b.1, b.2, b.3) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_s64_x4(a: *mut i64, b: int64x2x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -10996,6 +11789,7 @@ vst1q_s64_x4_(b.0, b.1, b.2, b.3, a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_u8_x2(a: *mut u8, b: uint8x8x2_t) { vst1_s8_x2(transmute(a), transmute(b)) } @@ -11006,6 +11800,7 @@ pub unsafe fn vst1_u8_x2(a: *mut u8, b: uint8x8x2_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_u16_x2(a: *mut u16, b: uint16x4x2_t) { vst1_s16_x2(transmute(a), transmute(b)) } @@ -11016,6 +11811,7 @@ pub unsafe fn vst1_u16_x2(a: *mut u16, b: uint16x4x2_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_u32_x2(a: *mut u32, b: uint32x2x2_t) { vst1_s32_x2(transmute(a), transmute(b)) } @@ -11026,6 +11822,7 @@ pub unsafe fn vst1_u32_x2(a: *mut u32, b: uint32x2x2_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_u64_x2(a: *mut u64, b: uint64x1x2_t) { vst1_s64_x2(transmute(a), transmute(b)) } @@ -11036,6 +11833,7 @@ pub unsafe fn vst1_u64_x2(a: *mut u64, b: uint64x1x2_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_u8_x2(a: *mut u8, b: uint8x16x2_t) { vst1q_s8_x2(transmute(a), transmute(b)) } @@ -11046,6 +11844,7 @@ pub unsafe fn vst1q_u8_x2(a: *mut u8, b: uint8x16x2_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_u16_x2(a: *mut u16, b: uint16x8x2_t) { vst1q_s16_x2(transmute(a), transmute(b)) } @@ -11056,6 +11855,7 @@ pub unsafe fn vst1q_u16_x2(a: *mut u16, b: uint16x8x2_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_u32_x2(a: *mut u32, b: uint32x4x2_t) { vst1q_s32_x2(transmute(a), transmute(b)) } @@ -11066,6 +11866,7 @@ pub unsafe fn vst1q_u32_x2(a: *mut u32, b: uint32x4x2_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_u64_x2(a: *mut u64, b: uint64x2x2_t) { vst1q_s64_x2(transmute(a), transmute(b)) } @@ -11076,6 +11877,7 @@ pub unsafe fn vst1q_u64_x2(a: *mut u64, b: uint64x2x2_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_u8_x3(a: *mut u8, b: uint8x8x3_t) { vst1_s8_x3(transmute(a), transmute(b)) } @@ -11086,6 +11888,7 @@ pub unsafe fn vst1_u8_x3(a: *mut u8, b: uint8x8x3_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_u16_x3(a: *mut u16, b: uint16x4x3_t) { vst1_s16_x3(transmute(a), transmute(b)) } @@ -11096,6 +11899,7 @@ pub unsafe fn vst1_u16_x3(a: *mut u16, b: uint16x4x3_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_u32_x3(a: *mut u32, b: uint32x2x3_t) { vst1_s32_x3(transmute(a), transmute(b)) } @@ -11106,6 +11910,7 @@ pub unsafe fn vst1_u32_x3(a: *mut u32, b: uint32x2x3_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_u64_x3(a: *mut u64, b: uint64x1x3_t) { vst1_s64_x3(transmute(a), transmute(b)) } @@ -11116,6 +11921,7 @@ pub unsafe fn vst1_u64_x3(a: *mut u64, b: uint64x1x3_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_u8_x3(a: *mut u8, b: uint8x16x3_t) { vst1q_s8_x3(transmute(a), transmute(b)) } @@ -11126,6 +11932,7 @@ pub unsafe fn vst1q_u8_x3(a: *mut u8, b: uint8x16x3_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_u16_x3(a: *mut u16, b: uint16x8x3_t) { vst1q_s16_x3(transmute(a), transmute(b)) } @@ -11136,6 +11943,7 @@ pub unsafe fn vst1q_u16_x3(a: *mut u16, b: uint16x8x3_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_u32_x3(a: *mut u32, b: uint32x4x3_t) { vst1q_s32_x3(transmute(a), transmute(b)) } @@ -11146,6 +11954,7 @@ pub unsafe fn vst1q_u32_x3(a: *mut u32, b: uint32x4x3_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_u64_x3(a: *mut u64, b: uint64x2x3_t) { vst1q_s64_x3(transmute(a), transmute(b)) } @@ -11156,6 +11965,7 @@ pub unsafe fn vst1q_u64_x3(a: *mut u64, b: uint64x2x3_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_u8_x4(a: *mut u8, b: uint8x8x4_t) { vst1_s8_x4(transmute(a), transmute(b)) } @@ -11166,6 +11976,7 @@ pub unsafe fn vst1_u8_x4(a: *mut u8, b: uint8x8x4_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_u16_x4(a: *mut u16, b: uint16x4x4_t) { vst1_s16_x4(transmute(a), transmute(b)) } @@ -11176,6 +11987,7 @@ pub unsafe fn vst1_u16_x4(a: *mut u16, b: uint16x4x4_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_u32_x4(a: *mut u32, b: uint32x2x4_t) { vst1_s32_x4(transmute(a), transmute(b)) } @@ -11186,6 +11998,7 @@ pub unsafe fn vst1_u32_x4(a: *mut u32, b: uint32x2x4_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_u64_x4(a: *mut u64, b: uint64x1x4_t) { vst1_s64_x4(transmute(a), transmute(b)) } @@ -11196,6 +12009,7 @@ pub unsafe fn vst1_u64_x4(a: *mut u64, b: uint64x1x4_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_u8_x4(a: *mut u8, b: uint8x16x4_t) { vst1q_s8_x4(transmute(a), transmute(b)) } @@ -11206,6 +12020,7 @@ pub unsafe fn vst1q_u8_x4(a: *mut u8, b: uint8x16x4_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_u16_x4(a: *mut u16, b: uint16x8x4_t) { vst1q_s16_x4(transmute(a), transmute(b)) } @@ -11216,6 +12031,7 @@ pub unsafe fn vst1q_u16_x4(a: *mut u16, b: uint16x8x4_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_u32_x4(a: *mut u32, b: uint32x4x4_t) { vst1q_s32_x4(transmute(a), transmute(b)) } @@ -11226,6 +12042,7 @@ pub unsafe fn vst1q_u32_x4(a: *mut u32, b: uint32x4x4_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_u64_x4(a: *mut u64, b: uint64x2x4_t) { vst1q_s64_x4(transmute(a), transmute(b)) } @@ -11236,6 +12053,7 @@ pub unsafe fn vst1q_u64_x4(a: *mut u64, b: uint64x2x4_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_p8_x2(a: *mut p8, b: poly8x8x2_t) { vst1_s8_x2(transmute(a), transmute(b)) } @@ -11246,6 +12064,7 @@ pub unsafe fn vst1_p8_x2(a: *mut p8, b: poly8x8x2_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_p8_x3(a: *mut p8, b: poly8x8x3_t) { vst1_s8_x3(transmute(a), transmute(b)) } @@ -11256,6 +12075,7 @@ pub unsafe fn vst1_p8_x3(a: *mut p8, b: poly8x8x3_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_p8_x4(a: *mut p8, b: poly8x8x4_t) { vst1_s8_x4(transmute(a), transmute(b)) } @@ -11266,6 +12086,7 @@ pub unsafe fn vst1_p8_x4(a: *mut p8, b: poly8x8x4_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_p8_x2(a: *mut p8, b: poly8x16x2_t) { vst1q_s8_x2(transmute(a), transmute(b)) } @@ -11276,6 +12097,7 @@ pub unsafe fn vst1q_p8_x2(a: *mut p8, b: poly8x16x2_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_p8_x3(a: *mut p8, b: poly8x16x3_t) { vst1q_s8_x3(transmute(a), transmute(b)) } @@ -11286,6 +12108,7 @@ pub unsafe fn vst1q_p8_x3(a: *mut p8, b: poly8x16x3_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_p8_x4(a: *mut p8, b: poly8x16x4_t) { vst1q_s8_x4(transmute(a), transmute(b)) } @@ -11296,6 +12119,7 @@ pub unsafe fn vst1q_p8_x4(a: *mut p8, b: poly8x16x4_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_p16_x2(a: *mut p16, b: poly16x4x2_t) { vst1_s16_x2(transmute(a), transmute(b)) } @@ -11306,6 +12130,7 @@ pub unsafe fn vst1_p16_x2(a: *mut p16, b: poly16x4x2_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_p16_x3(a: *mut p16, b: poly16x4x3_t) { vst1_s16_x3(transmute(a), transmute(b)) } @@ -11316,6 +12141,7 @@ pub unsafe fn vst1_p16_x3(a: *mut p16, b: poly16x4x3_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_p16_x4(a: *mut p16, b: poly16x4x4_t) { vst1_s16_x4(transmute(a), transmute(b)) } @@ -11326,6 +12152,7 @@ pub unsafe fn vst1_p16_x4(a: *mut p16, b: poly16x4x4_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_p16_x2(a: *mut p16, b: poly16x8x2_t) { vst1q_s16_x2(transmute(a), transmute(b)) } @@ -11336,6 +12163,7 @@ pub unsafe fn vst1q_p16_x2(a: *mut p16, b: poly16x8x2_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_p16_x3(a: *mut p16, b: poly16x8x3_t) { vst1q_s16_x3(transmute(a), transmute(b)) } @@ -11346,6 +12174,7 @@ pub unsafe fn vst1q_p16_x3(a: *mut p16, b: poly16x8x3_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_p16_x4(a: *mut p16, b: poly16x8x4_t) { vst1q_s16_x4(transmute(a), transmute(b)) } @@ -11356,6 +12185,7 @@ pub unsafe fn vst1q_p16_x4(a: *mut p16, b: poly16x8x4_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_p64_x2(a: *mut p64, b: poly64x1x2_t) { vst1_s64_x2(transmute(a), transmute(b)) } @@ -11366,6 +12196,7 @@ pub unsafe fn vst1_p64_x2(a: *mut p64, b: poly64x1x2_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_p64_x3(a: *mut p64, b: poly64x1x3_t) { vst1_s64_x3(transmute(a), transmute(b)) } @@ -11376,6 +12207,7 @@ pub unsafe fn vst1_p64_x3(a: *mut p64, b: poly64x1x3_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1_p64_x4(a: *mut p64, b: poly64x1x4_t) { vst1_s64_x4(transmute(a), transmute(b)) } @@ -11386,6 +12218,7 @@ pub unsafe fn vst1_p64_x4(a: *mut p64, b: poly64x1x4_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_p64_x2(a: *mut p64, b: poly64x2x2_t) { vst1q_s64_x2(transmute(a), transmute(b)) } @@ -11396,6 +12229,7 @@ pub unsafe fn vst1q_p64_x2(a: *mut p64, b: poly64x2x2_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_p64_x3(a: *mut p64, b: poly64x2x3_t) { vst1q_s64_x3(transmute(a), transmute(b)) } @@ -11406,6 +12240,7 @@ pub unsafe fn vst1q_p64_x3(a: *mut p64, b: poly64x2x3_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst1q_p64_x4(a: *mut p64, b: poly64x2x4_t) { vst1q_s64_x4(transmute(a), transmute(b)) } @@ -11414,7 +12249,7 @@ pub unsafe fn vst1q_p64_x4(a: *mut p64, b: poly64x2x4_t) { #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1_f32_x2(a: *mut f32, b: float32x2x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -11428,7 +12263,8 @@ vst1_f32_x2_(a, b.0, b.1) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_f32_x2(a: *mut f32, b: float32x2x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -11442,7 +12278,7 @@ vst1_f32_x2_(b.0, b.1, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1q_f32_x2(a: *mut f32, b: float32x4x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -11456,7 +12292,8 @@ vst1q_f32_x2_(a, b.0, b.1) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_f32_x2(a: *mut f32, b: float32x4x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -11470,7 +12307,7 @@ vst1q_f32_x2_(b.0, b.1, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1_f32_x3(a: *mut f32, b: float32x2x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -11484,7 +12321,8 @@ vst1_f32_x3_(a, b.0, b.1, b.2) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_f32_x3(a: *mut f32, b: float32x2x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -11498,7 +12336,7 @@ vst1_f32_x3_(b.0, b.1, b.2, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1q_f32_x3(a: *mut f32, b: float32x4x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -11512,7 +12350,8 @@ vst1q_f32_x3_(a, b.0, b.1, b.2) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_f32_x3(a: *mut f32, b: float32x4x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -11526,7 +12365,7 @@ vst1q_f32_x3_(b.0, b.1, b.2, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1_f32_x4(a: *mut f32, b: float32x2x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -11540,7 +12379,8 @@ vst1_f32_x4_(a, b.0, b.1, b.2, b.3) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_f32_x4(a: *mut f32, b: float32x2x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -11554,7 +12394,7 @@ vst1_f32_x4_(b.0, b.1, b.2, b.3, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst1))] +#[cfg_attr(test, assert_instr(vst1))] pub unsafe fn vst1q_f32_x4(a: *mut f32, b: float32x4x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -11568,7 +12408,8 @@ vst1q_f32_x4_(a, b.0, b.1, b.2, b.3) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st1))] +#[cfg_attr(test, assert_instr(st1))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_f32_x4(a: *mut f32, b: float32x4x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { @@ -11582,196 +12423,203 @@ vst1q_f32_x4_(b.0, b.1, b.2, b.3, a) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +#[cfg_attr(test, assert_instr(vst2))] pub unsafe fn vst2_s8(a: *mut i8, b: int8x8x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2.p0i8.v8i8")] fn vst2_s8_(ptr: *mut i8, a: int8x8_t, b: int8x8_t, size: i32); } -vst2_s8_(a.cast(), b.0, b.1, 1) +vst2_s8_(a as _, b.0, b.1, 1) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +#[cfg_attr(test, assert_instr(st2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2_s8(a: *mut i8, b: int8x8x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2.v8i8.p0i8")] fn vst2_s8_(a: int8x8_t, b: int8x8_t, ptr: *mut i8); } -vst2_s8_(b.0, b.1, a.cast()) +vst2_s8_(b.0, b.1, a as _) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +#[cfg_attr(test, assert_instr(vst2))] pub unsafe fn vst2_s16(a: *mut i16, b: int16x4x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2.p0i8.v4i16")] fn vst2_s16_(ptr: *mut i8, a: int16x4_t, b: int16x4_t, size: i32); } -vst2_s16_(a.cast(), b.0, b.1, 2) +vst2_s16_(a as _, b.0, b.1, 2) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +#[cfg_attr(test, assert_instr(st2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2_s16(a: *mut i16, b: int16x4x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2.v4i16.p0i8")] fn vst2_s16_(a: int16x4_t, b: int16x4_t, ptr: *mut i8); } -vst2_s16_(b.0, b.1, a.cast()) +vst2_s16_(b.0, b.1, a as _) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +#[cfg_attr(test, assert_instr(vst2))] pub unsafe fn vst2_s32(a: *mut i32, b: int32x2x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2.p0i8.v2i32")] fn vst2_s32_(ptr: *mut i8, a: int32x2_t, b: int32x2_t, size: i32); } -vst2_s32_(a.cast(), b.0, b.1, 4) +vst2_s32_(a as _, b.0, b.1, 4) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +#[cfg_attr(test, assert_instr(st2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2_s32(a: *mut i32, b: int32x2x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2.v2i32.p0i8")] fn vst2_s32_(a: int32x2_t, b: int32x2_t, ptr: *mut i8); } -vst2_s32_(b.0, b.1, a.cast()) +vst2_s32_(b.0, b.1, a as _) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +#[cfg_attr(test, assert_instr(vst2))] pub unsafe fn vst2q_s8(a: *mut i8, b: int8x16x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2.p0i8.v16i8")] fn vst2q_s8_(ptr: *mut i8, a: int8x16_t, b: int8x16_t, size: i32); } -vst2q_s8_(a.cast(), b.0, b.1, 1) +vst2q_s8_(a as _, b.0, b.1, 1) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +#[cfg_attr(test, assert_instr(st2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2q_s8(a: *mut i8, b: int8x16x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2.v16i8.p0i8")] fn vst2q_s8_(a: int8x16_t, b: int8x16_t, ptr: *mut i8); } -vst2q_s8_(b.0, b.1, a.cast()) +vst2q_s8_(b.0, b.1, a as _) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +#[cfg_attr(test, assert_instr(vst2))] pub unsafe fn vst2q_s16(a: *mut i16, b: int16x8x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2.p0i8.v8i16")] fn vst2q_s16_(ptr: *mut i8, a: int16x8_t, b: int16x8_t, size: i32); } -vst2q_s16_(a.cast(), b.0, b.1, 2) +vst2q_s16_(a as _, b.0, b.1, 2) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +#[cfg_attr(test, assert_instr(st2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2q_s16(a: *mut i16, b: int16x8x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2.v8i16.p0i8")] fn vst2q_s16_(a: int16x8_t, b: int16x8_t, ptr: *mut i8); } -vst2q_s16_(b.0, b.1, a.cast()) +vst2q_s16_(b.0, b.1, a as _) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +#[cfg_attr(test, assert_instr(vst2))] pub unsafe fn vst2q_s32(a: *mut i32, b: int32x4x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2.p0i8.v4i32")] fn vst2q_s32_(ptr: *mut i8, a: int32x4_t, b: int32x4_t, size: i32); } -vst2q_s32_(a.cast(), b.0, b.1, 4) +vst2q_s32_(a as _, b.0, b.1, 4) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +#[cfg_attr(test, assert_instr(st2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2q_s32(a: *mut i32, b: int32x4x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2.v4i32.p0i8")] fn vst2q_s32_(a: int32x4_t, b: int32x4_t, ptr: *mut i8); } -vst2q_s32_(b.0, b.1, a.cast()) +vst2q_s32_(b.0, b.1, a as _) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vst2_s64(a: *mut i64, b: int64x1x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2.p0i8.v1i64")] fn vst2_s64_(ptr: *mut i8, a: int64x1_t, b: int64x1_t, size: i32); } -vst2_s64_(a.cast(), b.0, b.1, 8) +vst2_s64_(a as _, b.0, b.1, 8) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2_s64(a: *mut i64, b: int64x1x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2.v1i64.p0i8")] fn vst2_s64_(a: int64x1_t, b: int64x1_t, ptr: *mut i8); } -vst2_s64_(b.0, b.1, a.cast()) +vst2_s64_(b.0, b.1, a as _) } /// Store multiple 2-element structures from two registers @@ -11780,6 +12628,7 @@ vst2_s64_(b.0, b.1, a.cast()) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst2_u8(a: *mut u8, b: uint8x8x2_t) { transmute(vst2_s8(transmute(a), transmute(b))) } @@ -11790,6 +12639,7 @@ pub unsafe fn vst2_u8(a: *mut u8, b: uint8x8x2_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst2_u16(a: *mut u16, b: uint16x4x2_t) { transmute(vst2_s16(transmute(a), transmute(b))) } @@ -11800,6 +12650,7 @@ pub unsafe fn vst2_u16(a: *mut u16, b: uint16x4x2_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst2_u32(a: *mut u32, b: uint32x2x2_t) { transmute(vst2_s32(transmute(a), transmute(b))) } @@ -11810,6 +12661,7 @@ pub unsafe fn vst2_u32(a: *mut u32, b: uint32x2x2_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst2q_u8(a: *mut u8, b: uint8x16x2_t) { transmute(vst2q_s8(transmute(a), transmute(b))) } @@ -11820,6 +12672,7 @@ pub unsafe fn vst2q_u8(a: *mut u8, b: uint8x16x2_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst2q_u16(a: *mut u16, b: uint16x8x2_t) { transmute(vst2q_s16(transmute(a), transmute(b))) } @@ -11830,6 +12683,7 @@ pub unsafe fn vst2q_u16(a: *mut u16, b: uint16x8x2_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst2q_u32(a: *mut u32, b: uint32x4x2_t) { transmute(vst2q_s32(transmute(a), transmute(b))) } @@ -11840,6 +12694,7 @@ pub unsafe fn vst2q_u32(a: *mut u32, b: uint32x4x2_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst2_p8(a: *mut p8, b: poly8x8x2_t) { transmute(vst2_s8(transmute(a), transmute(b))) } @@ -11850,6 +12705,7 @@ pub unsafe fn vst2_p8(a: *mut p8, b: poly8x8x2_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst2_p16(a: *mut p16, b: poly16x4x2_t) { transmute(vst2_s16(transmute(a), transmute(b))) } @@ -11860,6 +12716,7 @@ pub unsafe fn vst2_p16(a: *mut p16, b: poly16x4x2_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst2q_p8(a: *mut p8, b: poly8x16x2_t) { transmute(vst2q_s8(transmute(a), transmute(b))) } @@ -11870,6 +12727,7 @@ pub unsafe fn vst2q_p8(a: *mut p8, b: poly8x16x2_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst2q_p16(a: *mut p16, b: poly16x8x2_t) { transmute(vst2q_s16(transmute(a), transmute(b))) } @@ -11880,6 +12738,7 @@ pub unsafe fn vst2q_p16(a: *mut p16, b: poly16x8x2_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst2_u64(a: *mut u64, b: uint64x1x2_t) { transmute(vst2_s64(transmute(a), transmute(b))) } @@ -11890,6 +12749,7 @@ pub unsafe fn vst2_u64(a: *mut u64, b: uint64x1x2_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst2_p64(a: *mut p64, b: poly64x1x2_t) { transmute(vst2_s64(transmute(a), transmute(b))) } @@ -11898,63 +12758,65 @@ pub unsafe fn vst2_p64(a: *mut p64, b: poly64x1x2_t) { #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +#[cfg_attr(test, assert_instr(vst2))] pub unsafe fn vst2_f32(a: *mut f32, b: float32x2x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2.p0i8.v2f32")] fn vst2_f32_(ptr: *mut i8, a: float32x2_t, b: float32x2_t, size: i32); } -vst2_f32_(a.cast(), b.0, b.1, 4) +vst2_f32_(a as _, b.0, b.1, 4) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +#[cfg_attr(test, assert_instr(st2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2_f32(a: *mut f32, b: float32x2x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2.v2f32.p0i8")] fn vst2_f32_(a: float32x2_t, b: float32x2_t, ptr: *mut i8); } -vst2_f32_(b.0, b.1, a.cast()) +vst2_f32_(b.0, b.1, a as _) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2))] +#[cfg_attr(test, assert_instr(vst2))] pub unsafe fn vst2q_f32(a: *mut f32, b: float32x4x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2.p0i8.v4f32")] fn vst2q_f32_(ptr: *mut i8, a: float32x4_t, b: float32x4_t, size: i32); } -vst2q_f32_(a.cast(), b.0, b.1, 4) +vst2q_f32_(a as _, b.0, b.1, 4) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2))] +#[cfg_attr(test, assert_instr(st2))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2q_f32(a: *mut f32, b: float32x4x2_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2.v4f32.p0i8")] fn vst2q_f32_(a: float32x4_t, b: float32x4_t, ptr: *mut i8); } -vst2q_f32_(b.0, b.1, a.cast()) +vst2q_f32_(b.0, b.1, a as _) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] +#[cfg_attr(test, assert_instr(vst2, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vst2_lane_s8(a: *mut i8, b: int8x8x2_t) { static_assert_imm3!(LANE); @@ -11963,15 +12825,16 @@ pub unsafe fn vst2_lane_s8(a: *mut i8, b: int8x8x2_t) { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2lane.p0i8.v8i8")] fn vst2_lane_s8_(ptr: *mut i8, a: int8x8_t, b: int8x8_t, n: i32, size: i32); } -vst2_lane_s8_(a.cast(), b.0, b.1, LANE, 1) +vst2_lane_s8_(a as _, b.0, b.1, LANE, 1) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] +#[cfg_attr(test, assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2_lane_s8(a: *mut i8, b: int8x8x2_t) { static_assert_imm3!(LANE); #[allow(improper_ctypes)] @@ -11979,14 +12842,14 @@ pub unsafe fn vst2_lane_s8(a: *mut i8, b: int8x8x2_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2lane.v8i8.p0i8")] fn vst2_lane_s8_(a: int8x8_t, b: int8x8_t, n: i64, ptr: *mut i8); } -vst2_lane_s8_(b.0, b.1, LANE as i64, a.cast()) +vst2_lane_s8_(b.0, b.1, LANE as i64, a as _) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] +#[cfg_attr(test, assert_instr(vst2, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vst2_lane_s16(a: *mut i16, b: int16x4x2_t) { static_assert_imm2!(LANE); @@ -11995,15 +12858,16 @@ pub unsafe fn vst2_lane_s16(a: *mut i16, b: int16x4x2_t) { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2lane.p0i8.v4i16")] fn vst2_lane_s16_(ptr: *mut i8, a: int16x4_t, b: int16x4_t, n: i32, size: i32); } -vst2_lane_s16_(a.cast(), b.0, b.1, LANE, 2) +vst2_lane_s16_(a as _, b.0, b.1, LANE, 2) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] +#[cfg_attr(test, assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2_lane_s16(a: *mut i16, b: int16x4x2_t) { static_assert_imm2!(LANE); #[allow(improper_ctypes)] @@ -12011,14 +12875,14 @@ pub unsafe fn vst2_lane_s16(a: *mut i16, b: int16x4x2_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2lane.v4i16.p0i8")] fn vst2_lane_s16_(a: int16x4_t, b: int16x4_t, n: i64, ptr: *mut i8); } -vst2_lane_s16_(b.0, b.1, LANE as i64, a.cast()) +vst2_lane_s16_(b.0, b.1, LANE as i64, a as _) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] +#[cfg_attr(test, assert_instr(vst2, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vst2_lane_s32(a: *mut i32, b: int32x2x2_t) { static_assert_imm1!(LANE); @@ -12027,15 +12891,16 @@ pub unsafe fn vst2_lane_s32(a: *mut i32, b: int32x2x2_t) { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2lane.p0i8.v2i32")] fn vst2_lane_s32_(ptr: *mut i8, a: int32x2_t, b: int32x2_t, n: i32, size: i32); } -vst2_lane_s32_(a.cast(), b.0, b.1, LANE, 4) +vst2_lane_s32_(a as _, b.0, b.1, LANE, 4) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] +#[cfg_attr(test, assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2_lane_s32(a: *mut i32, b: int32x2x2_t) { static_assert_imm1!(LANE); #[allow(improper_ctypes)] @@ -12043,14 +12908,14 @@ pub unsafe fn vst2_lane_s32(a: *mut i32, b: int32x2x2_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2lane.v2i32.p0i8")] fn vst2_lane_s32_(a: int32x2_t, b: int32x2_t, n: i64, ptr: *mut i8); } -vst2_lane_s32_(b.0, b.1, LANE as i64, a.cast()) +vst2_lane_s32_(b.0, b.1, LANE as i64, a as _) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] +#[cfg_attr(test, assert_instr(vst2, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vst2q_lane_s16(a: *mut i16, b: int16x8x2_t) { static_assert_imm3!(LANE); @@ -12059,15 +12924,16 @@ pub unsafe fn vst2q_lane_s16(a: *mut i16, b: int16x8x2_t) { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2lane.p0i8.v8i16")] fn vst2q_lane_s16_(ptr: *mut i8, a: int16x8_t, b: int16x8_t, n: i32, size: i32); } -vst2q_lane_s16_(a.cast(), b.0, b.1, LANE, 2) +vst2q_lane_s16_(a as _, b.0, b.1, LANE, 2) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] +#[cfg_attr(test, assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2q_lane_s16(a: *mut i16, b: int16x8x2_t) { static_assert_imm3!(LANE); #[allow(improper_ctypes)] @@ -12075,14 +12941,14 @@ pub unsafe fn vst2q_lane_s16(a: *mut i16, b: int16x8x2_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2lane.v8i16.p0i8")] fn vst2q_lane_s16_(a: int16x8_t, b: int16x8_t, n: i64, ptr: *mut i8); } -vst2q_lane_s16_(b.0, b.1, LANE as i64, a.cast()) +vst2q_lane_s16_(b.0, b.1, LANE as i64, a as _) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] +#[cfg_attr(test, assert_instr(vst2, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vst2q_lane_s32(a: *mut i32, b: int32x4x2_t) { static_assert_imm2!(LANE); @@ -12091,15 +12957,16 @@ pub unsafe fn vst2q_lane_s32(a: *mut i32, b: int32x4x2_t) { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2lane.p0i8.v4i32")] fn vst2q_lane_s32_(ptr: *mut i8, a: int32x4_t, b: int32x4_t, n: i32, size: i32); } -vst2q_lane_s32_(a.cast(), b.0, b.1, LANE, 4) +vst2q_lane_s32_(a as _, b.0, b.1, LANE, 4) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] +#[cfg_attr(test, assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2q_lane_s32(a: *mut i32, b: int32x4x2_t) { static_assert_imm2!(LANE); #[allow(improper_ctypes)] @@ -12107,7 +12974,7 @@ pub unsafe fn vst2q_lane_s32(a: *mut i32, b: int32x4x2_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2lane.v4i32.p0i8")] fn vst2q_lane_s32_(a: int32x4_t, b: int32x4_t, n: i64, ptr: *mut i8); } -vst2q_lane_s32_(b.0, b.1, LANE as i64, a.cast()) +vst2q_lane_s32_(b.0, b.1, LANE as i64, a as _) } /// Store multiple 2-element structures from two registers @@ -12117,6 +12984,7 @@ vst2q_lane_s32_(b.0, b.1, LANE as i64, a.cast()) #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst2_lane_u8(a: *mut u8, b: uint8x8x2_t) { static_assert_imm3!(LANE); transmute(vst2_lane_s8::(transmute(a), transmute(b))) @@ -12129,6 +12997,7 @@ pub unsafe fn vst2_lane_u8(a: *mut u8, b: uint8x8x2_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst2_lane_u16(a: *mut u16, b: uint16x4x2_t) { static_assert_imm2!(LANE); transmute(vst2_lane_s16::(transmute(a), transmute(b))) @@ -12141,6 +13010,7 @@ pub unsafe fn vst2_lane_u16(a: *mut u16, b: uint16x4x2_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst2_lane_u32(a: *mut u32, b: uint32x2x2_t) { static_assert_imm1!(LANE); transmute(vst2_lane_s32::(transmute(a), transmute(b))) @@ -12153,6 +13023,7 @@ pub unsafe fn vst2_lane_u32(a: *mut u32, b: uint32x2x2_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst2q_lane_u16(a: *mut u16, b: uint16x8x2_t) { static_assert_imm3!(LANE); transmute(vst2q_lane_s16::(transmute(a), transmute(b))) @@ -12165,6 +13036,7 @@ pub unsafe fn vst2q_lane_u16(a: *mut u16, b: uint16x8x2_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst2q_lane_u32(a: *mut u32, b: uint32x4x2_t) { static_assert_imm2!(LANE); transmute(vst2q_lane_s32::(transmute(a), transmute(b))) @@ -12177,6 +13049,7 @@ pub unsafe fn vst2q_lane_u32(a: *mut u32, b: uint32x4x2_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst2_lane_p8(a: *mut p8, b: poly8x8x2_t) { static_assert_imm3!(LANE); transmute(vst2_lane_s8::(transmute(a), transmute(b))) @@ -12189,6 +13062,7 @@ pub unsafe fn vst2_lane_p8(a: *mut p8, b: poly8x8x2_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst2_lane_p16(a: *mut p16, b: poly16x4x2_t) { static_assert_imm2!(LANE); transmute(vst2_lane_s16::(transmute(a), transmute(b))) @@ -12201,6 +13075,7 @@ pub unsafe fn vst2_lane_p16(a: *mut p16, b: poly16x4x2_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst2q_lane_p16(a: *mut p16, b: poly16x8x2_t) { static_assert_imm3!(LANE); transmute(vst2q_lane_s16::(transmute(a), transmute(b))) @@ -12210,7 +13085,7 @@ pub unsafe fn vst2q_lane_p16(a: *mut p16, b: poly16x8x2_t) { #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] +#[cfg_attr(test, assert_instr(vst2, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vst2_lane_f32(a: *mut f32, b: float32x2x2_t) { static_assert_imm1!(LANE); @@ -12219,15 +13094,16 @@ pub unsafe fn vst2_lane_f32(a: *mut f32, b: float32x2x2_t) { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2lane.p0i8.v2f32")] fn vst2_lane_f32_(ptr: *mut i8, a: float32x2_t, b: float32x2_t, n: i32, size: i32); } -vst2_lane_f32_(a.cast(), b.0, b.1, LANE, 4) +vst2_lane_f32_(a as _, b.0, b.1, LANE, 4) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] +#[cfg_attr(test, assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2_lane_f32(a: *mut f32, b: float32x2x2_t) { static_assert_imm1!(LANE); #[allow(improper_ctypes)] @@ -12235,14 +13111,14 @@ pub unsafe fn vst2_lane_f32(a: *mut f32, b: float32x2x2_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2lane.v2f32.p0i8")] fn vst2_lane_f32_(a: float32x2_t, b: float32x2_t, n: i64, ptr: *mut i8); } -vst2_lane_f32_(b.0, b.1, LANE as i64, a.cast()) +vst2_lane_f32_(b.0, b.1, LANE as i64, a as _) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst2, LANE = 0))] +#[cfg_attr(test, assert_instr(vst2, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vst2q_lane_f32(a: *mut f32, b: float32x4x2_t) { static_assert_imm2!(LANE); @@ -12251,15 +13127,16 @@ pub unsafe fn vst2q_lane_f32(a: *mut f32, b: float32x4x2_t) { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst2lane.p0i8.v4f32")] fn vst2q_lane_f32_(ptr: *mut i8, a: float32x4_t, b: float32x4_t, n: i32, size: i32); } -vst2q_lane_f32_(a.cast(), b.0, b.1, LANE, 4) +vst2q_lane_f32_(a as _, b.0, b.1, LANE, 4) } /// Store multiple 2-element structures from two registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st2, LANE = 0))] +#[cfg_attr(test, assert_instr(st2, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst2q_lane_f32(a: *mut f32, b: float32x4x2_t) { static_assert_imm2!(LANE); #[allow(improper_ctypes)] @@ -12267,203 +13144,210 @@ pub unsafe fn vst2q_lane_f32(a: *mut f32, b: float32x4x2_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st2lane.v4f32.p0i8")] fn vst2q_lane_f32_(a: float32x4_t, b: float32x4_t, n: i64, ptr: *mut i8); } -vst2q_lane_f32_(b.0, b.1, LANE as i64, a.cast()) +vst2q_lane_f32_(b.0, b.1, LANE as i64, a as _) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +#[cfg_attr(test, assert_instr(vst3))] pub unsafe fn vst3_s8(a: *mut i8, b: int8x8x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3.p0i8.v8i8")] fn vst3_s8_(ptr: *mut i8, a: int8x8_t, b: int8x8_t, c: int8x8_t, size: i32); } -vst3_s8_(a.cast(), b.0, b.1, b.2, 1) +vst3_s8_(a as _, b.0, b.1, b.2, 1) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +#[cfg_attr(test, assert_instr(st3))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3_s8(a: *mut i8, b: int8x8x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3.v8i8.p0i8")] fn vst3_s8_(a: int8x8_t, b: int8x8_t, c: int8x8_t, ptr: *mut i8); } -vst3_s8_(b.0, b.1, b.2, a.cast()) +vst3_s8_(b.0, b.1, b.2, a as _) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +#[cfg_attr(test, assert_instr(vst3))] pub unsafe fn vst3_s16(a: *mut i16, b: int16x4x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3.p0i8.v4i16")] fn vst3_s16_(ptr: *mut i8, a: int16x4_t, b: int16x4_t, c: int16x4_t, size: i32); } -vst3_s16_(a.cast(), b.0, b.1, b.2, 2) +vst3_s16_(a as _, b.0, b.1, b.2, 2) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +#[cfg_attr(test, assert_instr(st3))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3_s16(a: *mut i16, b: int16x4x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3.v4i16.p0i8")] fn vst3_s16_(a: int16x4_t, b: int16x4_t, c: int16x4_t, ptr: *mut i8); } -vst3_s16_(b.0, b.1, b.2, a.cast()) +vst3_s16_(b.0, b.1, b.2, a as _) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +#[cfg_attr(test, assert_instr(vst3))] pub unsafe fn vst3_s32(a: *mut i32, b: int32x2x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3.p0i8.v2i32")] fn vst3_s32_(ptr: *mut i8, a: int32x2_t, b: int32x2_t, c: int32x2_t, size: i32); } -vst3_s32_(a.cast(), b.0, b.1, b.2, 4) +vst3_s32_(a as _, b.0, b.1, b.2, 4) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +#[cfg_attr(test, assert_instr(st3))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3_s32(a: *mut i32, b: int32x2x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3.v2i32.p0i8")] fn vst3_s32_(a: int32x2_t, b: int32x2_t, c: int32x2_t, ptr: *mut i8); } -vst3_s32_(b.0, b.1, b.2, a.cast()) +vst3_s32_(b.0, b.1, b.2, a as _) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +#[cfg_attr(test, assert_instr(vst3))] pub unsafe fn vst3q_s8(a: *mut i8, b: int8x16x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3.p0i8.v16i8")] fn vst3q_s8_(ptr: *mut i8, a: int8x16_t, b: int8x16_t, c: int8x16_t, size: i32); } -vst3q_s8_(a.cast(), b.0, b.1, b.2, 1) +vst3q_s8_(a as _, b.0, b.1, b.2, 1) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +#[cfg_attr(test, assert_instr(st3))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3q_s8(a: *mut i8, b: int8x16x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3.v16i8.p0i8")] fn vst3q_s8_(a: int8x16_t, b: int8x16_t, c: int8x16_t, ptr: *mut i8); } -vst3q_s8_(b.0, b.1, b.2, a.cast()) +vst3q_s8_(b.0, b.1, b.2, a as _) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +#[cfg_attr(test, assert_instr(vst3))] pub unsafe fn vst3q_s16(a: *mut i16, b: int16x8x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3.p0i8.v8i16")] fn vst3q_s16_(ptr: *mut i8, a: int16x8_t, b: int16x8_t, c: int16x8_t, size: i32); } -vst3q_s16_(a.cast(), b.0, b.1, b.2, 2) +vst3q_s16_(a as _, b.0, b.1, b.2, 2) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +#[cfg_attr(test, assert_instr(st3))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3q_s16(a: *mut i16, b: int16x8x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3.v8i16.p0i8")] fn vst3q_s16_(a: int16x8_t, b: int16x8_t, c: int16x8_t, ptr: *mut i8); } -vst3q_s16_(b.0, b.1, b.2, a.cast()) +vst3q_s16_(b.0, b.1, b.2, a as _) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +#[cfg_attr(test, assert_instr(vst3))] pub unsafe fn vst3q_s32(a: *mut i32, b: int32x4x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3.p0i8.v4i32")] fn vst3q_s32_(ptr: *mut i8, a: int32x4_t, b: int32x4_t, c: int32x4_t, size: i32); } -vst3q_s32_(a.cast(), b.0, b.1, b.2, 4) +vst3q_s32_(a as _, b.0, b.1, b.2, 4) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +#[cfg_attr(test, assert_instr(st3))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3q_s32(a: *mut i32, b: int32x4x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3.v4i32.p0i8")] fn vst3q_s32_(a: int32x4_t, b: int32x4_t, c: int32x4_t, ptr: *mut i8); } -vst3q_s32_(b.0, b.1, b.2, a.cast()) +vst3q_s32_(b.0, b.1, b.2, a as _) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vst3_s64(a: *mut i64, b: int64x1x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3.p0i8.v1i64")] fn vst3_s64_(ptr: *mut i8, a: int64x1_t, b: int64x1_t, c: int64x1_t, size: i32); } -vst3_s64_(a.cast(), b.0, b.1, b.2, 8) +vst3_s64_(a as _, b.0, b.1, b.2, 8) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3_s64(a: *mut i64, b: int64x1x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3.v1i64.p0i8")] fn vst3_s64_(a: int64x1_t, b: int64x1_t, c: int64x1_t, ptr: *mut i8); } -vst3_s64_(b.0, b.1, b.2, a.cast()) +vst3_s64_(b.0, b.1, b.2, a as _) } /// Store multiple 3-element structures from three registers @@ -12472,6 +13356,7 @@ vst3_s64_(b.0, b.1, b.2, a.cast()) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst3_u8(a: *mut u8, b: uint8x8x3_t) { transmute(vst3_s8(transmute(a), transmute(b))) } @@ -12482,6 +13367,7 @@ pub unsafe fn vst3_u8(a: *mut u8, b: uint8x8x3_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst3_u16(a: *mut u16, b: uint16x4x3_t) { transmute(vst3_s16(transmute(a), transmute(b))) } @@ -12492,6 +13378,7 @@ pub unsafe fn vst3_u16(a: *mut u16, b: uint16x4x3_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst3_u32(a: *mut u32, b: uint32x2x3_t) { transmute(vst3_s32(transmute(a), transmute(b))) } @@ -12502,6 +13389,7 @@ pub unsafe fn vst3_u32(a: *mut u32, b: uint32x2x3_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst3q_u8(a: *mut u8, b: uint8x16x3_t) { transmute(vst3q_s8(transmute(a), transmute(b))) } @@ -12512,6 +13400,7 @@ pub unsafe fn vst3q_u8(a: *mut u8, b: uint8x16x3_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst3q_u16(a: *mut u16, b: uint16x8x3_t) { transmute(vst3q_s16(transmute(a), transmute(b))) } @@ -12522,6 +13411,7 @@ pub unsafe fn vst3q_u16(a: *mut u16, b: uint16x8x3_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst3q_u32(a: *mut u32, b: uint32x4x3_t) { transmute(vst3q_s32(transmute(a), transmute(b))) } @@ -12532,6 +13422,7 @@ pub unsafe fn vst3q_u32(a: *mut u32, b: uint32x4x3_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst3_p8(a: *mut p8, b: poly8x8x3_t) { transmute(vst3_s8(transmute(a), transmute(b))) } @@ -12542,6 +13433,7 @@ pub unsafe fn vst3_p8(a: *mut p8, b: poly8x8x3_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst3_p16(a: *mut p16, b: poly16x4x3_t) { transmute(vst3_s16(transmute(a), transmute(b))) } @@ -12552,6 +13444,7 @@ pub unsafe fn vst3_p16(a: *mut p16, b: poly16x4x3_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst3q_p8(a: *mut p8, b: poly8x16x3_t) { transmute(vst3q_s8(transmute(a), transmute(b))) } @@ -12562,6 +13455,7 @@ pub unsafe fn vst3q_p8(a: *mut p8, b: poly8x16x3_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst3q_p16(a: *mut p16, b: poly16x8x3_t) { transmute(vst3q_s16(transmute(a), transmute(b))) } @@ -12572,6 +13466,7 @@ pub unsafe fn vst3q_p16(a: *mut p16, b: poly16x8x3_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst3_u64(a: *mut u64, b: uint64x1x3_t) { transmute(vst3_s64(transmute(a), transmute(b))) } @@ -12582,6 +13477,7 @@ pub unsafe fn vst3_u64(a: *mut u64, b: uint64x1x3_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst3_p64(a: *mut p64, b: poly64x1x3_t) { transmute(vst3_s64(transmute(a), transmute(b))) } @@ -12590,63 +13486,65 @@ pub unsafe fn vst3_p64(a: *mut p64, b: poly64x1x3_t) { #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +#[cfg_attr(test, assert_instr(vst3))] pub unsafe fn vst3_f32(a: *mut f32, b: float32x2x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3.p0i8.v2f32")] fn vst3_f32_(ptr: *mut i8, a: float32x2_t, b: float32x2_t, c: float32x2_t, size: i32); } -vst3_f32_(a.cast(), b.0, b.1, b.2, 4) +vst3_f32_(a as _, b.0, b.1, b.2, 4) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +#[cfg_attr(test, assert_instr(st3))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3_f32(a: *mut f32, b: float32x2x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3.v2f32.p0i8")] fn vst3_f32_(a: float32x2_t, b: float32x2_t, c: float32x2_t, ptr: *mut i8); } -vst3_f32_(b.0, b.1, b.2, a.cast()) +vst3_f32_(b.0, b.1, b.2, a as _) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3))] +#[cfg_attr(test, assert_instr(vst3))] pub unsafe fn vst3q_f32(a: *mut f32, b: float32x4x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3.p0i8.v4f32")] fn vst3q_f32_(ptr: *mut i8, a: float32x4_t, b: float32x4_t, c: float32x4_t, size: i32); } -vst3q_f32_(a.cast(), b.0, b.1, b.2, 4) +vst3q_f32_(a as _, b.0, b.1, b.2, 4) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3))] +#[cfg_attr(test, assert_instr(st3))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3q_f32(a: *mut f32, b: float32x4x3_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3.v4f32.p0i8")] fn vst3q_f32_(a: float32x4_t, b: float32x4_t, c: float32x4_t, ptr: *mut i8); } -vst3q_f32_(b.0, b.1, b.2, a.cast()) +vst3q_f32_(b.0, b.1, b.2, a as _) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] +#[cfg_attr(test, assert_instr(vst3, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vst3_lane_s8(a: *mut i8, b: int8x8x3_t) { static_assert_imm3!(LANE); @@ -12655,15 +13553,16 @@ pub unsafe fn vst3_lane_s8(a: *mut i8, b: int8x8x3_t) { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3lane.p0i8.v8i8")] fn vst3_lane_s8_(ptr: *mut i8, a: int8x8_t, b: int8x8_t, c: int8x8_t, n: i32, size: i32); } -vst3_lane_s8_(a.cast(), b.0, b.1, b.2, LANE, 1) +vst3_lane_s8_(a as _, b.0, b.1, b.2, LANE, 1) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] +#[cfg_attr(test, assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3_lane_s8(a: *mut i8, b: int8x8x3_t) { static_assert_imm3!(LANE); #[allow(improper_ctypes)] @@ -12671,14 +13570,14 @@ pub unsafe fn vst3_lane_s8(a: *mut i8, b: int8x8x3_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3lane.v8i8.p0i8")] fn vst3_lane_s8_(a: int8x8_t, b: int8x8_t, c: int8x8_t, n: i64, ptr: *mut i8); } -vst3_lane_s8_(b.0, b.1, b.2, LANE as i64, a.cast()) +vst3_lane_s8_(b.0, b.1, b.2, LANE as i64, a as _) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] +#[cfg_attr(test, assert_instr(vst3, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vst3_lane_s16(a: *mut i16, b: int16x4x3_t) { static_assert_imm2!(LANE); @@ -12687,15 +13586,16 @@ pub unsafe fn vst3_lane_s16(a: *mut i16, b: int16x4x3_t) { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3lane.p0i8.v4i16")] fn vst3_lane_s16_(ptr: *mut i8, a: int16x4_t, b: int16x4_t, c: int16x4_t, n: i32, size: i32); } -vst3_lane_s16_(a.cast(), b.0, b.1, b.2, LANE, 2) +vst3_lane_s16_(a as _, b.0, b.1, b.2, LANE, 2) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] +#[cfg_attr(test, assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3_lane_s16(a: *mut i16, b: int16x4x3_t) { static_assert_imm2!(LANE); #[allow(improper_ctypes)] @@ -12703,14 +13603,14 @@ pub unsafe fn vst3_lane_s16(a: *mut i16, b: int16x4x3_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3lane.v4i16.p0i8")] fn vst3_lane_s16_(a: int16x4_t, b: int16x4_t, c: int16x4_t, n: i64, ptr: *mut i8); } -vst3_lane_s16_(b.0, b.1, b.2, LANE as i64, a.cast()) +vst3_lane_s16_(b.0, b.1, b.2, LANE as i64, a as _) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] +#[cfg_attr(test, assert_instr(vst3, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vst3_lane_s32(a: *mut i32, b: int32x2x3_t) { static_assert_imm1!(LANE); @@ -12719,15 +13619,16 @@ pub unsafe fn vst3_lane_s32(a: *mut i32, b: int32x2x3_t) { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3lane.p0i8.v2i32")] fn vst3_lane_s32_(ptr: *mut i8, a: int32x2_t, b: int32x2_t, c: int32x2_t, n: i32, size: i32); } -vst3_lane_s32_(a.cast(), b.0, b.1, b.2, LANE, 4) +vst3_lane_s32_(a as _, b.0, b.1, b.2, LANE, 4) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] +#[cfg_attr(test, assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3_lane_s32(a: *mut i32, b: int32x2x3_t) { static_assert_imm1!(LANE); #[allow(improper_ctypes)] @@ -12735,14 +13636,14 @@ pub unsafe fn vst3_lane_s32(a: *mut i32, b: int32x2x3_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3lane.v2i32.p0i8")] fn vst3_lane_s32_(a: int32x2_t, b: int32x2_t, c: int32x2_t, n: i64, ptr: *mut i8); } -vst3_lane_s32_(b.0, b.1, b.2, LANE as i64, a.cast()) +vst3_lane_s32_(b.0, b.1, b.2, LANE as i64, a as _) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] +#[cfg_attr(test, assert_instr(vst3, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vst3q_lane_s16(a: *mut i16, b: int16x8x3_t) { static_assert_imm3!(LANE); @@ -12751,15 +13652,16 @@ pub unsafe fn vst3q_lane_s16(a: *mut i16, b: int16x8x3_t) { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3lane.p0i8.v8i16")] fn vst3q_lane_s16_(ptr: *mut i8, a: int16x8_t, b: int16x8_t, c: int16x8_t, n: i32, size: i32); } -vst3q_lane_s16_(a.cast(), b.0, b.1, b.2, LANE, 2) +vst3q_lane_s16_(a as _, b.0, b.1, b.2, LANE, 2) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] +#[cfg_attr(test, assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3q_lane_s16(a: *mut i16, b: int16x8x3_t) { static_assert_imm3!(LANE); #[allow(improper_ctypes)] @@ -12767,14 +13669,14 @@ pub unsafe fn vst3q_lane_s16(a: *mut i16, b: int16x8x3_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3lane.v8i16.p0i8")] fn vst3q_lane_s16_(a: int16x8_t, b: int16x8_t, c: int16x8_t, n: i64, ptr: *mut i8); } -vst3q_lane_s16_(b.0, b.1, b.2, LANE as i64, a.cast()) +vst3q_lane_s16_(b.0, b.1, b.2, LANE as i64, a as _) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] +#[cfg_attr(test, assert_instr(vst3, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vst3q_lane_s32(a: *mut i32, b: int32x4x3_t) { static_assert_imm2!(LANE); @@ -12783,15 +13685,16 @@ pub unsafe fn vst3q_lane_s32(a: *mut i32, b: int32x4x3_t) { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3lane.p0i8.v4i32")] fn vst3q_lane_s32_(ptr: *mut i8, a: int32x4_t, b: int32x4_t, c: int32x4_t, n: i32, size: i32); } -vst3q_lane_s32_(a.cast(), b.0, b.1, b.2, LANE, 4) +vst3q_lane_s32_(a as _, b.0, b.1, b.2, LANE, 4) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] +#[cfg_attr(test, assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3q_lane_s32(a: *mut i32, b: int32x4x3_t) { static_assert_imm2!(LANE); #[allow(improper_ctypes)] @@ -12799,7 +13702,7 @@ pub unsafe fn vst3q_lane_s32(a: *mut i32, b: int32x4x3_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3lane.v4i32.p0i8")] fn vst3q_lane_s32_(a: int32x4_t, b: int32x4_t, c: int32x4_t, n: i64, ptr: *mut i8); } -vst3q_lane_s32_(b.0, b.1, b.2, LANE as i64, a.cast()) +vst3q_lane_s32_(b.0, b.1, b.2, LANE as i64, a as _) } /// Store multiple 3-element structures from three registers @@ -12809,6 +13712,7 @@ vst3q_lane_s32_(b.0, b.1, b.2, LANE as i64, a.cast()) #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst3_lane_u8(a: *mut u8, b: uint8x8x3_t) { static_assert_imm3!(LANE); transmute(vst3_lane_s8::(transmute(a), transmute(b))) @@ -12821,6 +13725,7 @@ pub unsafe fn vst3_lane_u8(a: *mut u8, b: uint8x8x3_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst3_lane_u16(a: *mut u16, b: uint16x4x3_t) { static_assert_imm2!(LANE); transmute(vst3_lane_s16::(transmute(a), transmute(b))) @@ -12833,6 +13738,7 @@ pub unsafe fn vst3_lane_u16(a: *mut u16, b: uint16x4x3_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst3_lane_u32(a: *mut u32, b: uint32x2x3_t) { static_assert_imm1!(LANE); transmute(vst3_lane_s32::(transmute(a), transmute(b))) @@ -12845,6 +13751,7 @@ pub unsafe fn vst3_lane_u32(a: *mut u32, b: uint32x2x3_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst3q_lane_u16(a: *mut u16, b: uint16x8x3_t) { static_assert_imm3!(LANE); transmute(vst3q_lane_s16::(transmute(a), transmute(b))) @@ -12857,6 +13764,7 @@ pub unsafe fn vst3q_lane_u16(a: *mut u16, b: uint16x8x3_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst3q_lane_u32(a: *mut u32, b: uint32x4x3_t) { static_assert_imm2!(LANE); transmute(vst3q_lane_s32::(transmute(a), transmute(b))) @@ -12869,6 +13777,7 @@ pub unsafe fn vst3q_lane_u32(a: *mut u32, b: uint32x4x3_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst3_lane_p8(a: *mut p8, b: poly8x8x3_t) { static_assert_imm3!(LANE); transmute(vst3_lane_s8::(transmute(a), transmute(b))) @@ -12881,6 +13790,7 @@ pub unsafe fn vst3_lane_p8(a: *mut p8, b: poly8x8x3_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst3_lane_p16(a: *mut p16, b: poly16x4x3_t) { static_assert_imm2!(LANE); transmute(vst3_lane_s16::(transmute(a), transmute(b))) @@ -12893,6 +13803,7 @@ pub unsafe fn vst3_lane_p16(a: *mut p16, b: poly16x4x3_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst3q_lane_p16(a: *mut p16, b: poly16x8x3_t) { static_assert_imm3!(LANE); transmute(vst3q_lane_s16::(transmute(a), transmute(b))) @@ -12902,7 +13813,7 @@ pub unsafe fn vst3q_lane_p16(a: *mut p16, b: poly16x8x3_t) { #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] +#[cfg_attr(test, assert_instr(vst3, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vst3_lane_f32(a: *mut f32, b: float32x2x3_t) { static_assert_imm1!(LANE); @@ -12911,15 +13822,16 @@ pub unsafe fn vst3_lane_f32(a: *mut f32, b: float32x2x3_t) { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3lane.p0i8.v2f32")] fn vst3_lane_f32_(ptr: *mut i8, a: float32x2_t, b: float32x2_t, c: float32x2_t, n: i32, size: i32); } -vst3_lane_f32_(a.cast(), b.0, b.1, b.2, LANE, 4) +vst3_lane_f32_(a as _, b.0, b.1, b.2, LANE, 4) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] +#[cfg_attr(test, assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3_lane_f32(a: *mut f32, b: float32x2x3_t) { static_assert_imm1!(LANE); #[allow(improper_ctypes)] @@ -12927,14 +13839,14 @@ pub unsafe fn vst3_lane_f32(a: *mut f32, b: float32x2x3_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3lane.v2f32.p0i8")] fn vst3_lane_f32_(a: float32x2_t, b: float32x2_t, c: float32x2_t, n: i64, ptr: *mut i8); } -vst3_lane_f32_(b.0, b.1, b.2, LANE as i64, a.cast()) +vst3_lane_f32_(b.0, b.1, b.2, LANE as i64, a as _) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst3, LANE = 0))] +#[cfg_attr(test, assert_instr(vst3, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vst3q_lane_f32(a: *mut f32, b: float32x4x3_t) { static_assert_imm2!(LANE); @@ -12943,15 +13855,16 @@ pub unsafe fn vst3q_lane_f32(a: *mut f32, b: float32x4x3_t) { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst3lane.p0i8.v4f32")] fn vst3q_lane_f32_(ptr: *mut i8, a: float32x4_t, b: float32x4_t, c: float32x4_t, n: i32, size: i32); } -vst3q_lane_f32_(a.cast(), b.0, b.1, b.2, LANE, 4) +vst3q_lane_f32_(a as _, b.0, b.1, b.2, LANE, 4) } /// Store multiple 3-element structures from three registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st3, LANE = 0))] +#[cfg_attr(test, assert_instr(st3, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst3q_lane_f32(a: *mut f32, b: float32x4x3_t) { static_assert_imm2!(LANE); #[allow(improper_ctypes)] @@ -12959,203 +13872,210 @@ pub unsafe fn vst3q_lane_f32(a: *mut f32, b: float32x4x3_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st3lane.v4f32.p0i8")] fn vst3q_lane_f32_(a: float32x4_t, b: float32x4_t, c: float32x4_t, n: i64, ptr: *mut i8); } -vst3q_lane_f32_(b.0, b.1, b.2, LANE as i64, a.cast()) +vst3q_lane_f32_(b.0, b.1, b.2, LANE as i64, a as _) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +#[cfg_attr(test, assert_instr(vst4))] pub unsafe fn vst4_s8(a: *mut i8, b: int8x8x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4.p0i8.v8i8")] fn vst4_s8_(ptr: *mut i8, a: int8x8_t, b: int8x8_t, c: int8x8_t, d: int8x8_t, size: i32); } -vst4_s8_(a.cast(), b.0, b.1, b.2, b.3, 1) +vst4_s8_(a as _, b.0, b.1, b.2, b.3, 1) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +#[cfg_attr(test, assert_instr(st4))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4_s8(a: *mut i8, b: int8x8x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4.v8i8.p0i8")] fn vst4_s8_(a: int8x8_t, b: int8x8_t, c: int8x8_t, d: int8x8_t, ptr: *mut i8); } -vst4_s8_(b.0, b.1, b.2, b.3, a.cast()) +vst4_s8_(b.0, b.1, b.2, b.3, a as _) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +#[cfg_attr(test, assert_instr(vst4))] pub unsafe fn vst4_s16(a: *mut i16, b: int16x4x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4.p0i8.v4i16")] fn vst4_s16_(ptr: *mut i8, a: int16x4_t, b: int16x4_t, c: int16x4_t, d: int16x4_t, size: i32); } -vst4_s16_(a.cast(), b.0, b.1, b.2, b.3, 2) +vst4_s16_(a as _, b.0, b.1, b.2, b.3, 2) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +#[cfg_attr(test, assert_instr(st4))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4_s16(a: *mut i16, b: int16x4x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4.v4i16.p0i8")] fn vst4_s16_(a: int16x4_t, b: int16x4_t, c: int16x4_t, d: int16x4_t, ptr: *mut i8); } -vst4_s16_(b.0, b.1, b.2, b.3, a.cast()) +vst4_s16_(b.0, b.1, b.2, b.3, a as _) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +#[cfg_attr(test, assert_instr(vst4))] pub unsafe fn vst4_s32(a: *mut i32, b: int32x2x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4.p0i8.v2i32")] fn vst4_s32_(ptr: *mut i8, a: int32x2_t, b: int32x2_t, c: int32x2_t, d: int32x2_t, size: i32); } -vst4_s32_(a.cast(), b.0, b.1, b.2, b.3, 4) +vst4_s32_(a as _, b.0, b.1, b.2, b.3, 4) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +#[cfg_attr(test, assert_instr(st4))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4_s32(a: *mut i32, b: int32x2x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4.v2i32.p0i8")] fn vst4_s32_(a: int32x2_t, b: int32x2_t, c: int32x2_t, d: int32x2_t, ptr: *mut i8); } -vst4_s32_(b.0, b.1, b.2, b.3, a.cast()) +vst4_s32_(b.0, b.1, b.2, b.3, a as _) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +#[cfg_attr(test, assert_instr(vst4))] pub unsafe fn vst4q_s8(a: *mut i8, b: int8x16x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4.p0i8.v16i8")] fn vst4q_s8_(ptr: *mut i8, a: int8x16_t, b: int8x16_t, c: int8x16_t, d: int8x16_t, size: i32); } -vst4q_s8_(a.cast(), b.0, b.1, b.2, b.3, 1) +vst4q_s8_(a as _, b.0, b.1, b.2, b.3, 1) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +#[cfg_attr(test, assert_instr(st4))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4q_s8(a: *mut i8, b: int8x16x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4.v16i8.p0i8")] fn vst4q_s8_(a: int8x16_t, b: int8x16_t, c: int8x16_t, d: int8x16_t, ptr: *mut i8); } -vst4q_s8_(b.0, b.1, b.2, b.3, a.cast()) +vst4q_s8_(b.0, b.1, b.2, b.3, a as _) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +#[cfg_attr(test, assert_instr(vst4))] pub unsafe fn vst4q_s16(a: *mut i16, b: int16x8x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4.p0i8.v8i16")] fn vst4q_s16_(ptr: *mut i8, a: int16x8_t, b: int16x8_t, c: int16x8_t, d: int16x8_t, size: i32); } -vst4q_s16_(a.cast(), b.0, b.1, b.2, b.3, 2) +vst4q_s16_(a as _, b.0, b.1, b.2, b.3, 2) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +#[cfg_attr(test, assert_instr(st4))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4q_s16(a: *mut i16, b: int16x8x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4.v8i16.p0i8")] fn vst4q_s16_(a: int16x8_t, b: int16x8_t, c: int16x8_t, d: int16x8_t, ptr: *mut i8); } -vst4q_s16_(b.0, b.1, b.2, b.3, a.cast()) +vst4q_s16_(b.0, b.1, b.2, b.3, a as _) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +#[cfg_attr(test, assert_instr(vst4))] pub unsafe fn vst4q_s32(a: *mut i32, b: int32x4x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4.p0i8.v4i32")] fn vst4q_s32_(ptr: *mut i8, a: int32x4_t, b: int32x4_t, c: int32x4_t, d: int32x4_t, size: i32); } -vst4q_s32_(a.cast(), b.0, b.1, b.2, b.3, 4) +vst4q_s32_(a as _, b.0, b.1, b.2, b.3, 4) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +#[cfg_attr(test, assert_instr(st4))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4q_s32(a: *mut i32, b: int32x4x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4.v4i32.p0i8")] fn vst4q_s32_(a: int32x4_t, b: int32x4_t, c: int32x4_t, d: int32x4_t, ptr: *mut i8); } -vst4q_s32_(b.0, b.1, b.2, b.3, a.cast()) +vst4q_s32_(b.0, b.1, b.2, b.3, a as _) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] +#[cfg_attr(test, assert_instr(nop))] pub unsafe fn vst4_s64(a: *mut i64, b: int64x1x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4.p0i8.v1i64")] fn vst4_s64_(ptr: *mut i8, a: int64x1_t, b: int64x1_t, c: int64x1_t, d: int64x1_t, size: i32); } -vst4_s64_(a.cast(), b.0, b.1, b.2, b.3, 8) +vst4_s64_(a as _, b.0, b.1, b.2, b.3, 8) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(test, assert_instr(nop))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4_s64(a: *mut i64, b: int64x1x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4.v1i64.p0i8")] fn vst4_s64_(a: int64x1_t, b: int64x1_t, c: int64x1_t, d: int64x1_t, ptr: *mut i8); } -vst4_s64_(b.0, b.1, b.2, b.3, a.cast()) +vst4_s64_(b.0, b.1, b.2, b.3, a as _) } /// Store multiple 4-element structures from four registers @@ -13164,6 +14084,7 @@ vst4_s64_(b.0, b.1, b.2, b.3, a.cast()) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst4_u8(a: *mut u8, b: uint8x8x4_t) { transmute(vst4_s8(transmute(a), transmute(b))) } @@ -13174,6 +14095,7 @@ pub unsafe fn vst4_u8(a: *mut u8, b: uint8x8x4_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst4_u16(a: *mut u16, b: uint16x4x4_t) { transmute(vst4_s16(transmute(a), transmute(b))) } @@ -13184,6 +14106,7 @@ pub unsafe fn vst4_u16(a: *mut u16, b: uint16x4x4_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst4_u32(a: *mut u32, b: uint32x2x4_t) { transmute(vst4_s32(transmute(a), transmute(b))) } @@ -13194,6 +14117,7 @@ pub unsafe fn vst4_u32(a: *mut u32, b: uint32x2x4_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst4q_u8(a: *mut u8, b: uint8x16x4_t) { transmute(vst4q_s8(transmute(a), transmute(b))) } @@ -13204,6 +14128,7 @@ pub unsafe fn vst4q_u8(a: *mut u8, b: uint8x16x4_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst4q_u16(a: *mut u16, b: uint16x8x4_t) { transmute(vst4q_s16(transmute(a), transmute(b))) } @@ -13214,6 +14139,7 @@ pub unsafe fn vst4q_u16(a: *mut u16, b: uint16x8x4_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst4q_u32(a: *mut u32, b: uint32x4x4_t) { transmute(vst4q_s32(transmute(a), transmute(b))) } @@ -13224,6 +14150,7 @@ pub unsafe fn vst4q_u32(a: *mut u32, b: uint32x4x4_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst4_p8(a: *mut p8, b: poly8x8x4_t) { transmute(vst4_s8(transmute(a), transmute(b))) } @@ -13234,6 +14161,7 @@ pub unsafe fn vst4_p8(a: *mut p8, b: poly8x8x4_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst4_p16(a: *mut p16, b: poly16x4x4_t) { transmute(vst4_s16(transmute(a), transmute(b))) } @@ -13244,6 +14172,7 @@ pub unsafe fn vst4_p16(a: *mut p16, b: poly16x4x4_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst4q_p8(a: *mut p8, b: poly8x16x4_t) { transmute(vst4q_s8(transmute(a), transmute(b))) } @@ -13254,6 +14183,7 @@ pub unsafe fn vst4q_p8(a: *mut p8, b: poly8x16x4_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst4q_p16(a: *mut p16, b: poly16x8x4_t) { transmute(vst4q_s16(transmute(a), transmute(b))) } @@ -13264,6 +14194,7 @@ pub unsafe fn vst4q_p16(a: *mut p16, b: poly16x8x4_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst4_u64(a: *mut u64, b: uint64x1x4_t) { transmute(vst4_s64(transmute(a), transmute(b))) } @@ -13274,6 +14205,7 @@ pub unsafe fn vst4_u64(a: *mut u64, b: uint64x1x4_t) { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst4_p64(a: *mut p64, b: poly64x1x4_t) { transmute(vst4_s64(transmute(a), transmute(b))) } @@ -13282,63 +14214,65 @@ pub unsafe fn vst4_p64(a: *mut p64, b: poly64x1x4_t) { #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +#[cfg_attr(test, assert_instr(vst4))] pub unsafe fn vst4_f32(a: *mut f32, b: float32x2x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4.p0i8.v2f32")] fn vst4_f32_(ptr: *mut i8, a: float32x2_t, b: float32x2_t, c: float32x2_t, d: float32x2_t, size: i32); } -vst4_f32_(a.cast(), b.0, b.1, b.2, b.3, 4) +vst4_f32_(a as _, b.0, b.1, b.2, b.3, 4) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +#[cfg_attr(test, assert_instr(st4))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4_f32(a: *mut f32, b: float32x2x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4.v2f32.p0i8")] fn vst4_f32_(a: float32x2_t, b: float32x2_t, c: float32x2_t, d: float32x2_t, ptr: *mut i8); } -vst4_f32_(b.0, b.1, b.2, b.3, a.cast()) +vst4_f32_(b.0, b.1, b.2, b.3, a as _) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4))] +#[cfg_attr(test, assert_instr(vst4))] pub unsafe fn vst4q_f32(a: *mut f32, b: float32x4x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4.p0i8.v4f32")] fn vst4q_f32_(ptr: *mut i8, a: float32x4_t, b: float32x4_t, c: float32x4_t, d: float32x4_t, size: i32); } -vst4q_f32_(a.cast(), b.0, b.1, b.2, b.3, 4) +vst4q_f32_(a as _, b.0, b.1, b.2, b.3, 4) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4))] +#[cfg_attr(test, assert_instr(st4))] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4q_f32(a: *mut f32, b: float32x4x4_t) { #[allow(improper_ctypes)] extern "unadjusted" { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4.v4f32.p0i8")] fn vst4q_f32_(a: float32x4_t, b: float32x4_t, c: float32x4_t, d: float32x4_t, ptr: *mut i8); } -vst4q_f32_(b.0, b.1, b.2, b.3, a.cast()) +vst4q_f32_(b.0, b.1, b.2, b.3, a as _) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] +#[cfg_attr(test, assert_instr(vst4, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vst4_lane_s8(a: *mut i8, b: int8x8x4_t) { static_assert_imm3!(LANE); @@ -13347,15 +14281,16 @@ pub unsafe fn vst4_lane_s8(a: *mut i8, b: int8x8x4_t) { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4lane.p0i8.v8i8")] fn vst4_lane_s8_(ptr: *mut i8, a: int8x8_t, b: int8x8_t, c: int8x8_t, d: int8x8_t, n: i32, size: i32); } -vst4_lane_s8_(a.cast(), b.0, b.1, b.2, b.3, LANE, 1) +vst4_lane_s8_(a as _, b.0, b.1, b.2, b.3, LANE, 1) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] +#[cfg_attr(test, assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4_lane_s8(a: *mut i8, b: int8x8x4_t) { static_assert_imm3!(LANE); #[allow(improper_ctypes)] @@ -13363,14 +14298,14 @@ pub unsafe fn vst4_lane_s8(a: *mut i8, b: int8x8x4_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4lane.v8i8.p0i8")] fn vst4_lane_s8_(a: int8x8_t, b: int8x8_t, c: int8x8_t, d: int8x8_t, n: i64, ptr: *mut i8); } -vst4_lane_s8_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) +vst4_lane_s8_(b.0, b.1, b.2, b.3, LANE as i64, a as _) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] +#[cfg_attr(test, assert_instr(vst4, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vst4_lane_s16(a: *mut i16, b: int16x4x4_t) { static_assert_imm2!(LANE); @@ -13379,15 +14314,16 @@ pub unsafe fn vst4_lane_s16(a: *mut i16, b: int16x4x4_t) { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4lane.p0i8.v4i16")] fn vst4_lane_s16_(ptr: *mut i8, a: int16x4_t, b: int16x4_t, c: int16x4_t, d: int16x4_t, n: i32, size: i32); } -vst4_lane_s16_(a.cast(), b.0, b.1, b.2, b.3, LANE, 2) +vst4_lane_s16_(a as _, b.0, b.1, b.2, b.3, LANE, 2) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] +#[cfg_attr(test, assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4_lane_s16(a: *mut i16, b: int16x4x4_t) { static_assert_imm2!(LANE); #[allow(improper_ctypes)] @@ -13395,14 +14331,14 @@ pub unsafe fn vst4_lane_s16(a: *mut i16, b: int16x4x4_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4lane.v4i16.p0i8")] fn vst4_lane_s16_(a: int16x4_t, b: int16x4_t, c: int16x4_t, d: int16x4_t, n: i64, ptr: *mut i8); } -vst4_lane_s16_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) +vst4_lane_s16_(b.0, b.1, b.2, b.3, LANE as i64, a as _) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] +#[cfg_attr(test, assert_instr(vst4, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vst4_lane_s32(a: *mut i32, b: int32x2x4_t) { static_assert_imm1!(LANE); @@ -13411,15 +14347,16 @@ pub unsafe fn vst4_lane_s32(a: *mut i32, b: int32x2x4_t) { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4lane.p0i8.v2i32")] fn vst4_lane_s32_(ptr: *mut i8, a: int32x2_t, b: int32x2_t, c: int32x2_t, d: int32x2_t, n: i32, size: i32); } -vst4_lane_s32_(a.cast(), b.0, b.1, b.2, b.3, LANE, 4) +vst4_lane_s32_(a as _, b.0, b.1, b.2, b.3, LANE, 4) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] +#[cfg_attr(test, assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4_lane_s32(a: *mut i32, b: int32x2x4_t) { static_assert_imm1!(LANE); #[allow(improper_ctypes)] @@ -13427,14 +14364,14 @@ pub unsafe fn vst4_lane_s32(a: *mut i32, b: int32x2x4_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4lane.v2i32.p0i8")] fn vst4_lane_s32_(a: int32x2_t, b: int32x2_t, c: int32x2_t, d: int32x2_t, n: i64, ptr: *mut i8); } -vst4_lane_s32_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) +vst4_lane_s32_(b.0, b.1, b.2, b.3, LANE as i64, a as _) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] +#[cfg_attr(test, assert_instr(vst4, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vst4q_lane_s16(a: *mut i16, b: int16x8x4_t) { static_assert_imm3!(LANE); @@ -13443,15 +14380,16 @@ pub unsafe fn vst4q_lane_s16(a: *mut i16, b: int16x8x4_t) { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4lane.p0i8.v8i16")] fn vst4q_lane_s16_(ptr: *mut i8, a: int16x8_t, b: int16x8_t, c: int16x8_t, d: int16x8_t, n: i32, size: i32); } -vst4q_lane_s16_(a.cast(), b.0, b.1, b.2, b.3, LANE, 2) +vst4q_lane_s16_(a as _, b.0, b.1, b.2, b.3, LANE, 2) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] +#[cfg_attr(test, assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4q_lane_s16(a: *mut i16, b: int16x8x4_t) { static_assert_imm3!(LANE); #[allow(improper_ctypes)] @@ -13459,14 +14397,14 @@ pub unsafe fn vst4q_lane_s16(a: *mut i16, b: int16x8x4_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4lane.v8i16.p0i8")] fn vst4q_lane_s16_(a: int16x8_t, b: int16x8_t, c: int16x8_t, d: int16x8_t, n: i64, ptr: *mut i8); } -vst4q_lane_s16_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) +vst4q_lane_s16_(b.0, b.1, b.2, b.3, LANE as i64, a as _) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] +#[cfg_attr(test, assert_instr(vst4, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vst4q_lane_s32(a: *mut i32, b: int32x4x4_t) { static_assert_imm2!(LANE); @@ -13475,15 +14413,16 @@ pub unsafe fn vst4q_lane_s32(a: *mut i32, b: int32x4x4_t) { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4lane.p0i8.v4i32")] fn vst4q_lane_s32_(ptr: *mut i8, a: int32x4_t, b: int32x4_t, c: int32x4_t, d: int32x4_t, n: i32, size: i32); } -vst4q_lane_s32_(a.cast(), b.0, b.1, b.2, b.3, LANE, 4) +vst4q_lane_s32_(a as _, b.0, b.1, b.2, b.3, LANE, 4) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] +#[cfg_attr(test, assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4q_lane_s32(a: *mut i32, b: int32x4x4_t) { static_assert_imm2!(LANE); #[allow(improper_ctypes)] @@ -13491,7 +14430,7 @@ pub unsafe fn vst4q_lane_s32(a: *mut i32, b: int32x4x4_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4lane.v4i32.p0i8")] fn vst4q_lane_s32_(a: int32x4_t, b: int32x4_t, c: int32x4_t, d: int32x4_t, n: i64, ptr: *mut i8); } -vst4q_lane_s32_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) +vst4q_lane_s32_(b.0, b.1, b.2, b.3, LANE as i64, a as _) } /// Store multiple 4-element structures from four registers @@ -13501,6 +14440,7 @@ vst4q_lane_s32_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst4_lane_u8(a: *mut u8, b: uint8x8x4_t) { static_assert_imm3!(LANE); transmute(vst4_lane_s8::(transmute(a), transmute(b))) @@ -13513,6 +14453,7 @@ pub unsafe fn vst4_lane_u8(a: *mut u8, b: uint8x8x4_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst4_lane_u16(a: *mut u16, b: uint16x4x4_t) { static_assert_imm2!(LANE); transmute(vst4_lane_s16::(transmute(a), transmute(b))) @@ -13525,6 +14466,7 @@ pub unsafe fn vst4_lane_u16(a: *mut u16, b: uint16x4x4_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst4_lane_u32(a: *mut u32, b: uint32x2x4_t) { static_assert_imm1!(LANE); transmute(vst4_lane_s32::(transmute(a), transmute(b))) @@ -13537,6 +14479,7 @@ pub unsafe fn vst4_lane_u32(a: *mut u32, b: uint32x2x4_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst4q_lane_u16(a: *mut u16, b: uint16x8x4_t) { static_assert_imm3!(LANE); transmute(vst4q_lane_s16::(transmute(a), transmute(b))) @@ -13549,6 +14492,7 @@ pub unsafe fn vst4q_lane_u16(a: *mut u16, b: uint16x8x4_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst4q_lane_u32(a: *mut u32, b: uint32x4x4_t) { static_assert_imm2!(LANE); transmute(vst4q_lane_s32::(transmute(a), transmute(b))) @@ -13561,6 +14505,7 @@ pub unsafe fn vst4q_lane_u32(a: *mut u32, b: uint32x4x4_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst4_lane_p8(a: *mut p8, b: poly8x8x4_t) { static_assert_imm3!(LANE); transmute(vst4_lane_s8::(transmute(a), transmute(b))) @@ -13573,6 +14518,7 @@ pub unsafe fn vst4_lane_p8(a: *mut p8, b: poly8x8x4_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst4_lane_p16(a: *mut p16, b: poly16x4x4_t) { static_assert_imm2!(LANE); transmute(vst4_lane_s16::(transmute(a), transmute(b))) @@ -13585,6 +14531,7 @@ pub unsafe fn vst4_lane_p16(a: *mut p16, b: poly16x4x4_t) { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vst4q_lane_p16(a: *mut p16, b: poly16x8x4_t) { static_assert_imm3!(LANE); transmute(vst4q_lane_s16::(transmute(a), transmute(b))) @@ -13594,7 +14541,7 @@ pub unsafe fn vst4q_lane_p16(a: *mut p16, b: poly16x8x4_t) { #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] +#[cfg_attr(test, assert_instr(vst4, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vst4_lane_f32(a: *mut f32, b: float32x2x4_t) { static_assert_imm1!(LANE); @@ -13603,15 +14550,16 @@ pub unsafe fn vst4_lane_f32(a: *mut f32, b: float32x2x4_t) { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4lane.p0i8.v2f32")] fn vst4_lane_f32_(ptr: *mut i8, a: float32x2_t, b: float32x2_t, c: float32x2_t, d: float32x2_t, n: i32, size: i32); } -vst4_lane_f32_(a.cast(), b.0, b.1, b.2, b.3, LANE, 4) +vst4_lane_f32_(a as _, b.0, b.1, b.2, b.3, LANE, 4) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] +#[cfg_attr(test, assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4_lane_f32(a: *mut f32, b: float32x2x4_t) { static_assert_imm1!(LANE); #[allow(improper_ctypes)] @@ -13619,14 +14567,14 @@ pub unsafe fn vst4_lane_f32(a: *mut f32, b: float32x2x4_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4lane.v2f32.p0i8")] fn vst4_lane_f32_(a: float32x2_t, b: float32x2_t, c: float32x2_t, d: float32x2_t, n: i64, ptr: *mut i8); } -vst4_lane_f32_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) +vst4_lane_f32_(b.0, b.1, b.2, b.3, LANE as i64, a as _) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vst4, LANE = 0))] +#[cfg_attr(test, assert_instr(vst4, LANE = 0))] #[rustc_legacy_const_generics(2)] pub unsafe fn vst4q_lane_f32(a: *mut f32, b: float32x4x4_t) { static_assert_imm2!(LANE); @@ -13635,15 +14583,16 @@ pub unsafe fn vst4q_lane_f32(a: *mut f32, b: float32x4x4_t) { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vst4lane.p0i8.v4f32")] fn vst4q_lane_f32_(ptr: *mut i8, a: float32x4_t, b: float32x4_t, c: float32x4_t, d: float32x4_t, n: i32, size: i32); } -vst4q_lane_f32_(a.cast(), b.0, b.1, b.2, b.3, LANE, 4) +vst4q_lane_f32_(a as _, b.0, b.1, b.2, b.3, LANE, 4) } /// Store multiple 4-element structures from four registers #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(st4, LANE = 0))] +#[cfg_attr(test, assert_instr(st4, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst4q_lane_f32(a: *mut f32, b: float32x4x4_t) { static_assert_imm2!(LANE); #[allow(improper_ctypes)] @@ -13651,7 +14600,7 @@ pub unsafe fn vst4q_lane_f32(a: *mut f32, b: float32x4x4_t) { #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.st4lane.v4f32.p0i8")] fn vst4q_lane_f32_(a: float32x4_t, b: float32x4_t, c: float32x4_t, d: float32x4_t, n: i64, ptr: *mut i8); } -vst4q_lane_f32_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) +vst4q_lane_f32_(b.0, b.1, b.2, b.3, LANE as i64, a as _) } /// Multiply @@ -13660,6 +14609,7 @@ vst4q_lane_f32_(b.0, b.1, b.2, b.3, LANE as i64, a.cast()) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmul_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { simd_mul(a, b) } @@ -13670,6 +14620,7 @@ pub unsafe fn vmul_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmulq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { simd_mul(a, b) } @@ -13680,6 +14631,7 @@ pub unsafe fn vmulq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmul_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { simd_mul(a, b) } @@ -13690,6 +14642,7 @@ pub unsafe fn vmul_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmulq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { simd_mul(a, b) } @@ -13700,6 +14653,7 @@ pub unsafe fn vmulq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmul_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { simd_mul(a, b) } @@ -13710,6 +14664,7 @@ pub unsafe fn vmul_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmulq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { simd_mul(a, b) } @@ -13720,6 +14675,7 @@ pub unsafe fn vmulq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmul_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { simd_mul(a, b) } @@ -13730,6 +14686,7 @@ pub unsafe fn vmul_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmulq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { simd_mul(a, b) } @@ -13740,6 +14697,7 @@ pub unsafe fn vmulq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmul_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { simd_mul(a, b) } @@ -13750,6 +14708,7 @@ pub unsafe fn vmul_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmulq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { simd_mul(a, b) } @@ -13760,6 +14719,7 @@ pub unsafe fn vmulq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmul_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { simd_mul(a, b) } @@ -13770,6 +14730,7 @@ pub unsafe fn vmul_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmulq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { simd_mul(a, b) } @@ -13780,6 +14741,7 @@ pub unsafe fn vmulq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(pmul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmul_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -13796,6 +14758,7 @@ vmul_p8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(pmul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmulq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -13812,6 +14775,7 @@ vmulq_p8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmul_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { simd_mul(a, b) } @@ -13822,6 +14786,7 @@ pub unsafe fn vmul_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmul.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmulq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { simd_mul(a, b) } @@ -13832,6 +14797,7 @@ pub unsafe fn vmulq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmul_n_s16(a: int16x4_t, b: i16) -> int16x4_t { simd_mul(a, vdup_n_s16(b)) } @@ -13842,6 +14808,7 @@ pub unsafe fn vmul_n_s16(a: int16x4_t, b: i16) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmulq_n_s16(a: int16x8_t, b: i16) -> int16x8_t { simd_mul(a, vdupq_n_s16(b)) } @@ -13852,6 +14819,7 @@ pub unsafe fn vmulq_n_s16(a: int16x8_t, b: i16) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmul_n_s32(a: int32x2_t, b: i32) -> int32x2_t { simd_mul(a, vdup_n_s32(b)) } @@ -13862,6 +14830,7 @@ pub unsafe fn vmul_n_s32(a: int32x2_t, b: i32) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmulq_n_s32(a: int32x4_t, b: i32) -> int32x4_t { simd_mul(a, vdupq_n_s32(b)) } @@ -13872,6 +14841,7 @@ pub unsafe fn vmulq_n_s32(a: int32x4_t, b: i32) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmul_n_u16(a: uint16x4_t, b: u16) -> uint16x4_t { simd_mul(a, vdup_n_u16(b)) } @@ -13882,6 +14852,7 @@ pub unsafe fn vmul_n_u16(a: uint16x4_t, b: u16) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmulq_n_u16(a: uint16x8_t, b: u16) -> uint16x8_t { simd_mul(a, vdupq_n_u16(b)) } @@ -13892,6 +14863,7 @@ pub unsafe fn vmulq_n_u16(a: uint16x8_t, b: u16) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmul_n_u32(a: uint32x2_t, b: u32) -> uint32x2_t { simd_mul(a, vdup_n_u32(b)) } @@ -13902,6 +14874,7 @@ pub unsafe fn vmul_n_u32(a: uint32x2_t, b: u32) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmulq_n_u32(a: uint32x4_t, b: u32) -> uint32x4_t { simd_mul(a, vdupq_n_u32(b)) } @@ -13912,6 +14885,7 @@ pub unsafe fn vmulq_n_u32(a: uint32x4_t, b: u32) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmul_n_f32(a: float32x2_t, b: f32) -> float32x2_t { simd_mul(a, vdup_n_f32(b)) } @@ -13922,6 +14896,7 @@ pub unsafe fn vmul_n_f32(a: float32x2_t, b: f32) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmulq_n_f32(a: float32x4_t, b: f32) -> float32x4_t { simd_mul(a, vdupq_n_f32(b)) } @@ -13933,6 +14908,7 @@ pub unsafe fn vmulq_n_f32(a: float32x4_t, b: f32) -> float32x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmul_lane_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { static_assert_imm2!(LANE); simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -13945,6 +14921,7 @@ pub unsafe fn vmul_lane_s16(a: int16x4_t, b: int16x4_t) -> int1 #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmul_laneq_s16(a: int16x4_t, b: int16x8_t) -> int16x4_t { static_assert_imm3!(LANE); simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -13957,6 +14934,7 @@ pub unsafe fn vmul_laneq_s16(a: int16x4_t, b: int16x8_t) -> int #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmulq_lane_s16(a: int16x8_t, b: int16x4_t) -> int16x8_t { static_assert_imm2!(LANE); simd_mul(a, simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -13969,6 +14947,7 @@ pub unsafe fn vmulq_lane_s16(a: int16x8_t, b: int16x4_t) -> int #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmulq_laneq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { static_assert_imm3!(LANE); simd_mul(a, simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -13981,6 +14960,7 @@ pub unsafe fn vmulq_laneq_s16(a: int16x8_t, b: int16x8_t) -> in #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmul_lane_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { static_assert_imm1!(LANE); simd_mul(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) @@ -13993,6 +14973,7 @@ pub unsafe fn vmul_lane_s32(a: int32x2_t, b: int32x2_t) -> int3 #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmul_laneq_s32(a: int32x2_t, b: int32x4_t) -> int32x2_t { static_assert_imm2!(LANE); simd_mul(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) @@ -14005,6 +14986,7 @@ pub unsafe fn vmul_laneq_s32(a: int32x2_t, b: int32x4_t) -> int #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmulq_lane_s32(a: int32x4_t, b: int32x2_t) -> int32x4_t { static_assert_imm1!(LANE); simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -14017,6 +14999,7 @@ pub unsafe fn vmulq_lane_s32(a: int32x4_t, b: int32x2_t) -> int #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmulq_laneq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { static_assert_imm2!(LANE); simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -14029,6 +15012,7 @@ pub unsafe fn vmulq_laneq_s32(a: int32x4_t, b: int32x4_t) -> in #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmul_lane_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { static_assert_imm2!(LANE); simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -14041,6 +15025,7 @@ pub unsafe fn vmul_lane_u16(a: uint16x4_t, b: uint16x4_t) -> ui #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmul_laneq_u16(a: uint16x4_t, b: uint16x8_t) -> uint16x4_t { static_assert_imm3!(LANE); simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -14053,6 +15038,7 @@ pub unsafe fn vmul_laneq_u16(a: uint16x4_t, b: uint16x8_t) -> u #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmulq_lane_u16(a: uint16x8_t, b: uint16x4_t) -> uint16x8_t { static_assert_imm2!(LANE); simd_mul(a, simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -14065,6 +15051,7 @@ pub unsafe fn vmulq_lane_u16(a: uint16x8_t, b: uint16x4_t) -> u #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmulq_laneq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { static_assert_imm3!(LANE); simd_mul(a, simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -14077,6 +15064,7 @@ pub unsafe fn vmulq_laneq_u16(a: uint16x8_t, b: uint16x8_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmul_lane_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { static_assert_imm1!(LANE); simd_mul(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) @@ -14089,6 +15077,7 @@ pub unsafe fn vmul_lane_u32(a: uint32x2_t, b: uint32x2_t) -> ui #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmul_laneq_u32(a: uint32x2_t, b: uint32x4_t) -> uint32x2_t { static_assert_imm2!(LANE); simd_mul(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) @@ -14101,6 +15090,7 @@ pub unsafe fn vmul_laneq_u32(a: uint32x2_t, b: uint32x4_t) -> u #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmulq_lane_u32(a: uint32x4_t, b: uint32x2_t) -> uint32x4_t { static_assert_imm1!(LANE); simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -14113,6 +15103,7 @@ pub unsafe fn vmulq_lane_u32(a: uint32x4_t, b: uint32x2_t) -> u #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mul, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmulq_laneq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { static_assert_imm2!(LANE); simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -14125,6 +15116,7 @@ pub unsafe fn vmulq_laneq_u32(a: uint32x4_t, b: uint32x4_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmul_lane_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { static_assert_imm1!(LANE); simd_mul(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) @@ -14137,6 +15129,7 @@ pub unsafe fn vmul_lane_f32(a: float32x2_t, b: float32x2_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmul_laneq_f32(a: float32x2_t, b: float32x4_t) -> float32x2_t { static_assert_imm2!(LANE); simd_mul(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) @@ -14149,6 +15142,7 @@ pub unsafe fn vmul_laneq_f32(a: float32x2_t, b: float32x4_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmulq_lane_f32(a: float32x4_t, b: float32x2_t) -> float32x4_t { static_assert_imm1!(LANE); simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -14161,6 +15155,7 @@ pub unsafe fn vmulq_lane_f32(a: float32x4_t, b: float32x2_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmul, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmul, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmulq_laneq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { static_assert_imm2!(LANE); simd_mul(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -14172,6 +15167,7 @@ pub unsafe fn vmulq_laneq_f32(a: float32x4_t, b: float32x4_t) - #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmull_s8(a: int8x8_t, b: int8x8_t) -> int16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -14188,6 +15184,7 @@ vmull_s8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmull_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -14204,6 +15201,7 @@ vmull_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmull_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -14220,6 +15218,7 @@ vmull_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmull_u8(a: uint8x8_t, b: uint8x8_t) -> uint16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -14236,6 +15235,7 @@ vmull_u8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmull_u16(a: uint16x4_t, b: uint16x4_t) -> uint32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -14252,6 +15252,7 @@ vmull_u16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmull_u32(a: uint32x2_t, b: uint32x2_t) -> uint64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -14268,6 +15269,7 @@ vmull_u32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmull.p8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(pmull))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmull_p8(a: poly8x8_t, b: poly8x8_t) -> poly16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -14284,6 +15286,7 @@ vmull_p8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmull_n_s16(a: int16x4_t, b: i16) -> int32x4_t { vmull_s16(a, vdup_n_s16(b)) } @@ -14294,6 +15297,7 @@ pub unsafe fn vmull_n_s16(a: int16x4_t, b: i16) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmull_n_s32(a: int32x2_t, b: i32) -> int64x2_t { vmull_s32(a, vdup_n_s32(b)) } @@ -14304,6 +15308,7 @@ pub unsafe fn vmull_n_s32(a: int32x2_t, b: i32) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmull_n_u16(a: uint16x4_t, b: u16) -> uint32x4_t { vmull_u16(a, vdup_n_u16(b)) } @@ -14314,6 +15319,7 @@ pub unsafe fn vmull_n_u16(a: uint16x4_t, b: u16) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmull_n_u32(a: uint32x2_t, b: u32) -> uint64x2_t { vmull_u32(a, vdup_n_u32(b)) } @@ -14325,6 +15331,7 @@ pub unsafe fn vmull_n_u32(a: uint32x2_t, b: u32) -> uint64x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmull_lane_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t { static_assert_imm2!(LANE); vmull_s16(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -14337,6 +15344,7 @@ pub unsafe fn vmull_lane_s16(a: int16x4_t, b: int16x4_t) -> int #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmull_laneq_s16(a: int16x4_t, b: int16x8_t) -> int32x4_t { static_assert_imm3!(LANE); vmull_s16(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -14349,6 +15357,7 @@ pub unsafe fn vmull_laneq_s16(a: int16x4_t, b: int16x8_t) -> in #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmull_lane_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t { static_assert_imm1!(LANE); vmull_s32(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) @@ -14361,6 +15370,7 @@ pub unsafe fn vmull_lane_s32(a: int32x2_t, b: int32x2_t) -> int #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smull, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmull_laneq_s32(a: int32x2_t, b: int32x4_t) -> int64x2_t { static_assert_imm2!(LANE); vmull_s32(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) @@ -14373,6 +15383,7 @@ pub unsafe fn vmull_laneq_s32(a: int32x2_t, b: int32x4_t) -> in #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmull_lane_u16(a: uint16x4_t, b: uint16x4_t) -> uint32x4_t { static_assert_imm2!(LANE); vmull_u16(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -14385,6 +15396,7 @@ pub unsafe fn vmull_lane_u16(a: uint16x4_t, b: uint16x4_t) -> u #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmull_laneq_u16(a: uint16x4_t, b: uint16x8_t) -> uint32x4_t { static_assert_imm3!(LANE); vmull_u16(a, simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32])) @@ -14397,6 +15409,7 @@ pub unsafe fn vmull_laneq_u16(a: uint16x4_t, b: uint16x8_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmull_lane_u32(a: uint32x2_t, b: uint32x2_t) -> uint64x2_t { static_assert_imm1!(LANE); vmull_u32(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) @@ -14409,6 +15422,7 @@ pub unsafe fn vmull_lane_u32(a: uint32x2_t, b: uint32x2_t) -> u #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmull, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umull, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmull_laneq_u32(a: uint32x2_t, b: uint32x4_t) -> uint64x2_t { static_assert_imm2!(LANE); vmull_u32(a, simd_shuffle2!(b, b, [LANE as u32, LANE as u32])) @@ -14420,6 +15434,7 @@ pub unsafe fn vmull_laneq_u32(a: uint32x2_t, b: uint32x4_t) -> #[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfma))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmla))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vfma_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -14436,6 +15451,7 @@ vfma_f32_(b, c, a) #[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfma))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmla))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vfmaq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -14452,6 +15468,7 @@ vfmaq_f32_(b, c, a) #[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfma))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmla))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vfma_n_f32(a: float32x2_t, b: float32x2_t, c: f32) -> float32x2_t { vfma_f32(a, b, vdup_n_f32_vfp4(c)) } @@ -14462,6 +15479,7 @@ pub unsafe fn vfma_n_f32(a: float32x2_t, b: float32x2_t, c: f32) -> float32x2_t #[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfma))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmla))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vfmaq_n_f32(a: float32x4_t, b: float32x4_t, c: f32) -> float32x4_t { vfmaq_f32(a, b, vdupq_n_f32_vfp4(c)) } @@ -14472,6 +15490,7 @@ pub unsafe fn vfmaq_n_f32(a: float32x4_t, b: float32x4_t, c: f32) -> float32x4_t #[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfms))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vfms_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t { let b: float32x2_t = simd_neg(b); vfma_f32(a, b, c) @@ -14483,6 +15502,7 @@ pub unsafe fn vfms_f32(a: float32x2_t, b: float32x2_t, c: float32x2_t) -> float3 #[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfms))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vfmsq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t { let b: float32x4_t = simd_neg(b); vfmaq_f32(a, b, c) @@ -14494,6 +15514,7 @@ pub unsafe fn vfmsq_f32(a: float32x4_t, b: float32x4_t, c: float32x4_t) -> float #[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfms))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vfms_n_f32(a: float32x2_t, b: float32x2_t, c: f32) -> float32x2_t { vfms_f32(a, b, vdup_n_f32_vfp4(c)) } @@ -14504,6 +15525,7 @@ pub unsafe fn vfms_n_f32(a: float32x2_t, b: float32x2_t, c: f32) -> float32x2_t #[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vfms))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmls))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vfmsq_n_f32(a: float32x4_t, b: float32x4_t, c: f32) -> float32x4_t { vfmsq_f32(a, b, vdupq_n_f32_vfp4(c)) } @@ -14514,6 +15536,7 @@ pub unsafe fn vfmsq_n_f32(a: float32x4_t, b: float32x4_t, c: f32) -> float32x4_t #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsub_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { simd_sub(a, b) } @@ -14524,6 +15547,7 @@ pub unsafe fn vsub_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { simd_sub(a, b) } @@ -14534,6 +15558,7 @@ pub unsafe fn vsubq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsub_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { simd_sub(a, b) } @@ -14544,6 +15569,7 @@ pub unsafe fn vsub_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { simd_sub(a, b) } @@ -14554,6 +15580,7 @@ pub unsafe fn vsubq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsub_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { simd_sub(a, b) } @@ -14564,6 +15591,7 @@ pub unsafe fn vsub_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { simd_sub(a, b) } @@ -14574,6 +15602,7 @@ pub unsafe fn vsubq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsub_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { simd_sub(a, b) } @@ -14584,6 +15613,7 @@ pub unsafe fn vsub_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { simd_sub(a, b) } @@ -14594,6 +15624,7 @@ pub unsafe fn vsubq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsub_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { simd_sub(a, b) } @@ -14604,6 +15635,7 @@ pub unsafe fn vsub_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { simd_sub(a, b) } @@ -14614,6 +15646,7 @@ pub unsafe fn vsubq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsub_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { simd_sub(a, b) } @@ -14624,6 +15657,7 @@ pub unsafe fn vsub_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { simd_sub(a, b) } @@ -14634,6 +15668,7 @@ pub unsafe fn vsubq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i64"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsub_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { simd_sub(a, b) } @@ -14644,6 +15679,7 @@ pub unsafe fn vsub_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i64"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { simd_sub(a, b) } @@ -14654,6 +15690,7 @@ pub unsafe fn vsubq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i64"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsub_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { simd_sub(a, b) } @@ -14664,6 +15701,7 @@ pub unsafe fn vsub_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.i64"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { simd_sub(a, b) } @@ -14674,6 +15712,7 @@ pub unsafe fn vsubq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsub_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { simd_sub(a, b) } @@ -14684,6 +15723,7 @@ pub unsafe fn vsub_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vsub.f32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { simd_sub(a, b) } @@ -14694,6 +15734,7 @@ pub unsafe fn vsubq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vadd_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { simd_xor(a, b) } @@ -14704,6 +15745,7 @@ pub unsafe fn vadd_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vadd_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { simd_xor(a, b) } @@ -14714,6 +15756,7 @@ pub unsafe fn vadd_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vaddq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { simd_xor(a, b) } @@ -14724,6 +15767,7 @@ pub unsafe fn vaddq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vaddq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { simd_xor(a, b) } @@ -14734,6 +15778,7 @@ pub unsafe fn vaddq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vadd_p64(a: poly64x1_t, b: poly64x1_t) -> poly64x1_t { simd_xor(a, b) } @@ -14744,6 +15789,7 @@ pub unsafe fn vadd_p64(a: poly64x1_t, b: poly64x1_t) -> poly64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vaddq_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { simd_xor(a, b) } @@ -14754,6 +15800,7 @@ pub unsafe fn vaddq_p64(a: poly64x2_t, b: poly64x2_t) -> poly64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vaddq_p128(a: p128, b: p128) -> p128 { a ^ b } @@ -14764,6 +15811,7 @@ pub unsafe fn vaddq_p128(a: p128, b: p128) -> p128 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubhn_s16(a: int16x8_t, b: int16x8_t) -> int8x8_t { let c: i16x8 = i16x8::new(8, 8, 8, 8, 8, 8, 8, 8); simd_cast(simd_shr(simd_sub(a, b), transmute(c))) @@ -14775,6 +15823,7 @@ pub unsafe fn vsubhn_s16(a: int16x8_t, b: int16x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubhn_s32(a: int32x4_t, b: int32x4_t) -> int16x4_t { let c: i32x4 = i32x4::new(16, 16, 16, 16); simd_cast(simd_shr(simd_sub(a, b), transmute(c))) @@ -14786,6 +15835,7 @@ pub unsafe fn vsubhn_s32(a: int32x4_t, b: int32x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubhn_s64(a: int64x2_t, b: int64x2_t) -> int32x2_t { let c: i64x2 = i64x2::new(32, 32); simd_cast(simd_shr(simd_sub(a, b), transmute(c))) @@ -14797,6 +15847,7 @@ pub unsafe fn vsubhn_s64(a: int64x2_t, b: int64x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubhn_u16(a: uint16x8_t, b: uint16x8_t) -> uint8x8_t { let c: u16x8 = u16x8::new(8, 8, 8, 8, 8, 8, 8, 8); simd_cast(simd_shr(simd_sub(a, b), transmute(c))) @@ -14808,6 +15859,7 @@ pub unsafe fn vsubhn_u16(a: uint16x8_t, b: uint16x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubhn_u32(a: uint32x4_t, b: uint32x4_t) -> uint16x4_t { let c: u32x4 = u32x4::new(16, 16, 16, 16); simd_cast(simd_shr(simd_sub(a, b), transmute(c))) @@ -14819,6 +15871,7 @@ pub unsafe fn vsubhn_u32(a: uint32x4_t, b: uint32x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubhn_u64(a: uint64x2_t, b: uint64x2_t) -> uint32x2_t { let c: u64x2 = u64x2::new(32, 32); simd_cast(simd_shr(simd_sub(a, b), transmute(c))) @@ -14830,6 +15883,7 @@ pub unsafe fn vsubhn_u64(a: uint64x2_t, b: uint64x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubhn_high_s16(a: int8x8_t, b: int16x8_t, c: int16x8_t) -> int8x16_t { let d: int8x8_t = vsubhn_s16(b, c); simd_shuffle16!(a, d, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) @@ -14841,6 +15895,7 @@ pub unsafe fn vsubhn_high_s16(a: int8x8_t, b: int16x8_t, c: int16x8_t) -> int8x1 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubhn_high_s32(a: int16x4_t, b: int32x4_t, c: int32x4_t) -> int16x8_t { let d: int16x4_t = vsubhn_s32(b, c); simd_shuffle8!(a, d, [0, 1, 2, 3, 4, 5, 6, 7]) @@ -14852,6 +15907,7 @@ pub unsafe fn vsubhn_high_s32(a: int16x4_t, b: int32x4_t, c: int32x4_t) -> int16 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubhn_high_s64(a: int32x2_t, b: int64x2_t, c: int64x2_t) -> int32x4_t { let d: int32x2_t = vsubhn_s64(b, c); simd_shuffle4!(a, d, [0, 1, 2, 3]) @@ -14863,6 +15919,7 @@ pub unsafe fn vsubhn_high_s64(a: int32x2_t, b: int64x2_t, c: int64x2_t) -> int32 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubhn_high_u16(a: uint8x8_t, b: uint16x8_t, c: uint16x8_t) -> uint8x16_t { let d: uint8x8_t = vsubhn_u16(b, c); simd_shuffle16!(a, d, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) @@ -14874,6 +15931,7 @@ pub unsafe fn vsubhn_high_u16(a: uint8x8_t, b: uint16x8_t, c: uint16x8_t) -> uin #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubhn_high_u32(a: uint16x4_t, b: uint32x4_t, c: uint32x4_t) -> uint16x8_t { let d: uint16x4_t = vsubhn_u32(b, c); simd_shuffle8!(a, d, [0, 1, 2, 3, 4, 5, 6, 7]) @@ -14885,6 +15943,7 @@ pub unsafe fn vsubhn_high_u32(a: uint16x4_t, b: uint32x4_t, c: uint32x4_t) -> ui #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(subhn2))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubhn_high_u64(a: uint32x2_t, b: uint64x2_t, c: uint64x2_t) -> uint32x4_t { let d: uint32x2_t = vsubhn_u64(b, c); simd_shuffle4!(a, d, [0, 1, 2, 3]) @@ -14896,6 +15955,7 @@ pub unsafe fn vsubhn_high_u64(a: uint32x2_t, b: uint64x2_t, c: uint64x2_t) -> ui #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vhsub_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -14912,6 +15972,7 @@ vhsub_u8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vhsubq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -14928,6 +15989,7 @@ vhsubq_u8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vhsub_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -14944,6 +16006,7 @@ vhsub_u16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vhsubq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -14960,6 +16023,7 @@ vhsubq_u16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vhsub_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -14976,6 +16040,7 @@ vhsub_u32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uhsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vhsubq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -14992,6 +16057,7 @@ vhsubq_u32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vhsub_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15008,6 +16074,7 @@ vhsub_s8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vhsubq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15024,6 +16091,7 @@ vhsubq_s8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vhsub_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15040,6 +16108,7 @@ vhsub_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vhsubq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15056,6 +16125,7 @@ vhsubq_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vhsub_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15072,6 +16142,7 @@ vhsub_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vhsub.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shsub))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vhsubq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15088,6 +16159,7 @@ vhsubq_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubw))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssubw))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubw_s8(a: int16x8_t, b: int8x8_t) -> int16x8_t { simd_sub(a, simd_cast(b)) } @@ -15098,6 +16170,7 @@ pub unsafe fn vsubw_s8(a: int16x8_t, b: int8x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubw))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssubw))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubw_s16(a: int32x4_t, b: int16x4_t) -> int32x4_t { simd_sub(a, simd_cast(b)) } @@ -15108,6 +16181,7 @@ pub unsafe fn vsubw_s16(a: int32x4_t, b: int16x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubw))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssubw))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubw_s32(a: int64x2_t, b: int32x2_t) -> int64x2_t { simd_sub(a, simd_cast(b)) } @@ -15118,6 +16192,7 @@ pub unsafe fn vsubw_s32(a: int64x2_t, b: int32x2_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubw))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usubw))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubw_u8(a: uint16x8_t, b: uint8x8_t) -> uint16x8_t { simd_sub(a, simd_cast(b)) } @@ -15128,6 +16203,7 @@ pub unsafe fn vsubw_u8(a: uint16x8_t, b: uint8x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubw))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usubw))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubw_u16(a: uint32x4_t, b: uint16x4_t) -> uint32x4_t { simd_sub(a, simd_cast(b)) } @@ -15138,6 +16214,7 @@ pub unsafe fn vsubw_u16(a: uint32x4_t, b: uint16x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubw))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usubw))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubw_u32(a: uint64x2_t, b: uint32x2_t) -> uint64x2_t { simd_sub(a, simd_cast(b)) } @@ -15148,6 +16225,7 @@ pub unsafe fn vsubw_u32(a: uint64x2_t, b: uint32x2_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssubl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubl_s8(a: int8x8_t, b: int8x8_t) -> int16x8_t { let c: int16x8_t = simd_cast(a); let d: int16x8_t = simd_cast(b); @@ -15160,6 +16238,7 @@ pub unsafe fn vsubl_s8(a: int8x8_t, b: int8x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssubl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubl_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t { let c: int32x4_t = simd_cast(a); let d: int32x4_t = simd_cast(b); @@ -15172,6 +16251,7 @@ pub unsafe fn vsubl_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssubl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubl_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t { let c: int64x2_t = simd_cast(a); let d: int64x2_t = simd_cast(b); @@ -15184,6 +16264,7 @@ pub unsafe fn vsubl_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usubl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubl_u8(a: uint8x8_t, b: uint8x8_t) -> uint16x8_t { let c: uint16x8_t = simd_cast(a); let d: uint16x8_t = simd_cast(b); @@ -15196,6 +16277,7 @@ pub unsafe fn vsubl_u8(a: uint8x8_t, b: uint8x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usubl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubl_u16(a: uint16x4_t, b: uint16x4_t) -> uint32x4_t { let c: uint32x4_t = simd_cast(a); let d: uint32x4_t = simd_cast(b); @@ -15208,6 +16290,7 @@ pub unsafe fn vsubl_u16(a: uint16x4_t, b: uint16x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsubl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usubl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsubl_u32(a: uint32x2_t, b: uint32x2_t) -> uint64x2_t { let c: uint64x2_t = simd_cast(a); let d: uint64x2_t = simd_cast(b); @@ -15220,6 +16303,7 @@ pub unsafe fn vsubl_u32(a: uint32x2_t, b: uint32x2_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smax))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmax_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15236,6 +16320,7 @@ vmax_s8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smax))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmaxq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15252,6 +16337,7 @@ vmaxq_s8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smax))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmax_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15268,6 +16354,7 @@ vmax_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smax))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmaxq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15284,6 +16371,7 @@ vmaxq_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smax))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmax_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15300,6 +16388,7 @@ vmax_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smax))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmaxq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15316,6 +16405,7 @@ vmaxq_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umax))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmax_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15332,6 +16422,7 @@ vmax_u8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umax))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmaxq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15348,6 +16439,7 @@ vmaxq_u8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umax))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmax_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15364,6 +16456,7 @@ vmax_u16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umax))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmaxq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15380,6 +16473,7 @@ vmaxq_u16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umax))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmax_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15396,6 +16490,7 @@ vmax_u32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umax))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmaxq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15412,6 +16507,7 @@ vmaxq_u32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmax))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmax_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15428,6 +16524,7 @@ vmax_f32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmax))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmax))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmaxq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15444,6 +16541,7 @@ vmaxq_f32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmaxnm))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmaxnm))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmaxnm_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15460,6 +16558,7 @@ vmaxnm_f32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmaxnm))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmaxnm))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmaxnmq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15476,6 +16575,7 @@ vmaxnmq_f32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smin))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmin_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15492,6 +16592,7 @@ vmin_s8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smin))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vminq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15508,6 +16609,7 @@ vminq_s8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smin))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmin_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15524,6 +16626,7 @@ vmin_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smin))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vminq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15540,6 +16643,7 @@ vminq_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smin))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmin_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15556,6 +16660,7 @@ vmin_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smin))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vminq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15572,6 +16677,7 @@ vminq_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umin))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmin_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15588,6 +16694,7 @@ vmin_u8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umin))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vminq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15604,6 +16711,7 @@ vminq_u8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umin))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmin_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15620,6 +16728,7 @@ vmin_u16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umin))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vminq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15636,6 +16745,7 @@ vminq_u16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umin))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmin_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15652,6 +16762,7 @@ vmin_u32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umin))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vminq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15668,6 +16779,7 @@ vminq_u32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmin))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vmin_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15684,6 +16796,7 @@ vmin_f32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmin))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmin))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vminq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15700,6 +16813,7 @@ vminq_f32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vminnm))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fminnm))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vminnm_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15716,6 +16830,7 @@ vminnm_f32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "fp-armv8,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vminnm))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fminnm))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vminnmq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15732,6 +16847,7 @@ vminnmq_f32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpadd))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(faddp))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vpadd_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15748,6 +16864,7 @@ vpadd_f32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmull))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmull))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmull_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15764,6 +16881,7 @@ vqdmull_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmull))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmull))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmull_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15780,6 +16898,7 @@ vqdmull_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmull))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmull))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmull_n_s16(a: int16x4_t, b: i16) -> int32x4_t { vqdmull_s16(a, vdup_n_s16(b)) } @@ -15790,6 +16909,7 @@ pub unsafe fn vqdmull_n_s16(a: int16x4_t, b: i16) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmull))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmull))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmull_n_s32(a: int32x2_t, b: i32) -> int64x2_t { vqdmull_s32(a, vdup_n_s32(b)) } @@ -15801,6 +16921,7 @@ pub unsafe fn vqdmull_n_s32(a: int32x2_t, b: i32) -> int64x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmull, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmull, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmull_lane_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t { static_assert_imm2!(N); let b: int16x4_t = simd_shuffle4!(b, b, [N as u32, N as u32, N as u32, N as u32]); @@ -15814,6 +16935,7 @@ pub unsafe fn vqdmull_lane_s16(a: int16x4_t, b: int16x4_t) -> int3 #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmull, N = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmull, N = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmull_lane_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t { static_assert_imm1!(N); let b: int32x2_t = simd_shuffle2!(b, b, [N as u32, N as u32]); @@ -15826,6 +16948,7 @@ pub unsafe fn vqdmull_lane_s32(a: int32x2_t, b: int32x2_t) -> int6 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlal))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlal))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmlal_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t { vqaddq_s32(a, vqdmull_s16(b, c)) } @@ -15836,6 +16959,7 @@ pub unsafe fn vqdmlal_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlal))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlal))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmlal_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t { vqaddq_s64(a, vqdmull_s32(b, c)) } @@ -15846,6 +16970,7 @@ pub unsafe fn vqdmlal_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlal))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlal))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmlal_n_s16(a: int32x4_t, b: int16x4_t, c: i16) -> int32x4_t { vqaddq_s32(a, vqdmull_n_s16(b, c)) } @@ -15856,6 +16981,7 @@ pub unsafe fn vqdmlal_n_s16(a: int32x4_t, b: int16x4_t, c: i16) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlal))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlal))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmlal_n_s32(a: int64x2_t, b: int32x2_t, c: i32) -> int64x2_t { vqaddq_s64(a, vqdmull_n_s32(b, c)) } @@ -15867,6 +16993,7 @@ pub unsafe fn vqdmlal_n_s32(a: int64x2_t, b: int32x2_t, c: i32) -> int64x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlal, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlal, N = 2))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmlal_lane_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t { static_assert_imm2!(N); vqaddq_s32(a, vqdmull_lane_s16::(b, c)) @@ -15879,6 +17006,7 @@ pub unsafe fn vqdmlal_lane_s16(a: int32x4_t, b: int16x4_t, c: int1 #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlal, N = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlal, N = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmlal_lane_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t { static_assert_imm1!(N); vqaddq_s64(a, vqdmull_lane_s32::(b, c)) @@ -15890,6 +17018,7 @@ pub unsafe fn vqdmlal_lane_s32(a: int64x2_t, b: int32x2_t, c: int3 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlsl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmlsl_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t { vqsubq_s32(a, vqdmull_s16(b, c)) } @@ -15900,6 +17029,7 @@ pub unsafe fn vqdmlsl_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlsl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmlsl_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t { vqsubq_s64(a, vqdmull_s32(b, c)) } @@ -15910,6 +17040,7 @@ pub unsafe fn vqdmlsl_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlsl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmlsl_n_s16(a: int32x4_t, b: int16x4_t, c: i16) -> int32x4_t { vqsubq_s32(a, vqdmull_n_s16(b, c)) } @@ -15920,6 +17051,7 @@ pub unsafe fn vqdmlsl_n_s16(a: int32x4_t, b: int16x4_t, c: i16) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlsl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmlsl_n_s32(a: int64x2_t, b: int32x2_t, c: i32) -> int64x2_t { vqsubq_s64(a, vqdmull_n_s32(b, c)) } @@ -15931,6 +17063,7 @@ pub unsafe fn vqdmlsl_n_s32(a: int64x2_t, b: int32x2_t, c: i32) -> int64x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlsl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlsl, N = 2))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmlsl_lane_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t { static_assert_imm2!(N); vqsubq_s32(a, vqdmull_lane_s16::(b, c)) @@ -15943,6 +17076,7 @@ pub unsafe fn vqdmlsl_lane_s16(a: int32x4_t, b: int16x4_t, c: int1 #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmlsl, N = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmlsl, N = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmlsl_lane_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t { static_assert_imm1!(N); vqsubq_s64(a, vqdmull_lane_s32::(b, c)) @@ -15954,6 +17088,7 @@ pub unsafe fn vqdmlsl_lane_s32(a: int64x2_t, b: int32x2_t, c: int3 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmulh_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15970,6 +17105,7 @@ vqdmulh_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmulhq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -15986,6 +17122,7 @@ vqdmulhq_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmulh_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16002,6 +17139,7 @@ vqdmulh_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmulhq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16018,6 +17156,7 @@ vqdmulhq_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmulh_n_s16(a: int16x4_t, b: i16) -> int16x4_t { let b: int16x4_t = vdup_n_s16(b); vqdmulh_s16(a, b) @@ -16029,6 +17168,7 @@ pub unsafe fn vqdmulh_n_s16(a: int16x4_t, b: i16) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmulh_n_s32(a: int32x2_t, b: i32) -> int32x2_t { let b: int32x2_t = vdup_n_s32(b); vqdmulh_s32(a, b) @@ -16040,6 +17180,7 @@ pub unsafe fn vqdmulh_n_s32(a: int32x2_t, b: i32) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmulhq_n_s16(a: int16x8_t, b: i16) -> int16x8_t { let b: int16x8_t = vdupq_n_s16(b); vqdmulhq_s16(a, b) @@ -16051,6 +17192,7 @@ pub unsafe fn vqdmulhq_n_s16(a: int16x8_t, b: i16) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmulhq_n_s32(a: int32x4_t, b: i32) -> int32x4_t { let b: int32x4_t = vdupq_n_s32(b); vqdmulhq_s32(a, b) @@ -16063,6 +17205,7 @@ pub unsafe fn vqdmulhq_n_s32(a: int32x4_t, b: i32) -> int32x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmulhq_laneq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { static_assert_imm3!(LANE); vqdmulhq_s16(a, vdupq_n_s16(simd_extract(b, LANE as u32))) @@ -16075,6 +17218,7 @@ pub unsafe fn vqdmulhq_laneq_s16(a: int16x8_t, b: int16x8_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmulh_laneq_s16(a: int16x4_t, b: int16x8_t) -> int16x4_t { static_assert_imm3!(LANE); vqdmulh_s16(a, vdup_n_s16(simd_extract(b, LANE as u32))) @@ -16087,6 +17231,7 @@ pub unsafe fn vqdmulh_laneq_s16(a: int16x4_t, b: int16x8_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmulhq_laneq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { static_assert_imm2!(LANE); vqdmulhq_s32(a, vdupq_n_s32(simd_extract(b, LANE as u32))) @@ -16099,6 +17244,7 @@ pub unsafe fn vqdmulhq_laneq_s32(a: int32x4_t, b: int32x4_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqdmulh, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqdmulh, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqdmulh_laneq_s32(a: int32x2_t, b: int32x4_t) -> int32x2_t { static_assert_imm2!(LANE); vqdmulh_s32(a, vdup_n_s32(simd_extract(b, LANE as u32))) @@ -16110,6 +17256,7 @@ pub unsafe fn vqdmulh_laneq_s32(a: int32x2_t, b: int32x4_t) -> #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqmovn_s16(a: int16x8_t) -> int8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16126,6 +17273,7 @@ vqmovn_s16_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqmovn_s32(a: int32x4_t) -> int16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16142,6 +17290,7 @@ vqmovn_s32_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqmovn_s64(a: int64x2_t) -> int32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16158,6 +17307,7 @@ vqmovn_s64_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqxtn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqmovn_u16(a: uint16x8_t) -> uint8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16174,6 +17324,7 @@ vqmovn_u16_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqxtn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqmovn_u32(a: uint32x4_t) -> uint16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16190,6 +17341,7 @@ vqmovn_u32_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqxtn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqmovn_u64(a: uint64x2_t) -> uint32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16206,6 +17358,7 @@ vqmovn_u64_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovun))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtun))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqmovun_s16(a: int16x8_t) -> uint8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16222,6 +17375,7 @@ vqmovun_s16_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovun))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtun))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqmovun_s32(a: int32x4_t) -> uint16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16238,6 +17392,7 @@ vqmovun_s32_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqmovun))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqxtun))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqmovun_s64(a: int64x2_t) -> uint32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16254,6 +17409,7 @@ vqmovun_s64_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmulh_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16270,6 +17426,7 @@ vqrdmulh_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmulhq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16286,6 +17443,7 @@ vqrdmulhq_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmulh_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16302,6 +17460,7 @@ vqrdmulh_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmulhq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16318,6 +17477,7 @@ vqrdmulhq_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmulh_n_s16(a: int16x4_t, b: i16) -> int16x4_t { vqrdmulh_s16(a, vdup_n_s16(b)) } @@ -16328,6 +17488,7 @@ pub unsafe fn vqrdmulh_n_s16(a: int16x4_t, b: i16) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmulhq_n_s16(a: int16x8_t, b: i16) -> int16x8_t { vqrdmulhq_s16(a, vdupq_n_s16(b)) } @@ -16338,6 +17499,7 @@ pub unsafe fn vqrdmulhq_n_s16(a: int16x8_t, b: i16) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmulh_n_s32(a: int32x2_t, b: i32) -> int32x2_t { vqrdmulh_s32(a, vdup_n_s32(b)) } @@ -16348,6 +17510,7 @@ pub unsafe fn vqrdmulh_n_s32(a: int32x2_t, b: i32) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmulhq_n_s32(a: int32x4_t, b: i32) -> int32x4_t { vqrdmulhq_s32(a, vdupq_n_s32(b)) } @@ -16359,6 +17522,7 @@ pub unsafe fn vqrdmulhq_n_s32(a: int32x4_t, b: i32) -> int32x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmulh_lane_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { static_assert_imm2!(LANE); let b: int16x4_t = simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32]); @@ -16372,6 +17536,7 @@ pub unsafe fn vqrdmulh_lane_s16(a: int16x4_t, b: int16x4_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmulh_laneq_s16(a: int16x4_t, b: int16x8_t) -> int16x4_t { static_assert_imm3!(LANE); let b: int16x4_t = simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32]); @@ -16385,6 +17550,7 @@ pub unsafe fn vqrdmulh_laneq_s16(a: int16x4_t, b: int16x8_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmulhq_lane_s16(a: int16x8_t, b: int16x4_t) -> int16x8_t { static_assert_imm2!(LANE); let b: int16x8_t = simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32]); @@ -16398,6 +17564,7 @@ pub unsafe fn vqrdmulhq_lane_s16(a: int16x8_t, b: int16x4_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmulhq_laneq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { static_assert_imm3!(LANE); let b: int16x8_t = simd_shuffle8!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32, LANE as u32]); @@ -16411,6 +17578,7 @@ pub unsafe fn vqrdmulhq_laneq_s16(a: int16x8_t, b: int16x8_t) - #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmulh_lane_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { static_assert_imm1!(LANE); let b: int32x2_t = simd_shuffle2!(b, b, [LANE as u32, LANE as u32]); @@ -16424,6 +17592,7 @@ pub unsafe fn vqrdmulh_lane_s32(a: int32x2_t, b: int32x2_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmulh_laneq_s32(a: int32x2_t, b: int32x4_t) -> int32x2_t { static_assert_imm2!(LANE); let b: int32x2_t = simd_shuffle2!(b, b, [LANE as u32, LANE as u32]); @@ -16437,6 +17606,7 @@ pub unsafe fn vqrdmulh_laneq_s32(a: int32x2_t, b: int32x4_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmulhq_lane_s32(a: int32x4_t, b: int32x2_t) -> int32x4_t { static_assert_imm1!(LANE); let b: int32x4_t = simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32]); @@ -16450,6 +17620,7 @@ pub unsafe fn vqrdmulhq_lane_s32(a: int32x4_t, b: int32x2_t) -> #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmulhq_laneq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { static_assert_imm2!(LANE); let b: int32x4_t = simd_shuffle4!(b, b, [LANE as u32, LANE as u32, LANE as u32, LANE as u32]); @@ -16462,6 +17633,7 @@ pub unsafe fn vqrdmulhq_laneq_s32(a: int32x4_t, b: int32x4_t) - #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmlsh_s16(a: int16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t { vqsub_s16(a, vqrdmulh_s16(b, c)) } @@ -16472,6 +17644,7 @@ pub unsafe fn vqrdmlsh_s16(a: int16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_ #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmlshq_s16(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t { vqsubq_s16(a, vqrdmulhq_s16(b, c)) } @@ -16482,6 +17655,7 @@ pub unsafe fn vqrdmlshq_s16(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmlsh_s32(a: int32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t { vqsub_s32(a, vqrdmulh_s32(b, c)) } @@ -16492,6 +17666,7 @@ pub unsafe fn vqrdmlsh_s32(a: int32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_ #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmlshq_s32(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t { vqsubq_s32(a, vqrdmulhq_s32(b, c)) } @@ -16503,6 +17678,7 @@ pub unsafe fn vqrdmlshq_s32(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4 #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmlsh_lane_s16(a: int16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t { static_assert_imm2!(LANE); vqsub_s16(a, vqrdmulh_lane_s16::(b, c)) @@ -16515,6 +17691,7 @@ pub unsafe fn vqrdmlsh_lane_s16(a: int16x4_t, b: int16x4_t, c: #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmlsh_laneq_s16(a: int16x4_t, b: int16x4_t, c: int16x8_t) -> int16x4_t { static_assert_imm3!(LANE); vqsub_s16(a, vqrdmulh_laneq_s16::(b, c)) @@ -16527,6 +17704,7 @@ pub unsafe fn vqrdmlsh_laneq_s16(a: int16x4_t, b: int16x4_t, c: #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmlshq_lane_s16(a: int16x8_t, b: int16x8_t, c: int16x4_t) -> int16x8_t { static_assert_imm2!(LANE); vqsubq_s16(a, vqrdmulhq_lane_s16::(b, c)) @@ -16539,6 +17717,7 @@ pub unsafe fn vqrdmlshq_lane_s16(a: int16x8_t, b: int16x8_t, c: #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmlshq_laneq_s16(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t { static_assert_imm3!(LANE); vqsubq_s16(a, vqrdmulhq_laneq_s16::(b, c)) @@ -16551,6 +17730,7 @@ pub unsafe fn vqrdmlshq_laneq_s16(a: int16x8_t, b: int16x8_t, c #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmlsh_lane_s32(a: int32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t { static_assert_imm1!(LANE); vqsub_s32(a, vqrdmulh_lane_s32::(b, c)) @@ -16563,6 +17743,7 @@ pub unsafe fn vqrdmlsh_lane_s32(a: int32x2_t, b: int32x2_t, c: #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmlsh_laneq_s32(a: int32x2_t, b: int32x2_t, c: int32x4_t) -> int32x2_t { static_assert_imm2!(LANE); vqsub_s32(a, vqrdmulh_laneq_s32::(b, c)) @@ -16575,6 +17756,7 @@ pub unsafe fn vqrdmlsh_laneq_s32(a: int32x2_t, b: int32x2_t, c: #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmlshq_lane_s32(a: int32x4_t, b: int32x4_t, c: int32x2_t) -> int32x4_t { static_assert_imm1!(LANE); vqsubq_s32(a, vqrdmulhq_lane_s32::(b, c)) @@ -16587,6 +17769,7 @@ pub unsafe fn vqrdmlshq_lane_s32(a: int32x4_t, b: int32x4_t, c: #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrdmulh, LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrdmulh, LANE = 1))] #[rustc_legacy_const_generics(3)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrdmlshq_laneq_s32(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t { static_assert_imm2!(LANE); vqsubq_s32(a, vqrdmulhq_laneq_s32::(b, c)) @@ -16598,6 +17781,7 @@ pub unsafe fn vqrdmlshq_laneq_s32(a: int32x4_t, b: int32x4_t, c #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrshl_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16614,6 +17798,7 @@ vqrshl_s8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrshlq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16630,6 +17815,7 @@ vqrshlq_s8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrshl_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16646,6 +17832,7 @@ vqrshl_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrshlq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16662,6 +17849,7 @@ vqrshlq_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrshl_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16678,6 +17866,7 @@ vqrshl_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrshlq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16694,6 +17883,7 @@ vqrshlq_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrshl_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16710,6 +17900,7 @@ vqrshl_s64_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrshlq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16726,6 +17917,7 @@ vqrshlq_s64_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrshl_u8(a: uint8x8_t, b: int8x8_t) -> uint8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16742,6 +17934,7 @@ vqrshl_u8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrshlq_u8(a: uint8x16_t, b: int8x16_t) -> uint8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16758,6 +17951,7 @@ vqrshlq_u8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrshl_u16(a: uint16x4_t, b: int16x4_t) -> uint16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16774,6 +17968,7 @@ vqrshl_u16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrshlq_u16(a: uint16x8_t, b: int16x8_t) -> uint16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16790,6 +17985,7 @@ vqrshlq_u16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrshl_u32(a: uint32x2_t, b: int32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16806,6 +18002,7 @@ vqrshl_u32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrshlq_u32(a: uint32x4_t, b: int32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16822,6 +18019,7 @@ vqrshlq_u32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrshl_u64(a: uint64x1_t, b: int64x1_t) -> uint64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16838,6 +18036,7 @@ vqrshl_u64_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqrshlq_u64(a: uint64x2_t, b: int64x2_t) -> uint64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -16852,7 +18051,7 @@ vqrshlq_u64_(a, b) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrn, N = 2))] +#[cfg_attr(test, assert_instr(vqrshrn, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqrshrn_n_s16(a: int16x8_t) -> int8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); @@ -16868,8 +18067,9 @@ vqrshrn_n_s16_(a, int16x8_t(-N as i16, -N as i16, -N as i16, -N as i16, -N as i1 #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshrn, N = 2))] +#[cfg_attr(test, assert_instr(sqrshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrn_n_s16(a: int16x8_t) -> int8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); #[allow(improper_ctypes)] @@ -16884,7 +18084,7 @@ vqrshrn_n_s16_(a, N) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrn, N = 2))] +#[cfg_attr(test, assert_instr(vqrshrn, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqrshrn_n_s32(a: int32x4_t) -> int16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); @@ -16900,8 +18100,9 @@ vqrshrn_n_s32_(a, int32x4_t(-N as i32, -N as i32, -N as i32, -N as i32)) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshrn, N = 2))] +#[cfg_attr(test, assert_instr(sqrshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrn_n_s32(a: int32x4_t) -> int16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); #[allow(improper_ctypes)] @@ -16916,7 +18117,7 @@ vqrshrn_n_s32_(a, N) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrn, N = 2))] +#[cfg_attr(test, assert_instr(vqrshrn, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqrshrn_n_s64(a: int64x2_t) -> int32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); @@ -16932,8 +18133,9 @@ vqrshrn_n_s64_(a, int64x2_t(-N as i64, -N as i64)) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshrn, N = 2))] +#[cfg_attr(test, assert_instr(sqrshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrn_n_s64(a: int64x2_t) -> int32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] @@ -16948,7 +18150,7 @@ vqrshrn_n_s64_(a, N) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrn, N = 2))] +#[cfg_attr(test, assert_instr(vqrshrn, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqrshrn_n_u16(a: uint16x8_t) -> uint8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); @@ -16964,8 +18166,9 @@ vqrshrn_n_u16_(a, uint16x8_t(-N as u16, -N as u16, -N as u16, -N as u16, -N as u #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshrn, N = 2))] +#[cfg_attr(test, assert_instr(uqrshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrn_n_u16(a: uint16x8_t) -> uint8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); #[allow(improper_ctypes)] @@ -16980,7 +18183,7 @@ vqrshrn_n_u16_(a, N) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrn, N = 2))] +#[cfg_attr(test, assert_instr(vqrshrn, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqrshrn_n_u32(a: uint32x4_t) -> uint16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); @@ -16996,8 +18199,9 @@ vqrshrn_n_u32_(a, uint32x4_t(-N as u32, -N as u32, -N as u32, -N as u32)) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshrn, N = 2))] +#[cfg_attr(test, assert_instr(uqrshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrn_n_u32(a: uint32x4_t) -> uint16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); #[allow(improper_ctypes)] @@ -17012,7 +18216,7 @@ vqrshrn_n_u32_(a, N) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrn, N = 2))] +#[cfg_attr(test, assert_instr(vqrshrn, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqrshrn_n_u64(a: uint64x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); @@ -17028,8 +18232,9 @@ vqrshrn_n_u64_(a, uint64x2_t(-N as u64, -N as u64)) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqrshrn, N = 2))] +#[cfg_attr(test, assert_instr(uqrshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrn_n_u64(a: uint64x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] @@ -17044,7 +18249,7 @@ vqrshrn_n_u64_(a, N) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrun, N = 2))] +#[cfg_attr(test, assert_instr(vqrshrun, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqrshrun_n_s16(a: int16x8_t) -> uint8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); @@ -17060,8 +18265,9 @@ vqrshrun_n_s16_(a, int16x8_t(-N as i16, -N as i16, -N as i16, -N as i16, -N as i #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshrun, N = 2))] +#[cfg_attr(test, assert_instr(sqrshrun, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrun_n_s16(a: int16x8_t) -> uint8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); #[allow(improper_ctypes)] @@ -17076,7 +18282,7 @@ vqrshrun_n_s16_(a, N) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrun, N = 2))] +#[cfg_attr(test, assert_instr(vqrshrun, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqrshrun_n_s32(a: int32x4_t) -> uint16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); @@ -17092,8 +18298,9 @@ vqrshrun_n_s32_(a, int32x4_t(-N as i32, -N as i32, -N as i32, -N as i32)) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshrun, N = 2))] +#[cfg_attr(test, assert_instr(sqrshrun, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrun_n_s32(a: int32x4_t) -> uint16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); #[allow(improper_ctypes)] @@ -17108,7 +18315,7 @@ vqrshrun_n_s32_(a, N) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqrshrun, N = 2))] +#[cfg_attr(test, assert_instr(vqrshrun, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqrshrun_n_s64(a: int64x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); @@ -17124,8 +18331,9 @@ vqrshrun_n_s64_(a, int64x2_t(-N as i64, -N as i64)) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqrshrun, N = 2))] +#[cfg_attr(test, assert_instr(sqrshrun, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqrshrun_n_s64(a: int64x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] @@ -17142,6 +18350,7 @@ vqrshrun_n_s64_(a, N) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshl_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -17158,6 +18367,7 @@ vqshl_s8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshlq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -17174,6 +18384,7 @@ vqshlq_s8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshl_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -17190,6 +18401,7 @@ vqshl_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshlq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -17206,6 +18418,7 @@ vqshlq_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshl_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -17222,6 +18435,7 @@ vqshl_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshlq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -17238,6 +18452,7 @@ vqshlq_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshl_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -17254,6 +18469,7 @@ vqshl_s64_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshlq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -17270,6 +18486,7 @@ vqshlq_s64_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshl_u8(a: uint8x8_t, b: int8x8_t) -> uint8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -17286,6 +18503,7 @@ vqshl_u8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshlq_u8(a: uint8x16_t, b: int8x16_t) -> uint8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -17302,6 +18520,7 @@ vqshlq_u8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshl_u16(a: uint16x4_t, b: int16x4_t) -> uint16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -17318,6 +18537,7 @@ vqshl_u16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshlq_u16(a: uint16x8_t, b: int16x8_t) -> uint16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -17334,6 +18554,7 @@ vqshlq_u16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshl_u32(a: uint32x2_t, b: int32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -17350,6 +18571,7 @@ vqshl_u32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshlq_u32(a: uint32x4_t, b: int32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -17366,6 +18588,7 @@ vqshlq_u32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshl_u64(a: uint64x1_t, b: int64x1_t) -> uint64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -17382,6 +18605,7 @@ vqshl_u64_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshlq_u64(a: uint64x2_t, b: int64x2_t) -> uint64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -17399,9 +18623,10 @@ vqshlq_u64_(a, b) #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshl_n_s8(a: int8x8_t) -> int8x8_t { static_assert_imm3!(N); - vqshl_s8(a, vdup_n_s8(N.try_into().unwrap())) + vqshl_s8(a, vdup_n_s8(N as _)) } /// Signed saturating shift left @@ -17411,9 +18636,10 @@ pub unsafe fn vqshl_n_s8(a: int8x8_t) -> int8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshlq_n_s8(a: int8x16_t) -> int8x16_t { static_assert_imm3!(N); - vqshlq_s8(a, vdupq_n_s8(N.try_into().unwrap())) + vqshlq_s8(a, vdupq_n_s8(N as _)) } /// Signed saturating shift left @@ -17423,9 +18649,10 @@ pub unsafe fn vqshlq_n_s8(a: int8x16_t) -> int8x16_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshl_n_s16(a: int16x4_t) -> int16x4_t { static_assert_imm4!(N); - vqshl_s16(a, vdup_n_s16(N.try_into().unwrap())) + vqshl_s16(a, vdup_n_s16(N as _)) } /// Signed saturating shift left @@ -17435,9 +18662,10 @@ pub unsafe fn vqshl_n_s16(a: int16x4_t) -> int16x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshlq_n_s16(a: int16x8_t) -> int16x8_t { static_assert_imm4!(N); - vqshlq_s16(a, vdupq_n_s16(N.try_into().unwrap())) + vqshlq_s16(a, vdupq_n_s16(N as _)) } /// Signed saturating shift left @@ -17447,9 +18675,10 @@ pub unsafe fn vqshlq_n_s16(a: int16x8_t) -> int16x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshl_n_s32(a: int32x2_t) -> int32x2_t { static_assert_imm5!(N); - vqshl_s32(a, vdup_n_s32(N.try_into().unwrap())) + vqshl_s32(a, vdup_n_s32(N as _)) } /// Signed saturating shift left @@ -17459,9 +18688,10 @@ pub unsafe fn vqshl_n_s32(a: int32x2_t) -> int32x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshlq_n_s32(a: int32x4_t) -> int32x4_t { static_assert_imm5!(N); - vqshlq_s32(a, vdupq_n_s32(N.try_into().unwrap())) + vqshlq_s32(a, vdupq_n_s32(N as _)) } /// Signed saturating shift left @@ -17471,9 +18701,10 @@ pub unsafe fn vqshlq_n_s32(a: int32x4_t) -> int32x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshl_n_s64(a: int64x1_t) -> int64x1_t { static_assert_imm6!(N); - vqshl_s64(a, vdup_n_s64(N.try_into().unwrap())) + vqshl_s64(a, vdup_n_s64(N as _)) } /// Signed saturating shift left @@ -17483,9 +18714,10 @@ pub unsafe fn vqshl_n_s64(a: int64x1_t) -> int64x1_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshlq_n_s64(a: int64x2_t) -> int64x2_t { static_assert_imm6!(N); - vqshlq_s64(a, vdupq_n_s64(N.try_into().unwrap())) + vqshlq_s64(a, vdupq_n_s64(N as _)) } /// Unsigned saturating shift left @@ -17495,9 +18727,10 @@ pub unsafe fn vqshlq_n_s64(a: int64x2_t) -> int64x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshl_n_u8(a: uint8x8_t) -> uint8x8_t { static_assert_imm3!(N); - vqshl_u8(a, vdup_n_s8(N.try_into().unwrap())) + vqshl_u8(a, vdup_n_s8(N as _)) } /// Unsigned saturating shift left @@ -17507,9 +18740,10 @@ pub unsafe fn vqshl_n_u8(a: uint8x8_t) -> uint8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshlq_n_u8(a: uint8x16_t) -> uint8x16_t { static_assert_imm3!(N); - vqshlq_u8(a, vdupq_n_s8(N.try_into().unwrap())) + vqshlq_u8(a, vdupq_n_s8(N as _)) } /// Unsigned saturating shift left @@ -17519,9 +18753,10 @@ pub unsafe fn vqshlq_n_u8(a: uint8x16_t) -> uint8x16_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshl_n_u16(a: uint16x4_t) -> uint16x4_t { static_assert_imm4!(N); - vqshl_u16(a, vdup_n_s16(N.try_into().unwrap())) + vqshl_u16(a, vdup_n_s16(N as _)) } /// Unsigned saturating shift left @@ -17531,9 +18766,10 @@ pub unsafe fn vqshl_n_u16(a: uint16x4_t) -> uint16x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshlq_n_u16(a: uint16x8_t) -> uint16x8_t { static_assert_imm4!(N); - vqshlq_u16(a, vdupq_n_s16(N.try_into().unwrap())) + vqshlq_u16(a, vdupq_n_s16(N as _)) } /// Unsigned saturating shift left @@ -17543,9 +18779,10 @@ pub unsafe fn vqshlq_n_u16(a: uint16x8_t) -> uint16x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshl_n_u32(a: uint32x2_t) -> uint32x2_t { static_assert_imm5!(N); - vqshl_u32(a, vdup_n_s32(N.try_into().unwrap())) + vqshl_u32(a, vdup_n_s32(N as _)) } /// Unsigned saturating shift left @@ -17555,9 +18792,10 @@ pub unsafe fn vqshl_n_u32(a: uint32x2_t) -> uint32x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshlq_n_u32(a: uint32x4_t) -> uint32x4_t { static_assert_imm5!(N); - vqshlq_u32(a, vdupq_n_s32(N.try_into().unwrap())) + vqshlq_u32(a, vdupq_n_s32(N as _)) } /// Unsigned saturating shift left @@ -17567,9 +18805,10 @@ pub unsafe fn vqshlq_n_u32(a: uint32x4_t) -> uint32x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshl_n_u64(a: uint64x1_t) -> uint64x1_t { static_assert_imm6!(N); - vqshl_u64(a, vdup_n_s64(N.try_into().unwrap())) + vqshl_u64(a, vdup_n_s64(N as _)) } /// Unsigned saturating shift left @@ -17579,16 +18818,17 @@ pub unsafe fn vqshl_n_u64(a: uint64x1_t) -> uint64x1_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqshlq_n_u64(a: uint64x2_t) -> uint64x2_t { static_assert_imm6!(N); - vqshlq_u64(a, vdupq_n_s64(N.try_into().unwrap())) + vqshlq_u64(a, vdupq_n_s64(N as _)) } /// Signed saturating shift left unsigned #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshlu, N = 2))] +#[cfg_attr(test, assert_instr(vqshlu, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqshlu_n_s8(a: int8x8_t) -> uint8x8_t { static_assert_imm3!(N); @@ -17604,8 +18844,9 @@ vqshlu_n_s8_(a, int8x8_t(N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshlu, N = 2))] +#[cfg_attr(test, assert_instr(sqshlu, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshlu_n_s8(a: int8x8_t) -> uint8x8_t { static_assert_imm3!(N); #[allow(improper_ctypes)] @@ -17620,7 +18861,7 @@ vqshlu_n_s8_(a, int8x8_t(N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, N #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshlu, N = 2))] +#[cfg_attr(test, assert_instr(vqshlu, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqshlu_n_s16(a: int16x4_t) -> uint16x4_t { static_assert_imm4!(N); @@ -17636,8 +18877,9 @@ vqshlu_n_s16_(a, int16x4_t(N as i16, N as i16, N as i16, N as i16)) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshlu, N = 2))] +#[cfg_attr(test, assert_instr(sqshlu, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshlu_n_s16(a: int16x4_t) -> uint16x4_t { static_assert_imm4!(N); #[allow(improper_ctypes)] @@ -17652,7 +18894,7 @@ vqshlu_n_s16_(a, int16x4_t(N as i16, N as i16, N as i16, N as i16)) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshlu, N = 2))] +#[cfg_attr(test, assert_instr(vqshlu, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqshlu_n_s32(a: int32x2_t) -> uint32x2_t { static_assert_imm5!(N); @@ -17668,8 +18910,9 @@ vqshlu_n_s32_(a, int32x2_t(N as i32, N as i32)) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshlu, N = 2))] +#[cfg_attr(test, assert_instr(sqshlu, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshlu_n_s32(a: int32x2_t) -> uint32x2_t { static_assert_imm5!(N); #[allow(improper_ctypes)] @@ -17684,7 +18927,7 @@ vqshlu_n_s32_(a, int32x2_t(N as i32, N as i32)) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshlu, N = 2))] +#[cfg_attr(test, assert_instr(vqshlu, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqshlu_n_s64(a: int64x1_t) -> uint64x1_t { static_assert_imm6!(N); @@ -17700,8 +18943,9 @@ vqshlu_n_s64_(a, int64x1_t(N as i64)) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshlu, N = 2))] +#[cfg_attr(test, assert_instr(sqshlu, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshlu_n_s64(a: int64x1_t) -> uint64x1_t { static_assert_imm6!(N); #[allow(improper_ctypes)] @@ -17716,7 +18960,7 @@ vqshlu_n_s64_(a, int64x1_t(N as i64)) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshlu, N = 2))] +#[cfg_attr(test, assert_instr(vqshlu, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqshluq_n_s8(a: int8x16_t) -> uint8x16_t { static_assert_imm3!(N); @@ -17732,8 +18976,9 @@ vqshluq_n_s8_(a, int8x16_t(N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshlu, N = 2))] +#[cfg_attr(test, assert_instr(sqshlu, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshluq_n_s8(a: int8x16_t) -> uint8x16_t { static_assert_imm3!(N); #[allow(improper_ctypes)] @@ -17748,7 +18993,7 @@ vqshluq_n_s8_(a, int8x16_t(N as i8, N as i8, N as i8, N as i8, N as i8, N as i8, #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshlu, N = 2))] +#[cfg_attr(test, assert_instr(vqshlu, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqshluq_n_s16(a: int16x8_t) -> uint16x8_t { static_assert_imm4!(N); @@ -17764,8 +19009,9 @@ vqshluq_n_s16_(a, int16x8_t(N as i16, N as i16, N as i16, N as i16, N as i16, N #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshlu, N = 2))] +#[cfg_attr(test, assert_instr(sqshlu, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshluq_n_s16(a: int16x8_t) -> uint16x8_t { static_assert_imm4!(N); #[allow(improper_ctypes)] @@ -17780,7 +19026,7 @@ vqshluq_n_s16_(a, int16x8_t(N as i16, N as i16, N as i16, N as i16, N as i16, N #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshlu, N = 2))] +#[cfg_attr(test, assert_instr(vqshlu, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqshluq_n_s32(a: int32x4_t) -> uint32x4_t { static_assert_imm5!(N); @@ -17796,8 +19042,9 @@ vqshluq_n_s32_(a, int32x4_t(N as i32, N as i32, N as i32, N as i32)) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshlu, N = 2))] +#[cfg_attr(test, assert_instr(sqshlu, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshluq_n_s32(a: int32x4_t) -> uint32x4_t { static_assert_imm5!(N); #[allow(improper_ctypes)] @@ -17812,7 +19059,7 @@ vqshluq_n_s32_(a, int32x4_t(N as i32, N as i32, N as i32, N as i32)) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshlu, N = 2))] +#[cfg_attr(test, assert_instr(vqshlu, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqshluq_n_s64(a: int64x2_t) -> uint64x2_t { static_assert_imm6!(N); @@ -17828,8 +19075,9 @@ vqshluq_n_s64_(a, int64x2_t(N as i64, N as i64)) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshlu, N = 2))] +#[cfg_attr(test, assert_instr(sqshlu, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshluq_n_s64(a: int64x2_t) -> uint64x2_t { static_assert_imm6!(N); #[allow(improper_ctypes)] @@ -17844,7 +19092,7 @@ vqshluq_n_s64_(a, int64x2_t(N as i64, N as i64)) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrn, N = 2))] +#[cfg_attr(test, assert_instr(vqshrn, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqshrn_n_s16(a: int16x8_t) -> int8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); @@ -17860,8 +19108,9 @@ vqshrn_n_s16_(a, int16x8_t(-N as i16, -N as i16, -N as i16, -N as i16, -N as i16 #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshrn, N = 2))] +#[cfg_attr(test, assert_instr(sqshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrn_n_s16(a: int16x8_t) -> int8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); #[allow(improper_ctypes)] @@ -17876,7 +19125,7 @@ vqshrn_n_s16_(a, N) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrn, N = 2))] +#[cfg_attr(test, assert_instr(vqshrn, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqshrn_n_s32(a: int32x4_t) -> int16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); @@ -17892,8 +19141,9 @@ vqshrn_n_s32_(a, int32x4_t(-N as i32, -N as i32, -N as i32, -N as i32)) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshrn, N = 2))] +#[cfg_attr(test, assert_instr(sqshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrn_n_s32(a: int32x4_t) -> int16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); #[allow(improper_ctypes)] @@ -17908,7 +19158,7 @@ vqshrn_n_s32_(a, N) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrn, N = 2))] +#[cfg_attr(test, assert_instr(vqshrn, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqshrn_n_s64(a: int64x2_t) -> int32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); @@ -17924,8 +19174,9 @@ vqshrn_n_s64_(a, int64x2_t(-N as i64, -N as i64)) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshrn, N = 2))] +#[cfg_attr(test, assert_instr(sqshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrn_n_s64(a: int64x2_t) -> int32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] @@ -17940,7 +19191,7 @@ vqshrn_n_s64_(a, N) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrn, N = 2))] +#[cfg_attr(test, assert_instr(vqshrn, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqshrn_n_u16(a: uint16x8_t) -> uint8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); @@ -17956,8 +19207,9 @@ vqshrn_n_u16_(a, uint16x8_t(-N as u16, -N as u16, -N as u16, -N as u16, -N as u1 #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshrn, N = 2))] +#[cfg_attr(test, assert_instr(uqshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrn_n_u16(a: uint16x8_t) -> uint8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); #[allow(improper_ctypes)] @@ -17972,7 +19224,7 @@ vqshrn_n_u16_(a, N) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrn, N = 2))] +#[cfg_attr(test, assert_instr(vqshrn, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqshrn_n_u32(a: uint32x4_t) -> uint16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); @@ -17988,8 +19240,9 @@ vqshrn_n_u32_(a, uint32x4_t(-N as u32, -N as u32, -N as u32, -N as u32)) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshrn, N = 2))] +#[cfg_attr(test, assert_instr(uqshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrn_n_u32(a: uint32x4_t) -> uint16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); #[allow(improper_ctypes)] @@ -18004,7 +19257,7 @@ vqshrn_n_u32_(a, N) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrn, N = 2))] +#[cfg_attr(test, assert_instr(vqshrn, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqshrn_n_u64(a: uint64x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); @@ -18020,8 +19273,9 @@ vqshrn_n_u64_(a, uint64x2_t(-N as u64, -N as u64)) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uqshrn, N = 2))] +#[cfg_attr(test, assert_instr(uqshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrn_n_u64(a: uint64x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] @@ -18036,7 +19290,7 @@ vqshrn_n_u64_(a, N) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrun, N = 2))] +#[cfg_attr(test, assert_instr(vqshrun, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqshrun_n_s16(a: int16x8_t) -> uint8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); @@ -18052,8 +19306,9 @@ vqshrun_n_s16_(a, int16x8_t(-N as i16, -N as i16, -N as i16, -N as i16, -N as i1 #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshrun, N = 2))] +#[cfg_attr(test, assert_instr(sqshrun, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrun_n_s16(a: int16x8_t) -> uint8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); #[allow(improper_ctypes)] @@ -18068,7 +19323,7 @@ vqshrun_n_s16_(a, N) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrun, N = 2))] +#[cfg_attr(test, assert_instr(vqshrun, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqshrun_n_s32(a: int32x4_t) -> uint16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); @@ -18084,8 +19339,9 @@ vqshrun_n_s32_(a, int32x4_t(-N as i32, -N as i32, -N as i32, -N as i32)) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshrun, N = 2))] +#[cfg_attr(test, assert_instr(sqshrun, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrun_n_s32(a: int32x4_t) -> uint16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); #[allow(improper_ctypes)] @@ -18100,7 +19356,7 @@ vqshrun_n_s32_(a, N) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vqshrun, N = 2))] +#[cfg_attr(test, assert_instr(vqshrun, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vqshrun_n_s64(a: int64x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); @@ -18116,8 +19372,9 @@ vqshrun_n_s64_(a, int64x2_t(-N as i64, -N as i64)) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqshrun, N = 2))] +#[cfg_attr(test, assert_instr(sqshrun, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vqshrun_n_s64(a: int64x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] @@ -18134,6 +19391,7 @@ vqshrun_n_s64_(a, N) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsqrte))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frsqrte))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsqrte_f32(a: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -18150,6 +19408,7 @@ vrsqrte_f32_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsqrte))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frsqrte))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsqrteq_f32(a: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -18166,6 +19425,7 @@ vrsqrteq_f32_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsqrte))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursqrte))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsqrte_u32(a: uint32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -18182,6 +19442,7 @@ vrsqrte_u32_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsqrte))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursqrte))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsqrteq_u32(a: uint32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -18198,6 +19459,7 @@ vrsqrteq_u32_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsqrts))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frsqrts))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsqrts_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -18214,6 +19476,7 @@ vrsqrts_f32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsqrts))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frsqrts))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsqrtsq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -18230,6 +19493,7 @@ vrsqrtsq_f32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrecpe))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frecpe))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrecpe_f32(a: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -18246,6 +19510,7 @@ vrecpe_f32_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrecpe))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frecpe))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrecpeq_f32(a: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -18262,6 +19527,7 @@ vrecpeq_f32_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrecpe))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urecpe))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrecpe_u32(a: uint32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -18278,6 +19544,7 @@ vrecpe_u32_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrecpe))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urecpe))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrecpeq_u32(a: uint32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -18294,6 +19561,7 @@ vrecpeq_u32_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrecps))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frecps))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrecps_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -18310,6 +19578,7 @@ vrecps_f32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrecps))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(frecps))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrecpsq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -18326,6 +19595,7 @@ vrecpsq_f32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s8_u8(a: uint8x8_t) -> int8x8_t { transmute(a) } @@ -18336,6 +19606,7 @@ pub unsafe fn vreinterpret_s8_u8(a: uint8x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s8_p8(a: poly8x8_t) -> int8x8_t { transmute(a) } @@ -18346,6 +19617,7 @@ pub unsafe fn vreinterpret_s8_p8(a: poly8x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s16_p16(a: poly16x4_t) -> int16x4_t { transmute(a) } @@ -18356,6 +19628,7 @@ pub unsafe fn vreinterpret_s16_p16(a: poly16x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s16_u16(a: uint16x4_t) -> int16x4_t { transmute(a) } @@ -18366,6 +19639,7 @@ pub unsafe fn vreinterpret_s16_u16(a: uint16x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s32_u32(a: uint32x2_t) -> int32x2_t { transmute(a) } @@ -18376,6 +19650,7 @@ pub unsafe fn vreinterpret_s32_u32(a: uint32x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s64_u64(a: uint64x1_t) -> int64x1_t { transmute(a) } @@ -18386,6 +19661,7 @@ pub unsafe fn vreinterpret_s64_u64(a: uint64x1_t) -> int64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s8_u8(a: uint8x16_t) -> int8x16_t { transmute(a) } @@ -18396,6 +19672,7 @@ pub unsafe fn vreinterpretq_s8_u8(a: uint8x16_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s8_p8(a: poly8x16_t) -> int8x16_t { transmute(a) } @@ -18406,6 +19683,7 @@ pub unsafe fn vreinterpretq_s8_p8(a: poly8x16_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s16_p16(a: poly16x8_t) -> int16x8_t { transmute(a) } @@ -18416,6 +19694,7 @@ pub unsafe fn vreinterpretq_s16_p16(a: poly16x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s16_u16(a: uint16x8_t) -> int16x8_t { transmute(a) } @@ -18426,6 +19705,7 @@ pub unsafe fn vreinterpretq_s16_u16(a: uint16x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s32_u32(a: uint32x4_t) -> int32x4_t { transmute(a) } @@ -18436,6 +19716,7 @@ pub unsafe fn vreinterpretq_s32_u32(a: uint32x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s64_u64(a: uint64x2_t) -> int64x2_t { transmute(a) } @@ -18446,6 +19727,7 @@ pub unsafe fn vreinterpretq_s64_u64(a: uint64x2_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u8_p8(a: poly8x8_t) -> uint8x8_t { transmute(a) } @@ -18456,6 +19738,7 @@ pub unsafe fn vreinterpret_u8_p8(a: poly8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u8_s8(a: int8x8_t) -> uint8x8_t { transmute(a) } @@ -18466,6 +19749,7 @@ pub unsafe fn vreinterpret_u8_s8(a: int8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u16_p16(a: poly16x4_t) -> uint16x4_t { transmute(a) } @@ -18476,6 +19760,7 @@ pub unsafe fn vreinterpret_u16_p16(a: poly16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u16_s16(a: int16x4_t) -> uint16x4_t { transmute(a) } @@ -18486,6 +19771,7 @@ pub unsafe fn vreinterpret_u16_s16(a: int16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u32_s32(a: int32x2_t) -> uint32x2_t { transmute(a) } @@ -18496,6 +19782,7 @@ pub unsafe fn vreinterpret_u32_s32(a: int32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u64_s64(a: int64x1_t) -> uint64x1_t { transmute(a) } @@ -18506,6 +19793,7 @@ pub unsafe fn vreinterpret_u64_s64(a: int64x1_t) -> uint64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u8_p8(a: poly8x16_t) -> uint8x16_t { transmute(a) } @@ -18516,6 +19804,7 @@ pub unsafe fn vreinterpretq_u8_p8(a: poly8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u8_s8(a: int8x16_t) -> uint8x16_t { transmute(a) } @@ -18526,6 +19815,7 @@ pub unsafe fn vreinterpretq_u8_s8(a: int8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u16_p16(a: poly16x8_t) -> uint16x8_t { transmute(a) } @@ -18536,6 +19826,7 @@ pub unsafe fn vreinterpretq_u16_p16(a: poly16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u16_s16(a: int16x8_t) -> uint16x8_t { transmute(a) } @@ -18546,6 +19837,7 @@ pub unsafe fn vreinterpretq_u16_s16(a: int16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u32_s32(a: int32x4_t) -> uint32x4_t { transmute(a) } @@ -18556,6 +19848,7 @@ pub unsafe fn vreinterpretq_u32_s32(a: int32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u64_s64(a: int64x2_t) -> uint64x2_t { transmute(a) } @@ -18566,6 +19859,7 @@ pub unsafe fn vreinterpretq_u64_s64(a: int64x2_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p8_s8(a: int8x8_t) -> poly8x8_t { transmute(a) } @@ -18576,6 +19870,7 @@ pub unsafe fn vreinterpret_p8_s8(a: int8x8_t) -> poly8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p8_u8(a: uint8x8_t) -> poly8x8_t { transmute(a) } @@ -18586,6 +19881,7 @@ pub unsafe fn vreinterpret_p8_u8(a: uint8x8_t) -> poly8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p16_s16(a: int16x4_t) -> poly16x4_t { transmute(a) } @@ -18596,6 +19892,7 @@ pub unsafe fn vreinterpret_p16_s16(a: int16x4_t) -> poly16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p16_u16(a: uint16x4_t) -> poly16x4_t { transmute(a) } @@ -18606,6 +19903,7 @@ pub unsafe fn vreinterpret_p16_u16(a: uint16x4_t) -> poly16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p8_s8(a: int8x16_t) -> poly8x16_t { transmute(a) } @@ -18616,6 +19914,7 @@ pub unsafe fn vreinterpretq_p8_s8(a: int8x16_t) -> poly8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p8_u8(a: uint8x16_t) -> poly8x16_t { transmute(a) } @@ -18626,6 +19925,7 @@ pub unsafe fn vreinterpretq_p8_u8(a: uint8x16_t) -> poly8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p16_s16(a: int16x8_t) -> poly16x8_t { transmute(a) } @@ -18636,6 +19936,7 @@ pub unsafe fn vreinterpretq_p16_s16(a: int16x8_t) -> poly16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p16_u16(a: uint16x8_t) -> poly16x8_t { transmute(a) } @@ -18646,6 +19947,7 @@ pub unsafe fn vreinterpretq_p16_u16(a: uint16x8_t) -> poly16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s8_s16(a: int16x4_t) -> int8x8_t { transmute(a) } @@ -18656,6 +19958,7 @@ pub unsafe fn vreinterpret_s8_s16(a: int16x4_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s8_u16(a: uint16x4_t) -> int8x8_t { transmute(a) } @@ -18666,6 +19969,7 @@ pub unsafe fn vreinterpret_s8_u16(a: uint16x4_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s8_p16(a: poly16x4_t) -> int8x8_t { transmute(a) } @@ -18676,6 +19980,7 @@ pub unsafe fn vreinterpret_s8_p16(a: poly16x4_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s16_s32(a: int32x2_t) -> int16x4_t { transmute(a) } @@ -18686,6 +19991,7 @@ pub unsafe fn vreinterpret_s16_s32(a: int32x2_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s16_u32(a: uint32x2_t) -> int16x4_t { transmute(a) } @@ -18696,6 +20002,7 @@ pub unsafe fn vreinterpret_s16_u32(a: uint32x2_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s32_s64(a: int64x1_t) -> int32x2_t { transmute(a) } @@ -18706,6 +20013,7 @@ pub unsafe fn vreinterpret_s32_s64(a: int64x1_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s32_u64(a: uint64x1_t) -> int32x2_t { transmute(a) } @@ -18716,6 +20024,7 @@ pub unsafe fn vreinterpret_s32_u64(a: uint64x1_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s8_s16(a: int16x8_t) -> int8x16_t { transmute(a) } @@ -18726,6 +20035,7 @@ pub unsafe fn vreinterpretq_s8_s16(a: int16x8_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s8_u16(a: uint16x8_t) -> int8x16_t { transmute(a) } @@ -18736,6 +20046,7 @@ pub unsafe fn vreinterpretq_s8_u16(a: uint16x8_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s8_p16(a: poly16x8_t) -> int8x16_t { transmute(a) } @@ -18746,6 +20057,7 @@ pub unsafe fn vreinterpretq_s8_p16(a: poly16x8_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s16_s32(a: int32x4_t) -> int16x8_t { transmute(a) } @@ -18756,6 +20068,7 @@ pub unsafe fn vreinterpretq_s16_s32(a: int32x4_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s16_u32(a: uint32x4_t) -> int16x8_t { transmute(a) } @@ -18766,6 +20079,7 @@ pub unsafe fn vreinterpretq_s16_u32(a: uint32x4_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s32_s64(a: int64x2_t) -> int32x4_t { transmute(a) } @@ -18776,6 +20090,7 @@ pub unsafe fn vreinterpretq_s32_s64(a: int64x2_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s32_u64(a: uint64x2_t) -> int32x4_t { transmute(a) } @@ -18786,6 +20101,7 @@ pub unsafe fn vreinterpretq_s32_u64(a: uint64x2_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u8_p16(a: poly16x4_t) -> uint8x8_t { transmute(a) } @@ -18796,6 +20112,7 @@ pub unsafe fn vreinterpret_u8_p16(a: poly16x4_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u8_s16(a: int16x4_t) -> uint8x8_t { transmute(a) } @@ -18806,6 +20123,7 @@ pub unsafe fn vreinterpret_u8_s16(a: int16x4_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u8_u16(a: uint16x4_t) -> uint8x8_t { transmute(a) } @@ -18816,6 +20134,7 @@ pub unsafe fn vreinterpret_u8_u16(a: uint16x4_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u16_s32(a: int32x2_t) -> uint16x4_t { transmute(a) } @@ -18826,6 +20145,7 @@ pub unsafe fn vreinterpret_u16_s32(a: int32x2_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u16_u32(a: uint32x2_t) -> uint16x4_t { transmute(a) } @@ -18836,6 +20156,7 @@ pub unsafe fn vreinterpret_u16_u32(a: uint32x2_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u32_s64(a: int64x1_t) -> uint32x2_t { transmute(a) } @@ -18846,6 +20167,7 @@ pub unsafe fn vreinterpret_u32_s64(a: int64x1_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u32_u64(a: uint64x1_t) -> uint32x2_t { transmute(a) } @@ -18856,6 +20178,7 @@ pub unsafe fn vreinterpret_u32_u64(a: uint64x1_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u8_p16(a: poly16x8_t) -> uint8x16_t { transmute(a) } @@ -18866,6 +20189,7 @@ pub unsafe fn vreinterpretq_u8_p16(a: poly16x8_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u8_s16(a: int16x8_t) -> uint8x16_t { transmute(a) } @@ -18876,6 +20200,7 @@ pub unsafe fn vreinterpretq_u8_s16(a: int16x8_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u8_u16(a: uint16x8_t) -> uint8x16_t { transmute(a) } @@ -18886,6 +20211,7 @@ pub unsafe fn vreinterpretq_u8_u16(a: uint16x8_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u16_s32(a: int32x4_t) -> uint16x8_t { transmute(a) } @@ -18896,6 +20222,7 @@ pub unsafe fn vreinterpretq_u16_s32(a: int32x4_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u16_u32(a: uint32x4_t) -> uint16x8_t { transmute(a) } @@ -18906,6 +20233,7 @@ pub unsafe fn vreinterpretq_u16_u32(a: uint32x4_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u32_s64(a: int64x2_t) -> uint32x4_t { transmute(a) } @@ -18916,6 +20244,7 @@ pub unsafe fn vreinterpretq_u32_s64(a: int64x2_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u32_u64(a: uint64x2_t) -> uint32x4_t { transmute(a) } @@ -18926,6 +20255,7 @@ pub unsafe fn vreinterpretq_u32_u64(a: uint64x2_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p8_p16(a: poly16x4_t) -> poly8x8_t { transmute(a) } @@ -18936,6 +20266,7 @@ pub unsafe fn vreinterpret_p8_p16(a: poly16x4_t) -> poly8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p8_s16(a: int16x4_t) -> poly8x8_t { transmute(a) } @@ -18946,6 +20277,7 @@ pub unsafe fn vreinterpret_p8_s16(a: int16x4_t) -> poly8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p8_u16(a: uint16x4_t) -> poly8x8_t { transmute(a) } @@ -18956,6 +20288,7 @@ pub unsafe fn vreinterpret_p8_u16(a: uint16x4_t) -> poly8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p16_s32(a: int32x2_t) -> poly16x4_t { transmute(a) } @@ -18966,6 +20299,7 @@ pub unsafe fn vreinterpret_p16_s32(a: int32x2_t) -> poly16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p16_u32(a: uint32x2_t) -> poly16x4_t { transmute(a) } @@ -18976,6 +20310,7 @@ pub unsafe fn vreinterpret_p16_u32(a: uint32x2_t) -> poly16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p8_p16(a: poly16x8_t) -> poly8x16_t { transmute(a) } @@ -18986,6 +20321,7 @@ pub unsafe fn vreinterpretq_p8_p16(a: poly16x8_t) -> poly8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p8_s16(a: int16x8_t) -> poly8x16_t { transmute(a) } @@ -18996,6 +20332,7 @@ pub unsafe fn vreinterpretq_p8_s16(a: int16x8_t) -> poly8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p8_u16(a: uint16x8_t) -> poly8x16_t { transmute(a) } @@ -19006,6 +20343,7 @@ pub unsafe fn vreinterpretq_p8_u16(a: uint16x8_t) -> poly8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p16_s32(a: int32x4_t) -> poly16x8_t { transmute(a) } @@ -19016,6 +20354,7 @@ pub unsafe fn vreinterpretq_p16_s32(a: int32x4_t) -> poly16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p16_u32(a: uint32x4_t) -> poly16x8_t { transmute(a) } @@ -19026,6 +20365,7 @@ pub unsafe fn vreinterpretq_p16_u32(a: uint32x4_t) -> poly16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s32_p64(a: poly64x1_t) -> int32x2_t { transmute(a) } @@ -19036,6 +20376,7 @@ pub unsafe fn vreinterpret_s32_p64(a: poly64x1_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u32_p64(a: poly64x1_t) -> uint32x2_t { transmute(a) } @@ -19046,6 +20387,7 @@ pub unsafe fn vreinterpret_u32_p64(a: poly64x1_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s32_p64(a: poly64x2_t) -> int32x4_t { transmute(a) } @@ -19056,6 +20398,7 @@ pub unsafe fn vreinterpretq_s32_p64(a: poly64x2_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u32_p64(a: poly64x2_t) -> uint32x4_t { transmute(a) } @@ -19066,6 +20409,7 @@ pub unsafe fn vreinterpretq_u32_p64(a: poly64x2_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s64_p128(a: p128) -> int64x2_t { transmute(a) } @@ -19076,6 +20420,7 @@ pub unsafe fn vreinterpretq_s64_p128(a: p128) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u64_p128(a: p128) -> uint64x2_t { transmute(a) } @@ -19086,6 +20431,7 @@ pub unsafe fn vreinterpretq_u64_p128(a: p128) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p64_p128(a: p128) -> poly64x2_t { transmute(a) } @@ -19096,6 +20442,7 @@ pub unsafe fn vreinterpretq_p64_p128(a: p128) -> poly64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s16_p8(a: poly8x8_t) -> int16x4_t { transmute(a) } @@ -19106,6 +20453,7 @@ pub unsafe fn vreinterpret_s16_p8(a: poly8x8_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s16_s8(a: int8x8_t) -> int16x4_t { transmute(a) } @@ -19116,6 +20464,7 @@ pub unsafe fn vreinterpret_s16_s8(a: int8x8_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s16_u8(a: uint8x8_t) -> int16x4_t { transmute(a) } @@ -19126,6 +20475,7 @@ pub unsafe fn vreinterpret_s16_u8(a: uint8x8_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s32_p16(a: poly16x4_t) -> int32x2_t { transmute(a) } @@ -19136,6 +20486,7 @@ pub unsafe fn vreinterpret_s32_p16(a: poly16x4_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s32_s16(a: int16x4_t) -> int32x2_t { transmute(a) } @@ -19146,6 +20497,7 @@ pub unsafe fn vreinterpret_s32_s16(a: int16x4_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s32_u16(a: uint16x4_t) -> int32x2_t { transmute(a) } @@ -19156,6 +20508,7 @@ pub unsafe fn vreinterpret_s32_u16(a: uint16x4_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s64_s32(a: int32x2_t) -> int64x1_t { transmute(a) } @@ -19166,6 +20519,7 @@ pub unsafe fn vreinterpret_s64_s32(a: int32x2_t) -> int64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s64_u32(a: uint32x2_t) -> int64x1_t { transmute(a) } @@ -19176,6 +20530,7 @@ pub unsafe fn vreinterpret_s64_u32(a: uint32x2_t) -> int64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s16_p8(a: poly8x16_t) -> int16x8_t { transmute(a) } @@ -19186,6 +20541,7 @@ pub unsafe fn vreinterpretq_s16_p8(a: poly8x16_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s16_s8(a: int8x16_t) -> int16x8_t { transmute(a) } @@ -19196,6 +20552,7 @@ pub unsafe fn vreinterpretq_s16_s8(a: int8x16_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s16_u8(a: uint8x16_t) -> int16x8_t { transmute(a) } @@ -19206,6 +20563,7 @@ pub unsafe fn vreinterpretq_s16_u8(a: uint8x16_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s32_p16(a: poly16x8_t) -> int32x4_t { transmute(a) } @@ -19216,6 +20574,7 @@ pub unsafe fn vreinterpretq_s32_p16(a: poly16x8_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s32_s16(a: int16x8_t) -> int32x4_t { transmute(a) } @@ -19226,6 +20585,7 @@ pub unsafe fn vreinterpretq_s32_s16(a: int16x8_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s32_u16(a: uint16x8_t) -> int32x4_t { transmute(a) } @@ -19236,6 +20596,7 @@ pub unsafe fn vreinterpretq_s32_u16(a: uint16x8_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s64_s32(a: int32x4_t) -> int64x2_t { transmute(a) } @@ -19246,6 +20607,7 @@ pub unsafe fn vreinterpretq_s64_s32(a: int32x4_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s64_u32(a: uint32x4_t) -> int64x2_t { transmute(a) } @@ -19256,6 +20618,7 @@ pub unsafe fn vreinterpretq_s64_u32(a: uint32x4_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u16_p8(a: poly8x8_t) -> uint16x4_t { transmute(a) } @@ -19266,6 +20629,7 @@ pub unsafe fn vreinterpret_u16_p8(a: poly8x8_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u16_s8(a: int8x8_t) -> uint16x4_t { transmute(a) } @@ -19276,6 +20640,7 @@ pub unsafe fn vreinterpret_u16_s8(a: int8x8_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u16_u8(a: uint8x8_t) -> uint16x4_t { transmute(a) } @@ -19286,6 +20651,7 @@ pub unsafe fn vreinterpret_u16_u8(a: uint8x8_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u32_p16(a: poly16x4_t) -> uint32x2_t { transmute(a) } @@ -19296,6 +20662,7 @@ pub unsafe fn vreinterpret_u32_p16(a: poly16x4_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u32_s16(a: int16x4_t) -> uint32x2_t { transmute(a) } @@ -19306,6 +20673,7 @@ pub unsafe fn vreinterpret_u32_s16(a: int16x4_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u32_u16(a: uint16x4_t) -> uint32x2_t { transmute(a) } @@ -19316,6 +20684,7 @@ pub unsafe fn vreinterpret_u32_u16(a: uint16x4_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u64_s32(a: int32x2_t) -> uint64x1_t { transmute(a) } @@ -19326,6 +20695,7 @@ pub unsafe fn vreinterpret_u64_s32(a: int32x2_t) -> uint64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u64_u32(a: uint32x2_t) -> uint64x1_t { transmute(a) } @@ -19336,6 +20706,7 @@ pub unsafe fn vreinterpret_u64_u32(a: uint32x2_t) -> uint64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u16_p8(a: poly8x16_t) -> uint16x8_t { transmute(a) } @@ -19346,6 +20717,7 @@ pub unsafe fn vreinterpretq_u16_p8(a: poly8x16_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u16_s8(a: int8x16_t) -> uint16x8_t { transmute(a) } @@ -19356,6 +20728,7 @@ pub unsafe fn vreinterpretq_u16_s8(a: int8x16_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u16_u8(a: uint8x16_t) -> uint16x8_t { transmute(a) } @@ -19366,6 +20739,7 @@ pub unsafe fn vreinterpretq_u16_u8(a: uint8x16_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u32_p16(a: poly16x8_t) -> uint32x4_t { transmute(a) } @@ -19376,6 +20750,7 @@ pub unsafe fn vreinterpretq_u32_p16(a: poly16x8_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u32_s16(a: int16x8_t) -> uint32x4_t { transmute(a) } @@ -19386,6 +20761,7 @@ pub unsafe fn vreinterpretq_u32_s16(a: int16x8_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u32_u16(a: uint16x8_t) -> uint32x4_t { transmute(a) } @@ -19396,6 +20772,7 @@ pub unsafe fn vreinterpretq_u32_u16(a: uint16x8_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u64_s32(a: int32x4_t) -> uint64x2_t { transmute(a) } @@ -19406,6 +20783,7 @@ pub unsafe fn vreinterpretq_u64_s32(a: int32x4_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u64_u32(a: uint32x4_t) -> uint64x2_t { transmute(a) } @@ -19416,6 +20794,7 @@ pub unsafe fn vreinterpretq_u64_u32(a: uint32x4_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p16_p8(a: poly8x8_t) -> poly16x4_t { transmute(a) } @@ -19426,6 +20805,7 @@ pub unsafe fn vreinterpret_p16_p8(a: poly8x8_t) -> poly16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p16_s8(a: int8x8_t) -> poly16x4_t { transmute(a) } @@ -19436,6 +20816,7 @@ pub unsafe fn vreinterpret_p16_s8(a: int8x8_t) -> poly16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p16_u8(a: uint8x8_t) -> poly16x4_t { transmute(a) } @@ -19446,6 +20827,7 @@ pub unsafe fn vreinterpret_p16_u8(a: uint8x8_t) -> poly16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p16_p8(a: poly8x16_t) -> poly16x8_t { transmute(a) } @@ -19456,6 +20838,7 @@ pub unsafe fn vreinterpretq_p16_p8(a: poly8x16_t) -> poly16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p16_s8(a: int8x16_t) -> poly16x8_t { transmute(a) } @@ -19466,6 +20849,7 @@ pub unsafe fn vreinterpretq_p16_s8(a: int8x16_t) -> poly16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p16_u8(a: uint8x16_t) -> poly16x8_t { transmute(a) } @@ -19476,6 +20860,7 @@ pub unsafe fn vreinterpretq_p16_u8(a: uint8x16_t) -> poly16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p64_s32(a: int32x2_t) -> poly64x1_t { transmute(a) } @@ -19486,6 +20871,7 @@ pub unsafe fn vreinterpret_p64_s32(a: int32x2_t) -> poly64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p64_u32(a: uint32x2_t) -> poly64x1_t { transmute(a) } @@ -19496,6 +20882,7 @@ pub unsafe fn vreinterpret_p64_u32(a: uint32x2_t) -> poly64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p64_s32(a: int32x4_t) -> poly64x2_t { transmute(a) } @@ -19506,6 +20893,7 @@ pub unsafe fn vreinterpretq_p64_s32(a: int32x4_t) -> poly64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p64_u32(a: uint32x4_t) -> poly64x2_t { transmute(a) } @@ -19516,6 +20904,7 @@ pub unsafe fn vreinterpretq_p64_u32(a: uint32x4_t) -> poly64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p128_s64(a: int64x2_t) -> p128 { transmute(a) } @@ -19526,6 +20915,7 @@ pub unsafe fn vreinterpretq_p128_s64(a: int64x2_t) -> p128 { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p128_u64(a: uint64x2_t) -> p128 { transmute(a) } @@ -19536,6 +20926,7 @@ pub unsafe fn vreinterpretq_p128_u64(a: uint64x2_t) -> p128 { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p128_p64(a: poly64x2_t) -> p128 { transmute(a) } @@ -19546,6 +20937,7 @@ pub unsafe fn vreinterpretq_p128_p64(a: poly64x2_t) -> p128 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s8_s32(a: int32x2_t) -> int8x8_t { transmute(a) } @@ -19556,6 +20948,7 @@ pub unsafe fn vreinterpret_s8_s32(a: int32x2_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s8_u32(a: uint32x2_t) -> int8x8_t { transmute(a) } @@ -19566,6 +20959,7 @@ pub unsafe fn vreinterpret_s8_u32(a: uint32x2_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s16_s64(a: int64x1_t) -> int16x4_t { transmute(a) } @@ -19576,6 +20970,7 @@ pub unsafe fn vreinterpret_s16_s64(a: int64x1_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s16_u64(a: uint64x1_t) -> int16x4_t { transmute(a) } @@ -19586,6 +20981,7 @@ pub unsafe fn vreinterpret_s16_u64(a: uint64x1_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s8_s32(a: int32x4_t) -> int8x16_t { transmute(a) } @@ -19596,6 +20992,7 @@ pub unsafe fn vreinterpretq_s8_s32(a: int32x4_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s8_u32(a: uint32x4_t) -> int8x16_t { transmute(a) } @@ -19606,6 +21003,7 @@ pub unsafe fn vreinterpretq_s8_u32(a: uint32x4_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s16_s64(a: int64x2_t) -> int16x8_t { transmute(a) } @@ -19616,6 +21014,7 @@ pub unsafe fn vreinterpretq_s16_s64(a: int64x2_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s16_u64(a: uint64x2_t) -> int16x8_t { transmute(a) } @@ -19626,6 +21025,7 @@ pub unsafe fn vreinterpretq_s16_u64(a: uint64x2_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u8_s32(a: int32x2_t) -> uint8x8_t { transmute(a) } @@ -19636,6 +21036,7 @@ pub unsafe fn vreinterpret_u8_s32(a: int32x2_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u8_u32(a: uint32x2_t) -> uint8x8_t { transmute(a) } @@ -19646,6 +21047,7 @@ pub unsafe fn vreinterpret_u8_u32(a: uint32x2_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u16_s64(a: int64x1_t) -> uint16x4_t { transmute(a) } @@ -19656,6 +21058,7 @@ pub unsafe fn vreinterpret_u16_s64(a: int64x1_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u16_u64(a: uint64x1_t) -> uint16x4_t { transmute(a) } @@ -19666,6 +21069,7 @@ pub unsafe fn vreinterpret_u16_u64(a: uint64x1_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u8_s32(a: int32x4_t) -> uint8x16_t { transmute(a) } @@ -19676,6 +21080,7 @@ pub unsafe fn vreinterpretq_u8_s32(a: int32x4_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u8_u32(a: uint32x4_t) -> uint8x16_t { transmute(a) } @@ -19686,6 +21091,7 @@ pub unsafe fn vreinterpretq_u8_u32(a: uint32x4_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u16_s64(a: int64x2_t) -> uint16x8_t { transmute(a) } @@ -19696,6 +21102,7 @@ pub unsafe fn vreinterpretq_u16_s64(a: int64x2_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u16_u64(a: uint64x2_t) -> uint16x8_t { transmute(a) } @@ -19706,6 +21113,7 @@ pub unsafe fn vreinterpretq_u16_u64(a: uint64x2_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p8_s32(a: int32x2_t) -> poly8x8_t { transmute(a) } @@ -19716,6 +21124,7 @@ pub unsafe fn vreinterpret_p8_s32(a: int32x2_t) -> poly8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p8_u32(a: uint32x2_t) -> poly8x8_t { transmute(a) } @@ -19726,6 +21135,7 @@ pub unsafe fn vreinterpret_p8_u32(a: uint32x2_t) -> poly8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p16_s64(a: int64x1_t) -> poly16x4_t { transmute(a) } @@ -19736,6 +21146,7 @@ pub unsafe fn vreinterpret_p16_s64(a: int64x1_t) -> poly16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p16_u64(a: uint64x1_t) -> poly16x4_t { transmute(a) } @@ -19746,6 +21157,7 @@ pub unsafe fn vreinterpret_p16_u64(a: uint64x1_t) -> poly16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p8_s32(a: int32x4_t) -> poly8x16_t { transmute(a) } @@ -19756,6 +21168,7 @@ pub unsafe fn vreinterpretq_p8_s32(a: int32x4_t) -> poly8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p8_u32(a: uint32x4_t) -> poly8x16_t { transmute(a) } @@ -19766,6 +21179,7 @@ pub unsafe fn vreinterpretq_p8_u32(a: uint32x4_t) -> poly8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p16_s64(a: int64x2_t) -> poly16x8_t { transmute(a) } @@ -19776,6 +21190,7 @@ pub unsafe fn vreinterpretq_p16_s64(a: int64x2_t) -> poly16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p16_u64(a: uint64x2_t) -> poly16x8_t { transmute(a) } @@ -19786,6 +21201,7 @@ pub unsafe fn vreinterpretq_p16_u64(a: uint64x2_t) -> poly16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s16_p64(a: poly64x1_t) -> int16x4_t { transmute(a) } @@ -19796,6 +21212,7 @@ pub unsafe fn vreinterpret_s16_p64(a: poly64x1_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u16_p64(a: poly64x1_t) -> uint16x4_t { transmute(a) } @@ -19806,6 +21223,7 @@ pub unsafe fn vreinterpret_u16_p64(a: poly64x1_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p16_p64(a: poly64x1_t) -> poly16x4_t { transmute(a) } @@ -19816,6 +21234,7 @@ pub unsafe fn vreinterpret_p16_p64(a: poly64x1_t) -> poly16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s16_p64(a: poly64x2_t) -> int16x8_t { transmute(a) } @@ -19826,6 +21245,7 @@ pub unsafe fn vreinterpretq_s16_p64(a: poly64x2_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u16_p64(a: poly64x2_t) -> uint16x8_t { transmute(a) } @@ -19836,6 +21256,7 @@ pub unsafe fn vreinterpretq_u16_p64(a: poly64x2_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p16_p64(a: poly64x2_t) -> poly16x8_t { transmute(a) } @@ -19846,6 +21267,7 @@ pub unsafe fn vreinterpretq_p16_p64(a: poly64x2_t) -> poly16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s32_p128(a: p128) -> int32x4_t { transmute(a) } @@ -19856,6 +21278,7 @@ pub unsafe fn vreinterpretq_s32_p128(a: p128) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u32_p128(a: p128) -> uint32x4_t { transmute(a) } @@ -19866,6 +21289,7 @@ pub unsafe fn vreinterpretq_u32_p128(a: p128) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s32_p8(a: poly8x8_t) -> int32x2_t { transmute(a) } @@ -19876,6 +21300,7 @@ pub unsafe fn vreinterpret_s32_p8(a: poly8x8_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s32_s8(a: int8x8_t) -> int32x2_t { transmute(a) } @@ -19886,6 +21311,7 @@ pub unsafe fn vreinterpret_s32_s8(a: int8x8_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s32_u8(a: uint8x8_t) -> int32x2_t { transmute(a) } @@ -19896,6 +21322,7 @@ pub unsafe fn vreinterpret_s32_u8(a: uint8x8_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s64_p16(a: poly16x4_t) -> int64x1_t { transmute(a) } @@ -19906,6 +21333,7 @@ pub unsafe fn vreinterpret_s64_p16(a: poly16x4_t) -> int64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s64_s16(a: int16x4_t) -> int64x1_t { transmute(a) } @@ -19916,6 +21344,7 @@ pub unsafe fn vreinterpret_s64_s16(a: int16x4_t) -> int64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s64_u16(a: uint16x4_t) -> int64x1_t { transmute(a) } @@ -19926,6 +21355,7 @@ pub unsafe fn vreinterpret_s64_u16(a: uint16x4_t) -> int64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s32_p8(a: poly8x16_t) -> int32x4_t { transmute(a) } @@ -19936,6 +21366,7 @@ pub unsafe fn vreinterpretq_s32_p8(a: poly8x16_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s32_s8(a: int8x16_t) -> int32x4_t { transmute(a) } @@ -19946,6 +21377,7 @@ pub unsafe fn vreinterpretq_s32_s8(a: int8x16_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s32_u8(a: uint8x16_t) -> int32x4_t { transmute(a) } @@ -19956,6 +21388,7 @@ pub unsafe fn vreinterpretq_s32_u8(a: uint8x16_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s64_p16(a: poly16x8_t) -> int64x2_t { transmute(a) } @@ -19966,6 +21399,7 @@ pub unsafe fn vreinterpretq_s64_p16(a: poly16x8_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s64_s16(a: int16x8_t) -> int64x2_t { transmute(a) } @@ -19976,6 +21410,7 @@ pub unsafe fn vreinterpretq_s64_s16(a: int16x8_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s64_u16(a: uint16x8_t) -> int64x2_t { transmute(a) } @@ -19986,6 +21421,7 @@ pub unsafe fn vreinterpretq_s64_u16(a: uint16x8_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u32_p8(a: poly8x8_t) -> uint32x2_t { transmute(a) } @@ -19996,6 +21432,7 @@ pub unsafe fn vreinterpret_u32_p8(a: poly8x8_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u32_s8(a: int8x8_t) -> uint32x2_t { transmute(a) } @@ -20006,6 +21443,7 @@ pub unsafe fn vreinterpret_u32_s8(a: int8x8_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u32_u8(a: uint8x8_t) -> uint32x2_t { transmute(a) } @@ -20016,6 +21454,7 @@ pub unsafe fn vreinterpret_u32_u8(a: uint8x8_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u64_p16(a: poly16x4_t) -> uint64x1_t { transmute(a) } @@ -20026,6 +21465,7 @@ pub unsafe fn vreinterpret_u64_p16(a: poly16x4_t) -> uint64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u64_s16(a: int16x4_t) -> uint64x1_t { transmute(a) } @@ -20036,6 +21476,7 @@ pub unsafe fn vreinterpret_u64_s16(a: int16x4_t) -> uint64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u64_u16(a: uint16x4_t) -> uint64x1_t { transmute(a) } @@ -20046,6 +21487,7 @@ pub unsafe fn vreinterpret_u64_u16(a: uint16x4_t) -> uint64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u32_p8(a: poly8x16_t) -> uint32x4_t { transmute(a) } @@ -20056,6 +21498,7 @@ pub unsafe fn vreinterpretq_u32_p8(a: poly8x16_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u32_s8(a: int8x16_t) -> uint32x4_t { transmute(a) } @@ -20066,6 +21509,7 @@ pub unsafe fn vreinterpretq_u32_s8(a: int8x16_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u32_u8(a: uint8x16_t) -> uint32x4_t { transmute(a) } @@ -20076,6 +21520,7 @@ pub unsafe fn vreinterpretq_u32_u8(a: uint8x16_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u64_p16(a: poly16x8_t) -> uint64x2_t { transmute(a) } @@ -20086,6 +21531,7 @@ pub unsafe fn vreinterpretq_u64_p16(a: poly16x8_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u64_s16(a: int16x8_t) -> uint64x2_t { transmute(a) } @@ -20096,6 +21542,7 @@ pub unsafe fn vreinterpretq_u64_s16(a: int16x8_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u64_u16(a: uint16x8_t) -> uint64x2_t { transmute(a) } @@ -20106,6 +21553,7 @@ pub unsafe fn vreinterpretq_u64_u16(a: uint16x8_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p64_p16(a: poly16x4_t) -> poly64x1_t { transmute(a) } @@ -20116,6 +21564,7 @@ pub unsafe fn vreinterpret_p64_p16(a: poly16x4_t) -> poly64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p64_s16(a: int16x4_t) -> poly64x1_t { transmute(a) } @@ -20126,6 +21575,7 @@ pub unsafe fn vreinterpret_p64_s16(a: int16x4_t) -> poly64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p64_u16(a: uint16x4_t) -> poly64x1_t { transmute(a) } @@ -20136,6 +21586,7 @@ pub unsafe fn vreinterpret_p64_u16(a: uint16x4_t) -> poly64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p64_p16(a: poly16x8_t) -> poly64x2_t { transmute(a) } @@ -20146,6 +21597,7 @@ pub unsafe fn vreinterpretq_p64_p16(a: poly16x8_t) -> poly64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p64_s16(a: int16x8_t) -> poly64x2_t { transmute(a) } @@ -20156,6 +21608,7 @@ pub unsafe fn vreinterpretq_p64_s16(a: int16x8_t) -> poly64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p64_u16(a: uint16x8_t) -> poly64x2_t { transmute(a) } @@ -20166,6 +21619,7 @@ pub unsafe fn vreinterpretq_p64_u16(a: uint16x8_t) -> poly64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p128_s32(a: int32x4_t) -> p128 { transmute(a) } @@ -20176,6 +21630,7 @@ pub unsafe fn vreinterpretq_p128_s32(a: int32x4_t) -> p128 { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p128_u32(a: uint32x4_t) -> p128 { transmute(a) } @@ -20186,6 +21641,7 @@ pub unsafe fn vreinterpretq_p128_u32(a: uint32x4_t) -> p128 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s8_s64(a: int64x1_t) -> int8x8_t { transmute(a) } @@ -20196,6 +21652,7 @@ pub unsafe fn vreinterpret_s8_s64(a: int64x1_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s8_u64(a: uint64x1_t) -> int8x8_t { transmute(a) } @@ -20206,6 +21663,7 @@ pub unsafe fn vreinterpret_s8_u64(a: uint64x1_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u8_s64(a: int64x1_t) -> uint8x8_t { transmute(a) } @@ -20216,6 +21674,7 @@ pub unsafe fn vreinterpret_u8_s64(a: int64x1_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u8_u64(a: uint64x1_t) -> uint8x8_t { transmute(a) } @@ -20226,6 +21685,7 @@ pub unsafe fn vreinterpret_u8_u64(a: uint64x1_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p8_s64(a: int64x1_t) -> poly8x8_t { transmute(a) } @@ -20236,6 +21696,7 @@ pub unsafe fn vreinterpret_p8_s64(a: int64x1_t) -> poly8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p8_u64(a: uint64x1_t) -> poly8x8_t { transmute(a) } @@ -20246,6 +21707,7 @@ pub unsafe fn vreinterpret_p8_u64(a: uint64x1_t) -> poly8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s8_s64(a: int64x2_t) -> int8x16_t { transmute(a) } @@ -20256,6 +21718,7 @@ pub unsafe fn vreinterpretq_s8_s64(a: int64x2_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s8_u64(a: uint64x2_t) -> int8x16_t { transmute(a) } @@ -20266,6 +21729,7 @@ pub unsafe fn vreinterpretq_s8_u64(a: uint64x2_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u8_s64(a: int64x2_t) -> uint8x16_t { transmute(a) } @@ -20276,6 +21740,7 @@ pub unsafe fn vreinterpretq_u8_s64(a: int64x2_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u8_u64(a: uint64x2_t) -> uint8x16_t { transmute(a) } @@ -20286,6 +21751,7 @@ pub unsafe fn vreinterpretq_u8_u64(a: uint64x2_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p8_s64(a: int64x2_t) -> poly8x16_t { transmute(a) } @@ -20296,6 +21762,7 @@ pub unsafe fn vreinterpretq_p8_s64(a: int64x2_t) -> poly8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p8_u64(a: uint64x2_t) -> poly8x16_t { transmute(a) } @@ -20306,6 +21773,7 @@ pub unsafe fn vreinterpretq_p8_u64(a: uint64x2_t) -> poly8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s8_p64(a: poly64x1_t) -> int8x8_t { transmute(a) } @@ -20316,6 +21784,7 @@ pub unsafe fn vreinterpret_s8_p64(a: poly64x1_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u8_p64(a: poly64x1_t) -> uint8x8_t { transmute(a) } @@ -20326,6 +21795,7 @@ pub unsafe fn vreinterpret_u8_p64(a: poly64x1_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p8_p64(a: poly64x1_t) -> poly8x8_t { transmute(a) } @@ -20336,6 +21806,7 @@ pub unsafe fn vreinterpret_p8_p64(a: poly64x1_t) -> poly8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s8_p64(a: poly64x2_t) -> int8x16_t { transmute(a) } @@ -20346,6 +21817,7 @@ pub unsafe fn vreinterpretq_s8_p64(a: poly64x2_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u8_p64(a: poly64x2_t) -> uint8x16_t { transmute(a) } @@ -20356,6 +21828,7 @@ pub unsafe fn vreinterpretq_u8_p64(a: poly64x2_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p8_p64(a: poly64x2_t) -> poly8x16_t { transmute(a) } @@ -20366,6 +21839,7 @@ pub unsafe fn vreinterpretq_p8_p64(a: poly64x2_t) -> poly8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s16_p128(a: p128) -> int16x8_t { transmute(a) } @@ -20376,6 +21850,7 @@ pub unsafe fn vreinterpretq_s16_p128(a: p128) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u16_p128(a: p128) -> uint16x8_t { transmute(a) } @@ -20386,6 +21861,7 @@ pub unsafe fn vreinterpretq_u16_p128(a: p128) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p16_p128(a: p128) -> poly16x8_t { transmute(a) } @@ -20396,6 +21872,7 @@ pub unsafe fn vreinterpretq_p16_p128(a: p128) -> poly16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s64_p8(a: poly8x8_t) -> int64x1_t { transmute(a) } @@ -20406,6 +21883,7 @@ pub unsafe fn vreinterpret_s64_p8(a: poly8x8_t) -> int64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s64_s8(a: int8x8_t) -> int64x1_t { transmute(a) } @@ -20416,6 +21894,7 @@ pub unsafe fn vreinterpret_s64_s8(a: int8x8_t) -> int64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s64_u8(a: uint8x8_t) -> int64x1_t { transmute(a) } @@ -20426,6 +21905,7 @@ pub unsafe fn vreinterpret_s64_u8(a: uint8x8_t) -> int64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u64_p8(a: poly8x8_t) -> uint64x1_t { transmute(a) } @@ -20436,6 +21916,7 @@ pub unsafe fn vreinterpret_u64_p8(a: poly8x8_t) -> uint64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u64_s8(a: int8x8_t) -> uint64x1_t { transmute(a) } @@ -20446,6 +21927,7 @@ pub unsafe fn vreinterpret_u64_s8(a: int8x8_t) -> uint64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u64_u8(a: uint8x8_t) -> uint64x1_t { transmute(a) } @@ -20456,6 +21938,7 @@ pub unsafe fn vreinterpret_u64_u8(a: uint8x8_t) -> uint64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s64_p8(a: poly8x16_t) -> int64x2_t { transmute(a) } @@ -20466,6 +21949,7 @@ pub unsafe fn vreinterpretq_s64_p8(a: poly8x16_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s64_s8(a: int8x16_t) -> int64x2_t { transmute(a) } @@ -20476,6 +21960,7 @@ pub unsafe fn vreinterpretq_s64_s8(a: int8x16_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s64_u8(a: uint8x16_t) -> int64x2_t { transmute(a) } @@ -20486,6 +21971,7 @@ pub unsafe fn vreinterpretq_s64_u8(a: uint8x16_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u64_p8(a: poly8x16_t) -> uint64x2_t { transmute(a) } @@ -20496,6 +21982,7 @@ pub unsafe fn vreinterpretq_u64_p8(a: poly8x16_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u64_s8(a: int8x16_t) -> uint64x2_t { transmute(a) } @@ -20506,6 +21993,7 @@ pub unsafe fn vreinterpretq_u64_s8(a: int8x16_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u64_u8(a: uint8x16_t) -> uint64x2_t { transmute(a) } @@ -20516,6 +22004,7 @@ pub unsafe fn vreinterpretq_u64_u8(a: uint8x16_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p64_p8(a: poly8x8_t) -> poly64x1_t { transmute(a) } @@ -20526,6 +22015,7 @@ pub unsafe fn vreinterpret_p64_p8(a: poly8x8_t) -> poly64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p64_s8(a: int8x8_t) -> poly64x1_t { transmute(a) } @@ -20536,6 +22026,7 @@ pub unsafe fn vreinterpret_p64_s8(a: int8x8_t) -> poly64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p64_u8(a: uint8x8_t) -> poly64x1_t { transmute(a) } @@ -20546,6 +22037,7 @@ pub unsafe fn vreinterpret_p64_u8(a: uint8x8_t) -> poly64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p64_p8(a: poly8x16_t) -> poly64x2_t { transmute(a) } @@ -20556,6 +22048,7 @@ pub unsafe fn vreinterpretq_p64_p8(a: poly8x16_t) -> poly64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p64_s8(a: int8x16_t) -> poly64x2_t { transmute(a) } @@ -20566,6 +22059,7 @@ pub unsafe fn vreinterpretq_p64_s8(a: int8x16_t) -> poly64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p64_u8(a: uint8x16_t) -> poly64x2_t { transmute(a) } @@ -20576,6 +22070,7 @@ pub unsafe fn vreinterpretq_p64_u8(a: uint8x16_t) -> poly64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p128_s16(a: int16x8_t) -> p128 { transmute(a) } @@ -20586,6 +22081,7 @@ pub unsafe fn vreinterpretq_p128_s16(a: int16x8_t) -> p128 { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p128_u16(a: uint16x8_t) -> p128 { transmute(a) } @@ -20596,6 +22092,7 @@ pub unsafe fn vreinterpretq_p128_u16(a: uint16x8_t) -> p128 { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p128_p16(a: poly16x8_t) -> p128 { transmute(a) } @@ -20606,6 +22103,7 @@ pub unsafe fn vreinterpretq_p128_p16(a: poly16x8_t) -> p128 { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p128_s8(a: int8x16_t) -> p128 { transmute(a) } @@ -20616,6 +22114,7 @@ pub unsafe fn vreinterpretq_p128_s8(a: int8x16_t) -> p128 { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p128_u8(a: uint8x16_t) -> p128 { transmute(a) } @@ -20626,6 +22125,7 @@ pub unsafe fn vreinterpretq_p128_u8(a: uint8x16_t) -> p128 { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p128_p8(a: poly8x16_t) -> p128 { transmute(a) } @@ -20636,6 +22136,7 @@ pub unsafe fn vreinterpretq_p128_p8(a: poly8x16_t) -> p128 { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s8_p128(a: p128) -> int8x16_t { transmute(a) } @@ -20646,6 +22147,7 @@ pub unsafe fn vreinterpretq_s8_p128(a: p128) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u8_p128(a: p128) -> uint8x16_t { transmute(a) } @@ -20656,6 +22158,7 @@ pub unsafe fn vreinterpretq_u8_p128(a: p128) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "aes,v8"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p8_p128(a: p128) -> poly8x16_t { transmute(a) } @@ -20666,6 +22169,7 @@ pub unsafe fn vreinterpretq_p8_p128(a: p128) -> poly8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s8_f32(a: float32x2_t) -> int8x8_t { transmute(a) } @@ -20676,6 +22180,7 @@ pub unsafe fn vreinterpret_s8_f32(a: float32x2_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s16_f32(a: float32x2_t) -> int16x4_t { transmute(a) } @@ -20686,6 +22191,7 @@ pub unsafe fn vreinterpret_s16_f32(a: float32x2_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s32_f32(a: float32x2_t) -> int32x2_t { transmute(a) } @@ -20696,6 +22202,7 @@ pub unsafe fn vreinterpret_s32_f32(a: float32x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_s64_f32(a: float32x2_t) -> int64x1_t { transmute(a) } @@ -20706,6 +22213,7 @@ pub unsafe fn vreinterpret_s64_f32(a: float32x2_t) -> int64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s8_f32(a: float32x4_t) -> int8x16_t { transmute(a) } @@ -20716,6 +22224,7 @@ pub unsafe fn vreinterpretq_s8_f32(a: float32x4_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s16_f32(a: float32x4_t) -> int16x8_t { transmute(a) } @@ -20726,6 +22235,7 @@ pub unsafe fn vreinterpretq_s16_f32(a: float32x4_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s32_f32(a: float32x4_t) -> int32x4_t { transmute(a) } @@ -20736,6 +22246,7 @@ pub unsafe fn vreinterpretq_s32_f32(a: float32x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_s64_f32(a: float32x4_t) -> int64x2_t { transmute(a) } @@ -20746,6 +22257,7 @@ pub unsafe fn vreinterpretq_s64_f32(a: float32x4_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u8_f32(a: float32x2_t) -> uint8x8_t { transmute(a) } @@ -20756,6 +22268,7 @@ pub unsafe fn vreinterpret_u8_f32(a: float32x2_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u16_f32(a: float32x2_t) -> uint16x4_t { transmute(a) } @@ -20766,6 +22279,7 @@ pub unsafe fn vreinterpret_u16_f32(a: float32x2_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u32_f32(a: float32x2_t) -> uint32x2_t { transmute(a) } @@ -20776,6 +22290,7 @@ pub unsafe fn vreinterpret_u32_f32(a: float32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_u64_f32(a: float32x2_t) -> uint64x1_t { transmute(a) } @@ -20786,6 +22301,7 @@ pub unsafe fn vreinterpret_u64_f32(a: float32x2_t) -> uint64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u8_f32(a: float32x4_t) -> uint8x16_t { transmute(a) } @@ -20796,6 +22312,7 @@ pub unsafe fn vreinterpretq_u8_f32(a: float32x4_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u16_f32(a: float32x4_t) -> uint16x8_t { transmute(a) } @@ -20806,6 +22323,7 @@ pub unsafe fn vreinterpretq_u16_f32(a: float32x4_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u32_f32(a: float32x4_t) -> uint32x4_t { transmute(a) } @@ -20816,6 +22334,7 @@ pub unsafe fn vreinterpretq_u32_f32(a: float32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_u64_f32(a: float32x4_t) -> uint64x2_t { transmute(a) } @@ -20826,6 +22345,7 @@ pub unsafe fn vreinterpretq_u64_f32(a: float32x4_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p8_f32(a: float32x2_t) -> poly8x8_t { transmute(a) } @@ -20836,6 +22356,7 @@ pub unsafe fn vreinterpret_p8_f32(a: float32x2_t) -> poly8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_p16_f32(a: float32x2_t) -> poly16x4_t { transmute(a) } @@ -20846,6 +22367,7 @@ pub unsafe fn vreinterpret_p16_f32(a: float32x2_t) -> poly16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p8_f32(a: float32x4_t) -> poly8x16_t { transmute(a) } @@ -20856,6 +22378,7 @@ pub unsafe fn vreinterpretq_p8_f32(a: float32x4_t) -> poly8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p16_f32(a: float32x4_t) -> poly16x8_t { transmute(a) } @@ -20866,6 +22389,7 @@ pub unsafe fn vreinterpretq_p16_f32(a: float32x4_t) -> poly16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_p128_f32(a: float32x4_t) -> p128 { transmute(a) } @@ -20876,6 +22400,7 @@ pub unsafe fn vreinterpretq_p128_f32(a: float32x4_t) -> p128 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_f32_s8(a: int8x8_t) -> float32x2_t { transmute(a) } @@ -20886,6 +22411,7 @@ pub unsafe fn vreinterpret_f32_s8(a: int8x8_t) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_f32_s16(a: int16x4_t) -> float32x2_t { transmute(a) } @@ -20896,6 +22422,7 @@ pub unsafe fn vreinterpret_f32_s16(a: int16x4_t) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_f32_s32(a: int32x2_t) -> float32x2_t { transmute(a) } @@ -20906,6 +22433,7 @@ pub unsafe fn vreinterpret_f32_s32(a: int32x2_t) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_f32_s64(a: int64x1_t) -> float32x2_t { transmute(a) } @@ -20916,6 +22444,7 @@ pub unsafe fn vreinterpret_f32_s64(a: int64x1_t) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_f32_s8(a: int8x16_t) -> float32x4_t { transmute(a) } @@ -20926,6 +22455,7 @@ pub unsafe fn vreinterpretq_f32_s8(a: int8x16_t) -> float32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_f32_s16(a: int16x8_t) -> float32x4_t { transmute(a) } @@ -20936,6 +22466,7 @@ pub unsafe fn vreinterpretq_f32_s16(a: int16x8_t) -> float32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_f32_s32(a: int32x4_t) -> float32x4_t { transmute(a) } @@ -20946,6 +22477,7 @@ pub unsafe fn vreinterpretq_f32_s32(a: int32x4_t) -> float32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_f32_s64(a: int64x2_t) -> float32x4_t { transmute(a) } @@ -20956,6 +22488,7 @@ pub unsafe fn vreinterpretq_f32_s64(a: int64x2_t) -> float32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_f32_u8(a: uint8x8_t) -> float32x2_t { transmute(a) } @@ -20966,6 +22499,7 @@ pub unsafe fn vreinterpret_f32_u8(a: uint8x8_t) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_f32_u16(a: uint16x4_t) -> float32x2_t { transmute(a) } @@ -20976,6 +22510,7 @@ pub unsafe fn vreinterpret_f32_u16(a: uint16x4_t) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_f32_u32(a: uint32x2_t) -> float32x2_t { transmute(a) } @@ -20986,6 +22521,7 @@ pub unsafe fn vreinterpret_f32_u32(a: uint32x2_t) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_f32_u64(a: uint64x1_t) -> float32x2_t { transmute(a) } @@ -20996,6 +22532,7 @@ pub unsafe fn vreinterpret_f32_u64(a: uint64x1_t) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_f32_u8(a: uint8x16_t) -> float32x4_t { transmute(a) } @@ -21006,6 +22543,7 @@ pub unsafe fn vreinterpretq_f32_u8(a: uint8x16_t) -> float32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_f32_u16(a: uint16x8_t) -> float32x4_t { transmute(a) } @@ -21016,6 +22554,7 @@ pub unsafe fn vreinterpretq_f32_u16(a: uint16x8_t) -> float32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_f32_u32(a: uint32x4_t) -> float32x4_t { transmute(a) } @@ -21026,6 +22565,7 @@ pub unsafe fn vreinterpretq_f32_u32(a: uint32x4_t) -> float32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_f32_u64(a: uint64x2_t) -> float32x4_t { transmute(a) } @@ -21036,6 +22576,7 @@ pub unsafe fn vreinterpretq_f32_u64(a: uint64x2_t) -> float32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_f32_p8(a: poly8x8_t) -> float32x2_t { transmute(a) } @@ -21046,6 +22587,7 @@ pub unsafe fn vreinterpret_f32_p8(a: poly8x8_t) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpret_f32_p16(a: poly16x4_t) -> float32x2_t { transmute(a) } @@ -21056,6 +22598,7 @@ pub unsafe fn vreinterpret_f32_p16(a: poly16x4_t) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_f32_p8(a: poly8x16_t) -> float32x4_t { transmute(a) } @@ -21066,6 +22609,7 @@ pub unsafe fn vreinterpretq_f32_p8(a: poly8x16_t) -> float32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_f32_p16(a: poly16x8_t) -> float32x4_t { transmute(a) } @@ -21076,6 +22620,7 @@ pub unsafe fn vreinterpretq_f32_p16(a: poly16x8_t) -> float32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vreinterpretq_f32_p128(a: p128) -> float32x4_t { transmute(a) } @@ -21086,6 +22631,7 @@ pub unsafe fn vreinterpretq_f32_p128(a: p128) -> float32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshl_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -21102,6 +22648,7 @@ vrshl_s8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshlq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -21118,6 +22665,7 @@ vrshlq_s8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshl_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -21134,6 +22682,7 @@ vrshl_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshlq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -21150,6 +22699,7 @@ vrshlq_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshl_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -21166,6 +22716,7 @@ vrshl_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshlq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -21182,6 +22733,7 @@ vrshlq_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshl_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -21198,6 +22750,7 @@ vrshl_s64_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshlq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -21214,6 +22767,7 @@ vrshlq_s64_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshl_u8(a: uint8x8_t, b: int8x8_t) -> uint8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -21230,6 +22784,7 @@ vrshl_u8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshlq_u8(a: uint8x16_t, b: int8x16_t) -> uint8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -21246,6 +22801,7 @@ vrshlq_u8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshl_u16(a: uint16x4_t, b: int16x4_t) -> uint16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -21262,6 +22818,7 @@ vrshl_u16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshlq_u16(a: uint16x8_t, b: int16x8_t) -> uint16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -21278,6 +22835,7 @@ vrshlq_u16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshl_u32(a: uint32x2_t, b: int32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -21294,6 +22852,7 @@ vrshl_u32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshlq_u32(a: uint32x4_t, b: int32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -21310,6 +22869,7 @@ vrshlq_u32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshl_u64(a: uint64x1_t, b: int64x1_t) -> uint64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -21326,6 +22886,7 @@ vrshl_u64_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshlq_u64(a: uint64x2_t, b: int64x2_t) -> uint64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -21343,9 +22904,10 @@ vrshlq_u64_(a, b) #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshr_n_s8(a: int8x8_t) -> int8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); - vrshl_s8(a, vdup_n_s8((-N).try_into().unwrap())) + vrshl_s8(a, vdup_n_s8((-N) as _)) } /// Signed rounding shift right @@ -21355,9 +22917,10 @@ pub unsafe fn vrshr_n_s8(a: int8x8_t) -> int8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshrq_n_s8(a: int8x16_t) -> int8x16_t { static_assert!(N : i32 where N >= 1 && N <= 8); - vrshlq_s8(a, vdupq_n_s8((-N).try_into().unwrap())) + vrshlq_s8(a, vdupq_n_s8((-N) as _)) } /// Signed rounding shift right @@ -21367,9 +22930,10 @@ pub unsafe fn vrshrq_n_s8(a: int8x16_t) -> int8x16_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshr_n_s16(a: int16x4_t) -> int16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); - vrshl_s16(a, vdup_n_s16((-N).try_into().unwrap())) + vrshl_s16(a, vdup_n_s16((-N) as _)) } /// Signed rounding shift right @@ -21379,9 +22943,10 @@ pub unsafe fn vrshr_n_s16(a: int16x4_t) -> int16x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshrq_n_s16(a: int16x8_t) -> int16x8_t { static_assert!(N : i32 where N >= 1 && N <= 16); - vrshlq_s16(a, vdupq_n_s16((-N).try_into().unwrap())) + vrshlq_s16(a, vdupq_n_s16((-N) as _)) } /// Signed rounding shift right @@ -21391,9 +22956,10 @@ pub unsafe fn vrshrq_n_s16(a: int16x8_t) -> int16x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshr_n_s32(a: int32x2_t) -> int32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); - vrshl_s32(a, vdup_n_s32((-N).try_into().unwrap())) + vrshl_s32(a, vdup_n_s32((-N) as _)) } /// Signed rounding shift right @@ -21403,9 +22969,10 @@ pub unsafe fn vrshr_n_s32(a: int32x2_t) -> int32x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshrq_n_s32(a: int32x4_t) -> int32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); - vrshlq_s32(a, vdupq_n_s32((-N).try_into().unwrap())) + vrshlq_s32(a, vdupq_n_s32((-N) as _)) } /// Signed rounding shift right @@ -21415,9 +22982,10 @@ pub unsafe fn vrshrq_n_s32(a: int32x4_t) -> int32x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshr_n_s64(a: int64x1_t) -> int64x1_t { static_assert!(N : i32 where N >= 1 && N <= 64); - vrshl_s64(a, vdup_n_s64((-N).try_into().unwrap())) + vrshl_s64(a, vdup_n_s64((-N) as _)) } /// Signed rounding shift right @@ -21427,9 +22995,10 @@ pub unsafe fn vrshr_n_s64(a: int64x1_t) -> int64x1_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshrq_n_s64(a: int64x2_t) -> int64x2_t { static_assert!(N : i32 where N >= 1 && N <= 64); - vrshlq_s64(a, vdupq_n_s64((-N).try_into().unwrap())) + vrshlq_s64(a, vdupq_n_s64((-N) as _)) } /// Unsigned rounding shift right @@ -21439,9 +23008,10 @@ pub unsafe fn vrshrq_n_s64(a: int64x2_t) -> int64x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshr_n_u8(a: uint8x8_t) -> uint8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); - vrshl_u8(a, vdup_n_s8((-N).try_into().unwrap())) + vrshl_u8(a, vdup_n_s8((-N) as _)) } /// Unsigned rounding shift right @@ -21451,9 +23021,10 @@ pub unsafe fn vrshr_n_u8(a: uint8x8_t) -> uint8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshrq_n_u8(a: uint8x16_t) -> uint8x16_t { static_assert!(N : i32 where N >= 1 && N <= 8); - vrshlq_u8(a, vdupq_n_s8((-N).try_into().unwrap())) + vrshlq_u8(a, vdupq_n_s8((-N) as _)) } /// Unsigned rounding shift right @@ -21463,9 +23034,10 @@ pub unsafe fn vrshrq_n_u8(a: uint8x16_t) -> uint8x16_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshr_n_u16(a: uint16x4_t) -> uint16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); - vrshl_u16(a, vdup_n_s16((-N).try_into().unwrap())) + vrshl_u16(a, vdup_n_s16((-N) as _)) } /// Unsigned rounding shift right @@ -21475,9 +23047,10 @@ pub unsafe fn vrshr_n_u16(a: uint16x4_t) -> uint16x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshrq_n_u16(a: uint16x8_t) -> uint16x8_t { static_assert!(N : i32 where N >= 1 && N <= 16); - vrshlq_u16(a, vdupq_n_s16((-N).try_into().unwrap())) + vrshlq_u16(a, vdupq_n_s16((-N) as _)) } /// Unsigned rounding shift right @@ -21487,9 +23060,10 @@ pub unsafe fn vrshrq_n_u16(a: uint16x8_t) -> uint16x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshr_n_u32(a: uint32x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); - vrshl_u32(a, vdup_n_s32((-N).try_into().unwrap())) + vrshl_u32(a, vdup_n_s32((-N) as _)) } /// Unsigned rounding shift right @@ -21499,9 +23073,10 @@ pub unsafe fn vrshr_n_u32(a: uint32x2_t) -> uint32x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshrq_n_u32(a: uint32x4_t) -> uint32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); - vrshlq_u32(a, vdupq_n_s32((-N).try_into().unwrap())) + vrshlq_u32(a, vdupq_n_s32((-N) as _)) } /// Unsigned rounding shift right @@ -21511,9 +23086,10 @@ pub unsafe fn vrshrq_n_u32(a: uint32x4_t) -> uint32x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshr_n_u64(a: uint64x1_t) -> uint64x1_t { static_assert!(N : i32 where N >= 1 && N <= 64); - vrshl_u64(a, vdup_n_s64((-N).try_into().unwrap())) + vrshl_u64(a, vdup_n_s64((-N) as _)) } /// Unsigned rounding shift right @@ -21523,16 +23099,17 @@ pub unsafe fn vrshr_n_u64(a: uint64x1_t) -> uint64x1_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshr, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(urshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshrq_n_u64(a: uint64x2_t) -> uint64x2_t { static_assert!(N : i32 where N >= 1 && N <= 64); - vrshlq_u64(a, vdupq_n_s64((-N).try_into().unwrap())) + vrshlq_u64(a, vdupq_n_s64((-N) as _)) } /// Rounding shift right narrow #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshrn, N = 2))] +#[cfg_attr(test, assert_instr(vrshrn, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vrshrn_n_s16(a: int16x8_t) -> int8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); @@ -21548,8 +23125,9 @@ vrshrn_n_s16_(a, int16x8_t(-N as i16, -N as i16, -N as i16, -N as i16, -N as i16 #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rshrn, N = 2))] +#[cfg_attr(test, assert_instr(rshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrshrn_n_s16(a: int16x8_t) -> int8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); #[allow(improper_ctypes)] @@ -21564,7 +23142,7 @@ vrshrn_n_s16_(a, N) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshrn, N = 2))] +#[cfg_attr(test, assert_instr(vrshrn, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vrshrn_n_s32(a: int32x4_t) -> int16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); @@ -21580,8 +23158,9 @@ vrshrn_n_s32_(a, int32x4_t(-N as i32, -N as i32, -N as i32, -N as i32)) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rshrn, N = 2))] +#[cfg_attr(test, assert_instr(rshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrshrn_n_s32(a: int32x4_t) -> int16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); #[allow(improper_ctypes)] @@ -21596,7 +23175,7 @@ vrshrn_n_s32_(a, N) #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,v7")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshrn, N = 2))] +#[cfg_attr(test, assert_instr(vrshrn, N = 2))] #[rustc_legacy_const_generics(1)] pub unsafe fn vrshrn_n_s64(a: int64x2_t) -> int32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); @@ -21612,8 +23191,9 @@ vrshrn_n_s64_(a, int64x2_t(-N as i64, -N as i64)) #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "neon")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rshrn, N = 2))] +#[cfg_attr(test, assert_instr(rshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vrshrn_n_s64(a: int64x2_t) -> int32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); #[allow(improper_ctypes)] @@ -21631,6 +23211,7 @@ vrshrn_n_s64_(a, N) #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshrn, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshrn_n_u16(a: uint16x8_t) -> uint8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); transmute(vrshrn_n_s16::(transmute(a))) @@ -21643,6 +23224,7 @@ pub unsafe fn vrshrn_n_u16(a: uint16x8_t) -> uint8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshrn, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshrn_n_u32(a: uint32x4_t) -> uint16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); transmute(vrshrn_n_s32::(transmute(a))) @@ -21655,6 +23237,7 @@ pub unsafe fn vrshrn_n_u32(a: uint32x4_t) -> uint16x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrshrn, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rshrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrshrn_n_u64(a: uint64x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); transmute(vrshrn_n_s64::(transmute(a))) @@ -21667,6 +23250,7 @@ pub unsafe fn vrshrn_n_u64(a: uint64x2_t) -> uint32x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsra_n_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); simd_add(a, vrshr_n_s8::(b)) @@ -21679,6 +23263,7 @@ pub unsafe fn vrsra_n_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsraq_n_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { static_assert!(N : i32 where N >= 1 && N <= 8); simd_add(a, vrshrq_n_s8::(b)) @@ -21691,6 +23276,7 @@ pub unsafe fn vrsraq_n_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsra_n_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); simd_add(a, vrshr_n_s16::(b)) @@ -21703,6 +23289,7 @@ pub unsafe fn vrsra_n_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsraq_n_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { static_assert!(N : i32 where N >= 1 && N <= 16); simd_add(a, vrshrq_n_s16::(b)) @@ -21715,6 +23302,7 @@ pub unsafe fn vrsraq_n_s16(a: int16x8_t, b: int16x8_t) -> int16x8_ #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsra_n_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); simd_add(a, vrshr_n_s32::(b)) @@ -21727,6 +23315,7 @@ pub unsafe fn vrsra_n_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsraq_n_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); simd_add(a, vrshrq_n_s32::(b)) @@ -21739,6 +23328,7 @@ pub unsafe fn vrsraq_n_s32(a: int32x4_t, b: int32x4_t) -> int32x4_ #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsra_n_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { static_assert!(N : i32 where N >= 1 && N <= 64); simd_add(a, vrshr_n_s64::(b)) @@ -21751,6 +23341,7 @@ pub unsafe fn vrsra_n_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(srsra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsraq_n_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { static_assert!(N : i32 where N >= 1 && N <= 64); simd_add(a, vrshrq_n_s64::(b)) @@ -21763,6 +23354,7 @@ pub unsafe fn vrsraq_n_s64(a: int64x2_t, b: int64x2_t) -> int64x2_ #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsra_n_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); simd_add(a, vrshr_n_u8::(b)) @@ -21775,6 +23367,7 @@ pub unsafe fn vrsra_n_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsraq_n_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { static_assert!(N : i32 where N >= 1 && N <= 8); simd_add(a, vrshrq_n_u8::(b)) @@ -21787,6 +23380,7 @@ pub unsafe fn vrsraq_n_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x1 #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsra_n_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); simd_add(a, vrshr_n_u16::(b)) @@ -21799,6 +23393,7 @@ pub unsafe fn vrsra_n_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsraq_n_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { static_assert!(N : i32 where N >= 1 && N <= 16); simd_add(a, vrshrq_n_u16::(b)) @@ -21811,6 +23406,7 @@ pub unsafe fn vrsraq_n_u16(a: uint16x8_t, b: uint16x8_t) -> uint16 #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsra_n_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); simd_add(a, vrshr_n_u32::(b)) @@ -21823,6 +23419,7 @@ pub unsafe fn vrsra_n_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsraq_n_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); simd_add(a, vrshrq_n_u32::(b)) @@ -21835,6 +23432,7 @@ pub unsafe fn vrsraq_n_u32(a: uint32x4_t, b: uint32x4_t) -> uint32 #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsra_n_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { static_assert!(N : i32 where N >= 1 && N <= 64); simd_add(a, vrshr_n_u64::(b)) @@ -21847,6 +23445,7 @@ pub unsafe fn vrsra_n_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ursra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsraq_n_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { static_assert!(N : i32 where N >= 1 && N <= 64); simd_add(a, vrshrq_n_u64::(b)) @@ -21858,6 +23457,7 @@ pub unsafe fn vrsraq_n_u64(a: uint64x2_t, b: uint64x2_t) -> uint64 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsubhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rsubhn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsubhn_s16(a: int16x8_t, b: int16x8_t) -> int8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -21874,6 +23474,7 @@ vrsubhn_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsubhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rsubhn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsubhn_s32(a: int32x4_t, b: int32x4_t) -> int16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -21890,6 +23491,7 @@ vrsubhn_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsubhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rsubhn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsubhn_s64(a: int64x2_t, b: int64x2_t) -> int32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -21906,6 +23508,7 @@ vrsubhn_s64_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsubhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rsubhn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsubhn_u16(a: uint16x8_t, b: uint16x8_t) -> uint8x8_t { transmute(vrsubhn_s16(transmute(a), transmute(b))) } @@ -21916,6 +23519,7 @@ pub unsafe fn vrsubhn_u16(a: uint16x8_t, b: uint16x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsubhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rsubhn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsubhn_u32(a: uint32x4_t, b: uint32x4_t) -> uint16x4_t { transmute(vrsubhn_s32(transmute(a), transmute(b))) } @@ -21926,6 +23530,7 @@ pub unsafe fn vrsubhn_u32(a: uint32x4_t, b: uint32x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vrsubhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rsubhn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vrsubhn_u64(a: uint64x2_t, b: uint64x2_t) -> uint32x2_t { transmute(vrsubhn_s64(transmute(a), transmute(b))) } @@ -21937,6 +23542,7 @@ pub unsafe fn vrsubhn_u64(a: uint64x2_t, b: uint64x2_t) -> uint32x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vset_lane_s8(a: i8, b: int8x8_t) -> int8x8_t { static_assert_imm3!(LANE); simd_insert(b, LANE as u32, a) @@ -21949,6 +23555,7 @@ pub unsafe fn vset_lane_s8(a: i8, b: int8x8_t) -> int8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vset_lane_s16(a: i16, b: int16x4_t) -> int16x4_t { static_assert_imm2!(LANE); simd_insert(b, LANE as u32, a) @@ -21961,6 +23568,7 @@ pub unsafe fn vset_lane_s16(a: i16, b: int16x4_t) -> int16x4_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vset_lane_s32(a: i32, b: int32x2_t) -> int32x2_t { static_assert_imm1!(LANE); simd_insert(b, LANE as u32, a) @@ -21973,6 +23581,7 @@ pub unsafe fn vset_lane_s32(a: i32, b: int32x2_t) -> int32x2_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vset_lane_s64(a: i64, b: int64x1_t) -> int64x1_t { static_assert!(LANE : i32 where LANE == 0); simd_insert(b, LANE as u32, a) @@ -21985,6 +23594,7 @@ pub unsafe fn vset_lane_s64(a: i64, b: int64x1_t) -> int64x1_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vset_lane_u8(a: u8, b: uint8x8_t) -> uint8x8_t { static_assert_imm3!(LANE); simd_insert(b, LANE as u32, a) @@ -21997,6 +23607,7 @@ pub unsafe fn vset_lane_u8(a: u8, b: uint8x8_t) -> uint8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vset_lane_u16(a: u16, b: uint16x4_t) -> uint16x4_t { static_assert_imm2!(LANE); simd_insert(b, LANE as u32, a) @@ -22009,6 +23620,7 @@ pub unsafe fn vset_lane_u16(a: u16, b: uint16x4_t) -> uint16x4_ #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vset_lane_u32(a: u32, b: uint32x2_t) -> uint32x2_t { static_assert_imm1!(LANE); simd_insert(b, LANE as u32, a) @@ -22021,6 +23633,7 @@ pub unsafe fn vset_lane_u32(a: u32, b: uint32x2_t) -> uint32x2_ #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vset_lane_u64(a: u64, b: uint64x1_t) -> uint64x1_t { static_assert!(LANE : i32 where LANE == 0); simd_insert(b, LANE as u32, a) @@ -22033,6 +23646,7 @@ pub unsafe fn vset_lane_u64(a: u64, b: uint64x1_t) -> uint64x1_ #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vset_lane_p8(a: p8, b: poly8x8_t) -> poly8x8_t { static_assert_imm3!(LANE); simd_insert(b, LANE as u32, a) @@ -22045,6 +23659,7 @@ pub unsafe fn vset_lane_p8(a: p8, b: poly8x8_t) -> poly8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vset_lane_p16(a: p16, b: poly16x4_t) -> poly16x4_t { static_assert_imm2!(LANE); simd_insert(b, LANE as u32, a) @@ -22057,6 +23672,7 @@ pub unsafe fn vset_lane_p16(a: p16, b: poly16x4_t) -> poly16x4_ #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vset_lane_p64(a: p64, b: poly64x1_t) -> poly64x1_t { static_assert!(LANE : i32 where LANE == 0); simd_insert(b, LANE as u32, a) @@ -22069,6 +23685,7 @@ pub unsafe fn vset_lane_p64(a: p64, b: poly64x1_t) -> poly64x1_ #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsetq_lane_s8(a: i8, b: int8x16_t) -> int8x16_t { static_assert_imm4!(LANE); simd_insert(b, LANE as u32, a) @@ -22081,6 +23698,7 @@ pub unsafe fn vsetq_lane_s8(a: i8, b: int8x16_t) -> int8x16_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsetq_lane_s16(a: i16, b: int16x8_t) -> int16x8_t { static_assert_imm3!(LANE); simd_insert(b, LANE as u32, a) @@ -22093,6 +23711,7 @@ pub unsafe fn vsetq_lane_s16(a: i16, b: int16x8_t) -> int16x8_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsetq_lane_s32(a: i32, b: int32x4_t) -> int32x4_t { static_assert_imm2!(LANE); simd_insert(b, LANE as u32, a) @@ -22105,6 +23724,7 @@ pub unsafe fn vsetq_lane_s32(a: i32, b: int32x4_t) -> int32x4_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsetq_lane_s64(a: i64, b: int64x2_t) -> int64x2_t { static_assert_imm1!(LANE); simd_insert(b, LANE as u32, a) @@ -22117,6 +23737,7 @@ pub unsafe fn vsetq_lane_s64(a: i64, b: int64x2_t) -> int64x2_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsetq_lane_u8(a: u8, b: uint8x16_t) -> uint8x16_t { static_assert_imm4!(LANE); simd_insert(b, LANE as u32, a) @@ -22129,6 +23750,7 @@ pub unsafe fn vsetq_lane_u8(a: u8, b: uint8x16_t) -> uint8x16_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsetq_lane_u16(a: u16, b: uint16x8_t) -> uint16x8_t { static_assert_imm3!(LANE); simd_insert(b, LANE as u32, a) @@ -22141,6 +23763,7 @@ pub unsafe fn vsetq_lane_u16(a: u16, b: uint16x8_t) -> uint16x8 #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsetq_lane_u32(a: u32, b: uint32x4_t) -> uint32x4_t { static_assert_imm2!(LANE); simd_insert(b, LANE as u32, a) @@ -22153,6 +23776,7 @@ pub unsafe fn vsetq_lane_u32(a: u32, b: uint32x4_t) -> uint32x4 #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsetq_lane_u64(a: u64, b: uint64x2_t) -> uint64x2_t { static_assert_imm1!(LANE); simd_insert(b, LANE as u32, a) @@ -22165,6 +23789,7 @@ pub unsafe fn vsetq_lane_u64(a: u64, b: uint64x2_t) -> uint64x2 #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsetq_lane_p8(a: p8, b: poly8x16_t) -> poly8x16_t { static_assert_imm4!(LANE); simd_insert(b, LANE as u32, a) @@ -22177,6 +23802,7 @@ pub unsafe fn vsetq_lane_p8(a: p8, b: poly8x16_t) -> poly8x16_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsetq_lane_p16(a: p16, b: poly16x8_t) -> poly16x8_t { static_assert_imm3!(LANE); simd_insert(b, LANE as u32, a) @@ -22189,6 +23815,7 @@ pub unsafe fn vsetq_lane_p16(a: p16, b: poly16x8_t) -> poly16x8 #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsetq_lane_p64(a: p64, b: poly64x2_t) -> poly64x2_t { static_assert_imm1!(LANE); simd_insert(b, LANE as u32, a) @@ -22201,6 +23828,7 @@ pub unsafe fn vsetq_lane_p64(a: p64, b: poly64x2_t) -> poly64x2 #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vset_lane_f32(a: f32, b: float32x2_t) -> float32x2_t { static_assert_imm1!(LANE); simd_insert(b, LANE as u32, a) @@ -22213,6 +23841,7 @@ pub unsafe fn vset_lane_f32(a: f32, b: float32x2_t) -> float32x #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop, LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop, LANE = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsetq_lane_f32(a: f32, b: float32x4_t) -> float32x4_t { static_assert_imm2!(LANE); simd_insert(b, LANE as u32, a) @@ -22224,6 +23853,7 @@ pub unsafe fn vsetq_lane_f32(a: f32, b: float32x4_t) -> float32 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshl_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -22240,6 +23870,7 @@ vshl_s8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshlq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -22256,6 +23887,7 @@ vshlq_s8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshl_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -22272,6 +23904,7 @@ vshl_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshlq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -22288,6 +23921,7 @@ vshlq_s16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshl_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -22304,6 +23938,7 @@ vshl_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshlq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -22320,6 +23955,7 @@ vshlq_s32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshl_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -22336,6 +23972,7 @@ vshl_s64_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshlq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -22352,6 +23989,7 @@ vshlq_s64_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshl_u8(a: uint8x8_t, b: int8x8_t) -> uint8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -22368,6 +24006,7 @@ vshl_u8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshlq_u8(a: uint8x16_t, b: int8x16_t) -> uint8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -22384,6 +24023,7 @@ vshlq_u8_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshl_u16(a: uint16x4_t, b: int16x4_t) -> uint16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -22400,6 +24040,7 @@ vshl_u16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshlq_u16(a: uint16x8_t, b: int16x8_t) -> uint16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -22416,6 +24057,7 @@ vshlq_u16_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshl_u32(a: uint32x2_t, b: int32x2_t) -> uint32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -22432,6 +24074,7 @@ vshl_u32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshlq_u32(a: uint32x4_t, b: int32x4_t) -> uint32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -22448,6 +24091,7 @@ vshlq_u32_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshl_u64(a: uint64x1_t, b: int64x1_t) -> uint64x1_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -22464,6 +24108,7 @@ vshl_u64_(a, b) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushl))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshlq_u64(a: uint64x2_t, b: int64x2_t) -> uint64x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -22481,9 +24126,10 @@ vshlq_u64_(a, b) #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshl_n_s8(a: int8x8_t) -> int8x8_t { static_assert_imm3!(N); - simd_shl(a, vdup_n_s8(N.try_into().unwrap())) + simd_shl(a, vdup_n_s8(N as _)) } /// Shift left @@ -22493,9 +24139,10 @@ pub unsafe fn vshl_n_s8(a: int8x8_t) -> int8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshlq_n_s8(a: int8x16_t) -> int8x16_t { static_assert_imm3!(N); - simd_shl(a, vdupq_n_s8(N.try_into().unwrap())) + simd_shl(a, vdupq_n_s8(N as _)) } /// Shift left @@ -22505,9 +24152,10 @@ pub unsafe fn vshlq_n_s8(a: int8x16_t) -> int8x16_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshl_n_s16(a: int16x4_t) -> int16x4_t { static_assert_imm4!(N); - simd_shl(a, vdup_n_s16(N.try_into().unwrap())) + simd_shl(a, vdup_n_s16(N as _)) } /// Shift left @@ -22517,9 +24165,10 @@ pub unsafe fn vshl_n_s16(a: int16x4_t) -> int16x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshlq_n_s16(a: int16x8_t) -> int16x8_t { static_assert_imm4!(N); - simd_shl(a, vdupq_n_s16(N.try_into().unwrap())) + simd_shl(a, vdupq_n_s16(N as _)) } /// Shift left @@ -22529,9 +24178,10 @@ pub unsafe fn vshlq_n_s16(a: int16x8_t) -> int16x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshl_n_s32(a: int32x2_t) -> int32x2_t { static_assert_imm5!(N); - simd_shl(a, vdup_n_s32(N.try_into().unwrap())) + simd_shl(a, vdup_n_s32(N as _)) } /// Shift left @@ -22541,9 +24191,10 @@ pub unsafe fn vshl_n_s32(a: int32x2_t) -> int32x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshlq_n_s32(a: int32x4_t) -> int32x4_t { static_assert_imm5!(N); - simd_shl(a, vdupq_n_s32(N.try_into().unwrap())) + simd_shl(a, vdupq_n_s32(N as _)) } /// Shift left @@ -22553,9 +24204,10 @@ pub unsafe fn vshlq_n_s32(a: int32x4_t) -> int32x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshl_n_u8(a: uint8x8_t) -> uint8x8_t { static_assert_imm3!(N); - simd_shl(a, vdup_n_u8(N.try_into().unwrap())) + simd_shl(a, vdup_n_u8(N as _)) } /// Shift left @@ -22565,9 +24217,10 @@ pub unsafe fn vshl_n_u8(a: uint8x8_t) -> uint8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshlq_n_u8(a: uint8x16_t) -> uint8x16_t { static_assert_imm3!(N); - simd_shl(a, vdupq_n_u8(N.try_into().unwrap())) + simd_shl(a, vdupq_n_u8(N as _)) } /// Shift left @@ -22577,9 +24230,10 @@ pub unsafe fn vshlq_n_u8(a: uint8x16_t) -> uint8x16_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshl_n_u16(a: uint16x4_t) -> uint16x4_t { static_assert_imm4!(N); - simd_shl(a, vdup_n_u16(N.try_into().unwrap())) + simd_shl(a, vdup_n_u16(N as _)) } /// Shift left @@ -22589,9 +24243,10 @@ pub unsafe fn vshl_n_u16(a: uint16x4_t) -> uint16x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshlq_n_u16(a: uint16x8_t) -> uint16x8_t { static_assert_imm4!(N); - simd_shl(a, vdupq_n_u16(N.try_into().unwrap())) + simd_shl(a, vdupq_n_u16(N as _)) } /// Shift left @@ -22601,9 +24256,10 @@ pub unsafe fn vshlq_n_u16(a: uint16x8_t) -> uint16x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshl_n_u32(a: uint32x2_t) -> uint32x2_t { static_assert_imm5!(N); - simd_shl(a, vdup_n_u32(N.try_into().unwrap())) + simd_shl(a, vdup_n_u32(N as _)) } /// Shift left @@ -22613,9 +24269,10 @@ pub unsafe fn vshl_n_u32(a: uint32x2_t) -> uint32x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshlq_n_u32(a: uint32x4_t) -> uint32x4_t { static_assert_imm5!(N); - simd_shl(a, vdupq_n_u32(N.try_into().unwrap())) + simd_shl(a, vdupq_n_u32(N as _)) } /// Shift left @@ -22625,9 +24282,10 @@ pub unsafe fn vshlq_n_u32(a: uint32x4_t) -> uint32x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshl_n_s64(a: int64x1_t) -> int64x1_t { static_assert_imm6!(N); - simd_shl(a, vdup_n_s64(N.try_into().unwrap())) + simd_shl(a, vdup_n_s64(N as _)) } /// Shift left @@ -22637,9 +24295,10 @@ pub unsafe fn vshl_n_s64(a: int64x1_t) -> int64x1_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshlq_n_s64(a: int64x2_t) -> int64x2_t { static_assert_imm6!(N); - simd_shl(a, vdupq_n_s64(N.try_into().unwrap())) + simd_shl(a, vdupq_n_s64(N as _)) } /// Shift left @@ -22649,9 +24308,10 @@ pub unsafe fn vshlq_n_s64(a: int64x2_t) -> int64x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshl_n_u64(a: uint64x1_t) -> uint64x1_t { static_assert_imm6!(N); - simd_shl(a, vdup_n_u64(N.try_into().unwrap())) + simd_shl(a, vdup_n_u64(N as _)) } /// Shift left @@ -22661,9 +24321,10 @@ pub unsafe fn vshl_n_u64(a: uint64x1_t) -> uint64x1_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vshl, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shl, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshlq_n_u64(a: uint64x2_t) -> uint64x2_t { static_assert_imm6!(N); - simd_shl(a, vdupq_n_u64(N.try_into().unwrap())) + simd_shl(a, vdupq_n_u64(N as _)) } /// Signed shift left long @@ -22673,9 +24334,10 @@ pub unsafe fn vshlq_n_u64(a: uint64x2_t) -> uint64x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshll.s8", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshll, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshll_n_s8(a: int8x8_t) -> int16x8_t { static_assert!(N : i32 where N >= 0 && N <= 8); - simd_shl(simd_cast(a), vdupq_n_s16(N.try_into().unwrap())) + simd_shl(simd_cast(a), vdupq_n_s16(N as _)) } /// Signed shift left long @@ -22685,9 +24347,10 @@ pub unsafe fn vshll_n_s8(a: int8x8_t) -> int16x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshll.s16", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshll, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshll_n_s16(a: int16x4_t) -> int32x4_t { static_assert!(N : i32 where N >= 0 && N <= 16); - simd_shl(simd_cast(a), vdupq_n_s32(N.try_into().unwrap())) + simd_shl(simd_cast(a), vdupq_n_s32(N as _)) } /// Signed shift left long @@ -22697,9 +24360,10 @@ pub unsafe fn vshll_n_s16(a: int16x4_t) -> int32x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshll.s32", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshll, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshll_n_s32(a: int32x2_t) -> int64x2_t { static_assert!(N : i32 where N >= 0 && N <= 32); - simd_shl(simd_cast(a), vdupq_n_s64(N.try_into().unwrap())) + simd_shl(simd_cast(a), vdupq_n_s64(N as _)) } /// Signed shift left long @@ -22709,9 +24373,10 @@ pub unsafe fn vshll_n_s32(a: int32x2_t) -> int64x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshll.u8", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushll, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshll_n_u8(a: uint8x8_t) -> uint16x8_t { static_assert!(N : i32 where N >= 0 && N <= 8); - simd_shl(simd_cast(a), vdupq_n_u16(N.try_into().unwrap())) + simd_shl(simd_cast(a), vdupq_n_u16(N as _)) } /// Signed shift left long @@ -22721,9 +24386,10 @@ pub unsafe fn vshll_n_u8(a: uint8x8_t) -> uint16x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshll.u16", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushll, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshll_n_u16(a: uint16x4_t) -> uint32x4_t { static_assert!(N : i32 where N >= 0 && N <= 16); - simd_shl(simd_cast(a), vdupq_n_u32(N.try_into().unwrap())) + simd_shl(simd_cast(a), vdupq_n_u32(N as _)) } /// Signed shift left long @@ -22733,9 +24399,10 @@ pub unsafe fn vshll_n_u16(a: uint16x4_t) -> uint32x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshll.u32", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushll, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshll_n_u32(a: uint32x2_t) -> uint64x2_t { static_assert!(N : i32 where N >= 0 && N <= 32); - simd_shl(simd_cast(a), vdupq_n_u64(N.try_into().unwrap())) + simd_shl(simd_cast(a), vdupq_n_u64(N as _)) } /// Shift right @@ -22745,10 +24412,11 @@ pub unsafe fn vshll_n_u32(a: uint32x2_t) -> uint64x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s8", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshr_n_s8(a: int8x8_t) -> int8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); let n: i32 = if N == 8 { 7 } else { N }; - simd_shr(a, vdup_n_s8(n.try_into().unwrap())) + simd_shr(a, vdup_n_s8(n as _)) } /// Shift right @@ -22758,10 +24426,11 @@ pub unsafe fn vshr_n_s8(a: int8x8_t) -> int8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s8", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshrq_n_s8(a: int8x16_t) -> int8x16_t { static_assert!(N : i32 where N >= 1 && N <= 8); let n: i32 = if N == 8 { 7 } else { N }; - simd_shr(a, vdupq_n_s8(n.try_into().unwrap())) + simd_shr(a, vdupq_n_s8(n as _)) } /// Shift right @@ -22771,10 +24440,11 @@ pub unsafe fn vshrq_n_s8(a: int8x16_t) -> int8x16_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s16", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshr_n_s16(a: int16x4_t) -> int16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); let n: i32 = if N == 16 { 15 } else { N }; - simd_shr(a, vdup_n_s16(n.try_into().unwrap())) + simd_shr(a, vdup_n_s16(n as _)) } /// Shift right @@ -22784,10 +24454,11 @@ pub unsafe fn vshr_n_s16(a: int16x4_t) -> int16x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s16", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshrq_n_s16(a: int16x8_t) -> int16x8_t { static_assert!(N : i32 where N >= 1 && N <= 16); let n: i32 = if N == 16 { 15 } else { N }; - simd_shr(a, vdupq_n_s16(n.try_into().unwrap())) + simd_shr(a, vdupq_n_s16(n as _)) } /// Shift right @@ -22797,10 +24468,11 @@ pub unsafe fn vshrq_n_s16(a: int16x8_t) -> int16x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s32", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshr_n_s32(a: int32x2_t) -> int32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); let n: i32 = if N == 32 { 31 } else { N }; - simd_shr(a, vdup_n_s32(n.try_into().unwrap())) + simd_shr(a, vdup_n_s32(n as _)) } /// Shift right @@ -22810,10 +24482,11 @@ pub unsafe fn vshr_n_s32(a: int32x2_t) -> int32x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s32", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshrq_n_s32(a: int32x4_t) -> int32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); let n: i32 = if N == 32 { 31 } else { N }; - simd_shr(a, vdupq_n_s32(n.try_into().unwrap())) + simd_shr(a, vdupq_n_s32(n as _)) } /// Shift right @@ -22823,10 +24496,11 @@ pub unsafe fn vshrq_n_s32(a: int32x4_t) -> int32x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s64", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshr_n_s64(a: int64x1_t) -> int64x1_t { static_assert!(N : i32 where N >= 1 && N <= 64); let n: i32 = if N == 64 { 63 } else { N }; - simd_shr(a, vdup_n_s64(n.try_into().unwrap())) + simd_shr(a, vdup_n_s64(n as _)) } /// Shift right @@ -22836,10 +24510,11 @@ pub unsafe fn vshr_n_s64(a: int64x1_t) -> int64x1_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.s64", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sshr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshrq_n_s64(a: int64x2_t) -> int64x2_t { static_assert!(N : i32 where N >= 1 && N <= 64); let n: i32 = if N == 64 { 63 } else { N }; - simd_shr(a, vdupq_n_s64(n.try_into().unwrap())) + simd_shr(a, vdupq_n_s64(n as _)) } /// Shift right @@ -22849,10 +24524,11 @@ pub unsafe fn vshrq_n_s64(a: int64x2_t) -> int64x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u8", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshr_n_u8(a: uint8x8_t) -> uint8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); let n: i32 = if N == 8 { return vdup_n_u8(0); } else { N }; - simd_shr(a, vdup_n_u8(n.try_into().unwrap())) + simd_shr(a, vdup_n_u8(n as _)) } /// Shift right @@ -22862,10 +24538,11 @@ pub unsafe fn vshr_n_u8(a: uint8x8_t) -> uint8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u8", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshrq_n_u8(a: uint8x16_t) -> uint8x16_t { static_assert!(N : i32 where N >= 1 && N <= 8); let n: i32 = if N == 8 { return vdupq_n_u8(0); } else { N }; - simd_shr(a, vdupq_n_u8(n.try_into().unwrap())) + simd_shr(a, vdupq_n_u8(n as _)) } /// Shift right @@ -22875,10 +24552,11 @@ pub unsafe fn vshrq_n_u8(a: uint8x16_t) -> uint8x16_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u16", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshr_n_u16(a: uint16x4_t) -> uint16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); let n: i32 = if N == 16 { return vdup_n_u16(0); } else { N }; - simd_shr(a, vdup_n_u16(n.try_into().unwrap())) + simd_shr(a, vdup_n_u16(n as _)) } /// Shift right @@ -22888,10 +24566,11 @@ pub unsafe fn vshr_n_u16(a: uint16x4_t) -> uint16x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u16", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshrq_n_u16(a: uint16x8_t) -> uint16x8_t { static_assert!(N : i32 where N >= 1 && N <= 16); let n: i32 = if N == 16 { return vdupq_n_u16(0); } else { N }; - simd_shr(a, vdupq_n_u16(n.try_into().unwrap())) + simd_shr(a, vdupq_n_u16(n as _)) } /// Shift right @@ -22901,10 +24580,11 @@ pub unsafe fn vshrq_n_u16(a: uint16x8_t) -> uint16x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u32", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshr_n_u32(a: uint32x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); let n: i32 = if N == 32 { return vdup_n_u32(0); } else { N }; - simd_shr(a, vdup_n_u32(n.try_into().unwrap())) + simd_shr(a, vdup_n_u32(n as _)) } /// Shift right @@ -22914,10 +24594,11 @@ pub unsafe fn vshr_n_u32(a: uint32x2_t) -> uint32x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u32", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshrq_n_u32(a: uint32x4_t) -> uint32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); let n: i32 = if N == 32 { return vdupq_n_u32(0); } else { N }; - simd_shr(a, vdupq_n_u32(n.try_into().unwrap())) + simd_shr(a, vdupq_n_u32(n as _)) } /// Shift right @@ -22927,10 +24608,11 @@ pub unsafe fn vshrq_n_u32(a: uint32x4_t) -> uint32x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u64", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshr_n_u64(a: uint64x1_t) -> uint64x1_t { static_assert!(N : i32 where N >= 1 && N <= 64); let n: i32 = if N == 64 { return vdup_n_u64(0); } else { N }; - simd_shr(a, vdup_n_u64(n.try_into().unwrap())) + simd_shr(a, vdup_n_u64(n as _)) } /// Shift right @@ -22940,10 +24622,11 @@ pub unsafe fn vshr_n_u64(a: uint64x1_t) -> uint64x1_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshr.u64", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ushr, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshrq_n_u64(a: uint64x2_t) -> uint64x2_t { static_assert!(N : i32 where N >= 1 && N <= 64); let n: i32 = if N == 64 { return vdupq_n_u64(0); } else { N }; - simd_shr(a, vdupq_n_u64(n.try_into().unwrap())) + simd_shr(a, vdupq_n_u64(n as _)) } /// Shift right narrow @@ -22953,9 +24636,10 @@ pub unsafe fn vshrq_n_u64(a: uint64x2_t) -> uint64x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshrn.i16", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshrn_n_s16(a: int16x8_t) -> int8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); - simd_cast(simd_shr(a, vdupq_n_s16(N.try_into().unwrap()))) + simd_cast(simd_shr(a, vdupq_n_s16(N as _))) } /// Shift right narrow @@ -22965,9 +24649,10 @@ pub unsafe fn vshrn_n_s16(a: int16x8_t) -> int8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshrn.i32", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshrn_n_s32(a: int32x4_t) -> int16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); - simd_cast(simd_shr(a, vdupq_n_s32(N.try_into().unwrap()))) + simd_cast(simd_shr(a, vdupq_n_s32(N as _))) } /// Shift right narrow @@ -22977,9 +24662,10 @@ pub unsafe fn vshrn_n_s32(a: int32x4_t) -> int16x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshrn.i64", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshrn_n_s64(a: int64x2_t) -> int32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); - simd_cast(simd_shr(a, vdupq_n_s64(N.try_into().unwrap()))) + simd_cast(simd_shr(a, vdupq_n_s64(N as _))) } /// Shift right narrow @@ -22989,9 +24675,10 @@ pub unsafe fn vshrn_n_s64(a: int64x2_t) -> int32x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshrn.i16", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshrn_n_u16(a: uint16x8_t) -> uint8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); - simd_cast(simd_shr(a, vdupq_n_u16(N.try_into().unwrap()))) + simd_cast(simd_shr(a, vdupq_n_u16(N as _))) } /// Shift right narrow @@ -23001,9 +24688,10 @@ pub unsafe fn vshrn_n_u16(a: uint16x8_t) -> uint8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshrn.i32", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshrn_n_u32(a: uint32x4_t) -> uint16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); - simd_cast(simd_shr(a, vdupq_n_u32(N.try_into().unwrap()))) + simd_cast(simd_shr(a, vdupq_n_u32(N as _))) } /// Shift right narrow @@ -23013,9 +24701,10 @@ pub unsafe fn vshrn_n_u32(a: uint32x4_t) -> uint16x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vshrn.i64", N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(shrn, N = 2))] #[rustc_legacy_const_generics(1)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vshrn_n_u64(a: uint64x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); - simd_cast(simd_shr(a, vdupq_n_u64(N.try_into().unwrap()))) + simd_cast(simd_shr(a, vdupq_n_u64(N as _))) } /// Signed shift right and accumulate @@ -23025,6 +24714,7 @@ pub unsafe fn vshrn_n_u64(a: uint64x2_t) -> uint32x2_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsra_n_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); simd_add(a, vshr_n_s8::(b)) @@ -23037,6 +24727,7 @@ pub unsafe fn vsra_n_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsraq_n_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { static_assert!(N : i32 where N >= 1 && N <= 8); simd_add(a, vshrq_n_s8::(b)) @@ -23049,6 +24740,7 @@ pub unsafe fn vsraq_n_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsra_n_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); simd_add(a, vshr_n_s16::(b)) @@ -23061,6 +24753,7 @@ pub unsafe fn vsra_n_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsraq_n_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { static_assert!(N : i32 where N >= 1 && N <= 16); simd_add(a, vshrq_n_s16::(b)) @@ -23073,6 +24766,7 @@ pub unsafe fn vsraq_n_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsra_n_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); simd_add(a, vshr_n_s32::(b)) @@ -23085,6 +24779,7 @@ pub unsafe fn vsra_n_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsraq_n_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); simd_add(a, vshrq_n_s32::(b)) @@ -23097,6 +24792,7 @@ pub unsafe fn vsraq_n_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsra_n_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { static_assert!(N : i32 where N >= 1 && N <= 64); simd_add(a, vshr_n_s64::(b)) @@ -23109,6 +24805,7 @@ pub unsafe fn vsra_n_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ssra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsraq_n_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { static_assert!(N : i32 where N >= 1 && N <= 64); simd_add(a, vshrq_n_s64::(b)) @@ -23121,6 +24818,7 @@ pub unsafe fn vsraq_n_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsra_n_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { static_assert!(N : i32 where N >= 1 && N <= 8); simd_add(a, vshr_n_u8::(b)) @@ -23133,6 +24831,7 @@ pub unsafe fn vsra_n_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsraq_n_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { static_assert!(N : i32 where N >= 1 && N <= 8); simd_add(a, vshrq_n_u8::(b)) @@ -23145,6 +24844,7 @@ pub unsafe fn vsraq_n_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16 #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsra_n_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { static_assert!(N : i32 where N >= 1 && N <= 16); simd_add(a, vshr_n_u16::(b)) @@ -23157,6 +24857,7 @@ pub unsafe fn vsra_n_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4 #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsraq_n_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { static_assert!(N : i32 where N >= 1 && N <= 16); simd_add(a, vshrq_n_u16::(b)) @@ -23169,6 +24870,7 @@ pub unsafe fn vsraq_n_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsra_n_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { static_assert!(N : i32 where N >= 1 && N <= 32); simd_add(a, vshr_n_u32::(b)) @@ -23181,6 +24883,7 @@ pub unsafe fn vsra_n_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2 #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsraq_n_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { static_assert!(N : i32 where N >= 1 && N <= 32); simd_add(a, vshrq_n_u32::(b)) @@ -23193,6 +24896,7 @@ pub unsafe fn vsraq_n_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsra_n_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { static_assert!(N : i32 where N >= 1 && N <= 64); simd_add(a, vshr_n_u64::(b)) @@ -23205,6 +24909,7 @@ pub unsafe fn vsra_n_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1 #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vsra, N = 2))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(usra, N = 2))] #[rustc_legacy_const_generics(2)] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vsraq_n_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { static_assert!(N : i32 where N >= 1 && N <= 64); simd_add(a, vshrq_n_u64::(b)) @@ -23216,6 +24921,7 @@ pub unsafe fn vsraq_n_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtrn_s8(a: int8x8_t, b: int8x8_t) -> int8x8x2_t { let a1: int8x8_t = simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]); let b1: int8x8_t = simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]); @@ -23228,6 +24934,7 @@ pub unsafe fn vtrn_s8(a: int8x8_t, b: int8x8_t) -> int8x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtrn_s16(a: int16x4_t, b: int16x4_t) -> int16x4x2_t { let a1: int16x4_t = simd_shuffle4!(a, b, [0, 4, 2, 6]); let b1: int16x4_t = simd_shuffle4!(a, b, [1, 5, 3, 7]); @@ -23240,6 +24947,7 @@ pub unsafe fn vtrn_s16(a: int16x4_t, b: int16x4_t) -> int16x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtrnq_s8(a: int8x16_t, b: int8x16_t) -> int8x16x2_t { let a1: int8x16_t = simd_shuffle16!(a, b, [0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30]); let b1: int8x16_t = simd_shuffle16!(a, b, [1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31]); @@ -23252,6 +24960,7 @@ pub unsafe fn vtrnq_s8(a: int8x16_t, b: int8x16_t) -> int8x16x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtrnq_s16(a: int16x8_t, b: int16x8_t) -> int16x8x2_t { let a1: int16x8_t = simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]); let b1: int16x8_t = simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]); @@ -23264,6 +24973,7 @@ pub unsafe fn vtrnq_s16(a: int16x8_t, b: int16x8_t) -> int16x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtrnq_s32(a: int32x4_t, b: int32x4_t) -> int32x4x2_t { let a1: int32x4_t = simd_shuffle4!(a, b, [0, 4, 2, 6]); let b1: int32x4_t = simd_shuffle4!(a, b, [1, 5, 3, 7]); @@ -23276,6 +24986,7 @@ pub unsafe fn vtrnq_s32(a: int32x4_t, b: int32x4_t) -> int32x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtrn_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8x2_t { let a1: uint8x8_t = simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]); let b1: uint8x8_t = simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]); @@ -23288,6 +24999,7 @@ pub unsafe fn vtrn_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtrn_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4x2_t { let a1: uint16x4_t = simd_shuffle4!(a, b, [0, 4, 2, 6]); let b1: uint16x4_t = simd_shuffle4!(a, b, [1, 5, 3, 7]); @@ -23300,6 +25012,7 @@ pub unsafe fn vtrn_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtrnq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16x2_t { let a1: uint8x16_t = simd_shuffle16!(a, b, [0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30]); let b1: uint8x16_t = simd_shuffle16!(a, b, [1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31]); @@ -23312,6 +25025,7 @@ pub unsafe fn vtrnq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtrnq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8x2_t { let a1: uint16x8_t = simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]); let b1: uint16x8_t = simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]); @@ -23324,6 +25038,7 @@ pub unsafe fn vtrnq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtrnq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4x2_t { let a1: uint32x4_t = simd_shuffle4!(a, b, [0, 4, 2, 6]); let b1: uint32x4_t = simd_shuffle4!(a, b, [1, 5, 3, 7]); @@ -23336,6 +25051,7 @@ pub unsafe fn vtrnq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtrn_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8x2_t { let a1: poly8x8_t = simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]); let b1: poly8x8_t = simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]); @@ -23348,6 +25064,7 @@ pub unsafe fn vtrn_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtrn_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4x2_t { let a1: poly16x4_t = simd_shuffle4!(a, b, [0, 4, 2, 6]); let b1: poly16x4_t = simd_shuffle4!(a, b, [1, 5, 3, 7]); @@ -23360,6 +25077,7 @@ pub unsafe fn vtrn_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtrnq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16x2_t { let a1: poly8x16_t = simd_shuffle16!(a, b, [0, 16, 2, 18, 4, 20, 6, 22, 8, 24, 10, 26, 12, 28, 14, 30]); let b1: poly8x16_t = simd_shuffle16!(a, b, [1, 17, 3, 19, 5, 21, 7, 23, 9, 25, 11, 27, 13, 29, 15, 31]); @@ -23372,6 +25090,7 @@ pub unsafe fn vtrnq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtrnq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8x2_t { let a1: poly16x8_t = simd_shuffle8!(a, b, [0, 8, 2, 10, 4, 12, 6, 14]); let b1: poly16x8_t = simd_shuffle8!(a, b, [1, 9, 3, 11, 5, 13, 7, 15]); @@ -23384,6 +25103,7 @@ pub unsafe fn vtrnq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtrn_s32(a: int32x2_t, b: int32x2_t) -> int32x2x2_t { let a1: int32x2_t = simd_shuffle2!(a, b, [0, 2]); let b1: int32x2_t = simd_shuffle2!(a, b, [1, 3]); @@ -23396,6 +25116,7 @@ pub unsafe fn vtrn_s32(a: int32x2_t, b: int32x2_t) -> int32x2x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtrn_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2x2_t { let a1: uint32x2_t = simd_shuffle2!(a, b, [0, 2]); let b1: uint32x2_t = simd_shuffle2!(a, b, [1, 3]); @@ -23408,6 +25129,7 @@ pub unsafe fn vtrn_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtrn_f32(a: float32x2_t, b: float32x2_t) -> float32x2x2_t { let a1: float32x2_t = simd_shuffle2!(a, b, [0, 2]); let b1: float32x2_t = simd_shuffle2!(a, b, [1, 3]); @@ -23420,6 +25142,7 @@ pub unsafe fn vtrn_f32(a: float32x2_t, b: float32x2_t) -> float32x2x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(trn))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vtrnq_f32(a: float32x4_t, b: float32x4_t) -> float32x4x2_t { let a1: float32x4_t = simd_shuffle4!(a, b, [0, 4, 2, 6]); let b1: float32x4_t = simd_shuffle4!(a, b, [1, 5, 3, 7]); @@ -23432,6 +25155,7 @@ pub unsafe fn vtrnq_f32(a: float32x4_t, b: float32x4_t) -> float32x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vzip_s8(a: int8x8_t, b: int8x8_t) -> int8x8x2_t { let a0: int8x8_t = simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]); let b0: int8x8_t = simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]); @@ -23444,6 +25168,7 @@ pub unsafe fn vzip_s8(a: int8x8_t, b: int8x8_t) -> int8x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vzip_s16(a: int16x4_t, b: int16x4_t) -> int16x4x2_t { let a0: int16x4_t = simd_shuffle4!(a, b, [0, 4, 1, 5]); let b0: int16x4_t = simd_shuffle4!(a, b, [2, 6, 3, 7]); @@ -23456,6 +25181,7 @@ pub unsafe fn vzip_s16(a: int16x4_t, b: int16x4_t) -> int16x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vzip_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8x2_t { let a0: uint8x8_t = simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]); let b0: uint8x8_t = simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]); @@ -23468,6 +25194,7 @@ pub unsafe fn vzip_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vzip_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4x2_t { let a0: uint16x4_t = simd_shuffle4!(a, b, [0, 4, 1, 5]); let b0: uint16x4_t = simd_shuffle4!(a, b, [2, 6, 3, 7]); @@ -23480,6 +25207,7 @@ pub unsafe fn vzip_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vzip_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8x2_t { let a0: poly8x8_t = simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]); let b0: poly8x8_t = simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]); @@ -23492,6 +25220,7 @@ pub unsafe fn vzip_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vzip_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4x2_t { let a0: poly16x4_t = simd_shuffle4!(a, b, [0, 4, 1, 5]); let b0: poly16x4_t = simd_shuffle4!(a, b, [2, 6, 3, 7]); @@ -23504,6 +25233,7 @@ pub unsafe fn vzip_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vzip_s32(a: int32x2_t, b: int32x2_t) -> int32x2x2_t { let a0: int32x2_t = simd_shuffle2!(a, b, [0, 2]); let b0: int32x2_t = simd_shuffle2!(a, b, [1, 3]); @@ -23516,6 +25246,7 @@ pub unsafe fn vzip_s32(a: int32x2_t, b: int32x2_t) -> int32x2x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vzip_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2x2_t { let a0: uint32x2_t = simd_shuffle2!(a, b, [0, 2]); let b0: uint32x2_t = simd_shuffle2!(a, b, [1, 3]); @@ -23528,6 +25259,7 @@ pub unsafe fn vzip_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vzipq_s8(a: int8x16_t, b: int8x16_t) -> int8x16x2_t { let a0: int8x16_t = simd_shuffle16!(a, b, [0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23]); let b0: int8x16_t = simd_shuffle16!(a, b, [8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31]); @@ -23540,6 +25272,7 @@ pub unsafe fn vzipq_s8(a: int8x16_t, b: int8x16_t) -> int8x16x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vzipq_s16(a: int16x8_t, b: int16x8_t) -> int16x8x2_t { let a0: int16x8_t = simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]); let b0: int16x8_t = simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]); @@ -23552,6 +25285,7 @@ pub unsafe fn vzipq_s16(a: int16x8_t, b: int16x8_t) -> int16x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vzipq_s32(a: int32x4_t, b: int32x4_t) -> int32x4x2_t { let a0: int32x4_t = simd_shuffle4!(a, b, [0, 4, 1, 5]); let b0: int32x4_t = simd_shuffle4!(a, b, [2, 6, 3, 7]); @@ -23564,6 +25298,7 @@ pub unsafe fn vzipq_s32(a: int32x4_t, b: int32x4_t) -> int32x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vzipq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16x2_t { let a0: uint8x16_t = simd_shuffle16!(a, b, [0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23]); let b0: uint8x16_t = simd_shuffle16!(a, b, [8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31]); @@ -23576,6 +25311,7 @@ pub unsafe fn vzipq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vzipq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8x2_t { let a0: uint16x8_t = simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]); let b0: uint16x8_t = simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]); @@ -23588,6 +25324,7 @@ pub unsafe fn vzipq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vzipq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4x2_t { let a0: uint32x4_t = simd_shuffle4!(a, b, [0, 4, 1, 5]); let b0: uint32x4_t = simd_shuffle4!(a, b, [2, 6, 3, 7]); @@ -23600,6 +25337,7 @@ pub unsafe fn vzipq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vzipq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16x2_t { let a0: poly8x16_t = simd_shuffle16!(a, b, [0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23]); let b0: poly8x16_t = simd_shuffle16!(a, b, [8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31]); @@ -23612,6 +25350,7 @@ pub unsafe fn vzipq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vzipq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8x2_t { let a0: poly16x8_t = simd_shuffle8!(a, b, [0, 8, 1, 9, 2, 10, 3, 11]); let b0: poly16x8_t = simd_shuffle8!(a, b, [4, 12, 5, 13, 6, 14, 7, 15]); @@ -23624,6 +25363,7 @@ pub unsafe fn vzipq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vzip_f32(a: float32x2_t, b: float32x2_t) -> float32x2x2_t { let a0: float32x2_t = simd_shuffle2!(a, b, [0, 2]); let b0: float32x2_t = simd_shuffle2!(a, b, [1, 3]); @@ -23636,6 +25376,7 @@ pub unsafe fn vzip_f32(a: float32x2_t, b: float32x2_t) -> float32x2x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vzipq_f32(a: float32x4_t, b: float32x4_t) -> float32x4x2_t { let a0: float32x4_t = simd_shuffle4!(a, b, [0, 4, 1, 5]); let b0: float32x4_t = simd_shuffle4!(a, b, [2, 6, 3, 7]); @@ -23648,6 +25389,7 @@ pub unsafe fn vzipq_f32(a: float32x4_t, b: float32x4_t) -> float32x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vuzp_s8(a: int8x8_t, b: int8x8_t) -> int8x8x2_t { let a0: int8x8_t = simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]); let b0: int8x8_t = simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]); @@ -23660,6 +25402,7 @@ pub unsafe fn vuzp_s8(a: int8x8_t, b: int8x8_t) -> int8x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vuzp_s16(a: int16x4_t, b: int16x4_t) -> int16x4x2_t { let a0: int16x4_t = simd_shuffle4!(a, b, [0, 2, 4, 6]); let b0: int16x4_t = simd_shuffle4!(a, b, [1, 3, 5, 7]); @@ -23672,6 +25415,7 @@ pub unsafe fn vuzp_s16(a: int16x4_t, b: int16x4_t) -> int16x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vuzpq_s8(a: int8x16_t, b: int8x16_t) -> int8x16x2_t { let a0: int8x16_t = simd_shuffle16!(a, b, [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]); let b0: int8x16_t = simd_shuffle16!(a, b, [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]); @@ -23684,6 +25428,7 @@ pub unsafe fn vuzpq_s8(a: int8x16_t, b: int8x16_t) -> int8x16x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vuzpq_s16(a: int16x8_t, b: int16x8_t) -> int16x8x2_t { let a0: int16x8_t = simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]); let b0: int16x8_t = simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]); @@ -23696,6 +25441,7 @@ pub unsafe fn vuzpq_s16(a: int16x8_t, b: int16x8_t) -> int16x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vuzpq_s32(a: int32x4_t, b: int32x4_t) -> int32x4x2_t { let a0: int32x4_t = simd_shuffle4!(a, b, [0, 2, 4, 6]); let b0: int32x4_t = simd_shuffle4!(a, b, [1, 3, 5, 7]); @@ -23708,6 +25454,7 @@ pub unsafe fn vuzpq_s32(a: int32x4_t, b: int32x4_t) -> int32x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vuzp_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8x2_t { let a0: uint8x8_t = simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]); let b0: uint8x8_t = simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]); @@ -23720,6 +25467,7 @@ pub unsafe fn vuzp_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vuzp_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4x2_t { let a0: uint16x4_t = simd_shuffle4!(a, b, [0, 2, 4, 6]); let b0: uint16x4_t = simd_shuffle4!(a, b, [1, 3, 5, 7]); @@ -23732,6 +25480,7 @@ pub unsafe fn vuzp_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vuzpq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16x2_t { let a0: uint8x16_t = simd_shuffle16!(a, b, [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]); let b0: uint8x16_t = simd_shuffle16!(a, b, [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]); @@ -23744,6 +25493,7 @@ pub unsafe fn vuzpq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vuzpq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8x2_t { let a0: uint16x8_t = simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]); let b0: uint16x8_t = simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]); @@ -23756,6 +25506,7 @@ pub unsafe fn vuzpq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vuzpq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4x2_t { let a0: uint32x4_t = simd_shuffle4!(a, b, [0, 2, 4, 6]); let b0: uint32x4_t = simd_shuffle4!(a, b, [1, 3, 5, 7]); @@ -23768,6 +25519,7 @@ pub unsafe fn vuzpq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vuzp_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8x2_t { let a0: poly8x8_t = simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]); let b0: poly8x8_t = simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]); @@ -23780,6 +25532,7 @@ pub unsafe fn vuzp_p8(a: poly8x8_t, b: poly8x8_t) -> poly8x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vuzp_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4x2_t { let a0: poly16x4_t = simd_shuffle4!(a, b, [0, 2, 4, 6]); let b0: poly16x4_t = simd_shuffle4!(a, b, [1, 3, 5, 7]); @@ -23792,6 +25545,7 @@ pub unsafe fn vuzp_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vuzpq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16x2_t { let a0: poly8x16_t = simd_shuffle16!(a, b, [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]); let b0: poly8x16_t = simd_shuffle16!(a, b, [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]); @@ -23804,6 +25558,7 @@ pub unsafe fn vuzpq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vuzpq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8x2_t { let a0: poly16x8_t = simd_shuffle8!(a, b, [0, 2, 4, 6, 8, 10, 12, 14]); let b0: poly16x8_t = simd_shuffle8!(a, b, [1, 3, 5, 7, 9, 11, 13, 15]); @@ -23816,6 +25571,7 @@ pub unsafe fn vuzpq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vuzp_s32(a: int32x2_t, b: int32x2_t) -> int32x2x2_t { let a0: int32x2_t = simd_shuffle2!(a, b, [0, 2]); let b0: int32x2_t = simd_shuffle2!(a, b, [1, 3]); @@ -23828,6 +25584,7 @@ pub unsafe fn vuzp_s32(a: int32x2_t, b: int32x2_t) -> int32x2x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vuzp_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2x2_t { let a0: uint32x2_t = simd_shuffle2!(a, b, [0, 2]); let b0: uint32x2_t = simd_shuffle2!(a, b, [1, 3]); @@ -23840,6 +25597,7 @@ pub unsafe fn vuzp_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vtrn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(zip))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vuzp_f32(a: float32x2_t, b: float32x2_t) -> float32x2x2_t { let a0: float32x2_t = simd_shuffle2!(a, b, [0, 2]); let b0: float32x2_t = simd_shuffle2!(a, b, [1, 3]); @@ -23852,6 +25610,7 @@ pub unsafe fn vuzp_f32(a: float32x2_t, b: float32x2_t) -> float32x2x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vuzp))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uzp))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vuzpq_f32(a: float32x4_t, b: float32x4_t) -> float32x4x2_t { let a0: float32x4_t = simd_shuffle4!(a, b, [0, 2, 4, 6]); let b0: float32x4_t = simd_shuffle4!(a, b, [1, 3, 5, 7]); @@ -23864,6 +25623,7 @@ pub unsafe fn vuzpq_f32(a: float32x4_t, b: float32x4_t) -> float32x4x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabal.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabal))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabal_u8(a: uint16x8_t, b: uint8x8_t, c: uint8x8_t) -> uint16x8_t { let d: uint8x8_t = vabd_u8(b, c); simd_add(a, simd_cast(d)) @@ -23875,6 +25635,7 @@ pub unsafe fn vabal_u8(a: uint16x8_t, b: uint8x8_t, c: uint8x8_t) -> uint16x8_t #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabal.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabal))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabal_u16(a: uint32x4_t, b: uint16x4_t, c: uint16x4_t) -> uint32x4_t { let d: uint16x4_t = vabd_u16(b, c); simd_add(a, simd_cast(d)) @@ -23886,6 +25647,7 @@ pub unsafe fn vabal_u16(a: uint32x4_t, b: uint16x4_t, c: uint16x4_t) -> uint32x4 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabal.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uabal))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabal_u32(a: uint64x2_t, b: uint32x2_t, c: uint32x2_t) -> uint64x2_t { let d: uint32x2_t = vabd_u32(b, c); simd_add(a, simd_cast(d)) @@ -23897,6 +25659,7 @@ pub unsafe fn vabal_u32(a: uint64x2_t, b: uint32x2_t, c: uint32x2_t) -> uint64x2 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabal.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabal))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabal_s8(a: int16x8_t, b: int8x8_t, c: int8x8_t) -> int16x8_t { let d: int8x8_t = vabd_s8(b, c); let e: uint8x8_t = simd_cast(d); @@ -23909,6 +25672,7 @@ pub unsafe fn vabal_s8(a: int16x8_t, b: int8x8_t, c: int8x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabal.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabal))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabal_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t { let d: int16x4_t = vabd_s16(b, c); let e: uint16x4_t = simd_cast(d); @@ -23921,6 +25685,7 @@ pub unsafe fn vabal_s16(a: int32x4_t, b: int16x4_t, c: int16x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vabal.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sabal))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vabal_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t { let d: int32x2_t = vabd_s32(b, c); let e: uint32x2_t = simd_cast(d); @@ -23933,6 +25698,7 @@ pub unsafe fn vabal_s32(a: int64x2_t, b: int32x2_t, c: int32x2_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqabs.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqabs_s8(a: int8x8_t) -> int8x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -23949,6 +25715,7 @@ vqabs_s8_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqabs.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqabsq_s8(a: int8x16_t) -> int8x16_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -23965,6 +25732,7 @@ vqabsq_s8_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqabs.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqabs_s16(a: int16x4_t) -> int16x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -23981,6 +25749,7 @@ vqabs_s16_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqabs.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqabsq_s16(a: int16x8_t) -> int16x8_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -23997,6 +25766,7 @@ vqabsq_s16_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqabs.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqabs_s32(a: int32x2_t) -> int32x2_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -24013,6 +25783,7 @@ vqabs_s32_(a) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vqabs.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sqabs))] +#[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub unsafe fn vqabsq_s32(a: int32x4_t) -> int32x4_t { #[allow(improper_ctypes)] extern "unadjusted" { @@ -25039,6 +26810,24 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vtst_p16() { + let a: i16x4 = i16x4::new(-32768, 0x00, 0x01, 0x02); + let b: i16x4 = i16x4::new(-32768, 0x00, 0x01, 0x02); + let e: u16x4 = u16x4::new(0xFF_FF, 0, 0xFF_FF, 0xFF_FF); + let r: u16x4 = transmute(vtst_p16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vtstq_p16() { + let a: i16x8 = i16x8::new(-32768, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); + let b: i16x8 = i16x8::new(-32768, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); + let e: u16x8 = u16x8::new(0xFF_FF, 0, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF, 0xFF_FF); + let r: u16x8 = transmute(vtstq_p16(transmute(a), transmute(b))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vtst_u8() { let a: u8x8 = u8x8::new(0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); @@ -25664,48 +27453,48 @@ mod test { #[simd_test(enable = "neon")] unsafe fn test_vcls_u8() { let a: u8x8 = u8x8::new(0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let e: u8x8 = u8x8::new(7, 7, 7, 7, 7, 7, 7, 7); - let r: u8x8 = transmute(vcls_u8(transmute(a))); + let e: i8x8 = i8x8::new(7, 7, 7, 7, 7, 7, 7, 7); + let r: i8x8 = transmute(vcls_u8(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] unsafe fn test_vclsq_u8() { let a: u8x16 = u8x16::new(0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF); - let e: u8x16 = u8x16::new(7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7); - let r: u8x16 = transmute(vclsq_u8(transmute(a))); + let e: i8x16 = i8x16::new(7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7); + let r: i8x16 = transmute(vclsq_u8(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] unsafe fn test_vcls_u16() { let a: u16x4 = u16x4::new(0, 0xFF_FF, 0x00, 0x00); - let e: u16x4 = u16x4::new(15, 15, 15, 15); - let r: u16x4 = transmute(vcls_u16(transmute(a))); + let e: i16x4 = i16x4::new(15, 15, 15, 15); + let r: i16x4 = transmute(vcls_u16(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] unsafe fn test_vclsq_u16() { let a: u16x8 = u16x8::new(0, 0xFF_FF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - let e: u16x8 = u16x8::new(15, 15, 15, 15, 15, 15, 15, 15); - let r: u16x8 = transmute(vclsq_u16(transmute(a))); + let e: i16x8 = i16x8::new(15, 15, 15, 15, 15, 15, 15, 15); + let r: i16x8 = transmute(vclsq_u16(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] unsafe fn test_vcls_u32() { let a: u32x2 = u32x2::new(0, 0xFF_FF_FF_FF); - let e: u32x2 = u32x2::new(31, 31); - let r: u32x2 = transmute(vcls_u32(transmute(a))); + let e: i32x2 = i32x2::new(31, 31); + let r: i32x2 = transmute(vcls_u32(transmute(a))); assert_eq!(r, e); } #[simd_test(enable = "neon")] unsafe fn test_vclsq_u32() { let a: u32x4 = u32x4::new(0, 0xFF_FF_FF_FF, 0x00, 0x00); - let e: u32x4 = u32x4::new(31, 31, 31, 31); - let r: u32x4 = transmute(vclsq_u32(transmute(a))); + let e: i32x4 = i32x4::new(31, 31, 31, 31); + let r: i32x4 = transmute(vclsq_u32(transmute(a))); assert_eq!(r, e); } @@ -30499,7 +32288,7 @@ mod test { let a: [i8; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; let e: [i8; 8] = [1, 0, 0, 0, 0, 0, 0, 0]; let mut r: [i8; 8] = [0i8; 8]; - vst1_lane_s8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_lane_s8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30508,7 +32297,7 @@ mod test { let a: [i16; 5] = [0, 1, 2, 3, 4]; let e: [i16; 4] = [1, 0, 0, 0]; let mut r: [i16; 4] = [0i16; 4]; - vst1_lane_s16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_lane_s16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30517,7 +32306,7 @@ mod test { let a: [i32; 3] = [0, 1, 2]; let e: [i32; 2] = [1, 0]; let mut r: [i32; 2] = [0i32; 2]; - vst1_lane_s32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_lane_s32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30526,7 +32315,7 @@ mod test { let a: [i64; 2] = [0, 1]; let e: [i64; 1] = [1]; let mut r: [i64; 1] = [0i64; 1]; - vst1_lane_s64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_lane_s64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30535,7 +32324,7 @@ mod test { let a: [i8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let e: [i8; 16] = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [i8; 16] = [0i8; 16]; - vst1q_lane_s8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_lane_s8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30544,7 +32333,7 @@ mod test { let a: [i16; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; let e: [i16; 8] = [1, 0, 0, 0, 0, 0, 0, 0]; let mut r: [i16; 8] = [0i16; 8]; - vst1q_lane_s16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_lane_s16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30553,7 +32342,7 @@ mod test { let a: [i32; 5] = [0, 1, 2, 3, 4]; let e: [i32; 4] = [1, 0, 0, 0]; let mut r: [i32; 4] = [0i32; 4]; - vst1q_lane_s32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_lane_s32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30562,7 +32351,7 @@ mod test { let a: [i64; 3] = [0, 1, 2]; let e: [i64; 2] = [1, 0]; let mut r: [i64; 2] = [0i64; 2]; - vst1q_lane_s64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_lane_s64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30571,7 +32360,7 @@ mod test { let a: [u8; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; let e: [u8; 8] = [1, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u8; 8] = [0u8; 8]; - vst1_lane_u8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_lane_u8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30580,7 +32369,7 @@ mod test { let a: [u16; 5] = [0, 1, 2, 3, 4]; let e: [u16; 4] = [1, 0, 0, 0]; let mut r: [u16; 4] = [0u16; 4]; - vst1_lane_u16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_lane_u16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30589,7 +32378,7 @@ mod test { let a: [u32; 3] = [0, 1, 2]; let e: [u32; 2] = [1, 0]; let mut r: [u32; 2] = [0u32; 2]; - vst1_lane_u32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_lane_u32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30598,7 +32387,7 @@ mod test { let a: [u64; 2] = [0, 1]; let e: [u64; 1] = [1]; let mut r: [u64; 1] = [0u64; 1]; - vst1_lane_u64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_lane_u64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30607,7 +32396,7 @@ mod test { let a: [u8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let e: [u8; 16] = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u8; 16] = [0u8; 16]; - vst1q_lane_u8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_lane_u8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30616,7 +32405,7 @@ mod test { let a: [u16; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; let e: [u16; 8] = [1, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u16; 8] = [0u16; 8]; - vst1q_lane_u16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_lane_u16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30625,7 +32414,7 @@ mod test { let a: [u32; 5] = [0, 1, 2, 3, 4]; let e: [u32; 4] = [1, 0, 0, 0]; let mut r: [u32; 4] = [0u32; 4]; - vst1q_lane_u32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_lane_u32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30634,7 +32423,7 @@ mod test { let a: [u64; 3] = [0, 1, 2]; let e: [u64; 2] = [1, 0]; let mut r: [u64; 2] = [0u64; 2]; - vst1q_lane_u64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_lane_u64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30643,7 +32432,7 @@ mod test { let a: [u8; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; let e: [u8; 8] = [1, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u8; 8] = [0u8; 8]; - vst1_lane_p8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_lane_p8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30652,7 +32441,7 @@ mod test { let a: [u16; 5] = [0, 1, 2, 3, 4]; let e: [u16; 4] = [1, 0, 0, 0]; let mut r: [u16; 4] = [0u16; 4]; - vst1_lane_p16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_lane_p16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30661,7 +32450,7 @@ mod test { let a: [u8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let e: [u8; 16] = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u8; 16] = [0u8; 16]; - vst1q_lane_p8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_lane_p8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30670,7 +32459,7 @@ mod test { let a: [u16; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; let e: [u16; 8] = [1, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u16; 8] = [0u16; 8]; - vst1q_lane_p16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_lane_p16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30679,7 +32468,7 @@ mod test { let a: [u64; 2] = [0, 1]; let e: [u64; 1] = [1]; let mut r: [u64; 1] = [0u64; 1]; - vst1_lane_p64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_lane_p64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30688,7 +32477,7 @@ mod test { let a: [u64; 3] = [0, 1, 2]; let e: [u64; 2] = [1, 0]; let mut r: [u64; 2] = [0u64; 2]; - vst1q_lane_p64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_lane_p64::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30697,7 +32486,7 @@ mod test { let a: [f32; 3] = [0., 1., 2.]; let e: [f32; 2] = [1., 0.]; let mut r: [f32; 2] = [0f32; 2]; - vst1_lane_f32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_lane_f32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30706,7 +32495,7 @@ mod test { let a: [f32; 5] = [0., 1., 2., 3., 4.]; let e: [f32; 4] = [1., 0., 0., 0.]; let mut r: [f32; 4] = [0f32; 4]; - vst1q_lane_f32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_lane_f32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30715,7 +32504,7 @@ mod test { let a: [i8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let e: [i8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let mut r: [i8; 16] = [0i8; 16]; - vst1_s8_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_s8_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30724,7 +32513,7 @@ mod test { let a: [i16; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; let e: [i16; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; let mut r: [i16; 8] = [0i16; 8]; - vst1_s16_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_s16_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30733,7 +32522,7 @@ mod test { let a: [i32; 5] = [0, 1, 2, 3, 4]; let e: [i32; 4] = [1, 2, 3, 4]; let mut r: [i32; 4] = [0i32; 4]; - vst1_s32_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_s32_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30742,7 +32531,7 @@ mod test { let a: [i64; 3] = [0, 1, 2]; let e: [i64; 2] = [1, 2]; let mut r: [i64; 2] = [0i64; 2]; - vst1_s64_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_s64_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30751,7 +32540,7 @@ mod test { let a: [i8; 33] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; let e: [i8; 32] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; let mut r: [i8; 32] = [0i8; 32]; - vst1q_s8_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_s8_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30760,7 +32549,7 @@ mod test { let a: [i16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let e: [i16; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let mut r: [i16; 16] = [0i16; 16]; - vst1q_s16_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_s16_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30769,7 +32558,7 @@ mod test { let a: [i32; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; let e: [i32; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; let mut r: [i32; 8] = [0i32; 8]; - vst1q_s32_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_s32_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30778,7 +32567,7 @@ mod test { let a: [i64; 5] = [0, 1, 2, 3, 4]; let e: [i64; 4] = [1, 2, 3, 4]; let mut r: [i64; 4] = [0i64; 4]; - vst1q_s64_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_s64_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30787,7 +32576,7 @@ mod test { let a: [i8; 25] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; let e: [i8; 24] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; let mut r: [i8; 24] = [0i8; 24]; - vst1_s8_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_s8_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30796,7 +32585,7 @@ mod test { let a: [i16; 13] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; let e: [i16; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; let mut r: [i16; 12] = [0i16; 12]; - vst1_s16_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_s16_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30805,7 +32594,7 @@ mod test { let a: [i32; 7] = [0, 1, 2, 3, 4, 5, 6]; let e: [i32; 6] = [1, 2, 3, 4, 5, 6]; let mut r: [i32; 6] = [0i32; 6]; - vst1_s32_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_s32_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30814,7 +32603,7 @@ mod test { let a: [i64; 4] = [0, 1, 2, 3]; let e: [i64; 3] = [1, 2, 3]; let mut r: [i64; 3] = [0i64; 3]; - vst1_s64_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_s64_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30823,7 +32612,7 @@ mod test { let a: [i8; 49] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let e: [i8; 48] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let mut r: [i8; 48] = [0i8; 48]; - vst1q_s8_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_s8_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30832,7 +32621,7 @@ mod test { let a: [i16; 25] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; let e: [i16; 24] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; let mut r: [i16; 24] = [0i16; 24]; - vst1q_s16_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_s16_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30841,7 +32630,7 @@ mod test { let a: [i32; 13] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; let e: [i32; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; let mut r: [i32; 12] = [0i32; 12]; - vst1q_s32_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_s32_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30850,7 +32639,7 @@ mod test { let a: [i64; 7] = [0, 1, 2, 3, 4, 5, 6]; let e: [i64; 6] = [1, 2, 3, 4, 5, 6]; let mut r: [i64; 6] = [0i64; 6]; - vst1q_s64_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_s64_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30859,7 +32648,7 @@ mod test { let a: [i8; 33] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; let e: [i8; 32] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; let mut r: [i8; 32] = [0i8; 32]; - vst1_s8_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_s8_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30868,7 +32657,7 @@ mod test { let a: [i16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let e: [i16; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let mut r: [i16; 16] = [0i16; 16]; - vst1_s16_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_s16_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30877,7 +32666,7 @@ mod test { let a: [i32; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; let e: [i32; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; let mut r: [i32; 8] = [0i32; 8]; - vst1_s32_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_s32_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30886,7 +32675,7 @@ mod test { let a: [i64; 5] = [0, 1, 2, 3, 4]; let e: [i64; 4] = [1, 2, 3, 4]; let mut r: [i64; 4] = [0i64; 4]; - vst1_s64_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_s64_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30895,7 +32684,7 @@ mod test { let a: [i8; 65] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; let e: [i8; 64] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; let mut r: [i8; 64] = [0i8; 64]; - vst1q_s8_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_s8_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30904,7 +32693,7 @@ mod test { let a: [i16; 33] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; let e: [i16; 32] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; let mut r: [i16; 32] = [0i16; 32]; - vst1q_s16_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_s16_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30913,7 +32702,7 @@ mod test { let a: [i32; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let e: [i32; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let mut r: [i32; 16] = [0i32; 16]; - vst1q_s32_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_s32_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30922,7 +32711,7 @@ mod test { let a: [i64; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; let e: [i64; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; let mut r: [i64; 8] = [0i64; 8]; - vst1q_s64_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_s64_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30931,7 +32720,7 @@ mod test { let a: [u8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let e: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let mut r: [u8; 16] = [0u8; 16]; - vst1_u8_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_u8_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30940,7 +32729,7 @@ mod test { let a: [u16; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; let e: [u16; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; let mut r: [u16; 8] = [0u16; 8]; - vst1_u16_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_u16_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30949,7 +32738,7 @@ mod test { let a: [u32; 5] = [0, 1, 2, 3, 4]; let e: [u32; 4] = [1, 2, 3, 4]; let mut r: [u32; 4] = [0u32; 4]; - vst1_u32_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_u32_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30958,7 +32747,7 @@ mod test { let a: [u64; 3] = [0, 1, 2]; let e: [u64; 2] = [1, 2]; let mut r: [u64; 2] = [0u64; 2]; - vst1_u64_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_u64_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30967,7 +32756,7 @@ mod test { let a: [u8; 33] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; let e: [u8; 32] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; let mut r: [u8; 32] = [0u8; 32]; - vst1q_u8_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_u8_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30976,7 +32765,7 @@ mod test { let a: [u16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let e: [u16; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let mut r: [u16; 16] = [0u16; 16]; - vst1q_u16_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_u16_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30985,7 +32774,7 @@ mod test { let a: [u32; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; let e: [u32; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; let mut r: [u32; 8] = [0u32; 8]; - vst1q_u32_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_u32_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -30994,7 +32783,7 @@ mod test { let a: [u64; 5] = [0, 1, 2, 3, 4]; let e: [u64; 4] = [1, 2, 3, 4]; let mut r: [u64; 4] = [0u64; 4]; - vst1q_u64_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_u64_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31003,7 +32792,7 @@ mod test { let a: [u8; 25] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; let e: [u8; 24] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; let mut r: [u8; 24] = [0u8; 24]; - vst1_u8_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_u8_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31012,7 +32801,7 @@ mod test { let a: [u16; 13] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; let e: [u16; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; let mut r: [u16; 12] = [0u16; 12]; - vst1_u16_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_u16_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31021,7 +32810,7 @@ mod test { let a: [u32; 7] = [0, 1, 2, 3, 4, 5, 6]; let e: [u32; 6] = [1, 2, 3, 4, 5, 6]; let mut r: [u32; 6] = [0u32; 6]; - vst1_u32_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_u32_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31030,7 +32819,7 @@ mod test { let a: [u64; 4] = [0, 1, 2, 3]; let e: [u64; 3] = [1, 2, 3]; let mut r: [u64; 3] = [0u64; 3]; - vst1_u64_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_u64_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31039,7 +32828,7 @@ mod test { let a: [u8; 49] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let e: [u8; 48] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let mut r: [u8; 48] = [0u8; 48]; - vst1q_u8_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_u8_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31048,7 +32837,7 @@ mod test { let a: [u16; 25] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; let e: [u16; 24] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; let mut r: [u16; 24] = [0u16; 24]; - vst1q_u16_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_u16_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31057,7 +32846,7 @@ mod test { let a: [u32; 13] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; let e: [u32; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; let mut r: [u32; 12] = [0u32; 12]; - vst1q_u32_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_u32_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31066,7 +32855,7 @@ mod test { let a: [u64; 7] = [0, 1, 2, 3, 4, 5, 6]; let e: [u64; 6] = [1, 2, 3, 4, 5, 6]; let mut r: [u64; 6] = [0u64; 6]; - vst1q_u64_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_u64_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31075,7 +32864,7 @@ mod test { let a: [u8; 33] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; let e: [u8; 32] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; let mut r: [u8; 32] = [0u8; 32]; - vst1_u8_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_u8_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31084,7 +32873,7 @@ mod test { let a: [u16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let e: [u16; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let mut r: [u16; 16] = [0u16; 16]; - vst1_u16_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_u16_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31093,7 +32882,7 @@ mod test { let a: [u32; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; let e: [u32; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; let mut r: [u32; 8] = [0u32; 8]; - vst1_u32_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_u32_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31102,7 +32891,7 @@ mod test { let a: [u64; 5] = [0, 1, 2, 3, 4]; let e: [u64; 4] = [1, 2, 3, 4]; let mut r: [u64; 4] = [0u64; 4]; - vst1_u64_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_u64_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31111,7 +32900,7 @@ mod test { let a: [u8; 65] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; let e: [u8; 64] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; let mut r: [u8; 64] = [0u8; 64]; - vst1q_u8_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_u8_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31120,7 +32909,7 @@ mod test { let a: [u16; 33] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; let e: [u16; 32] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; let mut r: [u16; 32] = [0u16; 32]; - vst1q_u16_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_u16_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31129,7 +32918,7 @@ mod test { let a: [u32; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let e: [u32; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let mut r: [u32; 16] = [0u32; 16]; - vst1q_u32_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_u32_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31138,7 +32927,7 @@ mod test { let a: [u64; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; let e: [u64; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; let mut r: [u64; 8] = [0u64; 8]; - vst1q_u64_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_u64_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31147,7 +32936,7 @@ mod test { let a: [u8; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let e: [u8; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let mut r: [u8; 16] = [0u8; 16]; - vst1_p8_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_p8_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31156,7 +32945,7 @@ mod test { let a: [u8; 25] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; let e: [u8; 24] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; let mut r: [u8; 24] = [0u8; 24]; - vst1_p8_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_p8_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31165,7 +32954,7 @@ mod test { let a: [u8; 33] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; let e: [u8; 32] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; let mut r: [u8; 32] = [0u8; 32]; - vst1_p8_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_p8_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31174,7 +32963,7 @@ mod test { let a: [u8; 33] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; let e: [u8; 32] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; let mut r: [u8; 32] = [0u8; 32]; - vst1q_p8_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_p8_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31183,7 +32972,7 @@ mod test { let a: [u8; 49] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let e: [u8; 48] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let mut r: [u8; 48] = [0u8; 48]; - vst1q_p8_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_p8_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31192,7 +32981,7 @@ mod test { let a: [u8; 65] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; let e: [u8; 64] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; let mut r: [u8; 64] = [0u8; 64]; - vst1q_p8_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_p8_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31201,7 +32990,7 @@ mod test { let a: [u16; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; let e: [u16; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; let mut r: [u16; 8] = [0u16; 8]; - vst1_p16_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_p16_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31210,7 +32999,7 @@ mod test { let a: [u16; 13] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; let e: [u16; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; let mut r: [u16; 12] = [0u16; 12]; - vst1_p16_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_p16_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31219,7 +33008,7 @@ mod test { let a: [u16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let e: [u16; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let mut r: [u16; 16] = [0u16; 16]; - vst1_p16_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_p16_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31228,7 +33017,7 @@ mod test { let a: [u16; 17] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let e: [u16; 16] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let mut r: [u16; 16] = [0u16; 16]; - vst1q_p16_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_p16_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31237,7 +33026,7 @@ mod test { let a: [u16; 25] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; let e: [u16; 24] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]; let mut r: [u16; 24] = [0u16; 24]; - vst1q_p16_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_p16_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31246,7 +33035,7 @@ mod test { let a: [u16; 33] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; let e: [u16; 32] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]; let mut r: [u16; 32] = [0u16; 32]; - vst1q_p16_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_p16_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31255,7 +33044,7 @@ mod test { let a: [u64; 3] = [0, 1, 2]; let e: [u64; 2] = [1, 2]; let mut r: [u64; 2] = [0u64; 2]; - vst1_p64_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_p64_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31264,7 +33053,7 @@ mod test { let a: [u64; 4] = [0, 1, 2, 3]; let e: [u64; 3] = [1, 2, 3]; let mut r: [u64; 3] = [0u64; 3]; - vst1_p64_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_p64_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31273,7 +33062,7 @@ mod test { let a: [u64; 5] = [0, 1, 2, 3, 4]; let e: [u64; 4] = [1, 2, 3, 4]; let mut r: [u64; 4] = [0u64; 4]; - vst1_p64_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_p64_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31282,7 +33071,7 @@ mod test { let a: [u64; 5] = [0, 1, 2, 3, 4]; let e: [u64; 4] = [1, 2, 3, 4]; let mut r: [u64; 4] = [0u64; 4]; - vst1q_p64_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_p64_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31291,7 +33080,7 @@ mod test { let a: [u64; 7] = [0, 1, 2, 3, 4, 5, 6]; let e: [u64; 6] = [1, 2, 3, 4, 5, 6]; let mut r: [u64; 6] = [0u64; 6]; - vst1q_p64_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_p64_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31300,7 +33089,7 @@ mod test { let a: [u64; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; let e: [u64; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; let mut r: [u64; 8] = [0u64; 8]; - vst1q_p64_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_p64_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31309,7 +33098,7 @@ mod test { let a: [f32; 5] = [0., 1., 2., 3., 4.]; let e: [f32; 4] = [1., 2., 3., 4.]; let mut r: [f32; 4] = [0f32; 4]; - vst1_f32_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_f32_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31318,7 +33107,7 @@ mod test { let a: [f32; 9] = [0., 1., 2., 3., 4., 5., 6., 7., 8.]; let e: [f32; 8] = [1., 2., 3., 4., 5., 6., 7., 8.]; let mut r: [f32; 8] = [0f32; 8]; - vst1q_f32_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_f32_x2(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31327,7 +33116,7 @@ mod test { let a: [f32; 7] = [0., 1., 2., 3., 4., 5., 6.]; let e: [f32; 6] = [1., 2., 3., 4., 5., 6.]; let mut r: [f32; 6] = [0f32; 6]; - vst1_f32_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_f32_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31336,7 +33125,7 @@ mod test { let a: [f32; 13] = [0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; let e: [f32; 12] = [1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.]; let mut r: [f32; 12] = [0f32; 12]; - vst1q_f32_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_f32_x3(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31345,7 +33134,7 @@ mod test { let a: [f32; 9] = [0., 1., 2., 3., 4., 5., 6., 7., 8.]; let e: [f32; 8] = [1., 2., 3., 4., 5., 6., 7., 8.]; let mut r: [f32; 8] = [0f32; 8]; - vst1_f32_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1_f32_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31354,7 +33143,7 @@ mod test { let a: [f32; 17] = [0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16.]; let e: [f32; 16] = [1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15., 16.]; let mut r: [f32; 16] = [0f32; 16]; - vst1q_f32_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst1q_f32_x4(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31363,7 +33152,7 @@ mod test { let a: [i8; 17] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9]; let e: [i8; 16] = [1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9]; let mut r: [i8; 16] = [0i8; 16]; - vst2_s8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_s8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31372,7 +33161,7 @@ mod test { let a: [i16; 9] = [0, 1, 2, 2, 3, 2, 3, 4, 5]; let e: [i16; 8] = [1, 2, 2, 3, 2, 4, 3, 5]; let mut r: [i16; 8] = [0i16; 8]; - vst2_s16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_s16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31381,7 +33170,7 @@ mod test { let a: [i32; 5] = [0, 1, 2, 2, 3]; let e: [i32; 4] = [1, 2, 2, 3]; let mut r: [i32; 4] = [0i32; 4]; - vst2_s32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_s32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31390,7 +33179,7 @@ mod test { let a: [i8; 33] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]; let e: [i8; 32] = [1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16, 9, 17]; let mut r: [i8; 32] = [0i8; 32]; - vst2q_s8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_s8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31399,7 +33188,7 @@ mod test { let a: [i16; 17] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9]; let e: [i16; 16] = [1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9]; let mut r: [i16; 16] = [0i16; 16]; - vst2q_s16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_s16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31408,7 +33197,7 @@ mod test { let a: [i32; 9] = [0, 1, 2, 2, 3, 2, 3, 4, 5]; let e: [i32; 8] = [1, 2, 2, 3, 2, 4, 3, 5]; let mut r: [i32; 8] = [0i32; 8]; - vst2q_s32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_s32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31417,7 +33206,7 @@ mod test { let a: [i64; 3] = [0, 1, 2]; let e: [i64; 2] = [1, 2]; let mut r: [i64; 2] = [0i64; 2]; - vst2_s64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_s64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31426,7 +33215,7 @@ mod test { let a: [u8; 17] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9]; let e: [u8; 16] = [1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9]; let mut r: [u8; 16] = [0u8; 16]; - vst2_u8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_u8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31435,7 +33224,7 @@ mod test { let a: [u16; 9] = [0, 1, 2, 2, 3, 2, 3, 4, 5]; let e: [u16; 8] = [1, 2, 2, 3, 2, 4, 3, 5]; let mut r: [u16; 8] = [0u16; 8]; - vst2_u16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_u16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31444,7 +33233,7 @@ mod test { let a: [u32; 5] = [0, 1, 2, 2, 3]; let e: [u32; 4] = [1, 2, 2, 3]; let mut r: [u32; 4] = [0u32; 4]; - vst2_u32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_u32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31453,7 +33242,7 @@ mod test { let a: [u8; 33] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]; let e: [u8; 32] = [1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16, 9, 17]; let mut r: [u8; 32] = [0u8; 32]; - vst2q_u8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_u8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31462,7 +33251,7 @@ mod test { let a: [u16; 17] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9]; let e: [u16; 16] = [1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9]; let mut r: [u16; 16] = [0u16; 16]; - vst2q_u16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_u16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31471,7 +33260,7 @@ mod test { let a: [u32; 9] = [0, 1, 2, 2, 3, 2, 3, 4, 5]; let e: [u32; 8] = [1, 2, 2, 3, 2, 4, 3, 5]; let mut r: [u32; 8] = [0u32; 8]; - vst2q_u32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_u32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31480,7 +33269,7 @@ mod test { let a: [u8; 17] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9]; let e: [u8; 16] = [1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9]; let mut r: [u8; 16] = [0u8; 16]; - vst2_p8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_p8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31489,7 +33278,7 @@ mod test { let a: [u16; 9] = [0, 1, 2, 2, 3, 2, 3, 4, 5]; let e: [u16; 8] = [1, 2, 2, 3, 2, 4, 3, 5]; let mut r: [u16; 8] = [0u16; 8]; - vst2_p16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_p16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31498,7 +33287,7 @@ mod test { let a: [u8; 33] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]; let e: [u8; 32] = [1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15, 8, 16, 9, 17]; let mut r: [u8; 32] = [0u8; 32]; - vst2q_p8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_p8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31507,7 +33296,7 @@ mod test { let a: [u16; 17] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9]; let e: [u16; 16] = [1, 2, 2, 3, 2, 4, 3, 5, 2, 6, 3, 7, 4, 8, 5, 9]; let mut r: [u16; 16] = [0u16; 16]; - vst2q_p16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_p16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31516,7 +33305,7 @@ mod test { let a: [u64; 3] = [0, 1, 2]; let e: [u64; 2] = [1, 2]; let mut r: [u64; 2] = [0u64; 2]; - vst2_u64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_u64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31525,7 +33314,7 @@ mod test { let a: [u64; 3] = [0, 1, 2]; let e: [u64; 2] = [1, 2]; let mut r: [u64; 2] = [0u64; 2]; - vst2_p64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_p64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31534,7 +33323,7 @@ mod test { let a: [f32; 5] = [0., 1., 2., 2., 3.]; let e: [f32; 4] = [1., 2., 2., 3.]; let mut r: [f32; 4] = [0f32; 4]; - vst2_f32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_f32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31543,7 +33332,7 @@ mod test { let a: [f32; 9] = [0., 1., 2., 2., 3., 2., 3., 4., 5.]; let e: [f32; 8] = [1., 2., 2., 3., 2., 4., 3., 5.]; let mut r: [f32; 8] = [0f32; 8]; - vst2q_f32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_f32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31552,7 +33341,7 @@ mod test { let a: [i8; 17] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9]; let e: [i8; 16] = [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [i8; 16] = [0i8; 16]; - vst2_lane_s8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_lane_s8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31561,7 +33350,7 @@ mod test { let a: [i16; 9] = [0, 1, 2, 2, 3, 2, 3, 4, 5]; let e: [i16; 8] = [1, 2, 0, 0, 0, 0, 0, 0]; let mut r: [i16; 8] = [0i16; 8]; - vst2_lane_s16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_lane_s16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31570,7 +33359,7 @@ mod test { let a: [i32; 5] = [0, 1, 2, 2, 3]; let e: [i32; 4] = [1, 2, 0, 0]; let mut r: [i32; 4] = [0i32; 4]; - vst2_lane_s32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_lane_s32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31579,7 +33368,7 @@ mod test { let a: [i16; 17] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9]; let e: [i16; 16] = [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [i16; 16] = [0i16; 16]; - vst2q_lane_s16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_lane_s16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31588,7 +33377,7 @@ mod test { let a: [i32; 9] = [0, 1, 2, 2, 3, 2, 3, 4, 5]; let e: [i32; 8] = [1, 2, 0, 0, 0, 0, 0, 0]; let mut r: [i32; 8] = [0i32; 8]; - vst2q_lane_s32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_lane_s32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31597,7 +33386,7 @@ mod test { let a: [u8; 17] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9]; let e: [u8; 16] = [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u8; 16] = [0u8; 16]; - vst2_lane_u8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_lane_u8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31606,7 +33395,7 @@ mod test { let a: [u16; 9] = [0, 1, 2, 2, 3, 2, 3, 4, 5]; let e: [u16; 8] = [1, 2, 0, 0, 0, 0, 0, 0]; let mut r: [u16; 8] = [0u16; 8]; - vst2_lane_u16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_lane_u16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31615,7 +33404,7 @@ mod test { let a: [u32; 5] = [0, 1, 2, 2, 3]; let e: [u32; 4] = [1, 2, 0, 0]; let mut r: [u32; 4] = [0u32; 4]; - vst2_lane_u32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_lane_u32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31624,7 +33413,7 @@ mod test { let a: [u16; 17] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9]; let e: [u16; 16] = [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u16; 16] = [0u16; 16]; - vst2q_lane_u16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_lane_u16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31633,7 +33422,7 @@ mod test { let a: [u32; 9] = [0, 1, 2, 2, 3, 2, 3, 4, 5]; let e: [u32; 8] = [1, 2, 0, 0, 0, 0, 0, 0]; let mut r: [u32; 8] = [0u32; 8]; - vst2q_lane_u32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_lane_u32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31642,7 +33431,7 @@ mod test { let a: [u8; 17] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9]; let e: [u8; 16] = [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u8; 16] = [0u8; 16]; - vst2_lane_p8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_lane_p8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31651,7 +33440,7 @@ mod test { let a: [u16; 9] = [0, 1, 2, 2, 3, 2, 3, 4, 5]; let e: [u16; 8] = [1, 2, 0, 0, 0, 0, 0, 0]; let mut r: [u16; 8] = [0u16; 8]; - vst2_lane_p16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_lane_p16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31660,7 +33449,7 @@ mod test { let a: [u16; 17] = [0, 1, 2, 2, 3, 2, 3, 4, 5, 2, 3, 4, 5, 6, 7, 8, 9]; let e: [u16; 16] = [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u16; 16] = [0u16; 16]; - vst2q_lane_p16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_lane_p16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31669,7 +33458,7 @@ mod test { let a: [f32; 5] = [0., 1., 2., 2., 3.]; let e: [f32; 4] = [1., 2., 0., 0.]; let mut r: [f32; 4] = [0f32; 4]; - vst2_lane_f32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2_lane_f32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31678,7 +33467,7 @@ mod test { let a: [f32; 9] = [0., 1., 2., 2., 3., 2., 3., 4., 5.]; let e: [f32; 8] = [1., 2., 0., 0., 0., 0., 0., 0.]; let mut r: [f32; 8] = [0f32; 8]; - vst2q_lane_f32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst2q_lane_f32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31687,7 +33476,7 @@ mod test { let a: [i8; 25] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16]; let e: [i8; 24] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16]; let mut r: [i8; 24] = [0i8; 24]; - vst3_s8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_s8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31696,7 +33485,7 @@ mod test { let a: [i16; 13] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8]; let e: [i16; 12] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8]; let mut r: [i16; 12] = [0i16; 12]; - vst3_s16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_s16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31705,7 +33494,7 @@ mod test { let a: [i32; 7] = [0, 1, 2, 2, 4, 2, 4]; let e: [i32; 6] = [1, 2, 2, 2, 4, 4]; let mut r: [i32; 6] = [0i32; 6]; - vst3_s32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_s32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31714,7 +33503,7 @@ mod test { let a: [i8; 49] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16, 25, 26, 27, 28, 29, 30, 31, 32, 2, 4, 7, 8, 13, 14, 15, 16, 41, 42, 43, 44, 45, 46, 47, 48]; let e: [i8; 48] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16, 2, 25, 41, 4, 26, 42, 7, 27, 43, 8, 28, 44, 13, 29, 45, 14, 30, 46, 15, 31, 47, 16, 32, 48]; let mut r: [i8; 48] = [0i8; 48]; - vst3q_s8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_s8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31723,7 +33512,7 @@ mod test { let a: [i16; 25] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16]; let e: [i16; 24] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16]; let mut r: [i16; 24] = [0i16; 24]; - vst3q_s16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_s16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31732,7 +33521,7 @@ mod test { let a: [i32; 13] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8]; let e: [i32; 12] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8]; let mut r: [i32; 12] = [0i32; 12]; - vst3q_s32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_s32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31741,7 +33530,7 @@ mod test { let a: [i64; 4] = [0, 1, 2, 2]; let e: [i64; 3] = [1, 2, 2]; let mut r: [i64; 3] = [0i64; 3]; - vst3_s64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_s64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31750,7 +33539,7 @@ mod test { let a: [u8; 25] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16]; let e: [u8; 24] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16]; let mut r: [u8; 24] = [0u8; 24]; - vst3_u8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_u8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31759,7 +33548,7 @@ mod test { let a: [u16; 13] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8]; let e: [u16; 12] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8]; let mut r: [u16; 12] = [0u16; 12]; - vst3_u16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_u16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31768,7 +33557,7 @@ mod test { let a: [u32; 7] = [0, 1, 2, 2, 4, 2, 4]; let e: [u32; 6] = [1, 2, 2, 2, 4, 4]; let mut r: [u32; 6] = [0u32; 6]; - vst3_u32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_u32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31777,7 +33566,7 @@ mod test { let a: [u8; 49] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16, 25, 26, 27, 28, 29, 30, 31, 32, 2, 4, 7, 8, 13, 14, 15, 16, 41, 42, 43, 44, 45, 46, 47, 48]; let e: [u8; 48] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16, 2, 25, 41, 4, 26, 42, 7, 27, 43, 8, 28, 44, 13, 29, 45, 14, 30, 46, 15, 31, 47, 16, 32, 48]; let mut r: [u8; 48] = [0u8; 48]; - vst3q_u8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_u8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31786,7 +33575,7 @@ mod test { let a: [u16; 25] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16]; let e: [u16; 24] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16]; let mut r: [u16; 24] = [0u16; 24]; - vst3q_u16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_u16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31795,7 +33584,7 @@ mod test { let a: [u32; 13] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8]; let e: [u32; 12] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8]; let mut r: [u32; 12] = [0u32; 12]; - vst3q_u32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_u32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31804,7 +33593,7 @@ mod test { let a: [u8; 25] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16]; let e: [u8; 24] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16]; let mut r: [u8; 24] = [0u8; 24]; - vst3_p8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_p8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31813,7 +33602,7 @@ mod test { let a: [u16; 13] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8]; let e: [u16; 12] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8]; let mut r: [u16; 12] = [0u16; 12]; - vst3_p16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_p16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31822,7 +33611,7 @@ mod test { let a: [u8; 49] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16, 25, 26, 27, 28, 29, 30, 31, 32, 2, 4, 7, 8, 13, 14, 15, 16, 41, 42, 43, 44, 45, 46, 47, 48]; let e: [u8; 48] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16, 2, 25, 41, 4, 26, 42, 7, 27, 43, 8, 28, 44, 13, 29, 45, 14, 30, 46, 15, 31, 47, 16, 32, 48]; let mut r: [u8; 48] = [0u8; 48]; - vst3q_p8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_p8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31831,7 +33620,7 @@ mod test { let a: [u16; 25] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16]; let e: [u16; 24] = [1, 2, 2, 2, 4, 4, 2, 7, 7, 4, 8, 8, 2, 13, 13, 4, 14, 14, 7, 15, 15, 8, 16, 16]; let mut r: [u16; 24] = [0u16; 24]; - vst3q_p16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_p16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31840,7 +33629,7 @@ mod test { let a: [u64; 4] = [0, 1, 2, 2]; let e: [u64; 3] = [1, 2, 2]; let mut r: [u64; 3] = [0u64; 3]; - vst3_u64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_u64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31849,7 +33638,7 @@ mod test { let a: [u64; 4] = [0, 1, 2, 2]; let e: [u64; 3] = [1, 2, 2]; let mut r: [u64; 3] = [0u64; 3]; - vst3_p64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_p64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31858,7 +33647,7 @@ mod test { let a: [f32; 7] = [0., 1., 2., 2., 4., 2., 4.]; let e: [f32; 6] = [1., 2., 2., 2., 4., 4.]; let mut r: [f32; 6] = [0f32; 6]; - vst3_f32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_f32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31867,7 +33656,7 @@ mod test { let a: [f32; 13] = [0., 1., 2., 2., 4., 2., 4., 7., 8., 2., 4., 7., 8.]; let e: [f32; 12] = [1., 2., 2., 2., 4., 4., 2., 7., 7., 4., 8., 8.]; let mut r: [f32; 12] = [0f32; 12]; - vst3q_f32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_f32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31876,7 +33665,7 @@ mod test { let a: [i8; 25] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16]; let e: [i8; 24] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [i8; 24] = [0i8; 24]; - vst3_lane_s8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_lane_s8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31885,7 +33674,7 @@ mod test { let a: [i16; 13] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8]; let e: [i16; 12] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [i16; 12] = [0i16; 12]; - vst3_lane_s16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_lane_s16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31894,7 +33683,7 @@ mod test { let a: [i32; 7] = [0, 1, 2, 2, 4, 2, 4]; let e: [i32; 6] = [1, 2, 2, 0, 0, 0]; let mut r: [i32; 6] = [0i32; 6]; - vst3_lane_s32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_lane_s32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31903,7 +33692,7 @@ mod test { let a: [i16; 25] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16]; let e: [i16; 24] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [i16; 24] = [0i16; 24]; - vst3q_lane_s16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_lane_s16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31912,7 +33701,7 @@ mod test { let a: [i32; 13] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8]; let e: [i32; 12] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [i32; 12] = [0i32; 12]; - vst3q_lane_s32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_lane_s32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31921,7 +33710,7 @@ mod test { let a: [u8; 25] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16]; let e: [u8; 24] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u8; 24] = [0u8; 24]; - vst3_lane_u8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_lane_u8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31930,7 +33719,7 @@ mod test { let a: [u16; 13] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8]; let e: [u16; 12] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u16; 12] = [0u16; 12]; - vst3_lane_u16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_lane_u16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31939,7 +33728,7 @@ mod test { let a: [u32; 7] = [0, 1, 2, 2, 4, 2, 4]; let e: [u32; 6] = [1, 2, 2, 0, 0, 0]; let mut r: [u32; 6] = [0u32; 6]; - vst3_lane_u32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_lane_u32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31948,7 +33737,7 @@ mod test { let a: [u16; 25] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16]; let e: [u16; 24] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u16; 24] = [0u16; 24]; - vst3q_lane_u16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_lane_u16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31957,7 +33746,7 @@ mod test { let a: [u32; 13] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8]; let e: [u32; 12] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u32; 12] = [0u32; 12]; - vst3q_lane_u32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_lane_u32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31966,7 +33755,7 @@ mod test { let a: [u8; 25] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16]; let e: [u8; 24] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u8; 24] = [0u8; 24]; - vst3_lane_p8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_lane_p8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31975,7 +33764,7 @@ mod test { let a: [u16; 13] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8]; let e: [u16; 12] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u16; 12] = [0u16; 12]; - vst3_lane_p16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_lane_p16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31984,7 +33773,7 @@ mod test { let a: [u16; 25] = [0, 1, 2, 2, 4, 2, 4, 7, 8, 2, 4, 7, 8, 13, 14, 15, 16, 2, 4, 7, 8, 13, 14, 15, 16]; let e: [u16; 24] = [1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u16; 24] = [0u16; 24]; - vst3q_lane_p16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_lane_p16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -31993,7 +33782,7 @@ mod test { let a: [f32; 7] = [0., 1., 2., 2., 3., 2., 3.]; let e: [f32; 6] = [1., 2., 2., 0., 0., 0.]; let mut r: [f32; 6] = [0f32; 6]; - vst3_lane_f32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3_lane_f32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32002,7 +33791,7 @@ mod test { let a: [f32; 13] = [0., 1., 2., 2., 3., 2., 3., 4., 5., 2., 3., 4., 5.]; let e: [f32; 12] = [1., 2., 2., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; let mut r: [f32; 12] = [0f32; 12]; - vst3q_lane_f32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst3q_lane_f32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32011,7 +33800,7 @@ mod test { let a: [i8; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; let e: [i8; 32] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; let mut r: [i8; 32] = [0i8; 32]; - vst4_s8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_s8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32020,7 +33809,7 @@ mod test { let a: [i16; 17] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; let e: [i16; 16] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; let mut r: [i16; 16] = [0i16; 16]; - vst4_s16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_s16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32029,7 +33818,7 @@ mod test { let a: [i32; 9] = [0, 1, 2, 2, 6, 2, 6, 6, 8]; let e: [i32; 8] = [1, 2, 2, 6, 2, 6, 6, 8]; let mut r: [i32; 8] = [0i32; 8]; - vst4_s32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_s32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32038,7 +33827,7 @@ mod test { let a: [i8; 65] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64]; let e: [i8; 64] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64]; let mut r: [i8; 64] = [0i8; 64]; - vst4q_s8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_s8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32047,7 +33836,7 @@ mod test { let a: [i16; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; let e: [i16; 32] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; let mut r: [i16; 32] = [0i16; 32]; - vst4q_s16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_s16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32056,7 +33845,7 @@ mod test { let a: [i32; 17] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; let e: [i32; 16] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; let mut r: [i32; 16] = [0i32; 16]; - vst4q_s32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_s32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32065,7 +33854,7 @@ mod test { let a: [i64; 5] = [0, 1, 2, 2, 6]; let e: [i64; 4] = [1, 2, 2, 6]; let mut r: [i64; 4] = [0i64; 4]; - vst4_s64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_s64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32074,7 +33863,7 @@ mod test { let a: [u8; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; let e: [u8; 32] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; let mut r: [u8; 32] = [0u8; 32]; - vst4_u8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_u8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32083,7 +33872,7 @@ mod test { let a: [u16; 17] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; let e: [u16; 16] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; let mut r: [u16; 16] = [0u16; 16]; - vst4_u16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_u16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32092,7 +33881,7 @@ mod test { let a: [u32; 9] = [0, 1, 2, 2, 6, 2, 6, 6, 8]; let e: [u32; 8] = [1, 2, 2, 6, 2, 6, 6, 8]; let mut r: [u32; 8] = [0u32; 8]; - vst4_u32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_u32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32101,7 +33890,7 @@ mod test { let a: [u8; 65] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64]; let e: [u8; 64] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64]; let mut r: [u8; 64] = [0u8; 64]; - vst4q_u8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_u8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32110,7 +33899,7 @@ mod test { let a: [u16; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; let e: [u16; 32] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; let mut r: [u16; 32] = [0u16; 32]; - vst4q_u16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_u16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32119,7 +33908,7 @@ mod test { let a: [u32; 17] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; let e: [u32; 16] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; let mut r: [u32; 16] = [0u32; 16]; - vst4q_u32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_u32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32128,7 +33917,7 @@ mod test { let a: [u8; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; let e: [u8; 32] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; let mut r: [u8; 32] = [0u8; 32]; - vst4_p8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_p8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32137,7 +33926,7 @@ mod test { let a: [u16; 17] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; let e: [u16; 16] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; let mut r: [u16; 16] = [0u16; 16]; - vst4_p16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_p16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32146,7 +33935,7 @@ mod test { let a: [u8; 65] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64]; let e: [u8; 64] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 43, 44, 8, 16, 44, 48, 6, 8, 8, 16, 8, 16, 16, 32, 8, 16, 44, 48, 16, 32, 48, 64]; let mut r: [u8; 64] = [0u8; 64]; - vst4q_p8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_p8(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32155,7 +33944,7 @@ mod test { let a: [u16; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; let e: [u16; 32] = [1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; let mut r: [u16; 32] = [0u16; 32]; - vst4q_p16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_p16(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32164,7 +33953,7 @@ mod test { let a: [u64; 5] = [0, 1, 2, 2, 6]; let e: [u64; 4] = [1, 2, 2, 6]; let mut r: [u64; 4] = [0u64; 4]; - vst4_u64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_u64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32173,7 +33962,7 @@ mod test { let a: [u64; 5] = [0, 1, 2, 2, 6]; let e: [u64; 4] = [1, 2, 2, 6]; let mut r: [u64; 4] = [0u64; 4]; - vst4_p64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_p64(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32182,7 +33971,7 @@ mod test { let a: [f32; 9] = [0., 1., 2., 2., 6., 2., 6., 6., 8.]; let e: [f32; 8] = [1., 2., 2., 6., 2., 6., 6., 8.]; let mut r: [f32; 8] = [0f32; 8]; - vst4_f32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_f32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32191,7 +33980,7 @@ mod test { let a: [f32; 17] = [0., 1., 2., 2., 6., 2., 6., 6., 8., 2., 6., 6., 8., 6., 8., 8., 16.]; let e: [f32; 16] = [1., 2., 2., 6., 2., 6., 6., 8., 2., 6., 6., 8., 6., 8., 8., 16.]; let mut r: [f32; 16] = [0f32; 16]; - vst4q_f32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_f32(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32200,7 +33989,7 @@ mod test { let a: [i8; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; let e: [i8; 32] = [1, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [i8; 32] = [0i8; 32]; - vst4_lane_s8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_lane_s8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32209,7 +33998,7 @@ mod test { let a: [i16; 17] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; let e: [i16; 16] = [1, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [i16; 16] = [0i16; 16]; - vst4_lane_s16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_lane_s16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32218,7 +34007,7 @@ mod test { let a: [i32; 9] = [0, 1, 2, 2, 6, 2, 6, 6, 8]; let e: [i32; 8] = [1, 2, 2, 6, 0, 0, 0, 0]; let mut r: [i32; 8] = [0i32; 8]; - vst4_lane_s32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_lane_s32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32227,7 +34016,7 @@ mod test { let a: [i16; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; let e: [i16; 32] = [1, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [i16; 32] = [0i16; 32]; - vst4q_lane_s16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_lane_s16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32236,7 +34025,7 @@ mod test { let a: [i32; 17] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; let e: [i32; 16] = [1, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [i32; 16] = [0i32; 16]; - vst4q_lane_s32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_lane_s32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32245,7 +34034,7 @@ mod test { let a: [u8; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; let e: [u8; 32] = [1, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u8; 32] = [0u8; 32]; - vst4_lane_u8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_lane_u8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32254,7 +34043,7 @@ mod test { let a: [u16; 17] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; let e: [u16; 16] = [1, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u16; 16] = [0u16; 16]; - vst4_lane_u16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_lane_u16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32263,7 +34052,7 @@ mod test { let a: [u32; 9] = [0, 1, 2, 2, 6, 2, 6, 6, 8]; let e: [u32; 8] = [1, 2, 2, 6, 0, 0, 0, 0]; let mut r: [u32; 8] = [0u32; 8]; - vst4_lane_u32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_lane_u32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32272,7 +34061,7 @@ mod test { let a: [u16; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; let e: [u16; 32] = [1, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u16; 32] = [0u16; 32]; - vst4q_lane_u16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_lane_u16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32281,7 +34070,7 @@ mod test { let a: [u32; 17] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; let e: [u32; 16] = [1, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u32; 16] = [0u32; 16]; - vst4q_lane_u32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_lane_u32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32290,7 +34079,7 @@ mod test { let a: [u8; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; let e: [u8; 32] = [1, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u8; 32] = [0u8; 32]; - vst4_lane_p8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_lane_p8::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32299,7 +34088,7 @@ mod test { let a: [u16; 17] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16]; let e: [u16; 16] = [1, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u16; 16] = [0u16; 16]; - vst4_lane_p16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_lane_p16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32308,7 +34097,7 @@ mod test { let a: [u16; 33] = [0, 1, 2, 2, 6, 2, 6, 6, 8, 2, 6, 6, 8, 6, 8, 8, 16, 2, 6, 6, 8, 6, 8, 8, 16, 6, 8, 8, 16, 8, 16, 16, 32]; let e: [u16; 32] = [1, 2, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut r: [u16; 32] = [0u16; 32]; - vst4q_lane_p16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_lane_p16::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32317,7 +34106,7 @@ mod test { let a: [f32; 9] = [0., 1., 2., 2., 6., 2., 6., 6., 8.]; let e: [f32; 8] = [1., 2., 2., 6., 0., 0., 0., 0.]; let mut r: [f32; 8] = [0f32; 8]; - vst4_lane_f32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4_lane_f32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } @@ -32326,7 +34115,7 @@ mod test { let a: [f32; 17] = [0., 1., 2., 2., 6., 2., 6., 6., 8., 2., 6., 6., 8., 6., 8., 8., 16.]; let e: [f32; 16] = [1., 2., 2., 6., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]; let mut r: [f32; 16] = [0f32; 16]; - vst4q_lane_f32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + vst4q_lane_f32::<0>(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); } diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/mod.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/mod.rs index d348125a2a..7d170a00d1 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/mod.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/mod.rs @@ -6,8 +6,7 @@ mod generated; pub use self::generated::*; use crate::{ - convert::TryInto, core_arch::simd::*, core_arch::simd_llvm::*, hint::unreachable_unchecked, - mem::transmute, + core_arch::simd::*, core_arch::simd_llvm::*, hint::unreachable_unchecked, mem::transmute, }; #[cfg(test)] use stdarch_test::assert_instr; @@ -19,107 +18,179 @@ pub(crate) type p128 = u128; types! { /// ARM-specific 64-bit wide vector of eight packed `i8`. + #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub struct int8x8_t(pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8); /// ARM-specific 64-bit wide vector of eight packed `u8`. + #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub struct uint8x8_t(pub(crate) u8, pub(crate) u8, pub(crate) u8, pub(crate) u8, pub(crate) u8, pub(crate) u8, pub(crate) u8, pub(crate) u8); /// ARM-specific 64-bit wide polynomial vector of eight packed `p8`. + #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub struct poly8x8_t(pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8); /// ARM-specific 64-bit wide vector of four packed `i16`. + #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub struct int16x4_t(pub(crate) i16, pub(crate) i16, pub(crate) i16, pub(crate) i16); /// ARM-specific 64-bit wide vector of four packed `u16`. + #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub struct uint16x4_t(pub(crate) u16, pub(crate) u16, pub(crate) u16, pub(crate) u16); // FIXME: ARM-specific 64-bit wide vector of four packed `f16`. // pub struct float16x4_t(f16, f16, f16, f16); /// ARM-specific 64-bit wide vector of four packed `p16`. + #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub struct poly16x4_t(pub(crate) p16, pub(crate) p16, pub(crate) p16, pub(crate) p16); /// ARM-specific 64-bit wide vector of two packed `i32`. + #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub struct int32x2_t(pub(crate) i32, pub(crate) i32); /// ARM-specific 64-bit wide vector of two packed `u32`. + #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub struct uint32x2_t(pub(crate) u32, pub(crate) u32); /// ARM-specific 64-bit wide vector of two packed `f32`. + #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub struct float32x2_t(pub(crate) f32, pub(crate) f32); /// ARM-specific 64-bit wide vector of one packed `i64`. + #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub struct int64x1_t(pub(crate) i64); /// ARM-specific 64-bit wide vector of one packed `u64`. + #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub struct uint64x1_t(pub(crate) u64); /// ARM-specific 64-bit wide vector of one packed `p64`. + #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub struct poly64x1_t(pub(crate) p64); /// ARM-specific 128-bit wide vector of sixteen packed `i8`. + #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub struct int8x16_t( pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8 , pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8, pub(crate) i8 , pub(crate) i8, pub(crate) i8, ); /// ARM-specific 128-bit wide vector of sixteen packed `u8`. + #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub struct uint8x16_t( pub(crate) u8, pub(crate) u8 , pub(crate) u8, pub(crate) u8, pub(crate) u8, pub(crate) u8 , pub(crate) u8, pub(crate) u8, pub(crate) u8, pub(crate) u8 , pub(crate) u8, pub(crate) u8, pub(crate) u8, pub(crate) u8 , pub(crate) u8, pub(crate) u8, ); /// ARM-specific 128-bit wide vector of sixteen packed `p8`. + #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub struct poly8x16_t( pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, pub(crate) p8, ); /// ARM-specific 128-bit wide vector of eight packed `i16`. + #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub struct int16x8_t(pub(crate) i16, pub(crate) i16, pub(crate) i16, pub(crate) i16, pub(crate) i16, pub(crate) i16, pub(crate) i16, pub(crate) i16); /// ARM-specific 128-bit wide vector of eight packed `u16`. + #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub struct uint16x8_t(pub(crate) u16, pub(crate) u16, pub(crate) u16, pub(crate) u16, pub(crate) u16, pub(crate) u16, pub(crate) u16, pub(crate) u16); // FIXME: ARM-specific 128-bit wide vector of eight packed `f16`. // pub struct float16x8_t(f16, f16, f16, f16, f16, f16, f16); /// ARM-specific 128-bit wide vector of eight packed `p16`. + #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub struct poly16x8_t(pub(crate) p16, pub(crate) p16, pub(crate) p16, pub(crate) p16, pub(crate) p16, pub(crate) p16, pub(crate) p16, pub(crate) p16); /// ARM-specific 128-bit wide vector of four packed `i32`. + #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub struct int32x4_t(pub(crate) i32, pub(crate) i32, pub(crate) i32, pub(crate) i32); /// ARM-specific 128-bit wide vector of four packed `u32`. + #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub struct uint32x4_t(pub(crate) u32, pub(crate) u32, pub(crate) u32, pub(crate) u32); /// ARM-specific 128-bit wide vector of four packed `f32`. + #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub struct float32x4_t(pub(crate) f32, pub(crate) f32, pub(crate) f32, pub(crate) f32); /// ARM-specific 128-bit wide vector of two packed `i64`. + #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub struct int64x2_t(pub(crate) i64, pub(crate) i64); /// ARM-specific 128-bit wide vector of two packed `u64`. + #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub struct uint64x2_t(pub(crate) u64, pub(crate) u64); /// ARM-specific 128-bit wide vector of two packed `p64`. + #[cfg_attr(target_arch = "aarch64", stable(feature = "neon_intrinsics", since = "1.59.0"))] pub struct poly64x2_t(pub(crate) p64, pub(crate) p64); } /// ARM-specific type containing two `int8x8_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct int8x8x2_t(pub int8x8_t, pub int8x8_t); /// ARM-specific type containing three `int8x8_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct int8x8x3_t(pub int8x8_t, pub int8x8_t, pub int8x8_t); /// ARM-specific type containing four `int8x8_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct int8x8x4_t(pub int8x8_t, pub int8x8_t, pub int8x8_t, pub int8x8_t); /// ARM-specific type containing two `int8x16_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct int8x16x2_t(pub int8x16_t, pub int8x16_t); /// ARM-specific type containing three `int8x16_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct int8x16x3_t(pub int8x16_t, pub int8x16_t, pub int8x16_t); /// ARM-specific type containing four `int8x16_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct int8x16x4_t(pub int8x16_t, pub int8x16_t, pub int8x16_t, pub int8x16_t); /// ARM-specific type containing two `uint8x8_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct uint8x8x2_t(pub uint8x8_t, pub uint8x8_t); /// ARM-specific type containing three `uint8x8_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct uint8x8x3_t(pub uint8x8_t, pub uint8x8_t, pub uint8x8_t); /// ARM-specific type containing four `uint8x8_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct uint8x8x4_t(pub uint8x8_t, pub uint8x8_t, pub uint8x8_t, pub uint8x8_t); /// ARM-specific type containing two `uint8x16_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct uint8x16x2_t(pub uint8x16_t, pub uint8x16_t); /// ARM-specific type containing three `uint8x16_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct uint8x16x3_t(pub uint8x16_t, pub uint8x16_t, pub uint8x16_t); /// ARM-specific type containing four `uint8x16_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct uint8x16x4_t( pub uint8x16_t, pub uint8x16_t, @@ -129,22 +200,46 @@ pub struct uint8x16x4_t( /// ARM-specific type containing two `poly8x8_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct poly8x8x2_t(pub poly8x8_t, pub poly8x8_t); /// ARM-specific type containing three `poly8x8_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct poly8x8x3_t(pub poly8x8_t, pub poly8x8_t, pub poly8x8_t); /// ARM-specific type containing four `poly8x8_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct poly8x8x4_t(pub poly8x8_t, pub poly8x8_t, pub poly8x8_t, pub poly8x8_t); /// ARM-specific type containing two `poly8x16_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct poly8x16x2_t(pub poly8x16_t, pub poly8x16_t); /// ARM-specific type containing three `poly8x16_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct poly8x16x3_t(pub poly8x16_t, pub poly8x16_t, pub poly8x16_t); /// ARM-specific type containing four `poly8x16_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct poly8x16x4_t( pub poly8x16_t, pub poly8x16_t, @@ -154,32 +249,68 @@ pub struct poly8x16x4_t( /// ARM-specific type containing two `int16x4_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct int16x4x2_t(pub int16x4_t, pub int16x4_t); /// ARM-specific type containing three `int16x4_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct int16x4x3_t(pub int16x4_t, pub int16x4_t, pub int16x4_t); /// ARM-specific type containing four `int16x4_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct int16x4x4_t(pub int16x4_t, pub int16x4_t, pub int16x4_t, pub int16x4_t); /// ARM-specific type containing two `int16x8_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct int16x8x2_t(pub int16x8_t, pub int16x8_t); /// ARM-specific type containing three `int16x8_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct int16x8x3_t(pub int16x8_t, pub int16x8_t, pub int16x8_t); /// ARM-specific type containing four `int16x8_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct int16x8x4_t(pub int16x8_t, pub int16x8_t, pub int16x8_t, pub int16x8_t); /// ARM-specific type containing two `uint16x4_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct uint16x4x2_t(pub uint16x4_t, pub uint16x4_t); /// ARM-specific type containing three `uint16x4_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct uint16x4x3_t(pub uint16x4_t, pub uint16x4_t, pub uint16x4_t); /// ARM-specific type containing four `uint16x4_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct uint16x4x4_t( pub uint16x4_t, pub uint16x4_t, @@ -189,12 +320,24 @@ pub struct uint16x4x4_t( /// ARM-specific type containing two `uint16x8_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct uint16x8x2_t(pub uint16x8_t, pub uint16x8_t); /// ARM-specific type containing three `uint16x8_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct uint16x8x3_t(pub uint16x8_t, pub uint16x8_t, pub uint16x8_t); /// ARM-specific type containing four `uint16x8_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct uint16x8x4_t( pub uint16x8_t, pub uint16x8_t, @@ -204,12 +347,24 @@ pub struct uint16x8x4_t( /// ARM-specific type containing two `poly16x4_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct poly16x4x2_t(pub poly16x4_t, pub poly16x4_t); /// ARM-specific type containing three `poly16x4_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct poly16x4x3_t(pub poly16x4_t, pub poly16x4_t, pub poly16x4_t); /// ARM-specific type containing four `poly16x4_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct poly16x4x4_t( pub poly16x4_t, pub poly16x4_t, @@ -219,12 +374,24 @@ pub struct poly16x4x4_t( /// ARM-specific type containing two `poly16x8_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct poly16x8x2_t(pub poly16x8_t, pub poly16x8_t); /// ARM-specific type containing three `poly16x8_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct poly16x8x3_t(pub poly16x8_t, pub poly16x8_t, pub poly16x8_t); /// ARM-specific type containing four `poly16x8_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct poly16x8x4_t( pub poly16x8_t, pub poly16x8_t, @@ -234,32 +401,68 @@ pub struct poly16x8x4_t( /// ARM-specific type containing two `int32x2_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct int32x2x2_t(pub int32x2_t, pub int32x2_t); /// ARM-specific type containing three `int32x2_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct int32x2x3_t(pub int32x2_t, pub int32x2_t, pub int32x2_t); /// ARM-specific type containing four `int32x2_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct int32x2x4_t(pub int32x2_t, pub int32x2_t, pub int32x2_t, pub int32x2_t); /// ARM-specific type containing two `int32x4_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct int32x4x2_t(pub int32x4_t, pub int32x4_t); /// ARM-specific type containing three `int32x4_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct int32x4x3_t(pub int32x4_t, pub int32x4_t, pub int32x4_t); /// ARM-specific type containing four `int32x4_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct int32x4x4_t(pub int32x4_t, pub int32x4_t, pub int32x4_t, pub int32x4_t); /// ARM-specific type containing two `uint32x2_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct uint32x2x2_t(pub uint32x2_t, pub uint32x2_t); /// ARM-specific type containing three `uint32x2_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct uint32x2x3_t(pub uint32x2_t, pub uint32x2_t, pub uint32x2_t); /// ARM-specific type containing four `uint32x2_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct uint32x2x4_t( pub uint32x2_t, pub uint32x2_t, @@ -269,12 +472,24 @@ pub struct uint32x2x4_t( /// ARM-specific type containing two `uint32x4_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct uint32x4x2_t(pub uint32x4_t, pub uint32x4_t); /// ARM-specific type containing three `uint32x4_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct uint32x4x3_t(pub uint32x4_t, pub uint32x4_t, pub uint32x4_t); /// ARM-specific type containing four `uint32x4_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct uint32x4x4_t( pub uint32x4_t, pub uint32x4_t, @@ -284,12 +499,24 @@ pub struct uint32x4x4_t( /// ARM-specific type containing two `float32x2_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct float32x2x2_t(pub float32x2_t, pub float32x2_t); /// ARM-specific type containing three `float32x2_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct float32x2x3_t(pub float32x2_t, pub float32x2_t, pub float32x2_t); /// ARM-specific type containing four `float32x2_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct float32x2x4_t( pub float32x2_t, pub float32x2_t, @@ -299,12 +526,24 @@ pub struct float32x2x4_t( /// ARM-specific type containing two `float32x4_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct float32x4x2_t(pub float32x4_t, pub float32x4_t); /// ARM-specific type containing three `float32x4_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct float32x4x3_t(pub float32x4_t, pub float32x4_t, pub float32x4_t); /// ARM-specific type containing four `float32x4_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct float32x4x4_t( pub float32x4_t, pub float32x4_t, @@ -314,32 +553,68 @@ pub struct float32x4x4_t( /// ARM-specific type containing four `int64x1_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct int64x1x2_t(pub int64x1_t, pub int64x1_t); /// ARM-specific type containing four `int64x1_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct int64x1x3_t(pub int64x1_t, pub int64x1_t, pub int64x1_t); /// ARM-specific type containing four `int64x1_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct int64x1x4_t(pub int64x1_t, pub int64x1_t, pub int64x1_t, pub int64x1_t); /// ARM-specific type containing four `int64x2_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct int64x2x2_t(pub int64x2_t, pub int64x2_t); /// ARM-specific type containing four `int64x2_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct int64x2x3_t(pub int64x2_t, pub int64x2_t, pub int64x2_t); /// ARM-specific type containing four `int64x2_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct int64x2x4_t(pub int64x2_t, pub int64x2_t, pub int64x2_t, pub int64x2_t); /// ARM-specific type containing four `uint64x1_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct uint64x1x2_t(pub uint64x1_t, pub uint64x1_t); /// ARM-specific type containing four `uint64x1_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct uint64x1x3_t(pub uint64x1_t, pub uint64x1_t, pub uint64x1_t); /// ARM-specific type containing four `uint64x1_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct uint64x1x4_t( pub uint64x1_t, pub uint64x1_t, @@ -349,12 +624,24 @@ pub struct uint64x1x4_t( /// ARM-specific type containing four `uint64x2_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct uint64x2x2_t(pub uint64x2_t, pub uint64x2_t); /// ARM-specific type containing four `uint64x2_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct uint64x2x3_t(pub uint64x2_t, pub uint64x2_t, pub uint64x2_t); /// ARM-specific type containing four `uint64x2_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct uint64x2x4_t( pub uint64x2_t, pub uint64x2_t, @@ -364,12 +651,24 @@ pub struct uint64x2x4_t( /// ARM-specific type containing four `poly64x1_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct poly64x1x2_t(pub poly64x1_t, pub poly64x1_t); /// ARM-specific type containing four `poly64x1_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct poly64x1x3_t(pub poly64x1_t, pub poly64x1_t, pub poly64x1_t); /// ARM-specific type containing four `poly64x1_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct poly64x1x4_t( pub poly64x1_t, pub poly64x1_t, @@ -379,12 +678,24 @@ pub struct poly64x1x4_t( /// ARM-specific type containing four `poly64x2_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct poly64x2x2_t(pub poly64x2_t, pub poly64x2_t); /// ARM-specific type containing four `poly64x2_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct poly64x2x3_t(pub poly64x2_t, pub poly64x2_t, pub poly64x2_t); /// ARM-specific type containing four `poly64x2_t` vectors. #[derive(Copy, Clone, Debug)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub struct poly64x2x4_t( pub poly64x2_t, pub poly64x2_t, @@ -587,6 +898,10 @@ extern "unadjusted" { #[rustc_legacy_const_generics(2)] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8", LANE = 7))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1, LANE = 7))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1_lane_s8(ptr: *const i8, src: int8x8_t) -> int8x8_t { static_assert_imm3!(LANE); simd_insert(src, LANE as u32, *ptr) @@ -599,6 +914,10 @@ pub unsafe fn vld1_lane_s8(ptr: *const i8, src: int8x8_t) -> in #[rustc_legacy_const_generics(2)] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8", LANE = 15))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1, LANE = 15))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1q_lane_s8(ptr: *const i8, src: int8x16_t) -> int8x16_t { static_assert_imm4!(LANE); simd_insert(src, LANE as u32, *ptr) @@ -611,6 +930,10 @@ pub unsafe fn vld1q_lane_s8(ptr: *const i8, src: int8x16_t) -> #[rustc_legacy_const_generics(2)] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.16", LANE = 3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1, LANE = 3))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1_lane_s16(ptr: *const i16, src: int16x4_t) -> int16x4_t { static_assert_imm2!(LANE); simd_insert(src, LANE as u32, *ptr) @@ -623,6 +946,10 @@ pub unsafe fn vld1_lane_s16(ptr: *const i16, src: int16x4_t) -> #[rustc_legacy_const_generics(2)] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.16", LANE = 7))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1, LANE = 7))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1q_lane_s16(ptr: *const i16, src: int16x8_t) -> int16x8_t { static_assert_imm3!(LANE); simd_insert(src, LANE as u32, *ptr) @@ -635,6 +962,10 @@ pub unsafe fn vld1q_lane_s16(ptr: *const i16, src: int16x8_t) - #[rustc_legacy_const_generics(2)] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1, LANE = 1))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1_lane_s32(ptr: *const i32, src: int32x2_t) -> int32x2_t { static_assert_imm1!(LANE); simd_insert(src, LANE as u32, *ptr) @@ -647,6 +978,10 @@ pub unsafe fn vld1_lane_s32(ptr: *const i32, src: int32x2_t) -> #[rustc_legacy_const_generics(2)] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.32", LANE = 3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1, LANE = 3))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1q_lane_s32(ptr: *const i32, src: int32x4_t) -> int32x4_t { static_assert_imm2!(LANE); simd_insert(src, LANE as u32, *ptr) @@ -659,6 +994,10 @@ pub unsafe fn vld1q_lane_s32(ptr: *const i32, src: int32x4_t) - #[rustc_legacy_const_generics(2)] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vldr", LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ldr, LANE = 0))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1_lane_s64(ptr: *const i64, src: int64x1_t) -> int64x1_t { static_assert!(LANE : i32 where LANE == 0); simd_insert(src, LANE as u32, *ptr) @@ -671,6 +1010,10 @@ pub unsafe fn vld1_lane_s64(ptr: *const i64, src: int64x1_t) -> #[rustc_legacy_const_generics(2)] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vldr", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1, LANE = 1))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1q_lane_s64(ptr: *const i64, src: int64x2_t) -> int64x2_t { static_assert_imm1!(LANE); simd_insert(src, LANE as u32, *ptr) @@ -683,6 +1026,10 @@ pub unsafe fn vld1q_lane_s64(ptr: *const i64, src: int64x2_t) - #[rustc_legacy_const_generics(2)] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8", LANE = 7))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1, LANE = 7))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1_lane_u8(ptr: *const u8, src: uint8x8_t) -> uint8x8_t { static_assert_imm3!(LANE); simd_insert(src, LANE as u32, *ptr) @@ -695,6 +1042,10 @@ pub unsafe fn vld1_lane_u8(ptr: *const u8, src: uint8x8_t) -> u #[rustc_legacy_const_generics(2)] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8", LANE = 15))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1, LANE = 15))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1q_lane_u8(ptr: *const u8, src: uint8x16_t) -> uint8x16_t { static_assert_imm4!(LANE); simd_insert(src, LANE as u32, *ptr) @@ -707,6 +1058,10 @@ pub unsafe fn vld1q_lane_u8(ptr: *const u8, src: uint8x16_t) -> #[rustc_legacy_const_generics(2)] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.16", LANE = 3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1, LANE = 3))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1_lane_u16(ptr: *const u16, src: uint16x4_t) -> uint16x4_t { static_assert_imm2!(LANE); simd_insert(src, LANE as u32, *ptr) @@ -719,6 +1074,10 @@ pub unsafe fn vld1_lane_u16(ptr: *const u16, src: uint16x4_t) - #[rustc_legacy_const_generics(2)] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.16", LANE = 7))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1, LANE = 7))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1q_lane_u16(ptr: *const u16, src: uint16x8_t) -> uint16x8_t { static_assert_imm3!(LANE); simd_insert(src, LANE as u32, *ptr) @@ -731,6 +1090,10 @@ pub unsafe fn vld1q_lane_u16(ptr: *const u16, src: uint16x8_t) #[rustc_legacy_const_generics(2)] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1, LANE = 1))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1_lane_u32(ptr: *const u32, src: uint32x2_t) -> uint32x2_t { static_assert_imm1!(LANE); simd_insert(src, LANE as u32, *ptr) @@ -743,6 +1106,10 @@ pub unsafe fn vld1_lane_u32(ptr: *const u32, src: uint32x2_t) - #[rustc_legacy_const_generics(2)] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.32", LANE = 3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1, LANE = 3))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1q_lane_u32(ptr: *const u32, src: uint32x4_t) -> uint32x4_t { static_assert_imm2!(LANE); simd_insert(src, LANE as u32, *ptr) @@ -755,6 +1122,10 @@ pub unsafe fn vld1q_lane_u32(ptr: *const u32, src: uint32x4_t) #[rustc_legacy_const_generics(2)] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vldr", LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ldr, LANE = 0))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1_lane_u64(ptr: *const u64, src: uint64x1_t) -> uint64x1_t { static_assert!(LANE : i32 where LANE == 0); simd_insert(src, LANE as u32, *ptr) @@ -767,6 +1138,10 @@ pub unsafe fn vld1_lane_u64(ptr: *const u64, src: uint64x1_t) - #[rustc_legacy_const_generics(2)] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vldr", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1, LANE = 1))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1q_lane_u64(ptr: *const u64, src: uint64x2_t) -> uint64x2_t { static_assert_imm1!(LANE); simd_insert(src, LANE as u32, *ptr) @@ -779,6 +1154,10 @@ pub unsafe fn vld1q_lane_u64(ptr: *const u64, src: uint64x2_t) #[rustc_legacy_const_generics(2)] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8", LANE = 7))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1, LANE = 7))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1_lane_p8(ptr: *const p8, src: poly8x8_t) -> poly8x8_t { static_assert_imm3!(LANE); simd_insert(src, LANE as u32, *ptr) @@ -791,6 +1170,10 @@ pub unsafe fn vld1_lane_p8(ptr: *const p8, src: poly8x8_t) -> p #[rustc_legacy_const_generics(2)] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8", LANE = 15))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1, LANE = 15))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1q_lane_p8(ptr: *const p8, src: poly8x16_t) -> poly8x16_t { static_assert_imm4!(LANE); simd_insert(src, LANE as u32, *ptr) @@ -803,6 +1186,10 @@ pub unsafe fn vld1q_lane_p8(ptr: *const p8, src: poly8x16_t) -> #[rustc_legacy_const_generics(2)] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.16", LANE = 3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1, LANE = 3))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1_lane_p16(ptr: *const p16, src: poly16x4_t) -> poly16x4_t { static_assert_imm2!(LANE); simd_insert(src, LANE as u32, *ptr) @@ -815,6 +1202,10 @@ pub unsafe fn vld1_lane_p16(ptr: *const p16, src: poly16x4_t) - #[rustc_legacy_const_generics(2)] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.16", LANE = 7))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1, LANE = 7))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1q_lane_p16(ptr: *const p16, src: poly16x8_t) -> poly16x8_t { static_assert_imm3!(LANE); simd_insert(src, LANE as u32, *ptr) @@ -827,6 +1218,10 @@ pub unsafe fn vld1q_lane_p16(ptr: *const p16, src: poly16x8_t) #[rustc_legacy_const_generics(2)] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vldr", LANE = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ldr, LANE = 0))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1_lane_p64(ptr: *const p64, src: poly64x1_t) -> poly64x1_t { static_assert!(LANE : i32 where LANE == 0); simd_insert(src, LANE as u32, *ptr) @@ -839,6 +1234,10 @@ pub unsafe fn vld1_lane_p64(ptr: *const p64, src: poly64x1_t) - #[rustc_legacy_const_generics(2)] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vldr", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1, LANE = 1))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1q_lane_p64(ptr: *const p64, src: poly64x2_t) -> poly64x2_t { static_assert_imm1!(LANE); simd_insert(src, LANE as u32, *ptr) @@ -851,6 +1250,10 @@ pub unsafe fn vld1q_lane_p64(ptr: *const p64, src: poly64x2_t) #[rustc_legacy_const_generics(2)] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.32", LANE = 1))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1, LANE = 1))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1_lane_f32(ptr: *const f32, src: float32x2_t) -> float32x2_t { static_assert_imm1!(LANE); simd_insert(src, LANE as u32, *ptr) @@ -863,6 +1266,10 @@ pub unsafe fn vld1_lane_f32(ptr: *const f32, src: float32x2_t) #[rustc_legacy_const_generics(2)] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.32", LANE = 3))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1, LANE = 3))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1q_lane_f32(ptr: *const f32, src: float32x4_t) -> float32x4_t { static_assert_imm2!(LANE); simd_insert(src, LANE as u32, *ptr) @@ -874,6 +1281,10 @@ pub unsafe fn vld1q_lane_f32(ptr: *const f32, src: float32x4_t) #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1r))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1_dup_s8(ptr: *const i8) -> int8x8_t { let x = vld1_lane_s8::<0>(ptr, transmute(i8x8::splat(0))); simd_shuffle8!(x, x, [0, 0, 0, 0, 0, 0, 0, 0]) @@ -885,6 +1296,10 @@ pub unsafe fn vld1_dup_s8(ptr: *const i8) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1r))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1q_dup_s8(ptr: *const i8) -> int8x16_t { let x = vld1q_lane_s8::<0>(ptr, transmute(i8x16::splat(0))); simd_shuffle16!(x, x, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) @@ -896,6 +1311,10 @@ pub unsafe fn vld1q_dup_s8(ptr: *const i8) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1r))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1_dup_s16(ptr: *const i16) -> int16x4_t { let x = vld1_lane_s16::<0>(ptr, transmute(i16x4::splat(0))); simd_shuffle4!(x, x, [0, 0, 0, 0]) @@ -907,6 +1326,10 @@ pub unsafe fn vld1_dup_s16(ptr: *const i16) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1r))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1q_dup_s16(ptr: *const i16) -> int16x8_t { let x = vld1q_lane_s16::<0>(ptr, transmute(i16x8::splat(0))); simd_shuffle8!(x, x, [0, 0, 0, 0, 0, 0, 0, 0]) @@ -918,6 +1341,10 @@ pub unsafe fn vld1q_dup_s16(ptr: *const i16) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1r))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1_dup_s32(ptr: *const i32) -> int32x2_t { let x = vld1_lane_s32::<0>(ptr, transmute(i32x2::splat(0))); simd_shuffle2!(x, x, [0, 0]) @@ -929,6 +1356,10 @@ pub unsafe fn vld1_dup_s32(ptr: *const i32) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1r))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1q_dup_s32(ptr: *const i32) -> int32x4_t { let x = vld1q_lane_s32::<0>(ptr, transmute(i32x4::splat(0))); simd_shuffle4!(x, x, [0, 0, 0, 0]) @@ -940,6 +1371,10 @@ pub unsafe fn vld1q_dup_s32(ptr: *const i32) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vldr"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ldr))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1_dup_s64(ptr: *const i64) -> int64x1_t { #[cfg(target_arch = "aarch64")] { @@ -957,6 +1392,10 @@ pub unsafe fn vld1_dup_s64(ptr: *const i64) -> int64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vldr"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1r))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1q_dup_s64(ptr: *const i64) -> int64x2_t { let x = vld1q_lane_s64::<0>(ptr, transmute(i64x2::splat(0))); simd_shuffle2!(x, x, [0, 0]) @@ -968,6 +1407,10 @@ pub unsafe fn vld1q_dup_s64(ptr: *const i64) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1r))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1_dup_u8(ptr: *const u8) -> uint8x8_t { let x = vld1_lane_u8::<0>(ptr, transmute(u8x8::splat(0))); simd_shuffle8!(x, x, [0, 0, 0, 0, 0, 0, 0, 0]) @@ -979,6 +1422,10 @@ pub unsafe fn vld1_dup_u8(ptr: *const u8) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1r))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1q_dup_u8(ptr: *const u8) -> uint8x16_t { let x = vld1q_lane_u8::<0>(ptr, transmute(u8x16::splat(0))); simd_shuffle16!(x, x, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) @@ -990,6 +1437,10 @@ pub unsafe fn vld1q_dup_u8(ptr: *const u8) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1r))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1_dup_u16(ptr: *const u16) -> uint16x4_t { let x = vld1_lane_u16::<0>(ptr, transmute(u16x4::splat(0))); simd_shuffle4!(x, x, [0, 0, 0, 0]) @@ -1001,6 +1452,10 @@ pub unsafe fn vld1_dup_u16(ptr: *const u16) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1r))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1q_dup_u16(ptr: *const u16) -> uint16x8_t { let x = vld1q_lane_u16::<0>(ptr, transmute(u16x8::splat(0))); simd_shuffle8!(x, x, [0, 0, 0, 0, 0, 0, 0, 0]) @@ -1012,6 +1467,10 @@ pub unsafe fn vld1q_dup_u16(ptr: *const u16) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1r))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1_dup_u32(ptr: *const u32) -> uint32x2_t { let x = vld1_lane_u32::<0>(ptr, transmute(u32x2::splat(0))); simd_shuffle2!(x, x, [0, 0]) @@ -1023,6 +1482,10 @@ pub unsafe fn vld1_dup_u32(ptr: *const u32) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1r))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1q_dup_u32(ptr: *const u32) -> uint32x4_t { let x = vld1q_lane_u32::<0>(ptr, transmute(u32x4::splat(0))); simd_shuffle4!(x, x, [0, 0, 0, 0]) @@ -1034,6 +1497,10 @@ pub unsafe fn vld1q_dup_u32(ptr: *const u32) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vldr"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ldr))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1_dup_u64(ptr: *const u64) -> uint64x1_t { #[cfg(target_arch = "aarch64")] { @@ -1051,6 +1518,10 @@ pub unsafe fn vld1_dup_u64(ptr: *const u64) -> uint64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vldr"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1r))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1q_dup_u64(ptr: *const u64) -> uint64x2_t { let x = vld1q_lane_u64::<0>(ptr, transmute(u64x2::splat(0))); simd_shuffle2!(x, x, [0, 0]) @@ -1062,6 +1533,10 @@ pub unsafe fn vld1q_dup_u64(ptr: *const u64) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1r))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1_dup_p8(ptr: *const p8) -> poly8x8_t { let x = vld1_lane_p8::<0>(ptr, transmute(u8x8::splat(0))); simd_shuffle8!(x, x, [0, 0, 0, 0, 0, 0, 0, 0]) @@ -1073,6 +1548,10 @@ pub unsafe fn vld1_dup_p8(ptr: *const p8) -> poly8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1r))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1q_dup_p8(ptr: *const p8) -> poly8x16_t { let x = vld1q_lane_p8::<0>(ptr, transmute(u8x16::splat(0))); simd_shuffle16!(x, x, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) @@ -1084,6 +1563,10 @@ pub unsafe fn vld1q_dup_p8(ptr: *const p8) -> poly8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1r))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1_dup_p16(ptr: *const p16) -> poly16x4_t { let x = vld1_lane_p16::<0>(ptr, transmute(u16x4::splat(0))); simd_shuffle4!(x, x, [0, 0, 0, 0]) @@ -1095,6 +1578,10 @@ pub unsafe fn vld1_dup_p16(ptr: *const p16) -> poly16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1r))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1q_dup_p16(ptr: *const p16) -> poly16x8_t { let x = vld1q_lane_p16::<0>(ptr, transmute(u16x8::splat(0))); simd_shuffle8!(x, x, [0, 0, 0, 0, 0, 0, 0, 0]) @@ -1106,6 +1593,10 @@ pub unsafe fn vld1q_dup_p16(ptr: *const p16) -> poly16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1r))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1_dup_f32(ptr: *const f32) -> float32x2_t { let x = vld1_lane_f32::<0>(ptr, transmute(f32x2::splat(0.))); simd_shuffle2!(x, x, [0, 0]) @@ -1117,6 +1608,10 @@ pub unsafe fn vld1_dup_f32(ptr: *const f32) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vldr"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ldr))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1_dup_p64(ptr: *const p64) -> poly64x1_t { #[cfg(target_arch = "aarch64")] { @@ -1134,6 +1629,10 @@ pub unsafe fn vld1_dup_p64(ptr: *const p64) -> poly64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vldr"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1r))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1q_dup_p64(ptr: *const p64) -> poly64x2_t { let x = vld1q_lane_p64::<0>(ptr, transmute(u64x2::splat(0))); simd_shuffle2!(x, x, [0, 0]) @@ -1145,6 +1644,10 @@ pub unsafe fn vld1q_dup_p64(ptr: *const p64) -> poly64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ld1r))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vld1q_dup_f32(ptr: *const f32) -> float32x4_t { let x = vld1q_lane_f32::<0>(ptr, transmute(f32x4::splat(0.))); simd_shuffle4!(x, x, [0, 0, 0, 0]) @@ -1156,6 +1659,10 @@ pub unsafe fn vld1q_dup_f32(ptr: *const f32) -> float32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vaba.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr("saba"))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaba_s8(a: int8x8_t, b: int8x8_t, c: int8x8_t) -> int8x8_t { simd_add(a, vabd_s8(b, c)) } @@ -1164,6 +1671,10 @@ pub unsafe fn vaba_s8(a: int8x8_t, b: int8x8_t, c: int8x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vaba.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr("saba"))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaba_s16(a: int16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t { simd_add(a, vabd_s16(b, c)) } @@ -1172,6 +1683,10 @@ pub unsafe fn vaba_s16(a: int16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vaba.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr("saba"))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaba_s32(a: int32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t { simd_add(a, vabd_s32(b, c)) } @@ -1180,6 +1695,10 @@ pub unsafe fn vaba_s32(a: int32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vaba.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr("uaba"))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaba_u8(a: uint8x8_t, b: uint8x8_t, c: uint8x8_t) -> uint8x8_t { simd_add(a, vabd_u8(b, c)) } @@ -1188,6 +1707,10 @@ pub unsafe fn vaba_u8(a: uint8x8_t, b: uint8x8_t, c: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vaba.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr("uaba"))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaba_u16(a: uint16x4_t, b: uint16x4_t, c: uint16x4_t) -> uint16x4_t { simd_add(a, vabd_u16(b, c)) } @@ -1196,6 +1719,10 @@ pub unsafe fn vaba_u16(a: uint16x4_t, b: uint16x4_t, c: uint16x4_t) -> uint16x4_ #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vaba.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr("uaba"))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaba_u32(a: uint32x2_t, b: uint32x2_t, c: uint32x2_t) -> uint32x2_t { simd_add(a, vabd_u32(b, c)) } @@ -1205,6 +1732,10 @@ pub unsafe fn vaba_u32(a: uint32x2_t, b: uint32x2_t, c: uint32x2_t) -> uint32x2_ #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vaba.s8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr("saba"))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vabaq_s8(a: int8x16_t, b: int8x16_t, c: int8x16_t) -> int8x16_t { simd_add(a, vabdq_s8(b, c)) } @@ -1213,6 +1744,10 @@ pub unsafe fn vabaq_s8(a: int8x16_t, b: int8x16_t, c: int8x16_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vaba.s16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr("saba"))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vabaq_s16(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t { simd_add(a, vabdq_s16(b, c)) } @@ -1221,6 +1756,10 @@ pub unsafe fn vabaq_s16(a: int16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vaba.s32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr("saba"))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vabaq_s32(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t { simd_add(a, vabdq_s32(b, c)) } @@ -1229,6 +1768,10 @@ pub unsafe fn vabaq_s32(a: int32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vaba.u8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr("uaba"))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vabaq_u8(a: uint8x16_t, b: uint8x16_t, c: uint8x16_t) -> uint8x16_t { simd_add(a, vabdq_u8(b, c)) } @@ -1237,6 +1780,10 @@ pub unsafe fn vabaq_u8(a: uint8x16_t, b: uint8x16_t, c: uint8x16_t) -> uint8x16_ #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vaba.u16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr("uaba"))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vabaq_u16(a: uint16x8_t, b: uint16x8_t, c: uint16x8_t) -> uint16x8_t { simd_add(a, vabdq_u16(b, c)) } @@ -1245,6 +1792,10 @@ pub unsafe fn vabaq_u16(a: uint16x8_t, b: uint16x8_t, c: uint16x8_t) -> uint16x8 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vaba.u32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr("uaba"))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vabaq_u32(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4_t { simd_add(a, vabdq_u32(b, c)) } @@ -1255,6 +1806,10 @@ pub unsafe fn vabaq_u32(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vabs))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(abs))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vabs_s8(a: int8x8_t) -> int8x8_t { vabs_s8_(a) } @@ -1264,6 +1819,10 @@ pub unsafe fn vabs_s8(a: int8x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vabs))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(abs))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vabs_s16(a: int16x4_t) -> int16x4_t { vabs_s16_(a) } @@ -1273,6 +1832,10 @@ pub unsafe fn vabs_s16(a: int16x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vabs))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(abs))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vabs_s32(a: int32x2_t) -> int32x2_t { vabs_s32_(a) } @@ -1282,6 +1845,10 @@ pub unsafe fn vabs_s32(a: int32x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vabs))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(abs))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vabsq_s8(a: int8x16_t) -> int8x16_t { vabsq_s8_(a) } @@ -1291,6 +1858,10 @@ pub unsafe fn vabsq_s8(a: int8x16_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vabs))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(abs))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vabsq_s16(a: int16x8_t) -> int16x8_t { vabsq_s16_(a) } @@ -1300,6 +1871,10 @@ pub unsafe fn vabsq_s16(a: int16x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vabs))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(abs))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vabsq_s32(a: int32x4_t) -> int32x4_t { vabsq_s32_(a) } @@ -1310,6 +1885,10 @@ pub unsafe fn vabsq_s32(a: int32x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpadd))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(addp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpadd_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { vpadd_s16_(a, b) } @@ -1319,6 +1898,10 @@ pub unsafe fn vpadd_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpadd))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(addp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpadd_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { vpadd_s32_(a, b) } @@ -1328,6 +1911,10 @@ pub unsafe fn vpadd_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpadd))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(addp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpadd_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { vpadd_s8_(a, b) } @@ -1337,6 +1924,10 @@ pub unsafe fn vpadd_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpadd))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(addp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpadd_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { transmute(vpadd_s16_(transmute(a), transmute(b))) } @@ -1346,6 +1937,10 @@ pub unsafe fn vpadd_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpadd))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(addp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpadd_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { transmute(vpadd_s32_(transmute(a), transmute(b))) } @@ -1355,6 +1950,10 @@ pub unsafe fn vpadd_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpadd))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(addp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpadd_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { transmute(vpadd_s8_(transmute(a), transmute(b))) } @@ -1365,6 +1964,10 @@ pub unsafe fn vpadd_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vadd))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(add))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vadd_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { simd_add(a, b) } @@ -1375,6 +1978,10 @@ pub unsafe fn vadd_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vadd))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(add))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { simd_add(a, b) } @@ -1385,6 +1992,10 @@ pub unsafe fn vaddq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vadd))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(add))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vadd_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { simd_add(a, b) } @@ -1395,6 +2006,10 @@ pub unsafe fn vadd_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vadd))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(add))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { simd_add(a, b) } @@ -1405,6 +2020,10 @@ pub unsafe fn vaddq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vadd))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(add))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vadd_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { simd_add(a, b) } @@ -1415,6 +2034,10 @@ pub unsafe fn vadd_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vadd))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(add))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { simd_add(a, b) } @@ -1425,6 +2048,10 @@ pub unsafe fn vaddq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vadd))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(add))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { simd_add(a, b) } @@ -1435,6 +2062,10 @@ pub unsafe fn vaddq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vadd))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(add))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vadd_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { simd_add(a, b) } @@ -1445,6 +2076,10 @@ pub unsafe fn vadd_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vadd))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(add))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { simd_add(a, b) } @@ -1455,6 +2090,10 @@ pub unsafe fn vaddq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vadd))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(add))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vadd_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { simd_add(a, b) } @@ -1465,6 +2104,10 @@ pub unsafe fn vadd_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vadd))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(add))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { simd_add(a, b) } @@ -1475,6 +2118,10 @@ pub unsafe fn vaddq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vadd))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(add))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vadd_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { simd_add(a, b) } @@ -1485,6 +2132,10 @@ pub unsafe fn vadd_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vadd))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(add))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { simd_add(a, b) } @@ -1495,6 +2146,10 @@ pub unsafe fn vaddq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vadd))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(add))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { simd_add(a, b) } @@ -1505,6 +2160,10 @@ pub unsafe fn vaddq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vadd))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fadd))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vadd_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { simd_add(a, b) } @@ -1515,6 +2174,10 @@ pub unsafe fn vadd_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vadd))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fadd))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { simd_add(a, b) } @@ -1525,6 +2188,10 @@ pub unsafe fn vaddq_f32(a: float32x4_t, b: float32x4_t) -> float32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(saddl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddl_s8(a: int8x8_t, b: int8x8_t) -> int16x8_t { let a: int16x8_t = simd_cast(a); let b: int16x8_t = simd_cast(b); @@ -1537,6 +2204,10 @@ pub unsafe fn vaddl_s8(a: int8x8_t, b: int8x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(saddl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddl_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t { let a: int32x4_t = simd_cast(a); let b: int32x4_t = simd_cast(b); @@ -1549,6 +2220,10 @@ pub unsafe fn vaddl_s16(a: int16x4_t, b: int16x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(saddl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddl_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t { let a: int64x2_t = simd_cast(a); let b: int64x2_t = simd_cast(b); @@ -1561,6 +2236,10 @@ pub unsafe fn vaddl_s32(a: int32x2_t, b: int32x2_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uaddl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddl_u8(a: uint8x8_t, b: uint8x8_t) -> uint16x8_t { let a: uint16x8_t = simd_cast(a); let b: uint16x8_t = simd_cast(b); @@ -1573,6 +2252,10 @@ pub unsafe fn vaddl_u8(a: uint8x8_t, b: uint8x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uaddl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddl_u16(a: uint16x4_t, b: uint16x4_t) -> uint32x4_t { let a: uint32x4_t = simd_cast(a); let b: uint32x4_t = simd_cast(b); @@ -1585,6 +2268,10 @@ pub unsafe fn vaddl_u16(a: uint16x4_t, b: uint16x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uaddl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddl_u32(a: uint32x2_t, b: uint32x2_t) -> uint64x2_t { let a: uint64x2_t = simd_cast(a); let b: uint64x2_t = simd_cast(b); @@ -1597,6 +2284,10 @@ pub unsafe fn vaddl_u32(a: uint32x2_t, b: uint32x2_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(saddl2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddl_high_s8(a: int8x16_t, b: int8x16_t) -> int16x8_t { let a: int8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); let b: int8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); @@ -1611,6 +2302,10 @@ pub unsafe fn vaddl_high_s8(a: int8x16_t, b: int8x16_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(saddl2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddl_high_s16(a: int16x8_t, b: int16x8_t) -> int32x4_t { let a: int16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); let b: int16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); @@ -1625,6 +2320,10 @@ pub unsafe fn vaddl_high_s16(a: int16x8_t, b: int16x8_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(saddl2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddl_high_s32(a: int32x4_t, b: int32x4_t) -> int64x2_t { let a: int32x2_t = simd_shuffle2!(a, a, [2, 3]); let b: int32x2_t = simd_shuffle2!(b, b, [2, 3]); @@ -1639,6 +2338,10 @@ pub unsafe fn vaddl_high_s32(a: int32x4_t, b: int32x4_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uaddl2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddl_high_u8(a: uint8x16_t, b: uint8x16_t) -> uint16x8_t { let a: uint8x8_t = simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]); let b: uint8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); @@ -1653,6 +2356,10 @@ pub unsafe fn vaddl_high_u8(a: uint8x16_t, b: uint8x16_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uaddl2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddl_high_u16(a: uint16x8_t, b: uint16x8_t) -> uint32x4_t { let a: uint16x4_t = simd_shuffle4!(a, a, [4, 5, 6, 7]); let b: uint16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); @@ -1667,6 +2374,10 @@ pub unsafe fn vaddl_high_u16(a: uint16x8_t, b: uint16x8_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uaddl2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddl_high_u32(a: uint32x4_t, b: uint32x4_t) -> uint64x2_t { let a: uint32x2_t = simd_shuffle2!(a, a, [2, 3]); let b: uint32x2_t = simd_shuffle2!(b, b, [2, 3]); @@ -1681,6 +2392,10 @@ pub unsafe fn vaddl_high_u32(a: uint32x4_t, b: uint32x4_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddw))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(saddw))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddw_s8(a: int16x8_t, b: int8x8_t) -> int16x8_t { let b: int16x8_t = simd_cast(b); simd_add(a, b) @@ -1692,6 +2407,10 @@ pub unsafe fn vaddw_s8(a: int16x8_t, b: int8x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddw))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(saddw))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddw_s16(a: int32x4_t, b: int16x4_t) -> int32x4_t { let b: int32x4_t = simd_cast(b); simd_add(a, b) @@ -1703,6 +2422,10 @@ pub unsafe fn vaddw_s16(a: int32x4_t, b: int16x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddw))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(saddw))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddw_s32(a: int64x2_t, b: int32x2_t) -> int64x2_t { let b: int64x2_t = simd_cast(b); simd_add(a, b) @@ -1714,6 +2437,10 @@ pub unsafe fn vaddw_s32(a: int64x2_t, b: int32x2_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddw))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uaddw))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddw_u8(a: uint16x8_t, b: uint8x8_t) -> uint16x8_t { let b: uint16x8_t = simd_cast(b); simd_add(a, b) @@ -1725,6 +2452,10 @@ pub unsafe fn vaddw_u8(a: uint16x8_t, b: uint8x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddw))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uaddw))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddw_u16(a: uint32x4_t, b: uint16x4_t) -> uint32x4_t { let b: uint32x4_t = simd_cast(b); simd_add(a, b) @@ -1736,6 +2467,10 @@ pub unsafe fn vaddw_u16(a: uint32x4_t, b: uint16x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddw))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uaddw))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddw_u32(a: uint64x2_t, b: uint32x2_t) -> uint64x2_t { let b: uint64x2_t = simd_cast(b); simd_add(a, b) @@ -1747,6 +2482,10 @@ pub unsafe fn vaddw_u32(a: uint64x2_t, b: uint32x2_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddw))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(saddw2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddw_high_s8(a: int16x8_t, b: int8x16_t) -> int16x8_t { let b: int8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); let b: int16x8_t = simd_cast(b); @@ -1759,6 +2498,10 @@ pub unsafe fn vaddw_high_s8(a: int16x8_t, b: int8x16_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddw))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(saddw2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddw_high_s16(a: int32x4_t, b: int16x8_t) -> int32x4_t { let b: int16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); let b: int32x4_t = simd_cast(b); @@ -1771,6 +2514,10 @@ pub unsafe fn vaddw_high_s16(a: int32x4_t, b: int16x8_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddw))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(saddw2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddw_high_s32(a: int64x2_t, b: int32x4_t) -> int64x2_t { let b: int32x2_t = simd_shuffle2!(b, b, [2, 3]); let b: int64x2_t = simd_cast(b); @@ -1783,6 +2530,10 @@ pub unsafe fn vaddw_high_s32(a: int64x2_t, b: int32x4_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddw))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uaddw2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddw_high_u8(a: uint16x8_t, b: uint8x16_t) -> uint16x8_t { let b: uint8x8_t = simd_shuffle8!(b, b, [8, 9, 10, 11, 12, 13, 14, 15]); let b: uint16x8_t = simd_cast(b); @@ -1795,6 +2546,10 @@ pub unsafe fn vaddw_high_u8(a: uint16x8_t, b: uint8x16_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddw))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uaddw2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddw_high_u16(a: uint32x4_t, b: uint16x8_t) -> uint32x4_t { let b: uint16x4_t = simd_shuffle4!(b, b, [4, 5, 6, 7]); let b: uint32x4_t = simd_cast(b); @@ -1807,6 +2562,10 @@ pub unsafe fn vaddw_high_u16(a: uint32x4_t, b: uint16x8_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddw))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uaddw2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddw_high_u32(a: uint64x2_t, b: uint32x4_t) -> uint64x2_t { let b: uint32x2_t = simd_shuffle2!(b, b, [2, 3]); let b: uint64x2_t = simd_cast(b); @@ -1819,6 +2578,10 @@ pub unsafe fn vaddw_high_u32(a: uint64x2_t, b: uint32x4_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(addhn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddhn_s16(a: int16x8_t, b: int16x8_t) -> int8x8_t { simd_cast(simd_shr(simd_add(a, b), int16x8_t(8, 8, 8, 8, 8, 8, 8, 8))) } @@ -1829,6 +2592,10 @@ pub unsafe fn vaddhn_s16(a: int16x8_t, b: int16x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(addhn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddhn_s32(a: int32x4_t, b: int32x4_t) -> int16x4_t { simd_cast(simd_shr(simd_add(a, b), int32x4_t(16, 16, 16, 16))) } @@ -1839,6 +2606,10 @@ pub unsafe fn vaddhn_s32(a: int32x4_t, b: int32x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(addhn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddhn_s64(a: int64x2_t, b: int64x2_t) -> int32x2_t { simd_cast(simd_shr(simd_add(a, b), int64x2_t(32, 32))) } @@ -1849,6 +2620,10 @@ pub unsafe fn vaddhn_s64(a: int64x2_t, b: int64x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(addhn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddhn_u16(a: uint16x8_t, b: uint16x8_t) -> uint8x8_t { simd_cast(simd_shr(simd_add(a, b), uint16x8_t(8, 8, 8, 8, 8, 8, 8, 8))) } @@ -1859,6 +2634,10 @@ pub unsafe fn vaddhn_u16(a: uint16x8_t, b: uint16x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(addhn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddhn_u32(a: uint32x4_t, b: uint32x4_t) -> uint16x4_t { simd_cast(simd_shr(simd_add(a, b), uint32x4_t(16, 16, 16, 16))) } @@ -1869,6 +2648,10 @@ pub unsafe fn vaddhn_u32(a: uint32x4_t, b: uint32x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(addhn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddhn_u64(a: uint64x2_t, b: uint64x2_t) -> uint32x2_t { simd_cast(simd_shr(simd_add(a, b), uint64x2_t(32, 32))) } @@ -1879,6 +2662,10 @@ pub unsafe fn vaddhn_u64(a: uint64x2_t, b: uint64x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(addhn2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddhn_high_s16(r: int8x8_t, a: int16x8_t, b: int16x8_t) -> int8x16_t { let x = simd_cast(simd_shr(simd_add(a, b), int16x8_t(8, 8, 8, 8, 8, 8, 8, 8))); simd_shuffle16!(r, x, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) @@ -1890,6 +2677,10 @@ pub unsafe fn vaddhn_high_s16(r: int8x8_t, a: int16x8_t, b: int16x8_t) -> int8x1 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(addhn2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddhn_high_s32(r: int16x4_t, a: int32x4_t, b: int32x4_t) -> int16x8_t { let x = simd_cast(simd_shr(simd_add(a, b), int32x4_t(16, 16, 16, 16))); simd_shuffle8!(r, x, [0, 1, 2, 3, 4, 5, 6, 7]) @@ -1901,6 +2692,10 @@ pub unsafe fn vaddhn_high_s32(r: int16x4_t, a: int32x4_t, b: int32x4_t) -> int16 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(addhn2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddhn_high_s64(r: int32x2_t, a: int64x2_t, b: int64x2_t) -> int32x4_t { let x = simd_cast(simd_shr(simd_add(a, b), int64x2_t(32, 32))); simd_shuffle4!(r, x, [0, 1, 2, 3]) @@ -1912,6 +2707,10 @@ pub unsafe fn vaddhn_high_s64(r: int32x2_t, a: int64x2_t, b: int64x2_t) -> int32 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(addhn2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddhn_high_u16(r: uint8x8_t, a: uint16x8_t, b: uint16x8_t) -> uint8x16_t { let x = simd_cast(simd_shr(simd_add(a, b), uint16x8_t(8, 8, 8, 8, 8, 8, 8, 8))); simd_shuffle16!(r, x, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) @@ -1923,6 +2722,10 @@ pub unsafe fn vaddhn_high_u16(r: uint8x8_t, a: uint16x8_t, b: uint16x8_t) -> uin #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(addhn2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddhn_high_u32(r: uint16x4_t, a: uint32x4_t, b: uint32x4_t) -> uint16x8_t { let x = simd_cast(simd_shr(simd_add(a, b), uint32x4_t(16, 16, 16, 16))); simd_shuffle8!(r, x, [0, 1, 2, 3, 4, 5, 6, 7]) @@ -1934,6 +2737,10 @@ pub unsafe fn vaddhn_high_u32(r: uint16x4_t, a: uint32x4_t, b: uint32x4_t) -> ui #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vaddhn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(addhn2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vaddhn_high_u64(r: uint32x2_t, a: uint64x2_t, b: uint64x2_t) -> uint32x4_t { let x = simd_cast(simd_shr(simd_add(a, b), uint64x2_t(32, 32))); simd_shuffle4!(r, x, [0, 1, 2, 3]) @@ -1945,6 +2752,10 @@ pub unsafe fn vaddhn_high_u64(r: uint32x2_t, a: uint64x2_t, b: uint64x2_t) -> ui #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vraddhn.i16))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(raddhn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vraddhn_s16(a: int16x8_t, b: int16x8_t) -> int8x8_t { vraddhn_s16_(a, b) } @@ -1955,6 +2766,10 @@ pub unsafe fn vraddhn_s16(a: int16x8_t, b: int16x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vraddhn.i32))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(raddhn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vraddhn_s32(a: int32x4_t, b: int32x4_t) -> int16x4_t { vraddhn_s32_(a, b) } @@ -1965,6 +2780,10 @@ pub unsafe fn vraddhn_s32(a: int32x4_t, b: int32x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vraddhn.i64))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(raddhn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vraddhn_s64(a: int64x2_t, b: int64x2_t) -> int32x2_t { vraddhn_s64_(a, b) } @@ -1975,6 +2794,10 @@ pub unsafe fn vraddhn_s64(a: int64x2_t, b: int64x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vraddhn.i16))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(raddhn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vraddhn_u16(a: uint16x8_t, b: uint16x8_t) -> uint8x8_t { transmute(vraddhn_s16_(transmute(a), transmute(b))) } @@ -1985,6 +2808,10 @@ pub unsafe fn vraddhn_u16(a: uint16x8_t, b: uint16x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vraddhn.i32))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(raddhn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vraddhn_u32(a: uint32x4_t, b: uint32x4_t) -> uint16x4_t { transmute(vraddhn_s32_(transmute(a), transmute(b))) } @@ -1995,6 +2822,10 @@ pub unsafe fn vraddhn_u32(a: uint32x4_t, b: uint32x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vraddhn.i64))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(raddhn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vraddhn_u64(a: uint64x2_t, b: uint64x2_t) -> uint32x2_t { transmute(vraddhn_s64_(transmute(a), transmute(b))) } @@ -2005,6 +2836,10 @@ pub unsafe fn vraddhn_u64(a: uint64x2_t, b: uint64x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vraddhn.i16))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(raddhn2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vraddhn_high_s16(r: int8x8_t, a: int16x8_t, b: int16x8_t) -> int8x16_t { let x = vraddhn_s16_(a, b); simd_shuffle16!(r, x, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) @@ -2016,6 +2851,10 @@ pub unsafe fn vraddhn_high_s16(r: int8x8_t, a: int16x8_t, b: int16x8_t) -> int8x #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vraddhn.i32))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(raddhn2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vraddhn_high_s32(r: int16x4_t, a: int32x4_t, b: int32x4_t) -> int16x8_t { let x = vraddhn_s32_(a, b); simd_shuffle8!(r, x, [0, 1, 2, 3, 4, 5, 6, 7]) @@ -2027,6 +2866,10 @@ pub unsafe fn vraddhn_high_s32(r: int16x4_t, a: int32x4_t, b: int32x4_t) -> int1 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vraddhn.i64))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(raddhn2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vraddhn_high_s64(r: int32x2_t, a: int64x2_t, b: int64x2_t) -> int32x4_t { let x = vraddhn_s64_(a, b); simd_shuffle4!(r, x, [0, 1, 2, 3]) @@ -2038,6 +2881,10 @@ pub unsafe fn vraddhn_high_s64(r: int32x2_t, a: int64x2_t, b: int64x2_t) -> int3 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vraddhn.i16))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(raddhn2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vraddhn_high_u16(r: uint8x8_t, a: uint16x8_t, b: uint16x8_t) -> uint8x16_t { let x: uint8x8_t = transmute(vraddhn_s16_(transmute(a), transmute(b))); simd_shuffle16!(r, x, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) @@ -2049,6 +2896,10 @@ pub unsafe fn vraddhn_high_u16(r: uint8x8_t, a: uint16x8_t, b: uint16x8_t) -> ui #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vraddhn.i32))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(raddhn2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vraddhn_high_u32(r: uint16x4_t, a: uint32x4_t, b: uint32x4_t) -> uint16x8_t { let x: uint16x4_t = transmute(vraddhn_s32_(transmute(a), transmute(b))); simd_shuffle8!(r, x, [0, 1, 2, 3, 4, 5, 6, 7]) @@ -2060,6 +2911,10 @@ pub unsafe fn vraddhn_high_u32(r: uint16x4_t, a: uint32x4_t, b: uint32x4_t) -> u #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vraddhn.i64))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(raddhn2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vraddhn_high_u64(r: uint32x2_t, a: uint64x2_t, b: uint64x2_t) -> uint32x4_t { let x: uint32x2_t = transmute(vraddhn_s64_(transmute(a), transmute(b))); simd_shuffle4!(r, x, [0, 1, 2, 3]) @@ -2071,6 +2926,10 @@ pub unsafe fn vraddhn_high_u64(r: uint32x2_t, a: uint64x2_t, b: uint64x2_t) -> u #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpaddl.s8))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(saddlp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpaddl_s8(a: int8x8_t) -> int16x4_t { vpaddl_s8_(a) } @@ -2081,6 +2940,10 @@ pub unsafe fn vpaddl_s8(a: int8x8_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpaddl.s16))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(saddlp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpaddl_s16(a: int16x4_t) -> int32x2_t { vpaddl_s16_(a) } @@ -2091,6 +2954,10 @@ pub unsafe fn vpaddl_s16(a: int16x4_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpaddl.s32))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(saddlp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpaddl_s32(a: int32x2_t) -> int64x1_t { vpaddl_s32_(a) } @@ -2101,6 +2968,10 @@ pub unsafe fn vpaddl_s32(a: int32x2_t) -> int64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpaddl.s8))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(saddlp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpaddlq_s8(a: int8x16_t) -> int16x8_t { vpaddlq_s8_(a) } @@ -2111,6 +2982,10 @@ pub unsafe fn vpaddlq_s8(a: int8x16_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpaddl.s16))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(saddlp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpaddlq_s16(a: int16x8_t) -> int32x4_t { vpaddlq_s16_(a) } @@ -2121,6 +2996,10 @@ pub unsafe fn vpaddlq_s16(a: int16x8_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpaddl.s32))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(saddlp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpaddlq_s32(a: int32x4_t) -> int64x2_t { vpaddlq_s32_(a) } @@ -2131,6 +3010,10 @@ pub unsafe fn vpaddlq_s32(a: int32x4_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpaddl.u8))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uaddlp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpaddl_u8(a: uint8x8_t) -> uint16x4_t { vpaddl_u8_(a) } @@ -2141,6 +3024,10 @@ pub unsafe fn vpaddl_u8(a: uint8x8_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpaddl.u16))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uaddlp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpaddl_u16(a: uint16x4_t) -> uint32x2_t { vpaddl_u16_(a) } @@ -2151,6 +3038,10 @@ pub unsafe fn vpaddl_u16(a: uint16x4_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpaddl.u32))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uaddlp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpaddl_u32(a: uint32x2_t) -> uint64x1_t { vpaddl_u32_(a) } @@ -2161,6 +3052,10 @@ pub unsafe fn vpaddl_u32(a: uint32x2_t) -> uint64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpaddl.u8))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uaddlp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpaddlq_u8(a: uint8x16_t) -> uint16x8_t { vpaddlq_u8_(a) } @@ -2171,6 +3066,10 @@ pub unsafe fn vpaddlq_u8(a: uint8x16_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpaddl.u16))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uaddlp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpaddlq_u16(a: uint16x8_t) -> uint32x4_t { vpaddlq_u16_(a) } @@ -2181,6 +3080,10 @@ pub unsafe fn vpaddlq_u16(a: uint16x8_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpaddl.u32))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uaddlp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpaddlq_u32(a: uint32x4_t) -> uint64x2_t { vpaddlq_u32_(a) } @@ -2191,6 +3094,10 @@ pub unsafe fn vpaddlq_u32(a: uint32x4_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmovn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(xtn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmovn_s16(a: int16x8_t) -> int8x8_t { simd_cast(a) } @@ -2201,6 +3108,10 @@ pub unsafe fn vmovn_s16(a: int16x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmovn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(xtn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmovn_s32(a: int32x4_t) -> int16x4_t { simd_cast(a) } @@ -2211,6 +3122,10 @@ pub unsafe fn vmovn_s32(a: int32x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmovn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(xtn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmovn_s64(a: int64x2_t) -> int32x2_t { simd_cast(a) } @@ -2221,6 +3136,10 @@ pub unsafe fn vmovn_s64(a: int64x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmovn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(xtn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmovn_u16(a: uint16x8_t) -> uint8x8_t { simd_cast(a) } @@ -2231,6 +3150,10 @@ pub unsafe fn vmovn_u16(a: uint16x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmovn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(xtn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmovn_u32(a: uint32x4_t) -> uint16x4_t { simd_cast(a) } @@ -2241,6 +3164,10 @@ pub unsafe fn vmovn_u32(a: uint32x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmovn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(xtn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmovn_u64(a: uint64x2_t) -> uint32x2_t { simd_cast(a) } @@ -2251,6 +3178,10 @@ pub unsafe fn vmovn_u64(a: uint64x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmovl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sxtl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmovl_s8(a: int8x8_t) -> int16x8_t { simd_cast(a) } @@ -2261,6 +3192,10 @@ pub unsafe fn vmovl_s8(a: int8x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmovl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sxtl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmovl_s16(a: int16x4_t) -> int32x4_t { simd_cast(a) } @@ -2271,6 +3206,10 @@ pub unsafe fn vmovl_s16(a: int16x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmovl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sxtl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmovl_s32(a: int32x2_t) -> int64x2_t { simd_cast(a) } @@ -2281,6 +3220,10 @@ pub unsafe fn vmovl_s32(a: int32x2_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmovl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uxtl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmovl_u8(a: uint8x8_t) -> uint16x8_t { simd_cast(a) } @@ -2291,6 +3234,10 @@ pub unsafe fn vmovl_u8(a: uint8x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmovl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uxtl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmovl_u16(a: uint16x4_t) -> uint32x4_t { simd_cast(a) } @@ -2301,6 +3248,10 @@ pub unsafe fn vmovl_u16(a: uint16x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmovl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uxtl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmovl_u32(a: uint32x2_t) -> uint64x2_t { simd_cast(a) } @@ -2311,6 +3262,10 @@ pub unsafe fn vmovl_u32(a: uint32x2_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmvn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mvn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmvn_s8(a: int8x8_t) -> int8x8_t { let b = int8x8_t(-1, -1, -1, -1, -1, -1, -1, -1); simd_xor(a, b) @@ -2322,6 +3277,10 @@ pub unsafe fn vmvn_s8(a: int8x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmvn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mvn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmvnq_s8(a: int8x16_t) -> int8x16_t { let b = int8x16_t( -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -2335,6 +3294,10 @@ pub unsafe fn vmvnq_s8(a: int8x16_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmvn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mvn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmvn_s16(a: int16x4_t) -> int16x4_t { let b = int16x4_t(-1, -1, -1, -1); simd_xor(a, b) @@ -2346,6 +3309,10 @@ pub unsafe fn vmvn_s16(a: int16x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmvn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mvn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmvnq_s16(a: int16x8_t) -> int16x8_t { let b = int16x8_t(-1, -1, -1, -1, -1, -1, -1, -1); simd_xor(a, b) @@ -2357,6 +3324,10 @@ pub unsafe fn vmvnq_s16(a: int16x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmvn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mvn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmvn_s32(a: int32x2_t) -> int32x2_t { let b = int32x2_t(-1, -1); simd_xor(a, b) @@ -2368,6 +3339,10 @@ pub unsafe fn vmvn_s32(a: int32x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmvn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mvn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmvnq_s32(a: int32x4_t) -> int32x4_t { let b = int32x4_t(-1, -1, -1, -1); simd_xor(a, b) @@ -2379,6 +3354,10 @@ pub unsafe fn vmvnq_s32(a: int32x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmvn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mvn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmvn_u8(a: uint8x8_t) -> uint8x8_t { let b = uint8x8_t(255, 255, 255, 255, 255, 255, 255, 255); simd_xor(a, b) @@ -2390,6 +3369,10 @@ pub unsafe fn vmvn_u8(a: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmvn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mvn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmvnq_u8(a: uint8x16_t) -> uint8x16_t { let b = uint8x16_t( 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, @@ -2403,6 +3386,10 @@ pub unsafe fn vmvnq_u8(a: uint8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmvn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mvn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmvn_u16(a: uint16x4_t) -> uint16x4_t { let b = uint16x4_t(65_535, 65_535, 65_535, 65_535); simd_xor(a, b) @@ -2414,6 +3401,10 @@ pub unsafe fn vmvn_u16(a: uint16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmvn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mvn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmvnq_u16(a: uint16x8_t) -> uint16x8_t { let b = uint16x8_t( 65_535, 65_535, 65_535, 65_535, 65_535, 65_535, 65_535, 65_535, @@ -2427,6 +3418,10 @@ pub unsafe fn vmvnq_u16(a: uint16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmvn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mvn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmvn_u32(a: uint32x2_t) -> uint32x2_t { let b = uint32x2_t(4_294_967_295, 4_294_967_295); simd_xor(a, b) @@ -2438,6 +3433,10 @@ pub unsafe fn vmvn_u32(a: uint32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmvn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mvn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmvnq_u32(a: uint32x4_t) -> uint32x4_t { let b = uint32x4_t(4_294_967_295, 4_294_967_295, 4_294_967_295, 4_294_967_295); simd_xor(a, b) @@ -2449,6 +3448,10 @@ pub unsafe fn vmvnq_u32(a: uint32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmvn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mvn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmvn_p8(a: poly8x8_t) -> poly8x8_t { let b = poly8x8_t(255, 255, 255, 255, 255, 255, 255, 255); simd_xor(a, b) @@ -2460,6 +3463,10 @@ pub unsafe fn vmvn_p8(a: poly8x8_t) -> poly8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vmvn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(mvn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmvnq_p8(a: poly8x16_t) -> poly8x16_t { let b = poly8x16_t( 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, @@ -2473,6 +3480,10 @@ pub unsafe fn vmvnq_p8(a: poly8x16_t) -> poly8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbic))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bic))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbic_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { let c = int8x8_t(-1, -1, -1, -1, -1, -1, -1, -1); simd_and(simd_xor(b, c), a) @@ -2484,6 +3495,10 @@ pub unsafe fn vbic_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbic))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bic))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbicq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { let c = int8x16_t( -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -2497,6 +3512,10 @@ pub unsafe fn vbicq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbic))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bic))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbic_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { let c = int16x4_t(-1, -1, -1, -1); simd_and(simd_xor(b, c), a) @@ -2508,6 +3527,10 @@ pub unsafe fn vbic_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbic))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bic))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbicq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { let c = int16x8_t(-1, -1, -1, -1, -1, -1, -1, -1); simd_and(simd_xor(b, c), a) @@ -2519,6 +3542,10 @@ pub unsafe fn vbicq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbic))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bic))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbic_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { let c = int32x2_t(-1, -1); simd_and(simd_xor(b, c), a) @@ -2530,6 +3557,10 @@ pub unsafe fn vbic_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbic))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bic))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbicq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { let c = int32x4_t(-1, -1, -1, -1); simd_and(simd_xor(b, c), a) @@ -2541,6 +3572,10 @@ pub unsafe fn vbicq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbic))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bic))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbic_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { let c = int64x1_t(-1); simd_and(simd_xor(b, c), a) @@ -2552,6 +3587,10 @@ pub unsafe fn vbic_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbic))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bic))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbicq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { let c = int64x2_t(-1, -1); simd_and(simd_xor(b, c), a) @@ -2563,6 +3602,10 @@ pub unsafe fn vbicq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbic))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bic))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbic_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { let c = int8x8_t(-1, -1, -1, -1, -1, -1, -1, -1); simd_and(simd_xor(b, transmute(c)), a) @@ -2574,6 +3617,10 @@ pub unsafe fn vbic_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbic))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bic))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbicq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { let c = int8x16_t( -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -2587,6 +3634,10 @@ pub unsafe fn vbicq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbic))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bic))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbic_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { let c = int16x4_t(-1, -1, -1, -1); simd_and(simd_xor(b, transmute(c)), a) @@ -2598,6 +3649,10 @@ pub unsafe fn vbic_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbic))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bic))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbicq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { let c = int16x8_t(-1, -1, -1, -1, -1, -1, -1, -1); simd_and(simd_xor(b, transmute(c)), a) @@ -2609,6 +3664,10 @@ pub unsafe fn vbicq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbic))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bic))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbic_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { let c = int32x2_t(-1, -1); simd_and(simd_xor(b, transmute(c)), a) @@ -2620,6 +3679,10 @@ pub unsafe fn vbic_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbic))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bic))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbicq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { let c = int32x4_t(-1, -1, -1, -1); simd_and(simd_xor(b, transmute(c)), a) @@ -2631,6 +3694,10 @@ pub unsafe fn vbicq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbic))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bic))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbic_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { let c = int64x1_t(-1); simd_and(simd_xor(b, transmute(c)), a) @@ -2642,6 +3709,10 @@ pub unsafe fn vbic_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbic))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bic))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbicq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { let c = int64x2_t(-1, -1); simd_and(simd_xor(b, transmute(c)), a) @@ -2657,6 +3728,10 @@ pub unsafe fn vbicq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bsl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbsl_s8(a: uint8x8_t, b: int8x8_t, c: int8x8_t) -> int8x8_t { simd_select(transmute::<_, int8x8_t>(a), b, c) } @@ -2667,6 +3742,10 @@ pub unsafe fn vbsl_s8(a: uint8x8_t, b: int8x8_t, c: int8x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bsl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbsl_s16(a: uint16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t { simd_select(transmute::<_, int16x4_t>(a), b, c) } @@ -2677,6 +3756,10 @@ pub unsafe fn vbsl_s16(a: uint16x4_t, b: int16x4_t, c: int16x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bsl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbsl_s32(a: uint32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t { simd_select(transmute::<_, int32x2_t>(a), b, c) } @@ -2687,6 +3770,10 @@ pub unsafe fn vbsl_s32(a: uint32x2_t, b: int32x2_t, c: int32x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bsl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbsl_s64(a: uint64x1_t, b: int64x1_t, c: int64x1_t) -> int64x1_t { simd_select(transmute::<_, int64x1_t>(a), b, c) } @@ -2697,6 +3784,10 @@ pub unsafe fn vbsl_s64(a: uint64x1_t, b: int64x1_t, c: int64x1_t) -> int64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bsl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbsl_u8(a: uint8x8_t, b: uint8x8_t, c: uint8x8_t) -> uint8x8_t { simd_select(transmute::<_, int8x8_t>(a), b, c) } @@ -2707,6 +3798,10 @@ pub unsafe fn vbsl_u8(a: uint8x8_t, b: uint8x8_t, c: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bsl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbsl_u16(a: uint16x4_t, b: uint16x4_t, c: uint16x4_t) -> uint16x4_t { simd_select(transmute::<_, int16x4_t>(a), b, c) } @@ -2717,6 +3812,10 @@ pub unsafe fn vbsl_u16(a: uint16x4_t, b: uint16x4_t, c: uint16x4_t) -> uint16x4_ #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bsl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbsl_u32(a: uint32x2_t, b: uint32x2_t, c: uint32x2_t) -> uint32x2_t { simd_select(transmute::<_, int32x2_t>(a), b, c) } @@ -2727,6 +3826,10 @@ pub unsafe fn vbsl_u32(a: uint32x2_t, b: uint32x2_t, c: uint32x2_t) -> uint32x2_ #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bsl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbsl_u64(a: uint64x1_t, b: uint64x1_t, c: uint64x1_t) -> uint64x1_t { simd_select(transmute::<_, int64x1_t>(a), b, c) } @@ -2737,6 +3840,10 @@ pub unsafe fn vbsl_u64(a: uint64x1_t, b: uint64x1_t, c: uint64x1_t) -> uint64x1_ #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bsl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbsl_f32(a: uint32x2_t, b: float32x2_t, c: float32x2_t) -> float32x2_t { simd_select(transmute::<_, int32x2_t>(a), b, c) } @@ -2747,6 +3854,10 @@ pub unsafe fn vbsl_f32(a: uint32x2_t, b: float32x2_t, c: float32x2_t) -> float32 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bsl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbsl_p8(a: uint8x8_t, b: poly8x8_t, c: poly8x8_t) -> poly8x8_t { simd_select(transmute::<_, int8x8_t>(a), b, c) } @@ -2757,6 +3868,10 @@ pub unsafe fn vbsl_p8(a: uint8x8_t, b: poly8x8_t, c: poly8x8_t) -> poly8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bsl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbsl_p16(a: uint16x4_t, b: poly16x4_t, c: poly16x4_t) -> poly16x4_t { simd_select(transmute::<_, int16x4_t>(a), b, c) } @@ -2767,6 +3882,10 @@ pub unsafe fn vbsl_p16(a: uint16x4_t, b: poly16x4_t, c: poly16x4_t) -> poly16x4_ #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bsl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbslq_s8(a: uint8x16_t, b: int8x16_t, c: int8x16_t) -> int8x16_t { simd_select(transmute::<_, int8x16_t>(a), b, c) } @@ -2777,6 +3896,10 @@ pub unsafe fn vbslq_s8(a: uint8x16_t, b: int8x16_t, c: int8x16_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bsl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbslq_s16(a: uint16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t { simd_select(transmute::<_, int16x8_t>(a), b, c) } @@ -2787,6 +3910,10 @@ pub unsafe fn vbslq_s16(a: uint16x8_t, b: int16x8_t, c: int16x8_t) -> int16x8_t #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bsl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbslq_s32(a: uint32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t { simd_select(transmute::<_, int32x4_t>(a), b, c) } @@ -2797,6 +3924,10 @@ pub unsafe fn vbslq_s32(a: uint32x4_t, b: int32x4_t, c: int32x4_t) -> int32x4_t #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bsl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbslq_s64(a: uint64x2_t, b: int64x2_t, c: int64x2_t) -> int64x2_t { simd_select(transmute::<_, int64x2_t>(a), b, c) } @@ -2807,6 +3938,10 @@ pub unsafe fn vbslq_s64(a: uint64x2_t, b: int64x2_t, c: int64x2_t) -> int64x2_t #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bsl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbslq_u8(a: uint8x16_t, b: uint8x16_t, c: uint8x16_t) -> uint8x16_t { simd_select(transmute::<_, int8x16_t>(a), b, c) } @@ -2817,6 +3952,10 @@ pub unsafe fn vbslq_u8(a: uint8x16_t, b: uint8x16_t, c: uint8x16_t) -> uint8x16_ #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bsl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbslq_u16(a: uint16x8_t, b: uint16x8_t, c: uint16x8_t) -> uint16x8_t { simd_select(transmute::<_, int16x8_t>(a), b, c) } @@ -2827,6 +3966,10 @@ pub unsafe fn vbslq_u16(a: uint16x8_t, b: uint16x8_t, c: uint16x8_t) -> uint16x8 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bsl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbslq_u32(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4_t { simd_select(transmute::<_, int32x4_t>(a), b, c) } @@ -2837,6 +3980,10 @@ pub unsafe fn vbslq_u32(a: uint32x4_t, b: uint32x4_t, c: uint32x4_t) -> uint32x4 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bsl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbslq_u64(a: uint64x2_t, b: uint64x2_t, c: uint64x2_t) -> uint64x2_t { simd_select(transmute::<_, int64x2_t>(a), b, c) } @@ -2847,6 +3994,10 @@ pub unsafe fn vbslq_u64(a: uint64x2_t, b: uint64x2_t, c: uint64x2_t) -> uint64x2 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bsl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbslq_p8(a: uint8x16_t, b: poly8x16_t, c: poly8x16_t) -> poly8x16_t { simd_select(transmute::<_, int8x16_t>(a), b, c) } @@ -2857,6 +4008,10 @@ pub unsafe fn vbslq_p8(a: uint8x16_t, b: poly8x16_t, c: poly8x16_t) -> poly8x16_ #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bsl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbslq_p16(a: uint16x8_t, b: poly16x8_t, c: poly16x8_t) -> poly16x8_t { simd_select(transmute::<_, int16x8_t>(a), b, c) } @@ -2867,6 +4022,10 @@ pub unsafe fn vbslq_p16(a: uint16x8_t, b: poly16x8_t, c: poly16x8_t) -> poly16x8 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vbsl))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(bsl))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vbslq_f32(a: uint32x4_t, b: float32x4_t, c: float32x4_t) -> float32x4_t { simd_select(transmute::<_, int32x4_t>(a), b, c) } @@ -2877,6 +4036,10 @@ pub unsafe fn vbslq_f32(a: uint32x4_t, b: float32x4_t, c: float32x4_t) -> float3 #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vorn_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { let c = int8x8_t(-1, -1, -1, -1, -1, -1, -1, -1); simd_or(simd_xor(b, c), a) @@ -2888,6 +4051,10 @@ pub unsafe fn vorn_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vornq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { let c = int8x16_t( -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -2901,6 +4068,10 @@ pub unsafe fn vornq_s8(a: int8x16_t, b: int8x16_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vorn_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { let c = int16x4_t(-1, -1, -1, -1); simd_or(simd_xor(b, c), a) @@ -2912,6 +4083,10 @@ pub unsafe fn vorn_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vornq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { let c = int16x8_t(-1, -1, -1, -1, -1, -1, -1, -1); simd_or(simd_xor(b, c), a) @@ -2923,6 +4098,10 @@ pub unsafe fn vornq_s16(a: int16x8_t, b: int16x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vorn_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { let c = int32x2_t(-1, -1); simd_or(simd_xor(b, c), a) @@ -2934,6 +4113,10 @@ pub unsafe fn vorn_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vornq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { let c = int32x4_t(-1, -1, -1, -1); simd_or(simd_xor(b, c), a) @@ -2945,6 +4128,10 @@ pub unsafe fn vornq_s32(a: int32x4_t, b: int32x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vorn_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { let c = int64x1_t(-1); simd_or(simd_xor(b, c), a) @@ -2956,6 +4143,10 @@ pub unsafe fn vorn_s64(a: int64x1_t, b: int64x1_t) -> int64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vornq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { let c = int64x2_t(-1, -1); simd_or(simd_xor(b, c), a) @@ -2967,6 +4158,10 @@ pub unsafe fn vornq_s64(a: int64x2_t, b: int64x2_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vorn_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { let c = int8x8_t(-1, -1, -1, -1, -1, -1, -1, -1); simd_or(simd_xor(b, transmute(c)), a) @@ -2978,6 +4173,10 @@ pub unsafe fn vorn_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vornq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { let c = int8x16_t( -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -2991,6 +4190,10 @@ pub unsafe fn vornq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vorn_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { let c = int16x4_t(-1, -1, -1, -1); simd_or(simd_xor(b, transmute(c)), a) @@ -3002,6 +4205,10 @@ pub unsafe fn vorn_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vornq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { let c = int16x8_t(-1, -1, -1, -1, -1, -1, -1, -1); simd_or(simd_xor(b, transmute(c)), a) @@ -3013,6 +4220,10 @@ pub unsafe fn vornq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vorn_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { let c = int32x2_t(-1, -1); simd_or(simd_xor(b, transmute(c)), a) @@ -3024,6 +4235,10 @@ pub unsafe fn vorn_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vornq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { let c = int32x4_t(-1, -1, -1, -1); simd_or(simd_xor(b, transmute(c)), a) @@ -3035,6 +4250,10 @@ pub unsafe fn vornq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vorn_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { let c = int64x1_t(-1); simd_or(simd_xor(b, transmute(c)), a) @@ -3046,6 +4265,10 @@ pub unsafe fn vorn_u64(a: uint64x1_t, b: uint64x1_t) -> uint64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorn))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(orn))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vornq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { let c = int64x2_t(-1, -1); simd_or(simd_xor(b, transmute(c)), a) @@ -3057,6 +4280,10 @@ pub unsafe fn vornq_u64(a: uint64x2_t, b: uint64x2_t) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpmin))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sminp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpmin_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { vpmins_v8i8(a, b) } @@ -3067,6 +4294,10 @@ pub unsafe fn vpmin_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpmin))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sminp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpmin_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { vpmins_v4i16(a, b) } @@ -3077,6 +4308,10 @@ pub unsafe fn vpmin_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpmin))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sminp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpmin_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { vpmins_v2i32(a, b) } @@ -3087,6 +4322,10 @@ pub unsafe fn vpmin_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpmin))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uminp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpmin_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { vpminu_v8i8(a, b) } @@ -3097,6 +4336,10 @@ pub unsafe fn vpmin_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpmin))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uminp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpmin_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { vpminu_v4i16(a, b) } @@ -3107,6 +4350,10 @@ pub unsafe fn vpmin_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpmin))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uminp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpmin_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { vpminu_v2i32(a, b) } @@ -3117,6 +4364,10 @@ pub unsafe fn vpmin_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpmin))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fminp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpmin_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { vpminf_v2f32(a, b) } @@ -3127,6 +4378,10 @@ pub unsafe fn vpmin_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpmax))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smaxp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpmax_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { vpmaxs_v8i8(a, b) } @@ -3137,6 +4392,10 @@ pub unsafe fn vpmax_s8(a: int8x8_t, b: int8x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpmax))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smaxp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpmax_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { vpmaxs_v4i16(a, b) } @@ -3147,6 +4406,10 @@ pub unsafe fn vpmax_s16(a: int16x4_t, b: int16x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpmax))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(smaxp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpmax_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { vpmaxs_v2i32(a, b) } @@ -3157,6 +4420,10 @@ pub unsafe fn vpmax_s32(a: int32x2_t, b: int32x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpmax))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umaxp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpmax_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { vpmaxu_v8i8(a, b) } @@ -3167,6 +4434,10 @@ pub unsafe fn vpmax_u8(a: uint8x8_t, b: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpmax))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umaxp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpmax_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { vpmaxu_v4i16(a, b) } @@ -3177,6 +4448,10 @@ pub unsafe fn vpmax_u16(a: uint16x4_t, b: uint16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpmax))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(umaxp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpmax_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { vpmaxu_v2i32(a, b) } @@ -3187,6 +4462,10 @@ pub unsafe fn vpmax_u32(a: uint32x2_t, b: uint32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpmax))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmaxp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpmax_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { vpmaxf_v2f32(a, b) } @@ -3197,6 +4476,10 @@ pub unsafe fn vpmax_f32(a: float32x2_t, b: float32x2_t) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] #[cfg_attr(test, assert_instr(nop, IMM5 = 1))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vgetq_lane_u64(v: uint64x2_t) -> u64 { static_assert_imm1!(IMM5); simd_extract(v, IMM5 as u32) @@ -3208,6 +4491,10 @@ pub unsafe fn vgetq_lane_u64(v: uint64x2_t) -> u64 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] #[cfg_attr(test, assert_instr(nop, IMM5 = 0))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_lane_u64(v: uint64x1_t) -> u64 { static_assert!(IMM5 : i32 where IMM5 == 0); simd_extract(v, 0) @@ -3219,6 +4506,10 @@ pub unsafe fn vget_lane_u64(v: uint64x1_t) -> u64 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] #[cfg_attr(test, assert_instr(nop, IMM5 = 2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_lane_u16(v: uint16x4_t) -> u16 { static_assert_imm2!(IMM5); simd_extract(v, IMM5 as u32) @@ -3230,6 +4521,10 @@ pub unsafe fn vget_lane_u16(v: uint16x4_t) -> u16 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] #[cfg_attr(test, assert_instr(nop, IMM5 = 2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_lane_s16(v: int16x4_t) -> i16 { static_assert_imm2!(IMM5); simd_extract(v, IMM5 as u32) @@ -3241,6 +4536,10 @@ pub unsafe fn vget_lane_s16(v: int16x4_t) -> i16 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] #[cfg_attr(test, assert_instr(nop, IMM5 = 2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_lane_p16(v: poly16x4_t) -> p16 { static_assert_imm2!(IMM5); simd_extract(v, IMM5 as u32) @@ -3252,6 +4551,10 @@ pub unsafe fn vget_lane_p16(v: poly16x4_t) -> p16 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] #[cfg_attr(test, assert_instr(nop, IMM5 = 1))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_lane_u32(v: uint32x2_t) -> u32 { static_assert_imm1!(IMM5); simd_extract(v, IMM5 as u32) @@ -3263,6 +4566,10 @@ pub unsafe fn vget_lane_u32(v: uint32x2_t) -> u32 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] #[cfg_attr(test, assert_instr(nop, IMM5 = 1))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_lane_s32(v: int32x2_t) -> i32 { static_assert_imm1!(IMM5); simd_extract(v, IMM5 as u32) @@ -3274,6 +4581,10 @@ pub unsafe fn vget_lane_s32(v: int32x2_t) -> i32 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] #[cfg_attr(test, assert_instr(nop, IMM5 = 1))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_lane_f32(v: float32x2_t) -> f32 { static_assert_imm1!(IMM5); simd_extract(v, IMM5 as u32) @@ -3285,6 +4596,10 @@ pub unsafe fn vget_lane_f32(v: float32x2_t) -> f32 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] #[cfg_attr(test, assert_instr(nop, IMM5 = 1))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vgetq_lane_f32(v: float32x4_t) -> f32 { static_assert_imm2!(IMM5); simd_extract(v, IMM5 as u32) @@ -3296,6 +4611,10 @@ pub unsafe fn vgetq_lane_f32(v: float32x4_t) -> f32 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] #[cfg_attr(test, assert_instr(nop, IMM5 = 0))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_lane_p64(v: poly64x1_t) -> p64 { static_assert!(IMM5 : i32 where IMM5 == 0); simd_extract(v, IMM5 as u32) @@ -3307,6 +4626,10 @@ pub unsafe fn vget_lane_p64(v: poly64x1_t) -> p64 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] #[cfg_attr(test, assert_instr(nop, IMM5 = 0))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vgetq_lane_p64(v: poly64x2_t) -> p64 { static_assert_imm1!(IMM5); simd_extract(v, IMM5 as u32) @@ -3318,6 +4641,10 @@ pub unsafe fn vgetq_lane_p64(v: poly64x2_t) -> p64 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] #[cfg_attr(test, assert_instr(nop, IMM5 = 0))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_lane_s64(v: int64x1_t) -> i64 { static_assert!(IMM5 : i32 where IMM5 == 0); simd_extract(v, IMM5 as u32) @@ -3329,6 +4656,10 @@ pub unsafe fn vget_lane_s64(v: int64x1_t) -> i64 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] #[cfg_attr(test, assert_instr(nop, IMM5 = 0))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vgetq_lane_s64(v: int64x2_t) -> i64 { static_assert_imm1!(IMM5); simd_extract(v, IMM5 as u32) @@ -3340,6 +4671,10 @@ pub unsafe fn vgetq_lane_s64(v: int64x2_t) -> i64 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] #[cfg_attr(test, assert_instr(nop, IMM5 = 2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vgetq_lane_u16(v: uint16x8_t) -> u16 { static_assert_imm3!(IMM5); simd_extract(v, IMM5 as u32) @@ -3351,6 +4686,10 @@ pub unsafe fn vgetq_lane_u16(v: uint16x8_t) -> u16 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] #[cfg_attr(test, assert_instr(nop, IMM5 = 2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vgetq_lane_u32(v: uint32x4_t) -> u32 { static_assert_imm2!(IMM5); simd_extract(v, IMM5 as u32) @@ -3362,6 +4701,10 @@ pub unsafe fn vgetq_lane_u32(v: uint32x4_t) -> u32 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] #[cfg_attr(test, assert_instr(nop, IMM5 = 2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vgetq_lane_s16(v: int16x8_t) -> i16 { static_assert_imm3!(IMM5); simd_extract(v, IMM5 as u32) @@ -3373,6 +4716,10 @@ pub unsafe fn vgetq_lane_s16(v: int16x8_t) -> i16 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] #[cfg_attr(test, assert_instr(nop, IMM5 = 2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vgetq_lane_p16(v: poly16x8_t) -> p16 { static_assert_imm3!(IMM5); simd_extract(v, IMM5 as u32) @@ -3384,6 +4731,10 @@ pub unsafe fn vgetq_lane_p16(v: poly16x8_t) -> p16 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] #[cfg_attr(test, assert_instr(nop, IMM5 = 2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vgetq_lane_s32(v: int32x4_t) -> i32 { static_assert_imm2!(IMM5); simd_extract(v, IMM5 as u32) @@ -3395,6 +4746,10 @@ pub unsafe fn vgetq_lane_s32(v: int32x4_t) -> i32 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] #[cfg_attr(test, assert_instr(nop, IMM5 = 2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_lane_u8(v: uint8x8_t) -> u8 { static_assert_imm3!(IMM5); simd_extract(v, IMM5 as u32) @@ -3406,6 +4761,10 @@ pub unsafe fn vget_lane_u8(v: uint8x8_t) -> u8 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] #[cfg_attr(test, assert_instr(nop, IMM5 = 2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_lane_s8(v: int8x8_t) -> i8 { static_assert_imm3!(IMM5); simd_extract(v, IMM5 as u32) @@ -3417,6 +4776,10 @@ pub unsafe fn vget_lane_s8(v: int8x8_t) -> i8 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] #[cfg_attr(test, assert_instr(nop, IMM5 = 2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_lane_p8(v: poly8x8_t) -> p8 { static_assert_imm3!(IMM5); simd_extract(v, IMM5 as u32) @@ -3428,6 +4791,10 @@ pub unsafe fn vget_lane_p8(v: poly8x8_t) -> p8 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] #[cfg_attr(test, assert_instr(nop, IMM5 = 2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vgetq_lane_u8(v: uint8x16_t) -> u8 { static_assert_imm4!(IMM5); simd_extract(v, IMM5 as u32) @@ -3439,6 +4806,10 @@ pub unsafe fn vgetq_lane_u8(v: uint8x16_t) -> u8 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] #[cfg_attr(test, assert_instr(nop, IMM5 = 2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vgetq_lane_s8(v: int8x16_t) -> i8 { static_assert_imm4!(IMM5); simd_extract(v, IMM5 as u32) @@ -3450,6 +4821,10 @@ pub unsafe fn vgetq_lane_s8(v: int8x16_t) -> i8 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(1)] #[cfg_attr(test, assert_instr(nop, IMM5 = 2))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vgetq_lane_p8(v: poly8x16_t) -> p8 { static_assert_imm4!(IMM5); simd_extract(v, IMM5 as u32) @@ -3461,6 +4836,10 @@ pub unsafe fn vgetq_lane_p8(v: poly8x16_t) -> p8 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_high_s8(a: int8x16_t) -> int8x8_t { simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]) } @@ -3471,6 +4850,10 @@ pub unsafe fn vget_high_s8(a: int8x16_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_high_s16(a: int16x8_t) -> int16x4_t { simd_shuffle4!(a, a, [4, 5, 6, 7]) } @@ -3481,6 +4864,10 @@ pub unsafe fn vget_high_s16(a: int16x8_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_high_s32(a: int32x4_t) -> int32x2_t { simd_shuffle2!(a, a, [2, 3]) } @@ -3491,6 +4878,10 @@ pub unsafe fn vget_high_s32(a: int32x4_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_high_s64(a: int64x2_t) -> int64x1_t { int64x1_t(simd_extract(a, 1)) } @@ -3501,6 +4892,10 @@ pub unsafe fn vget_high_s64(a: int64x2_t) -> int64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_high_u8(a: uint8x16_t) -> uint8x8_t { simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]) } @@ -3511,6 +4906,10 @@ pub unsafe fn vget_high_u8(a: uint8x16_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_high_u16(a: uint16x8_t) -> uint16x4_t { simd_shuffle4!(a, a, [4, 5, 6, 7]) } @@ -3521,6 +4920,10 @@ pub unsafe fn vget_high_u16(a: uint16x8_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_high_u32(a: uint32x4_t) -> uint32x2_t { simd_shuffle2!(a, a, [2, 3]) } @@ -3531,6 +4934,10 @@ pub unsafe fn vget_high_u32(a: uint32x4_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_high_u64(a: uint64x2_t) -> uint64x1_t { uint64x1_t(simd_extract(a, 1)) } @@ -3541,6 +4948,10 @@ pub unsafe fn vget_high_u64(a: uint64x2_t) -> uint64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_high_p8(a: poly8x16_t) -> poly8x8_t { simd_shuffle8!(a, a, [8, 9, 10, 11, 12, 13, 14, 15]) } @@ -3551,6 +4962,10 @@ pub unsafe fn vget_high_p8(a: poly8x16_t) -> poly8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_high_p16(a: poly16x8_t) -> poly16x4_t { simd_shuffle4!(a, a, [4, 5, 6, 7]) } @@ -3561,6 +4976,10 @@ pub unsafe fn vget_high_p16(a: poly16x8_t) -> poly16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(ext))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_high_f32(a: float32x4_t) -> float32x2_t { simd_shuffle2!(a, a, [2, 3]) } @@ -3579,6 +4998,10 @@ pub unsafe fn vget_low_s8(a: int8x16_t) -> int8x8_t { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(test, assert_instr(nop))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_low_s16(a: int16x8_t) -> int16x4_t { simd_shuffle4!(a, a, [0, 1, 2, 3]) } @@ -3588,6 +5011,10 @@ pub unsafe fn vget_low_s16(a: int16x8_t) -> int16x4_t { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(test, assert_instr(nop))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_low_s32(a: int32x4_t) -> int32x2_t { simd_shuffle2!(a, a, [0, 1]) } @@ -3597,6 +5024,10 @@ pub unsafe fn vget_low_s32(a: int32x4_t) -> int32x2_t { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(test, assert_instr(nop))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_low_s64(a: int64x2_t) -> int64x1_t { int64x1_t(simd_extract(a, 0)) } @@ -3606,6 +5037,10 @@ pub unsafe fn vget_low_s64(a: int64x2_t) -> int64x1_t { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(test, assert_instr(nop))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_low_u8(a: uint8x16_t) -> uint8x8_t { simd_shuffle8!(a, a, [0, 1, 2, 3, 4, 5, 6, 7]) } @@ -3615,6 +5050,10 @@ pub unsafe fn vget_low_u8(a: uint8x16_t) -> uint8x8_t { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(test, assert_instr(nop))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_low_u16(a: uint16x8_t) -> uint16x4_t { simd_shuffle4!(a, a, [0, 1, 2, 3]) } @@ -3624,6 +5063,10 @@ pub unsafe fn vget_low_u16(a: uint16x8_t) -> uint16x4_t { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(test, assert_instr(nop))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_low_u32(a: uint32x4_t) -> uint32x2_t { simd_shuffle2!(a, a, [0, 1]) } @@ -3633,6 +5076,10 @@ pub unsafe fn vget_low_u32(a: uint32x4_t) -> uint32x2_t { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(test, assert_instr(nop))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_low_u64(a: uint64x2_t) -> uint64x1_t { uint64x1_t(simd_extract(a, 0)) } @@ -3642,6 +5089,10 @@ pub unsafe fn vget_low_u64(a: uint64x2_t) -> uint64x1_t { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(test, assert_instr(nop))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_low_p8(a: poly8x16_t) -> poly8x8_t { simd_shuffle8!(a, a, [0, 1, 2, 3, 4, 5, 6, 7]) } @@ -3651,6 +5102,10 @@ pub unsafe fn vget_low_p8(a: poly8x16_t) -> poly8x8_t { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(test, assert_instr(nop))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_low_p16(a: poly16x8_t) -> poly16x4_t { simd_shuffle4!(a, a, [0, 1, 2, 3]) } @@ -3660,6 +5115,10 @@ pub unsafe fn vget_low_p16(a: poly16x8_t) -> poly16x4_t { #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(test, assert_instr(nop))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vget_low_f32(a: float32x4_t) -> float32x2_t { simd_shuffle2!(a, a, [0, 1]) } @@ -3670,6 +5129,10 @@ pub unsafe fn vget_low_f32(a: float32x4_t) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vdupq_n_s8(value: i8) -> int8x16_t { int8x16_t( value, value, value, value, value, value, value, value, value, value, value, value, value, @@ -3683,6 +5146,10 @@ pub unsafe fn vdupq_n_s8(value: i8) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vdupq_n_s16(value: i16) -> int16x8_t { int16x8_t(value, value, value, value, value, value, value, value) } @@ -3693,6 +5160,10 @@ pub unsafe fn vdupq_n_s16(value: i16) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vdupq_n_s32(value: i32) -> int32x4_t { int32x4_t(value, value, value, value) } @@ -3703,6 +5174,10 @@ pub unsafe fn vdupq_n_s32(value: i32) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vdupq_n_s64(value: i64) -> int64x2_t { int64x2_t(value, value) } @@ -3713,6 +5188,10 @@ pub unsafe fn vdupq_n_s64(value: i64) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vdupq_n_u8(value: u8) -> uint8x16_t { uint8x16_t( value, value, value, value, value, value, value, value, value, value, value, value, value, @@ -3726,6 +5205,10 @@ pub unsafe fn vdupq_n_u8(value: u8) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vdupq_n_u16(value: u16) -> uint16x8_t { uint16x8_t(value, value, value, value, value, value, value, value) } @@ -3736,6 +5219,10 @@ pub unsafe fn vdupq_n_u16(value: u16) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vdupq_n_u32(value: u32) -> uint32x4_t { uint32x4_t(value, value, value, value) } @@ -3746,6 +5233,10 @@ pub unsafe fn vdupq_n_u32(value: u32) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vdupq_n_u64(value: u64) -> uint64x2_t { uint64x2_t(value, value) } @@ -3756,6 +5247,10 @@ pub unsafe fn vdupq_n_u64(value: u64) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vdupq_n_p8(value: p8) -> poly8x16_t { poly8x16_t( value, value, value, value, value, value, value, value, value, value, value, value, value, @@ -3769,6 +5264,10 @@ pub unsafe fn vdupq_n_p8(value: p8) -> poly8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vdupq_n_p16(value: p16) -> poly16x8_t { poly16x8_t(value, value, value, value, value, value, value, value) } @@ -3779,6 +5278,10 @@ pub unsafe fn vdupq_n_p16(value: p16) -> poly16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vdupq_n_f32(value: f32) -> float32x4_t { float32x4_t(value, value, value, value) } @@ -3792,6 +5295,10 @@ pub unsafe fn vdupq_n_f32(value: f32) -> float32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] unsafe fn vdupq_n_f32_vfp4(value: f32) -> float32x4_t { float32x4_t(value, value, value, value) } @@ -3802,6 +5309,10 @@ unsafe fn vdupq_n_f32_vfp4(value: f32) -> float32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vdup_n_s8(value: i8) -> int8x8_t { int8x8_t(value, value, value, value, value, value, value, value) } @@ -3812,6 +5323,10 @@ pub unsafe fn vdup_n_s8(value: i8) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vdup_n_s16(value: i16) -> int16x4_t { int16x4_t(value, value, value, value) } @@ -3822,6 +5337,10 @@ pub unsafe fn vdup_n_s16(value: i16) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vdup_n_s32(value: i32) -> int32x2_t { int32x2_t(value, value) } @@ -3832,6 +5351,10 @@ pub unsafe fn vdup_n_s32(value: i32) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmov))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vdup_n_s64(value: i64) -> int64x1_t { int64x1_t(value) } @@ -3842,6 +5365,10 @@ pub unsafe fn vdup_n_s64(value: i64) -> int64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vdup_n_u8(value: u8) -> uint8x8_t { uint8x8_t(value, value, value, value, value, value, value, value) } @@ -3852,6 +5379,10 @@ pub unsafe fn vdup_n_u8(value: u8) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vdup_n_u16(value: u16) -> uint16x4_t { uint16x4_t(value, value, value, value) } @@ -3862,6 +5393,10 @@ pub unsafe fn vdup_n_u16(value: u16) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vdup_n_u32(value: u32) -> uint32x2_t { uint32x2_t(value, value) } @@ -3872,6 +5407,10 @@ pub unsafe fn vdup_n_u32(value: u32) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmov))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vdup_n_u64(value: u64) -> uint64x1_t { uint64x1_t(value) } @@ -3882,6 +5421,10 @@ pub unsafe fn vdup_n_u64(value: u64) -> uint64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vdup_n_p8(value: p8) -> poly8x8_t { poly8x8_t(value, value, value, value, value, value, value, value) } @@ -3892,6 +5435,10 @@ pub unsafe fn vdup_n_p8(value: p8) -> poly8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vdup_n_p16(value: p16) -> poly16x4_t { poly16x4_t(value, value, value, value) } @@ -3902,6 +5449,10 @@ pub unsafe fn vdup_n_p16(value: p16) -> poly16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vdup_n_f32(value: f32) -> float32x2_t { float32x2_t(value, value) } @@ -3915,6 +5466,10 @@ pub unsafe fn vdup_n_f32(value: f32) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "vfp4"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] unsafe fn vdup_n_f32_vfp4(value: f32) -> float32x2_t { float32x2_t(value, value) } @@ -3925,6 +5480,10 @@ unsafe fn vdup_n_f32_vfp4(value: f32) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vldrq_p128(a: *const p128) -> p128 { *a } @@ -3935,6 +5494,10 @@ pub unsafe fn vldrq_p128(a: *const p128) -> p128 { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(nop))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(nop))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vstrq_p128(a: *mut p128, b: p128) { *a = b; } @@ -3945,6 +5508,10 @@ pub unsafe fn vstrq_p128(a: *mut p128, b: p128) { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmov_n_s8(value: i8) -> int8x8_t { vdup_n_s8(value) } @@ -3955,6 +5522,10 @@ pub unsafe fn vmov_n_s8(value: i8) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmov_n_s16(value: i16) -> int16x4_t { vdup_n_s16(value) } @@ -3965,6 +5536,10 @@ pub unsafe fn vmov_n_s16(value: i16) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmov_n_s32(value: i32) -> int32x2_t { vdup_n_s32(value) } @@ -3975,6 +5550,10 @@ pub unsafe fn vmov_n_s32(value: i32) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmov))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmov_n_s64(value: i64) -> int64x1_t { vdup_n_s64(value) } @@ -3985,6 +5564,10 @@ pub unsafe fn vmov_n_s64(value: i64) -> int64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmov_n_u8(value: u8) -> uint8x8_t { vdup_n_u8(value) } @@ -3995,6 +5578,10 @@ pub unsafe fn vmov_n_u8(value: u8) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmov_n_u16(value: u16) -> uint16x4_t { vdup_n_u16(value) } @@ -4005,6 +5592,10 @@ pub unsafe fn vmov_n_u16(value: u16) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmov_n_u32(value: u32) -> uint32x2_t { vdup_n_u32(value) } @@ -4015,6 +5606,10 @@ pub unsafe fn vmov_n_u32(value: u32) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fmov))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmov_n_u64(value: u64) -> uint64x1_t { vdup_n_u64(value) } @@ -4025,6 +5620,10 @@ pub unsafe fn vmov_n_u64(value: u64) -> uint64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmov_n_p8(value: p8) -> poly8x8_t { vdup_n_p8(value) } @@ -4035,6 +5634,10 @@ pub unsafe fn vmov_n_p8(value: p8) -> poly8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmov_n_p16(value: p16) -> poly16x4_t { vdup_n_p16(value) } @@ -4045,6 +5648,10 @@ pub unsafe fn vmov_n_p16(value: p16) -> poly16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmov_n_f32(value: f32) -> float32x2_t { vdup_n_f32(value) } @@ -4055,6 +5662,10 @@ pub unsafe fn vmov_n_f32(value: f32) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmovq_n_s8(value: i8) -> int8x16_t { vdupq_n_s8(value) } @@ -4065,6 +5676,10 @@ pub unsafe fn vmovq_n_s8(value: i8) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmovq_n_s16(value: i16) -> int16x8_t { vdupq_n_s16(value) } @@ -4075,6 +5690,10 @@ pub unsafe fn vmovq_n_s16(value: i16) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmovq_n_s32(value: i32) -> int32x4_t { vdupq_n_s32(value) } @@ -4085,6 +5704,10 @@ pub unsafe fn vmovq_n_s32(value: i32) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmovq_n_s64(value: i64) -> int64x2_t { vdupq_n_s64(value) } @@ -4095,6 +5718,10 @@ pub unsafe fn vmovq_n_s64(value: i64) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmovq_n_u8(value: u8) -> uint8x16_t { vdupq_n_u8(value) } @@ -4105,6 +5732,10 @@ pub unsafe fn vmovq_n_u8(value: u8) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmovq_n_u16(value: u16) -> uint16x8_t { vdupq_n_u16(value) } @@ -4115,6 +5746,10 @@ pub unsafe fn vmovq_n_u16(value: u16) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmovq_n_u32(value: u32) -> uint32x4_t { vdupq_n_u32(value) } @@ -4125,6 +5760,10 @@ pub unsafe fn vmovq_n_u32(value: u32) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vmov"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmovq_n_u64(value: u64) -> uint64x2_t { vdupq_n_u64(value) } @@ -4135,6 +5774,10 @@ pub unsafe fn vmovq_n_u64(value: u64) -> uint64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmovq_n_p8(value: p8) -> poly8x16_t { vdupq_n_p8(value) } @@ -4145,6 +5788,10 @@ pub unsafe fn vmovq_n_p8(value: p8) -> poly8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmovq_n_p16(value: p16) -> poly16x8_t { vdupq_n_p16(value) } @@ -4155,6 +5802,10 @@ pub unsafe fn vmovq_n_p16(value: p16) -> poly16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vdup.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(dup))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vmovq_n_f32(value: f32) -> float32x4_t { vdupq_n_f32(value) } @@ -4166,10 +5817,12 @@ pub unsafe fn vmovq_n_f32(value: f32) -> float32x4_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("nop", N = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr("nop", N = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vext_s64(a: int64x1_t, _b: int64x1_t) -> int64x1_t { - if N != 0 { - unreachable_unchecked() - } + static_assert!(N : i32 where N == 0); a } @@ -4180,10 +5833,12 @@ pub unsafe fn vext_s64(a: int64x1_t, _b: int64x1_t) -> int64x1_t { #[cfg_attr(all(test, target_arch = "arm"), assert_instr("nop", N = 0))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr("nop", N = 0))] #[rustc_legacy_const_generics(2)] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vext_u64(a: uint64x1_t, _b: uint64x1_t) -> uint64x1_t { - if N != 0 { - unreachable_unchecked() - } + static_assert!(N : i32 where N == 0); a } @@ -4193,6 +5848,10 @@ pub unsafe fn vext_u64(a: uint64x1_t, _b: uint64x1_t) -> uint64x1_ #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcnt))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cnt))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vcnt_s8(a: int8x8_t) -> int8x8_t { vcnt_s8_(a) } @@ -4202,6 +5861,10 @@ pub unsafe fn vcnt_s8(a: int8x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcnt))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cnt))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vcntq_s8(a: int8x16_t) -> int8x16_t { vcntq_s8_(a) } @@ -4211,6 +5874,10 @@ pub unsafe fn vcntq_s8(a: int8x16_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcnt))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cnt))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vcnt_u8(a: uint8x8_t) -> uint8x8_t { transmute(vcnt_s8_(transmute(a))) } @@ -4220,6 +5887,10 @@ pub unsafe fn vcnt_u8(a: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcnt))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cnt))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vcntq_u8(a: uint8x16_t) -> uint8x16_t { transmute(vcntq_s8_(transmute(a))) } @@ -4229,6 +5900,10 @@ pub unsafe fn vcntq_u8(a: uint8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcnt))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cnt))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vcnt_p8(a: poly8x8_t) -> poly8x8_t { transmute(vcnt_s8_(transmute(a))) } @@ -4238,6 +5913,10 @@ pub unsafe fn vcnt_p8(a: poly8x8_t) -> poly8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vcnt))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(cnt))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vcntq_p8(a: poly8x16_t) -> poly8x16_t { transmute(vcntq_s8_(transmute(a))) } @@ -4248,6 +5927,10 @@ pub unsafe fn vcntq_p8(a: poly8x16_t) -> poly8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev16.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev16))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev16_s8(a: int8x8_t) -> int8x8_t { simd_shuffle8!(a, a, [1, 0, 3, 2, 5, 4, 7, 6]) } @@ -4258,6 +5941,10 @@ pub unsafe fn vrev16_s8(a: int8x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev16.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev16))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev16q_s8(a: int8x16_t) -> int8x16_t { simd_shuffle16!(a, a, [1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14]) } @@ -4268,6 +5955,10 @@ pub unsafe fn vrev16q_s8(a: int8x16_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev16.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev16))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev16_u8(a: uint8x8_t) -> uint8x8_t { simd_shuffle8!(a, a, [1, 0, 3, 2, 5, 4, 7, 6]) } @@ -4278,6 +5969,10 @@ pub unsafe fn vrev16_u8(a: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev16.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev16))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev16q_u8(a: uint8x16_t) -> uint8x16_t { simd_shuffle16!(a, a, [1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14]) } @@ -4288,6 +5983,10 @@ pub unsafe fn vrev16q_u8(a: uint8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev16.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev16))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev16_p8(a: poly8x8_t) -> poly8x8_t { simd_shuffle8!(a, a, [1, 0, 3, 2, 5, 4, 7, 6]) } @@ -4298,6 +5997,10 @@ pub unsafe fn vrev16_p8(a: poly8x8_t) -> poly8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev16.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev16))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev16q_p8(a: poly8x16_t) -> poly8x16_t { simd_shuffle16!(a, a, [1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14]) } @@ -4308,6 +6011,10 @@ pub unsafe fn vrev16q_p8(a: poly8x16_t) -> poly8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev32.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev32))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev32_s8(a: int8x8_t) -> int8x8_t { simd_shuffle8!(a, a, [3, 2, 1, 0, 7, 6, 5, 4]) } @@ -4318,6 +6025,10 @@ pub unsafe fn vrev32_s8(a: int8x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev32.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev32))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev32q_s8(a: int8x16_t) -> int8x16_t { simd_shuffle16!(a, a, [3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12]) } @@ -4328,6 +6039,10 @@ pub unsafe fn vrev32q_s8(a: int8x16_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev32.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev32))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev32_u8(a: uint8x8_t) -> uint8x8_t { simd_shuffle8!(a, a, [3, 2, 1, 0, 7, 6, 5, 4]) } @@ -4338,6 +6053,10 @@ pub unsafe fn vrev32_u8(a: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev32.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev32))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev32q_u8(a: uint8x16_t) -> uint8x16_t { simd_shuffle16!(a, a, [3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12]) } @@ -4348,6 +6067,10 @@ pub unsafe fn vrev32q_u8(a: uint8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev32.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev32))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev32_s16(a: int16x4_t) -> int16x4_t { simd_shuffle4!(a, a, [1, 0, 3, 2]) } @@ -4358,6 +6081,10 @@ pub unsafe fn vrev32_s16(a: int16x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev32.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev32))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev32q_s16(a: int16x8_t) -> int16x8_t { simd_shuffle8!(a, a, [1, 0, 3, 2, 5, 4, 7, 6]) } @@ -4368,6 +6095,10 @@ pub unsafe fn vrev32q_s16(a: int16x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev32.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev32))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev32_p16(a: poly16x4_t) -> poly16x4_t { simd_shuffle4!(a, a, [1, 0, 3, 2]) } @@ -4378,6 +6109,10 @@ pub unsafe fn vrev32_p16(a: poly16x4_t) -> poly16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev32.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev32))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev32q_p16(a: poly16x8_t) -> poly16x8_t { simd_shuffle8!(a, a, [1, 0, 3, 2, 5, 4, 7, 6]) } @@ -4388,6 +6123,10 @@ pub unsafe fn vrev32q_p16(a: poly16x8_t) -> poly16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev32.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev32))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev32_u16(a: uint16x4_t) -> uint16x4_t { simd_shuffle4!(a, a, [1, 0, 3, 2]) } @@ -4398,6 +6137,10 @@ pub unsafe fn vrev32_u16(a: uint16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev32.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev32))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev32q_u16(a: uint16x8_t) -> uint16x8_t { simd_shuffle8!(a, a, [1, 0, 3, 2, 5, 4, 7, 6]) } @@ -4408,6 +6151,10 @@ pub unsafe fn vrev32q_u16(a: uint16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev32.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev32))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev32_p8(a: poly8x8_t) -> poly8x8_t { simd_shuffle8!(a, a, [3, 2, 1, 0, 7, 6, 5, 4]) } @@ -4418,6 +6165,10 @@ pub unsafe fn vrev32_p8(a: poly8x8_t) -> poly8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev32.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev32))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev32q_p8(a: poly8x16_t) -> poly8x16_t { simd_shuffle16!(a, a, [3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12]) } @@ -4428,6 +6179,10 @@ pub unsafe fn vrev32q_p8(a: poly8x16_t) -> poly8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev64.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev64))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev64_s8(a: int8x8_t) -> int8x8_t { simd_shuffle8!(a, a, [7, 6, 5, 4, 3, 2, 1, 0]) } @@ -4438,6 +6193,10 @@ pub unsafe fn vrev64_s8(a: int8x8_t) -> int8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev64.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev64))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev64q_s8(a: int8x16_t) -> int8x16_t { simd_shuffle16!(a, a, [7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8]) } @@ -4448,6 +6207,10 @@ pub unsafe fn vrev64q_s8(a: int8x16_t) -> int8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev64.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev64))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev64_s16(a: int16x4_t) -> int16x4_t { simd_shuffle4!(a, a, [3, 2, 1, 0]) } @@ -4458,6 +6221,10 @@ pub unsafe fn vrev64_s16(a: int16x4_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev64.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev64))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev64q_s16(a: int16x8_t) -> int16x8_t { simd_shuffle8!(a, a, [3, 2, 1, 0, 7, 6, 5, 4]) } @@ -4468,6 +6235,10 @@ pub unsafe fn vrev64q_s16(a: int16x8_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev64.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev64))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev64_s32(a: int32x2_t) -> int32x2_t { simd_shuffle2!(a, a, [1, 0]) } @@ -4478,6 +6249,10 @@ pub unsafe fn vrev64_s32(a: int32x2_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev64.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev64))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev64q_s32(a: int32x4_t) -> int32x4_t { simd_shuffle4!(a, a, [1, 0, 3, 2]) } @@ -4488,6 +6263,10 @@ pub unsafe fn vrev64q_s32(a: int32x4_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev64.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev64))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev64_u8(a: uint8x8_t) -> uint8x8_t { simd_shuffle8!(a, a, [7, 6, 5, 4, 3, 2, 1, 0]) } @@ -4498,6 +6277,10 @@ pub unsafe fn vrev64_u8(a: uint8x8_t) -> uint8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev64.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev64))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev64q_u8(a: uint8x16_t) -> uint8x16_t { simd_shuffle16!(a, a, [7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8]) } @@ -4508,6 +6291,10 @@ pub unsafe fn vrev64q_u8(a: uint8x16_t) -> uint8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev64.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev64))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev64_u16(a: uint16x4_t) -> uint16x4_t { simd_shuffle4!(a, a, [3, 2, 1, 0]) } @@ -4518,6 +6305,10 @@ pub unsafe fn vrev64_u16(a: uint16x4_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev64.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev64))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev64q_u16(a: uint16x8_t) -> uint16x8_t { simd_shuffle8!(a, a, [3, 2, 1, 0, 7, 6, 5, 4]) } @@ -4528,6 +6319,10 @@ pub unsafe fn vrev64q_u16(a: uint16x8_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev64.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev64))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev64_u32(a: uint32x2_t) -> uint32x2_t { simd_shuffle2!(a, a, [1, 0]) } @@ -4538,6 +6333,10 @@ pub unsafe fn vrev64_u32(a: uint32x2_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev64.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev64))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev64q_u32(a: uint32x4_t) -> uint32x4_t { simd_shuffle4!(a, a, [1, 0, 3, 2]) } @@ -4548,6 +6347,10 @@ pub unsafe fn vrev64q_u32(a: uint32x4_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev64.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev64))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev64_f32(a: float32x2_t) -> float32x2_t { simd_shuffle2!(a, a, [1, 0]) } @@ -4558,6 +6361,10 @@ pub unsafe fn vrev64_f32(a: float32x2_t) -> float32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev64.32"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev64))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev64q_f32(a: float32x4_t) -> float32x4_t { simd_shuffle4!(a, a, [1, 0, 3, 2]) } @@ -4568,6 +6375,10 @@ pub unsafe fn vrev64q_f32(a: float32x4_t) -> float32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev64.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev64))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev64_p8(a: poly8x8_t) -> poly8x8_t { simd_shuffle8!(a, a, [7, 6, 5, 4, 3, 2, 1, 0]) } @@ -4578,6 +6389,10 @@ pub unsafe fn vrev64_p8(a: poly8x8_t) -> poly8x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev64.8"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev64))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev64q_p8(a: poly8x16_t) -> poly8x16_t { simd_shuffle16!(a, a, [7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8]) } @@ -4588,6 +6403,10 @@ pub unsafe fn vrev64q_p8(a: poly8x16_t) -> poly8x16_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev64.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev64))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev64_p16(a: poly16x4_t) -> poly16x4_t { simd_shuffle4!(a, a, [3, 2, 1, 0]) } @@ -4598,6 +6417,10 @@ pub unsafe fn vrev64_p16(a: poly16x4_t) -> poly16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr("vrev64.16"))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(rev64))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vrev64q_p16(a: poly16x8_t) -> poly16x8_t { simd_shuffle8!(a, a, [3, 2, 1, 0, 7, 6, 5, 4]) } @@ -4608,6 +6431,10 @@ pub unsafe fn vrev64q_p16(a: poly16x8_t) -> poly16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpadal.s8))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sadalp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpadal_s8(a: int16x4_t, b: int8x8_t) -> int16x4_t { #[cfg(target_arch = "arm")] { @@ -4625,6 +6452,10 @@ pub unsafe fn vpadal_s8(a: int16x4_t, b: int8x8_t) -> int16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpadal.s16))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sadalp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpadal_s16(a: int32x2_t, b: int16x4_t) -> int32x2_t { #[cfg(target_arch = "arm")] { @@ -4642,6 +6473,10 @@ pub unsafe fn vpadal_s16(a: int32x2_t, b: int16x4_t) -> int32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpadal.s32))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sadalp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpadal_s32(a: int64x1_t, b: int32x2_t) -> int64x1_t { #[cfg(target_arch = "arm")] { @@ -4659,6 +6494,10 @@ pub unsafe fn vpadal_s32(a: int64x1_t, b: int32x2_t) -> int64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpadal.s8))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sadalp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpadalq_s8(a: int16x8_t, b: int8x16_t) -> int16x8_t { #[cfg(target_arch = "arm")] { @@ -4676,6 +6515,10 @@ pub unsafe fn vpadalq_s8(a: int16x8_t, b: int8x16_t) -> int16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpadal.s16))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sadalp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpadalq_s16(a: int32x4_t, b: int16x8_t) -> int32x4_t { #[cfg(target_arch = "arm")] { @@ -4693,6 +6536,10 @@ pub unsafe fn vpadalq_s16(a: int32x4_t, b: int16x8_t) -> int32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpadal.s32))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(sadalp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpadalq_s32(a: int64x2_t, b: int32x4_t) -> int64x2_t { #[cfg(target_arch = "arm")] { @@ -4710,6 +6557,10 @@ pub unsafe fn vpadalq_s32(a: int64x2_t, b: int32x4_t) -> int64x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpadal.u8))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uadalp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpadal_u8(a: uint16x4_t, b: uint8x8_t) -> uint16x4_t { #[cfg(target_arch = "arm")] { @@ -4727,6 +6578,10 @@ pub unsafe fn vpadal_u8(a: uint16x4_t, b: uint8x8_t) -> uint16x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpadal.u16))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uadalp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpadal_u16(a: uint32x2_t, b: uint16x4_t) -> uint32x2_t { #[cfg(target_arch = "arm")] { @@ -4744,6 +6599,10 @@ pub unsafe fn vpadal_u16(a: uint32x2_t, b: uint16x4_t) -> uint32x2_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpadal.u32))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uadalp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpadal_u32(a: uint64x1_t, b: uint32x2_t) -> uint64x1_t { #[cfg(target_arch = "arm")] { @@ -4761,6 +6620,10 @@ pub unsafe fn vpadal_u32(a: uint64x1_t, b: uint32x2_t) -> uint64x1_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpadal.u8))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uadalp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpadalq_u8(a: uint16x8_t, b: uint8x16_t) -> uint16x8_t { #[cfg(target_arch = "arm")] { @@ -4778,6 +6641,10 @@ pub unsafe fn vpadalq_u8(a: uint16x8_t, b: uint8x16_t) -> uint16x8_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpadal.u16))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uadalp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpadalq_u16(a: uint32x4_t, b: uint16x8_t) -> uint32x4_t { #[cfg(target_arch = "arm")] { @@ -4795,6 +6662,10 @@ pub unsafe fn vpadalq_u16(a: uint32x4_t, b: uint16x8_t) -> uint32x4_t { #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr(vpadal.u32))] #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(uadalp))] +#[cfg_attr( + target_arch = "aarch64", + stable(feature = "neon_intrinsics", since = "1.59.0") +)] pub unsafe fn vpadalq_u32(a: uint64x2_t, b: uint32x4_t) -> uint64x2_t { #[cfg(target_arch = "arm")] { diff --git a/library/stdarch/crates/core_arch/src/arm_shared/registers/mod.rs b/library/stdarch/crates/core_arch/src/arm_shared/registers/mod.rs index 71e94ee5cb..621efe2f57 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/registers/mod.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/registers/mod.rs @@ -4,7 +4,7 @@ macro_rules! rsr { impl super::super::sealed::Rsr for $R { unsafe fn __rsr(&self) -> u32 { let r: u32; - asm!(concat!("mrs {},", stringify!($R)), out(reg) r, options(nomem, nostack)); + crate::arch::asm!(concat!("mrs {},", stringify!($R)), out(reg) r, options(nomem, nostack)); r } } @@ -17,7 +17,7 @@ macro_rules! rsrp { impl super::super::sealed::Rsrp for $R { unsafe fn __rsrp(&self) -> *const u8 { let r: *const u8; - asm!(concat!("mrs {},", stringify!($R)), out(reg) r, options(nomem, nostack)); + crate::arch::asm!(concat!("mrs {},", stringify!($R)), out(reg) r, options(nomem, nostack)); r } } @@ -29,7 +29,7 @@ macro_rules! wsr { ($R:ident) => { impl super::super::sealed::Wsr for $R { unsafe fn __wsr(&self, value: u32) { - asm!(concat!("msr ", stringify!($R), ", {}"), in(reg) value, options(nomem, nostack)); + crate::arch::asm!(concat!("msr ", stringify!($R), ", {}"), in(reg) value, options(nomem, nostack)); } } }; @@ -40,7 +40,7 @@ macro_rules! wsrp { ($R:ident) => { impl super::super::sealed::Wsrp for $R { unsafe fn __wsrp(&self, value: *const u8) { - asm!(concat!("msr ", stringify!($R), ", {}"), in(reg) value, options(nomem, nostack)); + crate::arch::asm!(concat!("msr ", stringify!($R), ", {}"), in(reg) value, options(nomem, nostack)); } } }; diff --git a/library/stdarch/crates/core_arch/src/core_arch_docs.md b/library/stdarch/crates/core_arch/src/core_arch_docs.md index 96634f200f..58b7eda9a8 100644 --- a/library/stdarch/crates/core_arch/src/core_arch_docs.md +++ b/library/stdarch/crates/core_arch/src/core_arch_docs.md @@ -185,6 +185,8 @@ others at: * [`x86_64`] * [`arm`] * [`aarch64`] +* [`riscv32`] +* [`riscv64`] * [`mips`] * [`mips64`] * [`powerpc`] @@ -196,6 +198,8 @@ others at: [`x86_64`]: x86_64/index.html [`arm`]: arm/index.html [`aarch64`]: aarch64/index.html +[`riscv32`]: riscv32/index.html +[`riscv64`]: riscv64/index.html [`mips`]: mips/index.html [`mips64`]: mips64/index.html [`powerpc`]: powerpc/index.html diff --git a/library/stdarch/crates/core_arch/src/lib.rs b/library/stdarch/crates/core_arch/src/lib.rs index d43192b399..c73e309e72 100644 --- a/library/stdarch/crates/core_arch/src/lib.rs +++ b/library/stdarch/crates/core_arch/src/lib.rs @@ -4,7 +4,6 @@ #![allow(unused_features)] #![deny(rust_2018_idioms)] #![feature( - asm, custom_inner_attributes, link_llvm_intrinsics, platform_intrinsics, @@ -68,7 +67,10 @@ extern crate std_detect; #[path = "mod.rs"] mod core_arch; -pub use self::core_arch::arch; +pub mod arch { + pub use crate::core_arch::arch::*; + pub use core::arch::asm; +} #[allow(unused_imports)] use core::{convert, ffi, hint, intrinsics, marker, mem, ops, ptr, sync}; diff --git a/library/stdarch/crates/core_arch/src/mod.rs b/library/stdarch/crates/core_arch/src/mod.rs index 754336c7f6..20751eeec5 100644 --- a/library/stdarch/crates/core_arch/src/mod.rs +++ b/library/stdarch/crates/core_arch/src/mod.rs @@ -50,11 +50,36 @@ pub mod arch { /// See the [module documentation](../index.html) for more details. #[cfg(any(target_arch = "aarch64", doc))] #[doc(cfg(target_arch = "aarch64"))] - #[unstable(feature = "stdsimd", issue = "27731")] + #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub mod aarch64 { + #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub use crate::core_arch::aarch64::*; } + /// Platform-specific intrinsics for the `riscv32` platform. + /// + /// See the [module documentation](../index.html) for more details. + #[cfg(any(target_arch = "riscv32", doc))] + #[doc(cfg(any(target_arch = "riscv32")))] + #[unstable(feature = "stdsimd", issue = "27731")] + pub mod riscv32 { + pub use crate::core_arch::riscv_shared::*; + } + + /// Platform-specific intrinsics for the `riscv64` platform. + /// + /// See the [module documentation](../index.html) for more details. + #[cfg(any(target_arch = "riscv64", doc))] + #[doc(cfg(any(target_arch = "riscv64")))] + #[unstable(feature = "stdsimd", issue = "27731")] + pub mod riscv64 { + pub use crate::core_arch::riscv64::*; + // RISC-V RV64 supports all RV32 instructions as well in current specifications (2022-01-05). + // Module `riscv_shared` includes instructions available under all RISC-V platforms, + // i.e. RISC-V RV32 instructions. + pub use crate::core_arch::riscv_shared::*; + } + /// Platform-specific intrinsics for the `wasm32` platform. /// /// This module provides intrinsics specific to the WebAssembly @@ -251,6 +276,14 @@ mod aarch64; #[doc(cfg(any(target_arch = "arm")))] mod arm; +#[cfg(any(target_arch = "riscv32", target_arch = "riscv64", doc))] +#[doc(cfg(any(target_arch = "riscv32", target_arch = "riscv64")))] +mod riscv_shared; + +#[cfg(any(target_arch = "riscv64", doc))] +#[doc(cfg(any(target_arch = "riscv64")))] +mod riscv64; + #[cfg(any(target_family = "wasm", doc))] #[doc(cfg(target_family = "wasm"))] mod wasm32; diff --git a/library/stdarch/crates/core_arch/src/riscv64/mod.rs b/library/stdarch/crates/core_arch/src/riscv64/mod.rs new file mode 100644 index 0000000000..24aae78325 --- /dev/null +++ b/library/stdarch/crates/core_arch/src/riscv64/mod.rs @@ -0,0 +1,49 @@ +//! RISC-V RV64 specific intrinsics +use crate::arch::asm; + +/// Loads virtual machine memory by unsigned word integer +/// +/// This instruction performs an explicit memory access as though `V=1`; +/// i.e., with the address translation and protection, and the endianness, that apply to memory +/// accesses in either VS-mode or VU-mode. +/// +/// This operation is not available under RV32 base instruction set. +/// +/// This function is unsafe for it accesses the virtual supervisor or user via a `HLV.WU` +/// instruction which is effectively an unreference to any memory address. +#[inline] +pub unsafe fn hlv_wu(src: *const u32) -> u32 { + let value: u32; + asm!(".insn i 0x73, 0x4, {}, {}, 0x681", out(reg) value, in(reg) src, options(readonly, nostack)); + value +} + +/// Loads virtual machine memory by unsigned double integer +/// +/// This instruction performs an explicit memory access as though `V=1`; +/// i.e., with the address translation and protection, and the endianness, that apply to memory +/// accesses in either VS-mode or VU-mode. +/// +/// This operation is not available under RV32 base instruction set. +/// +/// This function is unsafe for it accesses the virtual supervisor or user via a `HLV.D` +/// instruction which is effectively an unreference to any memory address. +#[inline] +pub unsafe fn hlv_d(src: *const i64) -> i64 { + let value: i64; + asm!(".insn i 0x73, 0x4, {}, {}, 0x6C0", out(reg) value, in(reg) src, options(readonly, nostack)); + value +} + +/// Stores virtual machine memory by double integer +/// +/// This instruction performs an explicit memory access as though `V=1`; +/// i.e., with the address translation and protection, and the endianness, that apply to memory +/// accesses in either VS-mode or VU-mode. +/// +/// This function is unsafe for it accesses the virtual supervisor or user via a `HSV.D` +/// instruction which is effectively an unreference to any memory address. +#[inline] +pub unsafe fn hsv_d(dst: *mut i64, src: i64) { + asm!(".insn r 0x73, 0x4, 0x37, x0, {}, {}", in(reg) dst, in(reg) src, options(nostack)); +} diff --git a/library/stdarch/crates/core_arch/src/riscv_shared/mod.rs b/library/stdarch/crates/core_arch/src/riscv_shared/mod.rs new file mode 100644 index 0000000000..a2c9cb2436 --- /dev/null +++ b/library/stdarch/crates/core_arch/src/riscv_shared/mod.rs @@ -0,0 +1,481 @@ +//! Shared RISC-V intrinsics + +use crate::arch::asm; + +/// Generates the `PAUSE` instruction +/// +/// The PAUSE instruction is a HINT that indicates the current hart's rate of instruction retirement +/// should be temporarily reduced or paused. The duration of its effect must be bounded and may be zero. +#[inline] +pub fn pause() { + unsafe { asm!(".insn i 0x0F, 0, x0, x0, 0x010", options(nomem, nostack)) } +} + +/// Generates the `NOP` instruction +/// +/// The NOP instruction does not change any architecturally visible state, except for +/// advancing the `pc` and incrementing any applicable performance counters. +#[inline] +pub fn nop() { + unsafe { asm!("nop", options(nomem, nostack)) } +} + +/// Generates the `WFI` instruction +/// +/// The WFI instruction provides a hint to the implementation that the current hart can be stalled +/// until an interrupt might need servicing. This instruction is a hint, +/// and a legal implementation is to simply implement WFI as a NOP. +#[inline] +pub unsafe fn wfi() { + asm!("wfi", options(nomem, nostack)) +} + +/// Generates the `FENCE.I` instruction +/// +/// A FENCE.I instruction ensures that a subsequent instruction fetch on a RISC-V hart will see +/// any previous data stores already visible to the same RISC-V hart. +/// +/// FENCE.I does not ensure that other RISC-V harts' instruction fetches will observe the +/// local hart's stores in a multiprocessor system. +#[inline] +pub unsafe fn fence_i() { + asm!("fence.i", options(nostack)) +} + +/// Supervisor memory management fence for given virtual address and address space +/// +/// The fence orders only reads and writes made to leaf page table entries corresponding to +/// the virtual address in parameter `vaddr`, for the address space identified by integer parameter +/// `asid`. Accesses to global mappings are not ordered. The fence also invalidates all +/// address-translation cache entries that contain leaf page table entries corresponding to the +/// virtual address in parameter `vaddr` and that match the address space identified by integer +/// parameter `asid`, except for entries containing global mappings. +#[inline] +pub unsafe fn sfence_vma(vaddr: usize, asid: usize) { + asm!("sfence.vma {}, {}", in(reg) vaddr, in(reg) asid, options(nostack)) +} + +/// Supervisor memory management fence for given virtual address +/// +/// The fence orders only reads and writes made to leaf page table entries corresponding to +/// the virtual address in parameter `vaddr`, for all address spaces. +/// The fence also invalidates all address-translation cache entries that contain leaf page +/// table entries corresponding to the virtual address in parameter `vaddr`, for all address spaces. +#[inline] +pub unsafe fn sfence_vma_vaddr(vaddr: usize) { + asm!("sfence.vma {}, x0", in(reg) vaddr, options(nostack)) +} + +/// Supervisor memory management fence for given address space +/// +/// The fence orders all reads and writes made to any level of the page tables, +/// but only for the address space identified by integer parameter `asid`. +/// +/// Accesses to global mappings are not ordered. The fence also invalidates all +/// address-translation cache entries matching the address space identified by integer +/// parameter `asid`, except for entries containing global mappings. +#[inline] +pub unsafe fn sfence_vma_asid(asid: usize) { + asm!("sfence.vma x0, {}", in(reg) asid, options(nostack)) +} + +/// Supervisor memory management fence for all address spaces and virtual addresses +/// +/// The fence orders all reads and writes made to any level of the page +/// tables, for all address spaces. The fence also invalidates all address-translation cache entries, +/// for all address spaces. +#[inline] +pub unsafe fn sfence_vma_all() { + asm!("sfence.vma", options(nostack)) +} + +/// Invalidate supervisor translation cache for given virtual address and address space +/// +/// This instruction invalidates any address-translation cache entries that an +/// `SFENCE.VMA` instruction with the same values of `vaddr` and `asid` would invalidate. +#[inline] +pub unsafe fn sinval_vma(vaddr: usize, asid: usize) { + // asm!("sinval.vma {}, {}", in(reg) vaddr, in(reg) asid, options(nostack)) + asm!(".insn r 0x73, 0, 0x0B, x0, {}, {}", in(reg) vaddr, in(reg) asid, options(nostack)) +} + +/// Invalidate supervisor translation cache for given virtual address +/// +/// This instruction invalidates any address-translation cache entries that an +/// `SFENCE.VMA` instruction with the same values of `vaddr` and `asid` would invalidate. +#[inline] +pub unsafe fn sinval_vma_vaddr(vaddr: usize) { + asm!(".insn r 0x73, 0, 0x0B, x0, {}, x0", in(reg) vaddr, options(nostack)) +} + +/// Invalidate supervisor translation cache for given address space +/// +/// This instruction invalidates any address-translation cache entries that an +/// `SFENCE.VMA` instruction with the same values of `vaddr` and `asid` would invalidate. +#[inline] +pub unsafe fn sinval_vma_asid(asid: usize) { + asm!(".insn r 0x73, 0, 0x0B, x0, x0, {}", in(reg) asid, options(nostack)) +} + +/// Invalidate supervisor translation cache for all address spaces and virtual addresses +/// +/// This instruction invalidates any address-translation cache entries that an +/// `SFENCE.VMA` instruction with the same values of `vaddr` and `asid` would invalidate. +#[inline] +pub unsafe fn sinval_vma_all() { + asm!(".insn r 0x73, 0, 0x0B, x0, x0, x0", options(nostack)) +} + +/// Generates the `SFENCE.W.INVAL` instruction +/// +/// This instruction guarantees that any previous stores already visible to the current RISC-V hart +/// are ordered before subsequent `SINVAL.VMA` instructions executed by the same hart. +#[inline] +pub unsafe fn sfence_w_inval() { + // asm!("sfence.w.inval", options(nostack)) + asm!(".insn i 0x73, 0, x0, x0, 0x180", options(nostack)) +} + +/// Generates the `SFENCE.INVAL.IR` instruction +/// +/// This instruction guarantees that any previous SINVAL.VMA instructions executed by the current hart +/// are ordered before subsequent implicit references by that hart to the memory-management data structures. +#[inline] +pub unsafe fn sfence_inval_ir() { + // asm!("sfence.inval.ir", options(nostack)) + asm!(".insn i 0x73, 0, x0, x0, 0x181", options(nostack)) +} + +/// Loads virtual machine memory by signed byte integer +/// +/// This instruction performs an explicit memory access as though `V=1`; +/// i.e., with the address translation and protection, and the endianness, that apply to memory +/// accesses in either VS-mode or VU-mode. +/// +/// This function is unsafe for it accesses the virtual supervisor or user via a `HLV.B` +/// instruction which is effectively an unreference to any memory address. +#[inline] +pub unsafe fn hlv_b(src: *const i8) -> i8 { + let value: i8; + asm!(".insn i 0x73, 0x4, {}, {}, 0x600", out(reg) value, in(reg) src, options(readonly, nostack)); + value +} + +/// Loads virtual machine memory by unsigned byte integer +/// +/// This instruction performs an explicit memory access as though `V=1`; +/// i.e., with the address translation and protection, and the endianness, that apply to memory +/// accesses in either VS-mode or VU-mode. +/// +/// This function is unsafe for it accesses the virtual supervisor or user via a `HLV.BU` +/// instruction which is effectively an unreference to any memory address. +#[inline] +pub unsafe fn hlv_bu(src: *const u8) -> u8 { + let value: u8; + asm!(".insn i 0x73, 0x4, {}, {}, 0x601", out(reg) value, in(reg) src, options(readonly, nostack)); + value +} + +/// Loads virtual machine memory by signed half integer +/// +/// This instruction performs an explicit memory access as though `V=1`; +/// i.e., with the address translation and protection, and the endianness, that apply to memory +/// accesses in either VS-mode or VU-mode. +/// +/// This function is unsafe for it accesses the virtual supervisor or user via a `HLV.H` +/// instruction which is effectively an unreference to any memory address. +#[inline] +pub unsafe fn hlv_h(src: *const i16) -> i16 { + let value: i16; + asm!(".insn i 0x73, 0x4, {}, {}, 0x640", out(reg) value, in(reg) src, options(readonly, nostack)); + value +} + +/// Loads virtual machine memory by unsigned half integer +/// +/// This instruction performs an explicit memory access as though `V=1`; +/// i.e., with the address translation and protection, and the endianness, that apply to memory +/// accesses in either VS-mode or VU-mode. +/// +/// This function is unsafe for it accesses the virtual supervisor or user via a `HLV.HU` +/// instruction which is effectively an unreference to any memory address. +#[inline] +pub unsafe fn hlv_hu(src: *const u16) -> u16 { + let value: u16; + asm!(".insn i 0x73, 0x4, {}, {}, 0x641", out(reg) value, in(reg) src, options(readonly, nostack)); + value +} + +/// Accesses virtual machine instruction by unsigned half integer +/// +/// This instruction performs an explicit memory access as though `V=1`; +/// the memory being read must be executable in both stages of address translation, +/// but read permission is not required. +/// +/// This function is unsafe for it accesses the virtual supervisor or user via a `HLVX.HU` +/// instruction which is effectively an unreference to any memory address. +#[inline] +pub unsafe fn hlvx_hu(src: *const u16) -> u16 { + let insn: u16; + asm!(".insn i 0x73, 0x4, {}, {}, 0x643", out(reg) insn, in(reg) src, options(readonly, nostack)); + insn +} + +/// Loads virtual machine memory by signed word integer +/// +/// This instruction performs an explicit memory access as though `V=1`; +/// i.e., with the address translation and protection, and the endianness, that apply to memory +/// accesses in either VS-mode or VU-mode. +/// +/// This function is unsafe for it accesses the virtual supervisor or user via a `HLV.W` +/// instruction which is effectively an unreference to any memory address. +#[inline] +pub unsafe fn hlv_w(src: *const i32) -> i32 { + let value: i32; + asm!(".insn i 0x73, 0x4, {}, {}, 0x680", out(reg) value, in(reg) src, options(readonly, nostack)); + value +} + +/// Accesses virtual machine instruction by unsigned word integer +/// +/// This instruction performs an explicit memory access as though `V=1`; +/// the memory being read must be executable in both stages of address translation, +/// but read permission is not required. +/// +/// This function is unsafe for it accesses the virtual supervisor or user via a `HLVX.WU` +/// instruction which is effectively an unreference to any memory address. +#[inline] +pub unsafe fn hlvx_wu(src: *const u32) -> u32 { + let insn: u32; + asm!(".insn i 0x73, 0x4, {}, {}, 0x683", out(reg) insn, in(reg) src, options(readonly, nostack)); + insn +} + +/// Stores virtual machine memory by byte integer +/// +/// This instruction performs an explicit memory access as though `V=1`; +/// i.e., with the address translation and protection, and the endianness, that apply to memory +/// accesses in either VS-mode or VU-mode. +/// +/// This function is unsafe for it accesses the virtual supervisor or user via a `HSV.B` +/// instruction which is effectively an unreference to any memory address. +#[inline] +pub unsafe fn hsv_b(dst: *mut i8, src: i8) { + asm!(".insn r 0x73, 0x4, 0x31, x0, {}, {}", in(reg) dst, in(reg) src, options(nostack)); +} + +/// Stores virtual machine memory by half integer +/// +/// This instruction performs an explicit memory access as though `V=1`; +/// i.e., with the address translation and protection, and the endianness, that apply to memory +/// accesses in either VS-mode or VU-mode. +/// +/// This function is unsafe for it accesses the virtual supervisor or user via a `HSV.H` +/// instruction which is effectively an unreference to any memory address. +#[inline] +pub unsafe fn hsv_h(dst: *mut i16, src: i16) { + asm!(".insn r 0x73, 0x4, 0x33, x0, {}, {}", in(reg) dst, in(reg) src, options(nostack)); +} + +/// Stores virtual machine memory by word integer +/// +/// This instruction performs an explicit memory access as though `V=1`; +/// i.e., with the address translation and protection, and the endianness, that apply to memory +/// accesses in either VS-mode or VU-mode. +/// +/// This function is unsafe for it accesses the virtual supervisor or user via a `HSV.W` +/// instruction which is effectively an unreference to any memory address. +#[inline] +pub unsafe fn hsv_w(dst: *mut i32, src: i32) { + asm!(".insn r 0x73, 0x4, 0x35, x0, {}, {}", in(reg) dst, in(reg) src, options(nostack)); +} + +/// Hypervisor memory management fence for given guest virtual address and guest address space +/// +/// Guarantees that any previous stores already visible to the current hart are ordered before all +/// implicit reads by that hart done for VS-stage address translation for instructions that: +/// - are subsequent to the `HFENCE.VVMA`, and +/// - execute when `hgatp.VMID` has the same setting as it did when `HFENCE.VVMA` executed. +/// +/// This fence specifies a single guest virtual address, and a single guest address-space identifier. +#[inline] +pub unsafe fn hfence_vvma(vaddr: usize, asid: usize) { + // asm!("hfence.vvma {}, {}", in(reg) vaddr, in(reg) asid) + asm!(".insn r 0x73, 0, 0x11, x0, {}, {}", in(reg) vaddr, in(reg) asid, options(nostack)) +} + +/// Hypervisor memory management fence for given guest virtual address +/// +/// Guarantees that any previous stores already visible to the current hart are ordered before all +/// implicit reads by that hart done for VS-stage address translation for instructions that: +/// - are subsequent to the `HFENCE.VVMA`, and +/// - execute when `hgatp.VMID` has the same setting as it did when `HFENCE.VVMA` executed. +/// +/// This fence specifies a single guest virtual address. +#[inline] +pub unsafe fn hfence_vvma_vaddr(vaddr: usize) { + asm!(".insn r 0x73, 0, 0x11, x0, {}, x0", in(reg) vaddr, options(nostack)) +} + +/// Hypervisor memory management fence for given guest address space +/// +/// Guarantees that any previous stores already visible to the current hart are ordered before all +/// implicit reads by that hart done for VS-stage address translation for instructions that: +/// - are subsequent to the `HFENCE.VVMA`, and +/// - execute when `hgatp.VMID` has the same setting as it did when `HFENCE.VVMA` executed. +/// +/// This fence specifies a single guest address-space identifier. +#[inline] +pub unsafe fn hfence_vvma_asid(asid: usize) { + asm!(".insn r 0x73, 0, 0x11, x0, x0, {}", in(reg) asid, options(nostack)) +} + +/// Hypervisor memory management fence for all guest address spaces and guest virtual addresses +/// +/// Guarantees that any previous stores already visible to the current hart are ordered before all +/// implicit reads by that hart done for VS-stage address translation for instructions that: +/// - are subsequent to the `HFENCE.VVMA`, and +/// - execute when `hgatp.VMID` has the same setting as it did when `HFENCE.VVMA` executed. +/// +/// This fence applies to any guest address spaces and guest virtual addresses. +#[inline] +pub unsafe fn hfence_vvma_all() { + asm!(".insn r 0x73, 0, 0x11, x0, x0, x0", options(nostack)) +} + +/// Hypervisor memory management fence for guest physical address and virtual machine +/// +/// Guarantees that any previous stores already visible to the current hart are ordered before all implicit reads +/// by that hart done for G-stage address translation for instructions that follow the HFENCE.GVMA. +/// +/// This fence specifies a single guest physical address, **shifted right by 2 bits**, and a single virtual machine +/// by virtual machine identifier (VMID). +#[inline] +pub unsafe fn hfence_gvma(gaddr: usize, vmid: usize) { + // asm!("hfence.gvma {}, {}", in(reg) gaddr, in(reg) vmid, options(nostack)) + asm!(".insn r 0x73, 0, 0x31, x0, {}, {}", in(reg) gaddr, in(reg) vmid, options(nostack)) +} + +/// Hypervisor memory management fence for guest physical address +/// +/// Guarantees that any previous stores already visible to the current hart are ordered before all implicit reads +/// by that hart done for G-stage address translation for instructions that follow the HFENCE.GVMA. +/// +/// This fence specifies a single guest physical address; **the physical address should be shifted right by 2 bits**. +#[inline] +pub unsafe fn hfence_gvma_gaddr(gaddr: usize) { + asm!(".insn r 0x73, 0, 0x31, x0, {}, x0", in(reg) gaddr, options(nostack)) +} + +/// Hypervisor memory management fence for given virtual machine +/// +/// Guarantees that any previous stores already visible to the current hart are ordered before all implicit reads +/// by that hart done for G-stage address translation for instructions that follow the HFENCE.GVMA. +/// +/// This fence specifies a single virtual machine by virtual machine identifier (VMID). +#[inline] +pub unsafe fn hfence_gvma_vmid(vmid: usize) { + asm!(".insn r 0x73, 0, 0x31, x0, x0, {}", in(reg) vmid, options(nostack)) +} + +/// Hypervisor memory management fence for all virtual machines and guest physical addresses +/// +/// Guarantees that any previous stores already visible to the current hart are ordered before all implicit reads +/// by that hart done for G-stage address translation for instructions that follow the HFENCE.GVMA. +/// +/// This fence specifies all guest physical addresses and all virtual machines. +#[inline] +pub unsafe fn hfence_gvma_all() { + asm!(".insn r 0x73, 0, 0x31, x0, x0, x0", options(nostack)) +} + +/// Invalidate hypervisor translation cache for given guest virtual address and guest address space +/// +/// This instruction invalidates any address-translation cache entries that an +/// `HFENCE.VVMA` instruction with the same values of `vaddr` and `asid` would invalidate. +/// +/// This fence specifies a single guest virtual address, and a single guest address-space identifier. +#[inline] +pub unsafe fn hinval_vvma(vaddr: usize, asid: usize) { + // asm!("hinval.vvma {}, {}", in(reg) vaddr, in(reg) asid, options(nostack)) + asm!(".insn r 0x73, 0, 0x13, x0, {}, {}", in(reg) vaddr, in(reg) asid, options(nostack)) +} + +/// Invalidate hypervisor translation cache for given guest virtual address +/// +/// This instruction invalidates any address-translation cache entries that an +/// `HFENCE.VVMA` instruction with the same values of `vaddr` and `asid` would invalidate. +/// +/// This fence specifies a single guest virtual address. +#[inline] +pub unsafe fn hinval_vvma_vaddr(vaddr: usize) { + asm!(".insn r 0x73, 0, 0x13, x0, {}, x0", in(reg) vaddr, options(nostack)) +} + +/// Invalidate hypervisor translation cache for given guest address space +/// +/// This instruction invalidates any address-translation cache entries that an +/// `HFENCE.VVMA` instruction with the same values of `vaddr` and `asid` would invalidate. +/// +/// This fence specifies a single guest address-space identifier. +#[inline] +pub unsafe fn hinval_vvma_asid(asid: usize) { + asm!(".insn r 0x73, 0, 0x13, x0, x0, {}", in(reg) asid, options(nostack)) +} + +/// Invalidate hypervisor translation cache for all guest address spaces and guest virtual addresses +/// +/// This instruction invalidates any address-translation cache entries that an +/// `HFENCE.VVMA` instruction with the same values of `vaddr` and `asid` would invalidate. +/// +/// This fence applies to any guest address spaces and guest virtual addresses. +#[inline] +pub unsafe fn hinval_vvma_all() { + asm!(".insn r 0x73, 0, 0x13, x0, x0, x0", options(nostack)) +} + +/// Invalidate hypervisor translation cache for guest physical address and virtual machine +/// +/// This instruction invalidates any address-translation cache entries that an +/// `HFENCE.GVMA` instruction with the same values of `gaddr` and `vmid` would invalidate. +/// +/// This fence specifies a single guest physical address, **shifted right by 2 bits**, and a single virtual machine +/// by virtual machine identifier (VMID). +#[inline] +pub unsafe fn hinval_gvma(gaddr: usize, vmid: usize) { + // asm!("hinval.gvma {}, {}", in(reg) gaddr, in(reg) vmid, options(nostack)) + asm!(".insn r 0x73, 0, 0x33, x0, {}, {}", in(reg) gaddr, in(reg) vmid, options(nostack)) +} + +/// Invalidate hypervisor translation cache for guest physical address +/// +/// This instruction invalidates any address-translation cache entries that an +/// `HFENCE.GVMA` instruction with the same values of `gaddr` and `vmid` would invalidate. +/// +/// This fence specifies a single guest physical address; **the physical address should be shifted right by 2 bits**. +#[inline] +pub unsafe fn hinval_gvma_gaddr(gaddr: usize) { + asm!(".insn r 0x73, 0, 0x33, x0, {}, x0", in(reg) gaddr, options(nostack)) +} + +/// Invalidate hypervisor translation cache for given virtual machine +/// +/// This instruction invalidates any address-translation cache entries that an +/// `HFENCE.GVMA` instruction with the same values of `gaddr` and `vmid` would invalidate. +/// +/// This fence specifies a single virtual machine by virtual machine identifier (VMID). +#[inline] +pub unsafe fn hinval_gvma_vmid(vmid: usize) { + asm!(".insn r 0x73, 0, 0x33, x0, x0, {}", in(reg) vmid, options(nostack)) +} + +/// Invalidate hypervisor translation cache for all virtual machines and guest physical addresses +/// +/// This instruction invalidates any address-translation cache entries that an +/// `HFENCE.GVMA` instruction with the same values of `gaddr` and `vmid` would invalidate. +/// +/// This fence specifies all guest physical addresses and all virtual machines. +#[inline] +pub unsafe fn hinval_gvma_all() { + asm!(".insn r 0x73, 0, 0x33, x0, x0, x0", options(nostack)) +} diff --git a/library/stdarch/crates/core_arch/src/simd.rs b/library/stdarch/crates/core_arch/src/simd.rs index a2e393ab32..281fefba42 100644 --- a/library/stdarch/crates/core_arch/src/simd.rs +++ b/library/stdarch/crates/core_arch/src/simd.rs @@ -10,7 +10,7 @@ macro_rules! simd_ty { #[allow(clippy::use_self)] impl $id { - #[inline] + #[inline(always)] pub(crate) const fn new($($elem_name: $elem_ty),*) -> Self { $id($($elem_name),*) } @@ -43,12 +43,12 @@ macro_rules! simd_m_ty { #[allow(clippy::use_self)] impl $id { - #[inline] + #[inline(always)] const fn bool_to_internal(x: bool) -> $ety { [0 as $ety, !(0 as $ety)][x as usize] } - #[inline] + #[inline(always)] pub(crate) const fn new($($elem_name: bool),*) -> Self { $id($(Self::bool_to_internal($elem_name)),*) } diff --git a/library/stdarch/crates/core_arch/src/wasm32/atomic.rs b/library/stdarch/crates/core_arch/src/wasm32/atomic.rs index 4a3a5c6745..f79e946acc 100644 --- a/library/stdarch/crates/core_arch/src/wasm32/atomic.rs +++ b/library/stdarch/crates/core_arch/src/wasm32/atomic.rs @@ -16,7 +16,7 @@ extern "C" { /// pointed to by `ptr` is equal to `expression` (performing this action /// atomically). /// -/// The argument `timeout_ns` is a maxinum number of nanoseconds the calling +/// The argument `timeout_ns` is a maximum number of nanoseconds the calling /// thread will be blocked for, if it blocks. If the timeout is negative then /// the calling thread will be blocked forever. /// @@ -46,7 +46,7 @@ pub unsafe fn memory_atomic_wait32(ptr: *mut i32, expression: i32, timeout_ns: i /// pointed to by `ptr` is equal to `expression` (performing this action /// atomically). /// -/// The argument `timeout_ns` is a maxinum number of nanoseconds the calling +/// The argument `timeout_ns` is a maximum number of nanoseconds the calling /// thread will be blocked for, if it blocks. If the timeout is negative then /// the calling thread will be blocked forever. /// diff --git a/library/stdarch/crates/core_arch/src/wasm32/simd128.rs b/library/stdarch/crates/core_arch/src/wasm32/simd128.rs index f2c0a25d29..b93295602a 100644 --- a/library/stdarch/crates/core_arch/src/wasm32/simd128.rs +++ b/library/stdarch/crates/core_arch/src/wasm32/simd128.rs @@ -33,7 +33,7 @@ types! { /// * four 32-bit floats (`f32`) /// * two 64-bit floats (`f64`) /// - /// The `v128` type in Rust is intended to be quite analagous to the `v128` + /// The `v128` type in Rust is intended to be quite analogous to the `v128` /// type in WebAssembly. Operations on `v128` can only be performed with the /// functions in this module. // N.B., internals here are arbitrary. @@ -2305,7 +2305,7 @@ pub fn i8x16_abs(a: v128) -> v128 { } } -/// Negates a 128-bit vectors intepreted as sixteen 8-bit signed integers +/// Negates a 128-bit vectors interpreted as sixteen 8-bit signed integers #[inline] #[cfg_attr(test, assert_instr(i8x16.neg))] #[target_feature(enable = "simd128")] @@ -2602,7 +2602,7 @@ pub fn i16x8_abs(a: v128) -> v128 { } } -/// Negates a 128-bit vectors intepreted as eight 16-bit signed integers +/// Negates a 128-bit vectors interpreted as eight 16-bit signed integers #[inline] #[cfg_attr(test, assert_instr(i16x8.neg))] #[target_feature(enable = "simd128")] @@ -3090,7 +3090,7 @@ pub fn i32x4_abs(a: v128) -> v128 { } } -/// Negates a 128-bit vectors intepreted as four 32-bit signed integers +/// Negates a 128-bit vectors interpreted as four 32-bit signed integers #[inline] #[cfg_attr(test, assert_instr(i32x4.neg))] #[target_feature(enable = "simd128")] @@ -3472,7 +3472,7 @@ pub fn i64x2_abs(a: v128) -> v128 { } } -/// Negates a 128-bit vectors intepreted as two 64-bit signed integers +/// Negates a 128-bit vectors interpreted as two 64-bit signed integers #[inline] #[cfg_attr(test, assert_instr(i64x2.neg))] #[target_feature(enable = "simd128")] diff --git a/library/stdarch/crates/core_arch/src/x86/avx.rs b/library/stdarch/crates/core_arch/src/x86/avx.rs index 8e0af72ca5..07de99acb3 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx.rs @@ -53,7 +53,7 @@ pub unsafe fn _mm256_add_ps(a: __m256, b: __m256) -> __m256 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_and_pd) #[inline] #[target_feature(enable = "avx")] -// FIXME: Should be 'vandpd' instuction. +// FIXME: Should be 'vandpd' instruction. // See https://github.com/rust-lang/stdarch/issues/71 #[cfg_attr(test, assert_instr(vandps))] #[stable(feature = "simd_x86", since = "1.27.0")] @@ -83,7 +83,7 @@ pub unsafe fn _mm256_and_ps(a: __m256, b: __m256) -> __m256 { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_or_pd) #[inline] #[target_feature(enable = "avx")] -// FIXME: should be `vorpd` instuction. +// FIXME: should be `vorpd` instruction. // See . #[cfg_attr(test, assert_instr(vorps))] #[stable(feature = "simd_x86", since = "1.27.0")] diff --git a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs index 10e0096339..47d565ceaa 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs @@ -1,4 +1,5 @@ use crate::{ + arch::asm, core_arch::{simd::*, simd_llvm::*, x86::*}, mem::{self, transmute}, ptr, @@ -7,6 +8,8 @@ use crate::{ #[cfg(test)] use stdarch_test::assert_instr; +use super::avx512f::{vpl, vps}; + /// Compute the absolute value of packed signed 16-bit integers in a, and store the unsigned results in dst. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_abs_epi16&expand=30) @@ -4227,6 +4230,330 @@ pub unsafe fn _mm_storeu_epi8(mem_addr: *mut i8, a: __m128i) { ptr::write_unaligned(mem_addr as *mut __m128i, a); } +/// Load packed 16-bit integers from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_loadu_epi16) +#[inline] +#[target_feature(enable = "avx512f,avx512bw")] +pub unsafe fn _mm512_mask_loadu_epi16(src: __m512i, k: __mmask32, mem_addr: *const i16) -> __m512i { + let mut dst: __m512i = src; + asm!( + vpl!("vmovdqu16 {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(zmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 16-bit integers from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_loadu_epi16) +#[inline] +#[target_feature(enable = "avx512f,avx512bw")] +pub unsafe fn _mm512_maskz_loadu_epi16(k: __mmask32, mem_addr: *const i16) -> __m512i { + let mut dst: __m512i; + asm!( + vpl!("vmovdqu16 {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(zmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 8-bit integers from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_loadu_epi8) +#[inline] +#[target_feature(enable = "avx512f,avx512bw")] +pub unsafe fn _mm512_mask_loadu_epi8(src: __m512i, k: __mmask64, mem_addr: *const i8) -> __m512i { + let mut dst: __m512i = src; + asm!( + vpl!("vmovdqu8 {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(zmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 8-bit integers from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_loadu_epi8) +#[inline] +#[target_feature(enable = "avx512f,avx512bw")] +pub unsafe fn _mm512_maskz_loadu_epi8(k: __mmask64, mem_addr: *const i8) -> __m512i { + let mut dst: __m512i; + asm!( + vpl!("vmovdqu8 {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(zmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 16-bit integers from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_loadu_epi16) +#[inline] +#[target_feature(enable = "avx512f,avx512bw,avx512vl,avx")] +pub unsafe fn _mm256_mask_loadu_epi16(src: __m256i, k: __mmask16, mem_addr: *const i16) -> __m256i { + let mut dst: __m256i = src; + asm!( + vpl!("vmovdqu16 {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(ymm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 16-bit integers from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_loadu_epi16) +#[inline] +#[target_feature(enable = "avx512f,avx512bw,avx512vl,avx")] +pub unsafe fn _mm256_maskz_loadu_epi16(k: __mmask16, mem_addr: *const i16) -> __m256i { + let mut dst: __m256i; + asm!( + vpl!("vmovdqu16 {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(ymm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 8-bit integers from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_loadu_epi8) +#[inline] +#[target_feature(enable = "avx512f,avx512bw,avx512vl,avx")] +pub unsafe fn _mm256_mask_loadu_epi8(src: __m256i, k: __mmask32, mem_addr: *const i8) -> __m256i { + let mut dst: __m256i = src; + asm!( + vpl!("vmovdqu8 {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(ymm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 8-bit integers from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_loadu_epi8) +#[inline] +#[target_feature(enable = "avx512f,avx512bw,avx512vl,avx")] +pub unsafe fn _mm256_maskz_loadu_epi8(k: __mmask32, mem_addr: *const i8) -> __m256i { + let mut dst: __m256i; + asm!( + vpl!("vmovdqu8 {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(ymm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 16-bit integers from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_loadu_epi16) +#[inline] +#[target_feature(enable = "avx512f,avx512bw,avx512vl,avx,sse")] +pub unsafe fn _mm_mask_loadu_epi16(src: __m128i, k: __mmask8, mem_addr: *const i16) -> __m128i { + let mut dst: __m128i = src; + asm!( + vpl!("vmovdqu16 {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(xmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 16-bit integers from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_loadu_epi16) +#[inline] +#[target_feature(enable = "avx512f,avx512bw,avx512vl,avx,sse")] +pub unsafe fn _mm_maskz_loadu_epi16(k: __mmask8, mem_addr: *const i16) -> __m128i { + let mut dst: __m128i; + asm!( + vpl!("vmovdqu16 {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(xmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 8-bit integers from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_loadu_epi8) +#[inline] +#[target_feature(enable = "avx512f,avx512bw,avx512vl,avx,sse")] +pub unsafe fn _mm_mask_loadu_epi8(src: __m128i, k: __mmask16, mem_addr: *const i8) -> __m128i { + let mut dst: __m128i = src; + asm!( + vpl!("vmovdqu8 {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(xmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 8-bit integers from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_loadu_epi8) +#[inline] +#[target_feature(enable = "avx512f,avx512bw,avx512vl,avx,sse")] +pub unsafe fn _mm_maskz_loadu_epi8(k: __mmask16, mem_addr: *const i8) -> __m128i { + let mut dst: __m128i; + asm!( + vpl!("vmovdqu8 {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(xmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Store packed 16-bit integers from a into memory using writemask k. +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_storeu_epi16) +#[inline] +#[target_feature(enable = "avx512f,avx512bw")] +pub unsafe fn _mm512_mask_storeu_epi16(mem_addr: *mut i16, mask: __mmask32, a: __m512i) { + asm!( + vps!("vmovdqu16", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(zmm_reg) a, + options(nostack) + ); +} + +/// Store packed 8-bit integers from a into memory using writemask k. +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_storeu_epi8) +#[inline] +#[target_feature(enable = "avx512f,avx512bw")] +pub unsafe fn _mm512_mask_storeu_epi8(mem_addr: *mut i8, mask: __mmask64, a: __m512i) { + asm!( + vps!("vmovdqu8", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(zmm_reg) a, + options(nostack) + ); +} + +/// Store packed 16-bit integers from a into memory using writemask k. +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_storeu_epi16) +#[inline] +#[target_feature(enable = "avx512f,avx512bw,avx512vl,avx")] +pub unsafe fn _mm256_mask_storeu_epi16(mem_addr: *mut i16, mask: __mmask16, a: __m256i) { + asm!( + vps!("vmovdqu16", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(ymm_reg) a, + options(nostack) + ); +} + +/// Store packed 8-bit integers from a into memory using writemask k. +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_storeu_epi8) +#[inline] +#[target_feature(enable = "avx512f,avx512bw,avx512vl,avx")] +pub unsafe fn _mm256_mask_storeu_epi8(mem_addr: *mut i8, mask: __mmask32, a: __m256i) { + asm!( + vps!("vmovdqu8", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(ymm_reg) a, + options(nostack) + ); +} + +/// Store packed 16-bit integers from a into memory using writemask k. +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_storeu_epi16) +#[inline] +#[target_feature(enable = "avx512f,avx512bw,avx512vl,avx,sse")] +pub unsafe fn _mm_mask_storeu_epi16(mem_addr: *mut i16, mask: __mmask8, a: __m128i) { + asm!( + vps!("vmovdqu16", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(xmm_reg) a, + options(nostack) + ); +} + +/// Store packed 8-bit integers from a into memory using writemask k. +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_storeu_epi8) +#[inline] +#[target_feature(enable = "avx512f,avx512bw,avx512vl,avx,sse")] +pub unsafe fn _mm_mask_storeu_epi8(mem_addr: *mut i8, mask: __mmask16, a: __m128i) { + asm!( + vps!("vmovdqu8", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(xmm_reg) a, + options(nostack) + ); +} + /// Multiply packed signed 16-bit integers in a and b, producing intermediate signed 32-bit integers. Horizontally add adjacent pairs of intermediate 32-bit integers, and pack the results in dst. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_madd_epi16&expand=3511) @@ -13826,6 +14153,284 @@ mod tests { assert_eq_m128i(r, a); } + #[simd_test(enable = "avx512f,avx512bw")] + unsafe fn test_mm512_mask_loadu_epi16() { + let src = _mm512_set1_epi16(42); + let a = &[ + 1_i16, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, + ]; + let p = a.as_ptr(); + let m = 0b10101010_11001100_11101000_11001010; + let r = _mm512_mask_loadu_epi16(src, m, black_box(p)); + let e = &[ + 42_i16, 2, 42, 4, 42, 42, 7, 8, 42, 42, 42, 12, 42, 14, 15, 16, 42, 42, 19, 20, 42, 42, + 23, 24, 42, 26, 42, 28, 42, 30, 42, 32, + ]; + let e = _mm512_loadu_epi16(e.as_ptr()); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512f,avx512bw")] + unsafe fn test_mm512_maskz_loadu_epi16() { + let a = &[ + 1_i16, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, + ]; + let p = a.as_ptr(); + let m = 0b10101010_11001100_11101000_11001010; + let r = _mm512_maskz_loadu_epi16(m, black_box(p)); + let e = &[ + 0_i16, 2, 0, 4, 0, 0, 7, 8, 0, 0, 0, 12, 0, 14, 15, 16, 0, 0, 19, 20, 0, 0, 23, 24, 0, + 26, 0, 28, 0, 30, 0, 32, + ]; + let e = _mm512_loadu_epi16(e.as_ptr()); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512f,avx512bw")] + unsafe fn test_mm512_mask_storeu_epi16() { + let mut r = [42_i16; 32]; + let a = &[ + 1_i16, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, + ]; + let a = _mm512_loadu_epi16(a.as_ptr()); + let m = 0b10101010_11001100_11101000_11001010; + _mm512_mask_storeu_epi16(r.as_mut_ptr(), m, a); + let e = &[ + 42_i16, 2, 42, 4, 42, 42, 7, 8, 42, 42, 42, 12, 42, 14, 15, 16, 42, 42, 19, 20, 42, 42, + 23, 24, 42, 26, 42, 28, 42, 30, 42, 32, + ]; + let e = _mm512_loadu_epi16(e.as_ptr()); + assert_eq_m512i(_mm512_loadu_epi16(r.as_ptr()), e); + } + + #[simd_test(enable = "avx512f,avx512bw")] + unsafe fn test_mm512_mask_loadu_epi8() { + let src = _mm512_set1_epi8(42); + let a = &[ + 1_i8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + ]; + let p = a.as_ptr(); + let m = 0b00000000_11111111_11111111_00000000_10101010_11001100_11101000_11001010; + let r = _mm512_mask_loadu_epi8(src, m, black_box(p)); + let e = &[ + 42_i8, 2, 42, 4, 42, 42, 7, 8, 42, 42, 42, 12, 42, 14, 15, 16, 42, 42, 19, 20, 42, 42, + 23, 24, 42, 26, 42, 28, 42, 30, 42, 32, 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 42, 42, 42, 42, 42, 42, 42, 42, + ]; + let e = _mm512_loadu_epi8(e.as_ptr()); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512f,avx512bw")] + unsafe fn test_mm512_maskz_loadu_epi8() { + let a = &[ + 1_i8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + ]; + let p = a.as_ptr(); + let m = 0b00000000_11111111_11111111_00000000_10101010_11001100_11101000_11001010; + let r = _mm512_maskz_loadu_epi8(m, black_box(p)); + let e = &[ + 0_i8, 2, 0, 4, 0, 0, 7, 8, 0, 0, 0, 12, 0, 14, 15, 16, 0, 0, 19, 20, 0, 0, 23, 24, 0, + 26, 0, 28, 0, 30, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + let e = _mm512_loadu_epi8(e.as_ptr()); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512f,avx512bw")] + unsafe fn test_mm512_mask_storeu_epi8() { + let mut r = [42_i8; 64]; + let a = &[ + 1_i8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + ]; + let a = _mm512_loadu_epi8(a.as_ptr()); + let m = 0b00000000_11111111_11111111_00000000_10101010_11001100_11101000_11001010; + _mm512_mask_storeu_epi8(r.as_mut_ptr(), m, a); + let e = &[ + 42_i8, 2, 42, 4, 42, 42, 7, 8, 42, 42, 42, 12, 42, 14, 15, 16, 42, 42, 19, 20, 42, 42, + 23, 24, 42, 26, 42, 28, 42, 30, 42, 32, 42, 42, 42, 42, 42, 42, 42, 42, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 42, 42, 42, 42, 42, 42, 42, 42, + ]; + let e = _mm512_loadu_epi8(e.as_ptr()); + assert_eq_m512i(_mm512_loadu_epi8(r.as_ptr()), e); + } + + #[simd_test(enable = "avx512f,avx512bw,avx512vl")] + unsafe fn test_mm256_mask_loadu_epi16() { + let src = _mm256_set1_epi16(42); + let a = &[1_i16, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let p = a.as_ptr(); + let m = 0b11101000_11001010; + let r = _mm256_mask_loadu_epi16(src, m, black_box(p)); + let e = &[ + 42_i16, 2, 42, 4, 42, 42, 7, 8, 42, 42, 42, 12, 42, 14, 15, 16, + ]; + let e = _mm256_loadu_epi16(e.as_ptr()); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512bw,avx512vl")] + unsafe fn test_mm256_maskz_loadu_epi16() { + let a = &[1_i16, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let p = a.as_ptr(); + let m = 0b11101000_11001010; + let r = _mm256_maskz_loadu_epi16(m, black_box(p)); + let e = &[0_i16, 2, 0, 4, 0, 0, 7, 8, 0, 0, 0, 12, 0, 14, 15, 16]; + let e = _mm256_loadu_epi16(e.as_ptr()); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512bw,avx512vl")] + unsafe fn test_mm256_mask_storeu_epi16() { + let mut r = [42_i16; 16]; + let a = &[1_i16, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let a = _mm256_loadu_epi16(a.as_ptr()); + let m = 0b11101000_11001010; + _mm256_mask_storeu_epi16(r.as_mut_ptr(), m, a); + let e = &[ + 42_i16, 2, 42, 4, 42, 42, 7, 8, 42, 42, 42, 12, 42, 14, 15, 16, + ]; + let e = _mm256_loadu_epi16(e.as_ptr()); + assert_eq_m256i(_mm256_loadu_epi16(r.as_ptr()), e); + } + + #[simd_test(enable = "avx512f,avx512bw,avx512vl")] + unsafe fn test_mm256_mask_loadu_epi8() { + let src = _mm256_set1_epi8(42); + let a = &[ + 1_i8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, + ]; + let p = a.as_ptr(); + let m = 0b10101010_11001100_11101000_11001010; + let r = _mm256_mask_loadu_epi8(src, m, black_box(p)); + let e = &[ + 42_i8, 2, 42, 4, 42, 42, 7, 8, 42, 42, 42, 12, 42, 14, 15, 16, 42, 42, 19, 20, 42, 42, + 23, 24, 42, 26, 42, 28, 42, 30, 42, 32, + ]; + let e = _mm256_loadu_epi8(e.as_ptr()); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512bw,avx512vl")] + unsafe fn test_mm256_maskz_loadu_epi8() { + let a = &[ + 1_i8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, + ]; + let p = a.as_ptr(); + let m = 0b10101010_11001100_11101000_11001010; + let r = _mm256_maskz_loadu_epi8(m, black_box(p)); + let e = &[ + 0_i8, 2, 0, 4, 0, 0, 7, 8, 0, 0, 0, 12, 0, 14, 15, 16, 0, 0, 19, 20, 0, 0, 23, 24, 0, + 26, 0, 28, 0, 30, 0, 32, + ]; + let e = _mm256_loadu_epi8(e.as_ptr()); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512bw,avx512vl")] + unsafe fn test_mm256_mask_storeu_epi8() { + let mut r = [42_i8; 32]; + let a = &[ + 1_i8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, + ]; + let a = _mm256_loadu_epi8(a.as_ptr()); + let m = 0b10101010_11001100_11101000_11001010; + _mm256_mask_storeu_epi8(r.as_mut_ptr(), m, a); + let e = &[ + 42_i8, 2, 42, 4, 42, 42, 7, 8, 42, 42, 42, 12, 42, 14, 15, 16, 42, 42, 19, 20, 42, 42, + 23, 24, 42, 26, 42, 28, 42, 30, 42, 32, + ]; + let e = _mm256_loadu_epi8(e.as_ptr()); + assert_eq_m256i(_mm256_loadu_epi8(r.as_ptr()), e); + } + + #[simd_test(enable = "avx512f,avx512bw,avx512vl")] + unsafe fn test_mm_mask_loadu_epi16() { + let src = _mm_set1_epi16(42); + let a = &[1_i16, 2, 3, 4, 5, 6, 7, 8]; + let p = a.as_ptr(); + let m = 0b11001010; + let r = _mm_mask_loadu_epi16(src, m, black_box(p)); + let e = &[42_i16, 2, 42, 4, 42, 42, 7, 8]; + let e = _mm_loadu_epi16(e.as_ptr()); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512bw,avx512vl")] + unsafe fn test_mm_maskz_loadu_epi16() { + let a = &[1_i16, 2, 3, 4, 5, 6, 7, 8]; + let p = a.as_ptr(); + let m = 0b11001010; + let r = _mm_maskz_loadu_epi16(m, black_box(p)); + let e = &[0_i16, 2, 0, 4, 0, 0, 7, 8]; + let e = _mm_loadu_epi16(e.as_ptr()); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512bw,avx512vl")] + unsafe fn test_mm_mask_storeu_epi16() { + let mut r = [42_i16; 8]; + let a = &[1_i16, 2, 3, 4, 5, 6, 7, 8]; + let a = _mm_loadu_epi16(a.as_ptr()); + let m = 0b11001010; + _mm_mask_storeu_epi16(r.as_mut_ptr(), m, a); + let e = &[42_i16, 2, 42, 4, 42, 42, 7, 8]; + let e = _mm_loadu_epi16(e.as_ptr()); + assert_eq_m128i(_mm_loadu_epi16(r.as_ptr()), e); + } + + #[simd_test(enable = "avx512f,avx512bw,avx512vl")] + unsafe fn test_mm_mask_loadu_epi8() { + let src = _mm_set1_epi8(42); + let a = &[1_i8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let p = a.as_ptr(); + let m = 0b11101000_11001010; + let r = _mm_mask_loadu_epi8(src, m, black_box(p)); + let e = &[ + 42_i8, 2, 42, 4, 42, 42, 7, 8, 42, 42, 42, 12, 42, 14, 15, 16, + ]; + let e = _mm_loadu_epi8(e.as_ptr()); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512bw,avx512vl")] + unsafe fn test_mm_maskz_loadu_epi8() { + let a = &[1_i8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let p = a.as_ptr(); + let m = 0b11101000_11001010; + let r = _mm_maskz_loadu_epi8(m, black_box(p)); + let e = &[0_i8, 2, 0, 4, 0, 0, 7, 8, 0, 0, 0, 12, 0, 14, 15, 16]; + let e = _mm_loadu_epi8(e.as_ptr()); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512bw,avx512vl")] + unsafe fn test_mm_mask_storeu_epi8() { + let mut r = [42_i8; 16]; + let a = &[1_i8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let a = _mm_loadu_epi8(a.as_ptr()); + let m = 0b11101000_11001010; + _mm_mask_storeu_epi8(r.as_mut_ptr(), m, a); + let e = &[ + 42_i8, 2, 42, 4, 42, 42, 7, 8, 42, 42, 42, 12, 42, 14, 15, 16, + ]; + let e = _mm_loadu_epi8(e.as_ptr()); + assert_eq_m128i(_mm_loadu_epi8(r.as_ptr()), e); + } + #[simd_test(enable = "avx512bw")] unsafe fn test_mm512_madd_epi16() { let a = _mm512_set1_epi16(1); diff --git a/library/stdarch/crates/core_arch/src/x86/avx512f.rs b/library/stdarch/crates/core_arch/src/x86/avx512f.rs index 766acf46f7..97c6f6c4d6 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512f.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512f.rs @@ -1,9 +1,41 @@ use crate::{ + arch::asm, core_arch::{simd::*, simd_llvm::*, x86::*}, mem::{self, transmute}, ptr, }; +// x86-32 wants to use a 32-bit address size, but asm! defaults to using the full +// register name (e.g. rax). We have to explicitly override the placeholder to +// use the 32-bit register name in that case. + +#[cfg(target_pointer_width = "32")] +macro_rules! vpl { + ($inst:expr) => { + concat!($inst, ", [{p:e}]") + }; +} +#[cfg(target_pointer_width = "64")] +macro_rules! vpl { + ($inst:expr) => { + concat!($inst, ", [{p}]") + }; +} +#[cfg(target_pointer_width = "32")] +macro_rules! vps { + ($inst1:expr, $inst2:expr) => { + concat!($inst1, " [{p:e}]", $inst2) + }; +} +#[cfg(target_pointer_width = "64")] +macro_rules! vps { + ($inst1:expr, $inst2:expr) => { + concat!($inst1, " [{p}]", $inst2) + }; +} + +pub(crate) use {vpl, vps}; + #[cfg(test)] use stdarch_test::assert_instr; @@ -19447,7 +19479,7 @@ pub unsafe fn _mm_maskz_permute_pd(k: __mmask8, a: __m128d) -> /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutex_epi64&expand=4208) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vperm, MASK = 0b10_01_10_11))] //shoud be vpermq +#[cfg_attr(test, assert_instr(vperm, MASK = 0b10_01_10_11))] //should be vpermq #[rustc_legacy_const_generics(1)] pub unsafe fn _mm512_permutex_epi64(a: __m512i) -> __m512i { static_assert_imm8!(MASK); @@ -19503,7 +19535,7 @@ pub unsafe fn _mm512_maskz_permutex_epi64(k: __mmask8, a: __m51 /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_permutex_epi64&expand=4205) #[inline] #[target_feature(enable = "avx512f,avx512vl")] -#[cfg_attr(test, assert_instr(vperm, MASK = 0b10_01_10_11))] //shoud be vpermq +#[cfg_attr(test, assert_instr(vperm, MASK = 0b10_01_10_11))] //should be vpermq #[rustc_legacy_const_generics(1)] pub unsafe fn _mm256_permutex_epi64(a: __m256i) -> __m256i { static_assert_imm8!(MASK); @@ -19555,7 +19587,7 @@ pub unsafe fn _mm256_maskz_permutex_epi64(k: __mmask8, a: __m25 /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_permutex_pd&expand=4214) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vperm, MASK = 0b10_01_10_11))] //shoud be vpermpd +#[cfg_attr(test, assert_instr(vperm, MASK = 0b10_01_10_11))] //should be vpermpd #[rustc_legacy_const_generics(1)] pub unsafe fn _mm512_permutex_pd(a: __m512d) -> __m512d { static_assert_imm8!(MASK); @@ -19580,7 +19612,7 @@ pub unsafe fn _mm512_permutex_pd(a: __m512d) -> __m512d { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_permutex_pd&expand=4212) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vperm, MASK = 0b10_01_10_11))] //shoud be vpermpd +#[cfg_attr(test, assert_instr(vperm, MASK = 0b10_01_10_11))] //should be vpermpd #[rustc_legacy_const_generics(3)] pub unsafe fn _mm512_mask_permutex_pd( src: __m512d, @@ -19596,7 +19628,7 @@ pub unsafe fn _mm512_mask_permutex_pd( /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_permutex_pd&expand=4213) #[inline] #[target_feature(enable = "avx512f")] -#[cfg_attr(test, assert_instr(vperm, MASK = 0b10_01_10_11))] //shoud be vpermpd +#[cfg_attr(test, assert_instr(vperm, MASK = 0b10_01_10_11))] //should be vpermpd #[rustc_legacy_const_generics(2)] pub unsafe fn _mm512_maskz_permutex_pd(k: __mmask8, a: __m512d) -> __m512d { let r = _mm512_permutex_pd::(a); @@ -19609,7 +19641,7 @@ pub unsafe fn _mm512_maskz_permutex_pd(k: __mmask8, a: __m512d) /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_permutex_pd&expand=4211) #[inline] #[target_feature(enable = "avx512f,avx512vl")] -#[cfg_attr(test, assert_instr(vperm, MASK = 0b10_01_10_11))] //shoud be vpermpd +#[cfg_attr(test, assert_instr(vperm, MASK = 0b10_01_10_11))] //should be vpermpd #[rustc_legacy_const_generics(1)] pub unsafe fn _mm256_permutex_pd(a: __m256d) -> __m256d { static_assert_imm8!(MASK); @@ -19630,7 +19662,7 @@ pub unsafe fn _mm256_permutex_pd(a: __m256d) -> __m256d { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_permutex_pd&expand=4209) #[inline] #[target_feature(enable = "avx512f,avx512vl")] -#[cfg_attr(test, assert_instr(vperm, MASK = 0b10_01_10_11))] //shoud be vpermpd +#[cfg_attr(test, assert_instr(vperm, MASK = 0b10_01_10_11))] //should be vpermpd #[rustc_legacy_const_generics(3)] pub unsafe fn _mm256_mask_permutex_pd( src: __m256d, @@ -19647,7 +19679,7 @@ pub unsafe fn _mm256_mask_permutex_pd( /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_permutex_pd&expand=4210) #[inline] #[target_feature(enable = "avx512f,avx512vl")] -#[cfg_attr(test, assert_instr(vperm, MASK = 0b10_01_10_11))] //shoud be vpermpd +#[cfg_attr(test, assert_instr(vperm, MASK = 0b10_01_10_11))] //should be vpermpd #[rustc_legacy_const_generics(2)] pub unsafe fn _mm256_maskz_permutex_pd(k: __mmask8, a: __m256d) -> __m256d { static_assert_imm8!(MASK); @@ -30323,6 +30355,1302 @@ pub unsafe fn _mm512_store_pd(mem_addr: *mut f64, a: __m512d) { ptr::write(mem_addr as *mut __m512d, a); } +/// Load packed 32-bit integers from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_loadu_epi32) +#[inline] +#[target_feature(enable = "avx512f")] +pub unsafe fn _mm512_mask_loadu_epi32(src: __m512i, k: __mmask16, mem_addr: *const i32) -> __m512i { + let mut dst: __m512i = src; + asm!( + vpl!("vmovdqu32 {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(zmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 32-bit integers from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_loadu_epi32) +#[inline] +#[target_feature(enable = "avx512f")] +pub unsafe fn _mm512_maskz_loadu_epi32(k: __mmask16, mem_addr: *const i32) -> __m512i { + let mut dst: __m512i; + asm!( + vpl!("vmovdqu32 {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(zmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 64-bit integers from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_loadu_epi64) +#[inline] +#[target_feature(enable = "avx512f")] +pub unsafe fn _mm512_mask_loadu_epi64(src: __m512i, k: __mmask8, mem_addr: *const i64) -> __m512i { + let mut dst: __m512i = src; + asm!( + vpl!("vmovdqu64 {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(zmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 64-bit integers from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_loadu_epi64) +#[inline] +#[target_feature(enable = "avx512f")] +pub unsafe fn _mm512_maskz_loadu_epi64(k: __mmask8, mem_addr: *const i64) -> __m512i { + let mut dst: __m512i; + asm!( + vpl!("vmovdqu64 {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(zmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed single-precision (32-bit) floating-point elements from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_loadu_ps) +#[inline] +#[target_feature(enable = "avx512f")] +pub unsafe fn _mm512_mask_loadu_ps(src: __m512, k: __mmask16, mem_addr: *const f32) -> __m512 { + let mut dst: __m512 = src; + asm!( + vpl!("vmovups {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(zmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed single-precision (32-bit) floating-point elements from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_loadu_ps) +#[inline] +#[target_feature(enable = "avx512f")] +pub unsafe fn _mm512_maskz_loadu_ps(k: __mmask16, mem_addr: *const f32) -> __m512 { + let mut dst: __m512; + asm!( + vpl!("vmovups {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(zmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed double-precision (64-bit) floating-point elements from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_loadu_pd) +#[inline] +#[target_feature(enable = "avx512f")] +pub unsafe fn _mm512_mask_loadu_pd(src: __m512d, k: __mmask8, mem_addr: *const f64) -> __m512d { + let mut dst: __m512d = src; + asm!( + vpl!("vmovupd {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(zmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed double-precision (64-bit) floating-point elements from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_loadu_pd) +#[inline] +#[target_feature(enable = "avx512f")] +pub unsafe fn _mm512_maskz_loadu_pd(k: __mmask8, mem_addr: *const f64) -> __m512d { + let mut dst: __m512d; + asm!( + vpl!("vmovupd {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(zmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 32-bit integers from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_loadu_epi32) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx")] +pub unsafe fn _mm256_mask_loadu_epi32(src: __m256i, k: __mmask8, mem_addr: *const i32) -> __m256i { + let mut dst: __m256i = src; + asm!( + vpl!("vmovdqu32 {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(ymm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 32-bit integers from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_loadu_epi32) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx")] +pub unsafe fn _mm256_maskz_loadu_epi32(k: __mmask8, mem_addr: *const i32) -> __m256i { + let mut dst: __m256i; + asm!( + vpl!("vmovdqu32 {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(ymm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 64-bit integers from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_loadu_epi64) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx")] +pub unsafe fn _mm256_mask_loadu_epi64(src: __m256i, k: __mmask8, mem_addr: *const i64) -> __m256i { + let mut dst: __m256i = src; + asm!( + vpl!("vmovdqu64 {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(ymm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 64-bit integers from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_loadu_epi64) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx")] +pub unsafe fn _mm256_maskz_loadu_epi64(k: __mmask8, mem_addr: *const i64) -> __m256i { + let mut dst: __m256i; + asm!( + vpl!("vmovdqu64 {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(ymm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed single-precision (32-bit) floating-point elements from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_loadu_ps) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx")] +pub unsafe fn _mm256_mask_loadu_ps(src: __m256, k: __mmask8, mem_addr: *const f32) -> __m256 { + let mut dst: __m256 = src; + asm!( + vpl!("vmovups {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(ymm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed single-precision (32-bit) floating-point elements from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_loadu_ps) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx")] +pub unsafe fn _mm256_maskz_loadu_ps(k: __mmask8, mem_addr: *const f32) -> __m256 { + let mut dst: __m256; + asm!( + vpl!("vmovups {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(ymm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed double-precision (64-bit) floating-point elements from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_loadu_pd) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx")] +pub unsafe fn _mm256_mask_loadu_pd(src: __m256d, k: __mmask8, mem_addr: *const f64) -> __m256d { + let mut dst: __m256d = src; + asm!( + vpl!("vmovupd {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(ymm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed double-precision (64-bit) floating-point elements from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_loadu_pd) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx")] +pub unsafe fn _mm256_maskz_loadu_pd(k: __mmask8, mem_addr: *const f64) -> __m256d { + let mut dst: __m256d; + asm!( + vpl!("vmovupd {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(ymm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 32-bit integers from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_loadu_epi32) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx,sse")] +pub unsafe fn _mm_mask_loadu_epi32(src: __m128i, k: __mmask8, mem_addr: *const i32) -> __m128i { + let mut dst: __m128i = src; + asm!( + vpl!("vmovdqu32 {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(xmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 32-bit integers from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_loadu_epi32) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx,sse")] +pub unsafe fn _mm_maskz_loadu_epi32(k: __mmask8, mem_addr: *const i32) -> __m128i { + let mut dst: __m128i; + asm!( + vpl!("vmovdqu32 {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(xmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 64-bit integers from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_loadu_epi64) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx,sse")] +pub unsafe fn _mm_mask_loadu_epi64(src: __m128i, k: __mmask8, mem_addr: *const i64) -> __m128i { + let mut dst: __m128i = src; + asm!( + vpl!("vmovdqu64 {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(xmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 64-bit integers from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_loadu_epi64) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx,sse")] +pub unsafe fn _mm_maskz_loadu_epi64(k: __mmask8, mem_addr: *const i64) -> __m128i { + let mut dst: __m128i; + asm!( + vpl!("vmovdqu64 {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(xmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed single-precision (32-bit) floating-point elements from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_loadu_ps) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx,sse")] +pub unsafe fn _mm_mask_loadu_ps(src: __m128, k: __mmask8, mem_addr: *const f32) -> __m128 { + let mut dst: __m128 = src; + asm!( + vpl!("vmovups {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(xmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed single-precision (32-bit) floating-point elements from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_loadu_ps) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx,sse")] +pub unsafe fn _mm_maskz_loadu_ps(k: __mmask8, mem_addr: *const f32) -> __m128 { + let mut dst: __m128; + asm!( + vpl!("vmovups {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(xmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed double-precision (64-bit) floating-point elements from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_loadu_pd) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx,sse")] +pub unsafe fn _mm_mask_loadu_pd(src: __m128d, k: __mmask8, mem_addr: *const f64) -> __m128d { + let mut dst: __m128d = src; + asm!( + vpl!("vmovupd {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(xmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed double-precision (64-bit) floating-point elements from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_loadu_pd) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx,sse")] +pub unsafe fn _mm_maskz_loadu_pd(k: __mmask8, mem_addr: *const f64) -> __m128d { + let mut dst: __m128d; + asm!( + vpl!("vmovupd {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(xmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 32-bit integers from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr must be aligned on a 64-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_load_epi32) +#[inline] +#[target_feature(enable = "avx512f")] +pub unsafe fn _mm512_mask_load_epi32(src: __m512i, k: __mmask16, mem_addr: *const i32) -> __m512i { + let mut dst: __m512i = src; + asm!( + vpl!("vmovdqa32 {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(zmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 32-bit integers from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr must be aligned on a 64-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_load_epi32) +#[inline] +#[target_feature(enable = "avx512f")] +pub unsafe fn _mm512_maskz_load_epi32(k: __mmask16, mem_addr: *const i32) -> __m512i { + let mut dst: __m512i; + asm!( + vpl!("vmovdqa32 {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(zmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 64-bit integers from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr must be aligned on a 64-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_load_epi64) +#[inline] +#[target_feature(enable = "avx512f")] +pub unsafe fn _mm512_mask_load_epi64(src: __m512i, k: __mmask8, mem_addr: *const i64) -> __m512i { + let mut dst: __m512i = src; + asm!( + vpl!("vmovdqa64 {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(zmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 64-bit integers from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr must be aligned on a 64-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_load_epi64) +#[inline] +#[target_feature(enable = "avx512f")] +pub unsafe fn _mm512_maskz_load_epi64(k: __mmask8, mem_addr: *const i64) -> __m512i { + let mut dst: __m512i; + asm!( + vpl!("vmovdqa64 {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(zmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed single-precision (32-bit) floating-point elements from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr must be aligned on a 64-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_load_ps) +#[inline] +#[target_feature(enable = "avx512f")] +pub unsafe fn _mm512_mask_load_ps(src: __m512, k: __mmask16, mem_addr: *const f32) -> __m512 { + let mut dst: __m512 = src; + asm!( + vpl!("vmovaps {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(zmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed single-precision (32-bit) floating-point elements from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr must be aligned on a 64-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_load_ps) +#[inline] +#[target_feature(enable = "avx512f")] +pub unsafe fn _mm512_maskz_load_ps(k: __mmask16, mem_addr: *const f32) -> __m512 { + let mut dst: __m512; + asm!( + vpl!("vmovaps {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(zmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed double-precision (64-bit) floating-point elements from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr must be aligned on a 64-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_load_pd) +#[inline] +#[target_feature(enable = "avx512f")] +pub unsafe fn _mm512_mask_load_pd(src: __m512d, k: __mmask8, mem_addr: *const f64) -> __m512d { + let mut dst: __m512d = src; + asm!( + vpl!("vmovapd {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(zmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed double-precision (64-bit) floating-point elements from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr must be aligned on a 64-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_maskz_load_pd) +#[inline] +#[target_feature(enable = "avx512f")] +pub unsafe fn _mm512_maskz_load_pd(k: __mmask8, mem_addr: *const f64) -> __m512d { + let mut dst: __m512d; + asm!( + vpl!("vmovapd {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(zmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 32-bit integers from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr must be aligned on a 32-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_load_epi32) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx")] +pub unsafe fn _mm256_mask_load_epi32(src: __m256i, k: __mmask8, mem_addr: *const i32) -> __m256i { + let mut dst: __m256i = src; + asm!( + vpl!("vmovdqa32 {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(ymm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 32-bit integers from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr must be aligned on a 32-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_load_epi32) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx")] +pub unsafe fn _mm256_maskz_load_epi32(k: __mmask8, mem_addr: *const i32) -> __m256i { + let mut dst: __m256i; + asm!( + vpl!("vmovdqa32 {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(ymm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 64-bit integers from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr must be aligned on a 32-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_load_epi64) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx")] +pub unsafe fn _mm256_mask_load_epi64(src: __m256i, k: __mmask8, mem_addr: *const i64) -> __m256i { + let mut dst: __m256i = src; + asm!( + vpl!("vmovdqa64 {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(ymm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 64-bit integers from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr must be aligned on a 32-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_load_epi64) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx")] +pub unsafe fn _mm256_maskz_load_epi64(k: __mmask8, mem_addr: *const i64) -> __m256i { + let mut dst: __m256i; + asm!( + vpl!("vmovdqa64 {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(ymm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed single-precision (32-bit) floating-point elements from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr must be aligned on a 32-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_load_ps) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx")] +pub unsafe fn _mm256_mask_load_ps(src: __m256, k: __mmask8, mem_addr: *const f32) -> __m256 { + let mut dst: __m256 = src; + asm!( + vpl!("vmovaps {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(ymm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed single-precision (32-bit) floating-point elements from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr must be aligned on a 32-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_load_ps) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx")] +pub unsafe fn _mm256_maskz_load_ps(k: __mmask8, mem_addr: *const f32) -> __m256 { + let mut dst: __m256; + asm!( + vpl!("vmovaps {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(ymm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed double-precision (64-bit) floating-point elements from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr must be aligned on a 32-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_load_pd) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx")] +pub unsafe fn _mm256_mask_load_pd(src: __m256d, k: __mmask8, mem_addr: *const f64) -> __m256d { + let mut dst: __m256d = src; + asm!( + vpl!("vmovapd {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(ymm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed double-precision (64-bit) floating-point elements from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr must be aligned on a 32-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_maskz_load_pd) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx")] +pub unsafe fn _mm256_maskz_load_pd(k: __mmask8, mem_addr: *const f64) -> __m256d { + let mut dst: __m256d; + asm!( + vpl!("vmovapd {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(ymm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 32-bit integers from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr must be aligned on a 16-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_load_epi32) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx,sse")] +pub unsafe fn _mm_mask_load_epi32(src: __m128i, k: __mmask8, mem_addr: *const i32) -> __m128i { + let mut dst: __m128i = src; + asm!( + vpl!("vmovdqa32 {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(xmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 32-bit integers from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr must be aligned on a 16-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_load_epi32) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx,sse")] +pub unsafe fn _mm_maskz_load_epi32(k: __mmask8, mem_addr: *const i32) -> __m128i { + let mut dst: __m128i; + asm!( + vpl!("vmovdqa32 {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(xmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 64-bit integers from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr must be aligned on a 16-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_load_epi64) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx,sse")] +pub unsafe fn _mm_mask_load_epi64(src: __m128i, k: __mmask8, mem_addr: *const i64) -> __m128i { + let mut dst: __m128i = src; + asm!( + vpl!("vmovdqa64 {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(xmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed 64-bit integers from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr must be aligned on a 16-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_load_epi64) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx,sse")] +pub unsafe fn _mm_maskz_load_epi64(k: __mmask8, mem_addr: *const i64) -> __m128i { + let mut dst: __m128i; + asm!( + vpl!("vmovdqa64 {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(xmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed single-precision (32-bit) floating-point elements from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr must be aligned on a 16-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_load_ps) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx,sse")] +pub unsafe fn _mm_mask_load_ps(src: __m128, k: __mmask8, mem_addr: *const f32) -> __m128 { + let mut dst: __m128 = src; + asm!( + vpl!("vmovaps {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(xmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed single-precision (32-bit) floating-point elements from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr must be aligned on a 16-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_load_ps) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx,sse")] +pub unsafe fn _mm_maskz_load_ps(k: __mmask8, mem_addr: *const f32) -> __m128 { + let mut dst: __m128; + asm!( + vpl!("vmovaps {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(xmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed double-precision (64-bit) floating-point elements from memory into dst using writemask k +/// (elements are copied from src when the corresponding mask bit is not set). +/// mem_addr must be aligned on a 16-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_load_pd) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx,sse")] +pub unsafe fn _mm_mask_load_pd(src: __m128d, k: __mmask8, mem_addr: *const f64) -> __m128d { + let mut dst: __m128d = src; + asm!( + vpl!("vmovapd {dst}{{{k}}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = inout(xmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Load packed double-precision (64-bit) floating-point elements from memory into dst using zeromask k +/// (elements are zeroed out when the corresponding mask bit is not set). +/// mem_addr must be aligned on a 16-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_maskz_load_pd) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx,sse")] +pub unsafe fn _mm_maskz_load_pd(k: __mmask8, mem_addr: *const f64) -> __m128d { + let mut dst: __m128d; + asm!( + vpl!("vmovapd {dst}{{{k}}} {{z}}"), + p = in(reg) mem_addr, + k = in(kreg) k, + dst = out(xmm_reg) dst, + options(pure, readonly, nostack) + ); + dst +} + +/// Store packed 32-bit integers from a into memory using writemask k. +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_storeu_epi32) +#[inline] +#[target_feature(enable = "avx512f")] +pub unsafe fn _mm512_mask_storeu_epi32(mem_addr: *mut i32, mask: __mmask16, a: __m512i) { + asm!( + vps!("vmovdqu32", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(zmm_reg) a, + options(nostack) + ); +} + +/// Store packed 64-bit integers from a into memory using writemask k. +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_storeu_epi64) +#[inline] +#[target_feature(enable = "avx512f")] +pub unsafe fn _mm512_mask_storeu_epi64(mem_addr: *mut i64, mask: __mmask8, a: __m512i) { + asm!( + vps!("vmovdqu64", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(zmm_reg) a, + options(nostack) + ); +} + +/// Store packed single-precision (32-bit) floating-point elements from a into memory using writemask k. +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_storeu_ps) +#[inline] +#[target_feature(enable = "avx512f")] +pub unsafe fn _mm512_mask_storeu_ps(mem_addr: *mut f32, mask: __mmask16, a: __m512) { + asm!( + vps!("vmovups", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(zmm_reg) a, + options(nostack) + ); +} + +/// Store packed double-precision (64-bit) floating-point elements from a into memory using writemask k. +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_storeu_pd) +#[inline] +#[target_feature(enable = "avx512f")] +pub unsafe fn _mm512_mask_storeu_pd(mem_addr: *mut f64, mask: __mmask8, a: __m512d) { + asm!( + vps!("vmovupd", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(zmm_reg) a, + options(nostack) + ); +} + +/// Store packed 32-bit integers from a into memory using writemask k. +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_storeu_epi32) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx")] +pub unsafe fn _mm256_mask_storeu_epi32(mem_addr: *mut i32, mask: __mmask8, a: __m256i) { + asm!( + vps!("vmovdqu32", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(ymm_reg) a, + options(nostack) + ); +} + +/// Store packed 64-bit integers from a into memory using writemask k. +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_storeu_epi64) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx")] +pub unsafe fn _mm256_mask_storeu_epi64(mem_addr: *mut i64, mask: __mmask8, a: __m256i) { + asm!( + vps!("vmovdqu64", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(ymm_reg) a, + options(nostack) + ); +} + +/// Store packed single-precision (32-bit) floating-point elements from a into memory using writemask k. +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_storeu_ps) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx")] +pub unsafe fn _mm256_mask_storeu_ps(mem_addr: *mut f32, mask: __mmask8, a: __m256) { + asm!( + vps!("vmovups", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(ymm_reg) a, + options(nostack) + ); +} + +/// Store packed double-precision (64-bit) floating-point elements from a into memory using writemask k. +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_storeu_pd) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx")] +pub unsafe fn _mm256_mask_storeu_pd(mem_addr: *mut f64, mask: __mmask8, a: __m256d) { + asm!( + vps!("vmovupd", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(ymm_reg) a, + options(nostack) + ); +} + +/// Store packed 32-bit integers from a into memory using writemask k. +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_storeu_epi32) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx,sse")] +pub unsafe fn _mm_mask_storeu_epi32(mem_addr: *mut i32, mask: __mmask8, a: __m128i) { + asm!( + vps!("vmovdqu32", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(xmm_reg) a, + options(nostack) + ); +} + +/// Store packed 64-bit integers from a into memory using writemask k. +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_storeu_epi64) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx,sse")] +pub unsafe fn _mm_mask_storeu_epi64(mem_addr: *mut i64, mask: __mmask8, a: __m128i) { + asm!( + vps!("vmovdqu64", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(xmm_reg) a, + options(nostack) + ); +} + +/// Store packed single-precision (32-bit) floating-point elements from a into memory using writemask k. +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_storeu_ps) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx,sse")] +pub unsafe fn _mm_mask_storeu_ps(mem_addr: *mut f32, mask: __mmask8, a: __m128) { + asm!( + vps!("vmovups", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(xmm_reg) a, + options(nostack) + ); +} + +/// Store packed double-precision (64-bit) floating-point elements from a into memory using writemask k. +/// mem_addr does not need to be aligned on any particular boundary. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_storeu_pd) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx,sse")] +pub unsafe fn _mm_mask_storeu_pd(mem_addr: *mut f64, mask: __mmask8, a: __m128d) { + asm!( + vps!("vmovupd", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(xmm_reg) a, + options(nostack) + ); +} + +/// Store packed 32-bit integers from a into memory using writemask k. +/// mem_addr must be aligned on a 64-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_store_epi32) +#[inline] +#[target_feature(enable = "avx512f")] +pub unsafe fn _mm512_mask_store_epi32(mem_addr: *mut i32, mask: __mmask16, a: __m512i) { + asm!( + vps!("vmovdqa32", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(zmm_reg) a, + options(nostack) + ); +} + +/// Store packed 64-bit integers from a into memory using writemask k. +/// mem_addr must be aligned on a 64-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_store_epi64) +#[inline] +#[target_feature(enable = "avx512f")] +pub unsafe fn _mm512_mask_store_epi64(mem_addr: *mut i64, mask: __mmask8, a: __m512i) { + asm!( + vps!("vmovdqa64", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(zmm_reg) a, + options(nostack) + ); +} + +/// Store packed single-precision (32-bit) floating-point elements from a into memory using writemask k. +/// mem_addr must be aligned on a 64-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_store_ps) +#[inline] +#[target_feature(enable = "avx512f")] +pub unsafe fn _mm512_mask_store_ps(mem_addr: *mut f32, mask: __mmask16, a: __m512) { + asm!( + vps!("vmovaps", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(zmm_reg) a, + options(nostack) + ); +} + +/// Store packed double-precision (64-bit) floating-point elements from a into memory using writemask k. +/// mem_addr must be aligned on a 64-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_mask_store_pd) +#[inline] +#[target_feature(enable = "avx512f")] +pub unsafe fn _mm512_mask_store_pd(mem_addr: *mut f64, mask: __mmask8, a: __m512d) { + asm!( + vps!("vmovapd", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(zmm_reg) a, + options(nostack) + ); +} + +/// Store packed 32-bit integers from a into memory using writemask k. +/// mem_addr must be aligned on a 32-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_store_epi32) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx")] +pub unsafe fn _mm256_mask_store_epi32(mem_addr: *mut i32, mask: __mmask8, a: __m256i) { + asm!( + vps!("vmovdqa32", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(ymm_reg) a, + options(nostack) + ); +} + +/// Store packed 64-bit integers from a into memory using writemask k. +/// mem_addr must be aligned on a 32-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_store_epi64) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx")] +pub unsafe fn _mm256_mask_store_epi64(mem_addr: *mut i64, mask: __mmask8, a: __m256i) { + asm!( + vps!("vmovdqa64", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(ymm_reg) a, + options(nostack) + ); +} + +/// Store packed single-precision (32-bit) floating-point elements from a into memory using writemask k. +/// mem_addr must be aligned on a 32-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_store_ps) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx")] +pub unsafe fn _mm256_mask_store_ps(mem_addr: *mut f32, mask: __mmask8, a: __m256) { + asm!( + vps!("vmovaps", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(ymm_reg) a, + options(nostack) + ); +} + +/// Store packed double-precision (64-bit) floating-point elements from a into memory using writemask k. +/// mem_addr must be aligned on a 32-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm256_mask_store_pd) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx")] +pub unsafe fn _mm256_mask_store_pd(mem_addr: *mut f64, mask: __mmask8, a: __m256d) { + asm!( + vps!("vmovapd", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(ymm_reg) a, + options(nostack) + ); +} + +/// Store packed 32-bit integers from a into memory using writemask k. +/// mem_addr must be aligned on a 16-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_store_epi32) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx,sse")] +pub unsafe fn _mm_mask_store_epi32(mem_addr: *mut i32, mask: __mmask8, a: __m128i) { + asm!( + vps!("vmovdqa32", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(xmm_reg) a, + options(nostack) + ); +} + +/// Store packed 64-bit integers from a into memory using writemask k. +/// mem_addr must be aligned on a 16-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_store_epi64) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx,sse")] +pub unsafe fn _mm_mask_store_epi64(mem_addr: *mut i64, mask: __mmask8, a: __m128i) { + asm!( + vps!("vmovdqa64", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(xmm_reg) a, + options(nostack) + ); +} + +/// Store packed single-precision (32-bit) floating-point elements from a into memory using writemask k. +/// mem_addr must be aligned on a 16-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_store_ps) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx,sse")] +pub unsafe fn _mm_mask_store_ps(mem_addr: *mut f32, mask: __mmask8, a: __m128) { + asm!( + vps!("vmovaps", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(xmm_reg) a, + options(nostack) + ); +} + +/// Store packed double-precision (64-bit) floating-point elements from a into memory using writemask k. +/// mem_addr must be aligned on a 16-byte boundary or a general-protection exception may be generated. +/// +/// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mask_store_pd) +#[inline] +#[target_feature(enable = "avx512f,avx512vl,avx,sse")] +pub unsafe fn _mm_mask_store_pd(mem_addr: *mut f64, mask: __mmask8, a: __m128d) { + asm!( + vps!("vmovapd", "{{{mask}}}, {a}"), + p = in(reg) mem_addr, + mask = in(kreg) mask, + a = in(xmm_reg) a, + options(nostack) + ); +} + /// Set packed double-precision (64-bit) floating-point elements in dst with the supplied values in reverse order. /// /// [Intel's documentation]( https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm512_setr_pd&expand=5002) @@ -44587,6 +45915,971 @@ mod tests { assert_eq_m512(r, a); } + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_loadu_epi32() { + let src = _mm512_set1_epi32(42); + let a = &[1_i32, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let p = a.as_ptr(); + let m = 0b11101000_11001010; + let r = _mm512_mask_loadu_epi32(src, m, black_box(p)); + let e = _mm512_setr_epi32(42, 2, 42, 4, 42, 42, 7, 8, 42, 42, 42, 12, 42, 14, 15, 16); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_maskz_loadu_epi32() { + let a = &[1_i32, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; + let p = a.as_ptr(); + let m = 0b11101000_11001010; + let r = _mm512_maskz_loadu_epi32(m, black_box(p)); + let e = _mm512_setr_epi32(0, 2, 0, 4, 0, 0, 7, 8, 0, 0, 0, 12, 0, 14, 15, 16); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_load_epi32() { + #[repr(align(64))] + struct Align { + data: [i32; 16], // 64 bytes + } + let src = _mm512_set1_epi32(42); + let a = Align { + data: [1_i32, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], + }; + let p = a.data.as_ptr(); + let m = 0b11101000_11001010; + let r = _mm512_mask_load_epi32(src, m, black_box(p)); + let e = _mm512_setr_epi32(42, 2, 42, 4, 42, 42, 7, 8, 42, 42, 42, 12, 42, 14, 15, 16); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_maskz_load_epi32() { + #[repr(align(64))] + struct Align { + data: [i32; 16], // 64 bytes + } + let a = Align { + data: [1_i32, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], + }; + let p = a.data.as_ptr(); + let m = 0b11101000_11001010; + let r = _mm512_maskz_load_epi32(m, black_box(p)); + let e = _mm512_setr_epi32(0, 2, 0, 4, 0, 0, 7, 8, 0, 0, 0, 12, 0, 14, 15, 16); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_storeu_epi32() { + let mut r = [42_i32; 16]; + let a = _mm512_setr_epi32(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let m = 0b11101000_11001010; + _mm512_mask_storeu_epi32(r.as_mut_ptr(), m, a); + let e = _mm512_setr_epi32(42, 2, 42, 4, 42, 42, 7, 8, 42, 42, 42, 12, 42, 14, 15, 16); + assert_eq_m512i(_mm512_loadu_epi32(r.as_ptr()), e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_store_epi32() { + #[repr(align(64))] + struct Align { + data: [i32; 16], + } + let mut r = Align { data: [42; 16] }; + let a = _mm512_setr_epi32(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + let m = 0b11101000_11001010; + _mm512_mask_store_epi32(r.data.as_mut_ptr(), m, a); + let e = _mm512_setr_epi32(42, 2, 42, 4, 42, 42, 7, 8, 42, 42, 42, 12, 42, 14, 15, 16); + assert_eq_m512i(_mm512_load_epi32(r.data.as_ptr()), e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_loadu_epi64() { + let src = _mm512_set1_epi64(42); + let a = &[1_i64, 2, 3, 4, 5, 6, 7, 8]; + let p = a.as_ptr(); + let m = 0b11001010; + let r = _mm512_mask_loadu_epi64(src, m, black_box(p)); + let e = _mm512_setr_epi64(42, 2, 42, 4, 42, 42, 7, 8); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_maskz_loadu_epi64() { + let a = &[1_i64, 2, 3, 4, 5, 6, 7, 8]; + let p = a.as_ptr(); + let m = 0b11001010; + let r = _mm512_maskz_loadu_epi64(m, black_box(p)); + let e = _mm512_setr_epi64(0, 2, 0, 4, 0, 0, 7, 8); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_load_epi64() { + #[repr(align(64))] + struct Align { + data: [i64; 8], // 64 bytes + } + let src = _mm512_set1_epi64(42); + let a = Align { + data: [1_i64, 2, 3, 4, 5, 6, 7, 8], + }; + let p = a.data.as_ptr(); + let m = 0b11001010; + let r = _mm512_mask_load_epi64(src, m, black_box(p)); + let e = _mm512_setr_epi64(42, 2, 42, 4, 42, 42, 7, 8); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_maskz_load_epi64() { + #[repr(align(64))] + struct Align { + data: [i64; 8], // 64 bytes + } + let a = Align { + data: [1_i64, 2, 3, 4, 5, 6, 7, 8], + }; + let p = a.data.as_ptr(); + let m = 0b11001010; + let r = _mm512_maskz_load_epi64(m, black_box(p)); + let e = _mm512_setr_epi64(0, 2, 0, 4, 0, 0, 7, 8); + assert_eq_m512i(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_storeu_epi64() { + let mut r = [42_i64; 8]; + let a = _mm512_setr_epi64(1, 2, 3, 4, 5, 6, 7, 8); + let m = 0b11001010; + _mm512_mask_storeu_epi64(r.as_mut_ptr(), m, a); + let e = _mm512_setr_epi64(42, 2, 42, 4, 42, 42, 7, 8); + assert_eq_m512i(_mm512_loadu_epi64(r.as_ptr()), e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_store_epi64() { + #[repr(align(64))] + struct Align { + data: [i64; 8], + } + let mut r = Align { data: [42; 8] }; + let a = _mm512_setr_epi64(1, 2, 3, 4, 5, 6, 7, 8); + let m = 0b11001010; + let p = r.data.as_mut_ptr(); + _mm512_mask_store_epi64(p, m, a); + let e = _mm512_setr_epi64(42, 2, 42, 4, 42, 42, 7, 8); + assert_eq_m512i(_mm512_load_epi64(r.data.as_ptr()), e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_loadu_ps() { + let src = _mm512_set1_ps(42.0); + let a = &[ + 1.0_f32, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, + 16.0, + ]; + let p = a.as_ptr(); + let m = 0b11101000_11001010; + let r = _mm512_mask_loadu_ps(src, m, black_box(p)); + let e = _mm512_setr_ps( + 42.0, 2.0, 42.0, 4.0, 42.0, 42.0, 7.0, 8.0, 42.0, 42.0, 42.0, 12.0, 42.0, 14.0, 15.0, + 16.0, + ); + assert_eq_m512(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_maskz_loadu_ps() { + let a = &[ + 1.0_f32, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, + 16.0, + ]; + let p = a.as_ptr(); + let m = 0b11101000_11001010; + let r = _mm512_maskz_loadu_ps(m, black_box(p)); + let e = _mm512_setr_ps( + 0.0, 2.0, 0.0, 4.0, 0.0, 0.0, 7.0, 8.0, 0.0, 0.0, 0.0, 12.0, 0.0, 14.0, 15.0, 16.0, + ); + assert_eq_m512(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_load_ps() { + #[repr(align(64))] + struct Align { + data: [f32; 16], // 64 bytes + } + let src = _mm512_set1_ps(42.0); + let a = Align { + data: [ + 1.0_f32, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, + 15.0, 16.0, + ], + }; + let p = a.data.as_ptr(); + let m = 0b11101000_11001010; + let r = _mm512_mask_load_ps(src, m, black_box(p)); + let e = _mm512_setr_ps( + 42.0, 2.0, 42.0, 4.0, 42.0, 42.0, 7.0, 8.0, 42.0, 42.0, 42.0, 12.0, 42.0, 14.0, 15.0, + 16.0, + ); + assert_eq_m512(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_maskz_load_ps() { + #[repr(align(64))] + struct Align { + data: [f32; 16], // 64 bytes + } + let a = Align { + data: [ + 1.0_f32, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, + 15.0, 16.0, + ], + }; + let p = a.data.as_ptr(); + let m = 0b11101000_11001010; + let r = _mm512_maskz_load_ps(m, black_box(p)); + let e = _mm512_setr_ps( + 0.0, 2.0, 0.0, 4.0, 0.0, 0.0, 7.0, 8.0, 0.0, 0.0, 0.0, 12.0, 0.0, 14.0, 15.0, 16.0, + ); + assert_eq_m512(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_storeu_ps() { + let mut r = [42_f32; 16]; + let a = _mm512_setr_ps( + 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, + ); + let m = 0b11101000_11001010; + _mm512_mask_storeu_ps(r.as_mut_ptr(), m, a); + let e = _mm512_setr_ps( + 42.0, 2.0, 42.0, 4.0, 42.0, 42.0, 7.0, 8.0, 42.0, 42.0, 42.0, 12.0, 42.0, 14.0, 15.0, + 16.0, + ); + assert_eq_m512(_mm512_loadu_ps(r.as_ptr()), e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_store_ps() { + #[repr(align(64))] + struct Align { + data: [f32; 16], + } + let mut r = Align { data: [42.0; 16] }; + let a = _mm512_setr_ps( + 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, + ); + let m = 0b11101000_11001010; + _mm512_mask_store_ps(r.data.as_mut_ptr(), m, a); + let e = _mm512_setr_ps( + 42.0, 2.0, 42.0, 4.0, 42.0, 42.0, 7.0, 8.0, 42.0, 42.0, 42.0, 12.0, 42.0, 14.0, 15.0, + 16.0, + ); + assert_eq_m512(_mm512_load_ps(r.data.as_ptr()), e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_loadu_pd() { + let src = _mm512_set1_pd(42.0); + let a = &[1.0_f64, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]; + let p = a.as_ptr(); + let m = 0b11001010; + let r = _mm512_mask_loadu_pd(src, m, black_box(p)); + let e = _mm512_setr_pd(42.0, 2.0, 42.0, 4.0, 42.0, 42.0, 7.0, 8.0); + assert_eq_m512d(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_maskz_loadu_pd() { + let a = &[1.0_f64, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]; + let p = a.as_ptr(); + let m = 0b11001010; + let r = _mm512_maskz_loadu_pd(m, black_box(p)); + let e = _mm512_setr_pd(0.0, 2.0, 0.0, 4.0, 0.0, 0.0, 7.0, 8.0); + assert_eq_m512d(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_load_pd() { + #[repr(align(64))] + struct Align { + data: [f64; 8], // 64 bytes + } + let src = _mm512_set1_pd(42.0); + let a = Align { + data: [1.0_f64, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0], + }; + let p = a.data.as_ptr(); + let m = 0b11001010; + let r = _mm512_mask_load_pd(src, m, black_box(p)); + let e = _mm512_setr_pd(42.0, 2.0, 42.0, 4.0, 42.0, 42.0, 7.0, 8.0); + assert_eq_m512d(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_maskz_load_pd() { + #[repr(align(64))] + struct Align { + data: [f64; 8], // 64 bytes + } + let a = Align { + data: [1.0_f64, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0], + }; + let p = a.data.as_ptr(); + let m = 0b11001010; + let r = _mm512_maskz_load_pd(m, black_box(p)); + let e = _mm512_setr_pd(0.0, 2.0, 0.0, 4.0, 0.0, 0.0, 7.0, 8.0); + assert_eq_m512d(r, e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_storeu_pd() { + let mut r = [42_f64; 8]; + let a = _mm512_setr_pd(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0); + let m = 0b11001010; + _mm512_mask_storeu_pd(r.as_mut_ptr(), m, a); + let e = _mm512_setr_pd(42.0, 2.0, 42.0, 4.0, 42.0, 42.0, 7.0, 8.0); + assert_eq_m512d(_mm512_loadu_pd(r.as_ptr()), e); + } + + #[simd_test(enable = "avx512f")] + unsafe fn test_mm512_mask_store_pd() { + #[repr(align(64))] + struct Align { + data: [f64; 8], + } + let mut r = Align { data: [42.0; 8] }; + let a = _mm512_setr_pd(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0); + let m = 0b11001010; + _mm512_mask_store_pd(r.data.as_mut_ptr(), m, a); + let e = _mm512_setr_pd(42.0, 2.0, 42.0, 4.0, 42.0, 42.0, 7.0, 8.0); + assert_eq_m512d(_mm512_load_pd(r.data.as_ptr()), e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_loadu_epi32() { + let src = _mm256_set1_epi32(42); + let a = &[1_i32, 2, 3, 4, 5, 6, 7, 8]; + let p = a.as_ptr(); + let m = 0b11001010; + let r = _mm256_mask_loadu_epi32(src, m, black_box(p)); + let e = _mm256_setr_epi32(42, 2, 42, 4, 42, 42, 7, 8); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_loadu_epi32() { + let a = &[1_i32, 2, 3, 4, 5, 6, 7, 8]; + let p = a.as_ptr(); + let m = 0b11001010; + let r = _mm256_maskz_loadu_epi32(m, black_box(p)); + let e = _mm256_setr_epi32(0, 2, 0, 4, 0, 0, 7, 8); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_load_epi32() { + #[repr(align(32))] + struct Align { + data: [i32; 8], // 32 bytes + } + let src = _mm256_set1_epi32(42); + let a = Align { + data: [1_i32, 2, 3, 4, 5, 6, 7, 8], + }; + let p = a.data.as_ptr(); + let m = 0b11001010; + let r = _mm256_mask_load_epi32(src, m, black_box(p)); + let e = _mm256_setr_epi32(42, 2, 42, 4, 42, 42, 7, 8); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_load_epi32() { + #[repr(align(32))] + struct Align { + data: [i32; 8], // 32 bytes + } + let a = Align { + data: [1_i32, 2, 3, 4, 5, 6, 7, 8], + }; + let p = a.data.as_ptr(); + let m = 0b11001010; + let r = _mm256_maskz_load_epi32(m, black_box(p)); + let e = _mm256_setr_epi32(0, 2, 0, 4, 0, 0, 7, 8); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_storeu_epi32() { + let mut r = [42_i32; 8]; + let a = _mm256_setr_epi32(1, 2, 3, 4, 5, 6, 7, 8); + let m = 0b11001010; + _mm256_mask_storeu_epi32(r.as_mut_ptr(), m, a); + let e = _mm256_setr_epi32(42, 2, 42, 4, 42, 42, 7, 8); + assert_eq_m256i(_mm256_loadu_epi32(r.as_ptr()), e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_store_epi32() { + #[repr(align(64))] + struct Align { + data: [i32; 8], + } + let mut r = Align { data: [42; 8] }; + let a = _mm256_setr_epi32(1, 2, 3, 4, 5, 6, 7, 8); + let m = 0b11001010; + _mm256_mask_store_epi32(r.data.as_mut_ptr(), m, a); + let e = _mm256_setr_epi32(42, 2, 42, 4, 42, 42, 7, 8); + assert_eq_m256i(_mm256_load_epi32(r.data.as_ptr()), e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_loadu_epi64() { + let src = _mm256_set1_epi64x(42); + let a = &[1_i64, 2, 3, 4]; + let p = a.as_ptr(); + let m = 0b1010; + let r = _mm256_mask_loadu_epi64(src, m, black_box(p)); + let e = _mm256_setr_epi64x(42, 2, 42, 4); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_loadu_epi64() { + let a = &[1_i64, 2, 3, 4]; + let p = a.as_ptr(); + let m = 0b1010; + let r = _mm256_maskz_loadu_epi64(m, black_box(p)); + let e = _mm256_setr_epi64x(0, 2, 0, 4); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_load_epi64() { + #[repr(align(32))] + struct Align { + data: [i64; 4], // 32 bytes + } + let src = _mm256_set1_epi64x(42); + let a = Align { + data: [1_i64, 2, 3, 4], + }; + let p = a.data.as_ptr(); + let m = 0b1010; + let r = _mm256_mask_load_epi64(src, m, black_box(p)); + let e = _mm256_setr_epi64x(42, 2, 42, 4); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_load_epi64() { + #[repr(align(32))] + struct Align { + data: [i64; 4], // 32 bytes + } + let a = Align { + data: [1_i64, 2, 3, 4], + }; + let p = a.data.as_ptr(); + let m = 0b1010; + let r = _mm256_maskz_load_epi64(m, black_box(p)); + let e = _mm256_setr_epi64x(0, 2, 0, 4); + assert_eq_m256i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_storeu_epi64() { + let mut r = [42_i64; 4]; + let a = _mm256_setr_epi64x(1, 2, 3, 4); + let m = 0b1010; + _mm256_mask_storeu_epi64(r.as_mut_ptr(), m, a); + let e = _mm256_setr_epi64x(42, 2, 42, 4); + assert_eq_m256i(_mm256_loadu_epi64(r.as_ptr()), e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_store_epi64() { + #[repr(align(32))] + struct Align { + data: [i64; 4], + } + let mut r = Align { data: [42; 4] }; + let a = _mm256_setr_epi64x(1, 2, 3, 4); + let m = 0b1010; + _mm256_mask_store_epi64(r.data.as_mut_ptr(), m, a); + let e = _mm256_setr_epi64x(42, 2, 42, 4); + assert_eq_m256i(_mm256_load_epi64(r.data.as_ptr()), e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_loadu_ps() { + let src = _mm256_set1_ps(42.0); + let a = &[1.0_f32, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]; + let p = a.as_ptr(); + let m = 0b11001010; + let r = _mm256_mask_loadu_ps(src, m, black_box(p)); + let e = _mm256_setr_ps(42.0, 2.0, 42.0, 4.0, 42.0, 42.0, 7.0, 8.0); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_loadu_ps() { + let a = &[1.0_f32, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]; + let p = a.as_ptr(); + let m = 0b11001010; + let r = _mm256_maskz_loadu_ps(m, black_box(p)); + let e = _mm256_setr_ps(0.0, 2.0, 0.0, 4.0, 0.0, 0.0, 7.0, 8.0); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_load_ps() { + #[repr(align(32))] + struct Align { + data: [f32; 8], // 32 bytes + } + let src = _mm256_set1_ps(42.0); + let a = Align { + data: [1.0_f32, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0], + }; + let p = a.data.as_ptr(); + let m = 0b11001010; + let r = _mm256_mask_load_ps(src, m, black_box(p)); + let e = _mm256_setr_ps(42.0, 2.0, 42.0, 4.0, 42.0, 42.0, 7.0, 8.0); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_load_ps() { + #[repr(align(32))] + struct Align { + data: [f32; 8], // 32 bytes + } + let a = Align { + data: [1.0_f32, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0], + }; + let p = a.data.as_ptr(); + let m = 0b11001010; + let r = _mm256_maskz_load_ps(m, black_box(p)); + let e = _mm256_setr_ps(0.0, 2.0, 0.0, 4.0, 0.0, 0.0, 7.0, 8.0); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_storeu_ps() { + let mut r = [42_f32; 8]; + let a = _mm256_setr_ps(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0); + let m = 0b11001010; + _mm256_mask_storeu_ps(r.as_mut_ptr(), m, a); + let e = _mm256_setr_ps(42.0, 2.0, 42.0, 4.0, 42.0, 42.0, 7.0, 8.0); + assert_eq_m256(_mm256_loadu_ps(r.as_ptr()), e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_store_ps() { + #[repr(align(32))] + struct Align { + data: [f32; 8], + } + let mut r = Align { data: [42.0; 8] }; + let a = _mm256_setr_ps(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0); + let m = 0b11001010; + _mm256_mask_store_ps(r.data.as_mut_ptr(), m, a); + let e = _mm256_setr_ps(42.0, 2.0, 42.0, 4.0, 42.0, 42.0, 7.0, 8.0); + assert_eq_m256(_mm256_load_ps(r.data.as_ptr()), e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_loadu_pd() { + let src = _mm256_set1_pd(42.0); + let a = &[1.0_f64, 2.0, 3.0, 4.0]; + let p = a.as_ptr(); + let m = 0b1010; + let r = _mm256_mask_loadu_pd(src, m, black_box(p)); + let e = _mm256_setr_pd(42.0, 2.0, 42.0, 4.0); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_loadu_pd() { + let a = &[1.0_f64, 2.0, 3.0, 4.0]; + let p = a.as_ptr(); + let m = 0b1010; + let r = _mm256_maskz_loadu_pd(m, black_box(p)); + let e = _mm256_setr_pd(0.0, 2.0, 0.0, 4.0); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_load_pd() { + #[repr(align(32))] + struct Align { + data: [f64; 4], // 32 bytes + } + let src = _mm256_set1_pd(42.0); + let a = Align { + data: [1.0_f64, 2.0, 3.0, 4.0], + }; + let p = a.data.as_ptr(); + let m = 0b1010; + let r = _mm256_mask_load_pd(src, m, black_box(p)); + let e = _mm256_setr_pd(42.0, 2.0, 42.0, 4.0); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_maskz_load_pd() { + #[repr(align(32))] + struct Align { + data: [f64; 4], // 32 bytes + } + let a = Align { + data: [1.0_f64, 2.0, 3.0, 4.0], + }; + let p = a.data.as_ptr(); + let m = 0b1010; + let r = _mm256_maskz_load_pd(m, black_box(p)); + let e = _mm256_setr_pd(0.0, 2.0, 0.0, 4.0); + assert_eq_m256d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_storeu_pd() { + let mut r = [42_f64; 4]; + let a = _mm256_setr_pd(1.0, 2.0, 3.0, 4.0); + let m = 0b1010; + _mm256_mask_storeu_pd(r.as_mut_ptr(), m, a); + let e = _mm256_setr_pd(42.0, 2.0, 42.0, 4.0); + assert_eq_m256d(_mm256_loadu_pd(r.as_ptr()), e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm256_mask_store_pd() { + #[repr(align(32))] + struct Align { + data: [f64; 4], + } + let mut r = Align { data: [42.0; 4] }; + let a = _mm256_setr_pd(1.0, 2.0, 3.0, 4.0); + let m = 0b1010; + _mm256_mask_store_pd(r.data.as_mut_ptr(), m, a); + let e = _mm256_setr_pd(42.0, 2.0, 42.0, 4.0); + assert_eq_m256d(_mm256_load_pd(r.data.as_ptr()), e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_loadu_epi32() { + let src = _mm_set1_epi32(42); + let a = &[1_i32, 2, 3, 4]; + let p = a.as_ptr(); + let m = 0b1010; + let r = _mm_mask_loadu_epi32(src, m, black_box(p)); + let e = _mm_setr_epi32(42, 2, 42, 4); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_loadu_epi32() { + let a = &[1_i32, 2, 3, 4]; + let p = a.as_ptr(); + let m = 0b1010; + let r = _mm_maskz_loadu_epi32(m, black_box(p)); + let e = _mm_setr_epi32(0, 2, 0, 4); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_load_epi32() { + #[repr(align(16))] + struct Align { + data: [i32; 4], // 32 bytes + } + let src = _mm_set1_epi32(42); + let a = Align { + data: [1_i32, 2, 3, 4], + }; + let p = a.data.as_ptr(); + let m = 0b1010; + let r = _mm_mask_load_epi32(src, m, black_box(p)); + let e = _mm_setr_epi32(42, 2, 42, 4); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_load_epi32() { + #[repr(align(16))] + struct Align { + data: [i32; 4], // 16 bytes + } + let a = Align { + data: [1_i32, 2, 3, 4], + }; + let p = a.data.as_ptr(); + let m = 0b1010; + let r = _mm_maskz_load_epi32(m, black_box(p)); + let e = _mm_setr_epi32(0, 2, 0, 4); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_storeu_epi32() { + let mut r = [42_i32; 4]; + let a = _mm_setr_epi32(1, 2, 3, 4); + let m = 0b1010; + _mm_mask_storeu_epi32(r.as_mut_ptr(), m, a); + let e = _mm_setr_epi32(42, 2, 42, 4); + assert_eq_m128i(_mm_loadu_epi32(r.as_ptr()), e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_store_epi32() { + #[repr(align(16))] + struct Align { + data: [i32; 4], // 16 bytes + } + let mut r = Align { data: [42; 4] }; + let a = _mm_setr_epi32(1, 2, 3, 4); + let m = 0b1010; + _mm_mask_store_epi32(r.data.as_mut_ptr(), m, a); + let e = _mm_setr_epi32(42, 2, 42, 4); + assert_eq_m128i(_mm_load_epi32(r.data.as_ptr()), e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_loadu_epi64() { + let src = _mm_set1_epi64x(42); + let a = &[1_i64, 2]; + let p = a.as_ptr(); + let m = 0b10; + let r = _mm_mask_loadu_epi64(src, m, black_box(p)); + let e = _mm_setr_epi64x(42, 2); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_loadu_epi64() { + let a = &[1_i64, 2]; + let p = a.as_ptr(); + let m = 0b10; + let r = _mm_maskz_loadu_epi64(m, black_box(p)); + let e = _mm_setr_epi64x(0, 2); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_load_epi64() { + #[repr(align(16))] + struct Align { + data: [i64; 2], // 16 bytes + } + let src = _mm_set1_epi64x(42); + let a = Align { data: [1_i64, 2] }; + let p = a.data.as_ptr(); + let m = 0b10; + let r = _mm_mask_load_epi64(src, m, black_box(p)); + let e = _mm_setr_epi64x(42, 2); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_load_epi64() { + #[repr(align(16))] + struct Align { + data: [i64; 2], // 16 bytes + } + let a = Align { data: [1_i64, 2] }; + let p = a.data.as_ptr(); + let m = 0b10; + let r = _mm_maskz_load_epi64(m, black_box(p)); + let e = _mm_setr_epi64x(0, 2); + assert_eq_m128i(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_storeu_epi64() { + let mut r = [42_i64; 2]; + let a = _mm_setr_epi64x(1, 2); + let m = 0b10; + _mm_mask_storeu_epi64(r.as_mut_ptr(), m, a); + let e = _mm_setr_epi64x(42, 2); + assert_eq_m128i(_mm_loadu_epi64(r.as_ptr()), e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_store_epi64() { + #[repr(align(16))] + struct Align { + data: [i64; 2], // 16 bytes + } + let mut r = Align { data: [42; 2] }; + let a = _mm_setr_epi64x(1, 2); + let m = 0b10; + _mm_mask_store_epi64(r.data.as_mut_ptr(), m, a); + let e = _mm_setr_epi64x(42, 2); + assert_eq_m128i(_mm_load_epi64(r.data.as_ptr()), e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_loadu_ps() { + let src = _mm_set1_ps(42.0); + let a = &[1.0_f32, 2.0, 3.0, 4.0]; + let p = a.as_ptr(); + let m = 0b1010; + let r = _mm_mask_loadu_ps(src, m, black_box(p)); + let e = _mm_setr_ps(42.0, 2.0, 42.0, 4.0); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_loadu_ps() { + let a = &[1.0_f32, 2.0, 3.0, 4.0]; + let p = a.as_ptr(); + let m = 0b1010; + let r = _mm_maskz_loadu_ps(m, black_box(p)); + let e = _mm_setr_ps(0.0, 2.0, 0.0, 4.0); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_load_ps() { + #[repr(align(16))] + struct Align { + data: [f32; 4], // 16 bytes + } + let src = _mm_set1_ps(42.0); + let a = Align { + data: [1.0_f32, 2.0, 3.0, 4.0], + }; + let p = a.data.as_ptr(); + let m = 0b1010; + let r = _mm_mask_load_ps(src, m, black_box(p)); + let e = _mm_setr_ps(42.0, 2.0, 42.0, 4.0); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_load_ps() { + #[repr(align(16))] + struct Align { + data: [f32; 4], // 16 bytes + } + let a = Align { + data: [1.0_f32, 2.0, 3.0, 4.0], + }; + let p = a.data.as_ptr(); + let m = 0b1010; + let r = _mm_maskz_load_ps(m, black_box(p)); + let e = _mm_setr_ps(0.0, 2.0, 0.0, 4.0); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_storeu_ps() { + let mut r = [42_f32; 4]; + let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); + let m = 0b1010; + _mm_mask_storeu_ps(r.as_mut_ptr(), m, a); + let e = _mm_setr_ps(42.0, 2.0, 42.0, 4.0); + assert_eq_m128(_mm_loadu_ps(r.as_ptr()), e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_store_ps() { + #[repr(align(16))] + struct Align { + data: [f32; 4], // 16 bytes + } + let mut r = Align { data: [42.0; 4] }; + let a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0); + let m = 0b1010; + _mm_mask_store_ps(r.data.as_mut_ptr(), m, a); + let e = _mm_setr_ps(42.0, 2.0, 42.0, 4.0); + assert_eq_m128(_mm_load_ps(r.data.as_ptr()), e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_loadu_pd() { + let src = _mm_set1_pd(42.0); + let a = &[1.0_f64, 2.0]; + let p = a.as_ptr(); + let m = 0b10; + let r = _mm_mask_loadu_pd(src, m, black_box(p)); + let e = _mm_setr_pd(42.0, 2.0); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_loadu_pd() { + let a = &[1.0_f64, 2.0]; + let p = a.as_ptr(); + let m = 0b10; + let r = _mm_maskz_loadu_pd(m, black_box(p)); + let e = _mm_setr_pd(0.0, 2.0); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_load_pd() { + #[repr(align(16))] + struct Align { + data: [f64; 2], // 16 bytes + } + let src = _mm_set1_pd(42.0); + let a = Align { + data: [1.0_f64, 2.0], + }; + let p = a.data.as_ptr(); + let m = 0b10; + let r = _mm_mask_load_pd(src, m, black_box(p)); + let e = _mm_setr_pd(42.0, 2.0); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_maskz_load_pd() { + #[repr(align(16))] + struct Align { + data: [f64; 2], // 16 bytes + } + let a = Align { + data: [1.0_f64, 2.0], + }; + let p = a.data.as_ptr(); + let m = 0b10; + let r = _mm_maskz_load_pd(m, black_box(p)); + let e = _mm_setr_pd(0.0, 2.0); + assert_eq_m128d(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_storeu_pd() { + let mut r = [42_f64; 2]; + let a = _mm_setr_pd(1.0, 2.0); + let m = 0b10; + _mm_mask_storeu_pd(r.as_mut_ptr(), m, a); + let e = _mm_setr_pd(42.0, 2.0); + assert_eq_m128d(_mm_loadu_pd(r.as_ptr()), e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + unsafe fn test_mm_mask_store_pd() { + #[repr(align(16))] + struct Align { + data: [f64; 2], // 16 bytes + } + let mut r = Align { data: [42.0; 2] }; + let a = _mm_setr_pd(1.0, 2.0); + let m = 0b10; + _mm_mask_store_pd(r.data.as_mut_ptr(), m, a); + let e = _mm_setr_pd(42.0, 2.0); + assert_eq_m128d(_mm_load_pd(r.data.as_ptr()), e); + } + #[simd_test(enable = "avx512f")] unsafe fn test_mm512_setr_pd() { let r = _mm512_set_pd(0., 1., 2., 3., 4., 5., 6., 7.); diff --git a/library/stdarch/crates/core_arch/src/x86/avx512gfni.rs b/library/stdarch/crates/core_arch/src/x86/avx512gfni.rs index 7b6d796237..d8ac5c29cc 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512gfni.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512gfni.rs @@ -819,7 +819,7 @@ mod tests { for i in 0..NUM_TEST_ENTRIES { left[i] = (i % 256) as u8; - right[i] = left[i] * 101; + right[i] = left[i].wrapping_mul(101); result[i] = mulbyte(left[i], right[i]); } diff --git a/library/stdarch/crates/core_arch/src/x86/bt.rs b/library/stdarch/crates/core_arch/src/x86/bt.rs index 37429d3db0..338cb97a38 100644 --- a/library/stdarch/crates/core_arch/src/x86/bt.rs +++ b/library/stdarch/crates/core_arch/src/x86/bt.rs @@ -1,3 +1,4 @@ +use crate::arch::asm; #[cfg(test)] use stdarch_test::assert_instr; diff --git a/library/stdarch/crates/core_arch/src/x86/cpuid.rs b/library/stdarch/crates/core_arch/src/x86/cpuid.rs index ed383e917d..6b90295ef6 100644 --- a/library/stdarch/crates/core_arch/src/x86/cpuid.rs +++ b/library/stdarch/crates/core_arch/src/x86/cpuid.rs @@ -1,6 +1,7 @@ //! `cpuid` intrinsics #![allow(clippy::module_name_repetitions)] +use crate::arch::asm; #[cfg(test)] use stdarch_test::assert_instr; diff --git a/library/stdarch/crates/core_arch/src/x86/eflags.rs b/library/stdarch/crates/core_arch/src/x86/eflags.rs index 368240378f..9bd4d6828b 100644 --- a/library/stdarch/crates/core_arch/src/x86/eflags.rs +++ b/library/stdarch/crates/core_arch/src/x86/eflags.rs @@ -1,5 +1,7 @@ //! `i386` intrinsics +use crate::arch::asm; + /// Reads EFLAGS. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=__readeflags) diff --git a/library/stdarch/crates/core_arch/src/x86/fxsr.rs b/library/stdarch/crates/core_arch/src/x86/fxsr.rs index 4a39bb8de9..8ea1bfab74 100644 --- a/library/stdarch/crates/core_arch/src/x86/fxsr.rs +++ b/library/stdarch/crates/core_arch/src/x86/fxsr.rs @@ -1,4 +1,4 @@ -//! FXSR floating-point context fast save and restor. +//! FXSR floating-point context fast save and restore. #[cfg(test)] use stdarch_test::assert_instr; diff --git a/library/stdarch/crates/core_arch/src/x86/sse.rs b/library/stdarch/crates/core_arch/src/x86/sse.rs index f7a46b198e..2c4295ef61 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse.rs @@ -1412,19 +1412,19 @@ pub unsafe fn _mm_getcsr() -> u32 { /// * `_MM_EXCEPT_DENORM`: An operation attempted to operate on a denormalized /// number. Mainly this can cause loss of precision. /// -/// * `_MM_EXCEPT_DIV_ZERO`: Division by zero occured. +/// * `_MM_EXCEPT_DIV_ZERO`: Division by zero occurred. /// -/// * `_MM_EXCEPT_OVERFLOW`: A numeric overflow exception occured, i.e., a +/// * `_MM_EXCEPT_OVERFLOW`: A numeric overflow exception occurred, i.e., a /// result was too large to be represented (e.g., an `f32` with absolute /// value /// greater than `2^128`). /// -/// * `_MM_EXCEPT_UNDERFLOW`: A numeric underflow exception occured, i.e., a +/// * `_MM_EXCEPT_UNDERFLOW`: A numeric underflow exception occurred, i.e., a /// result was too small to be represented in a normalized way (e.g., an /// `f32` /// with absulte value smaller than `2^-126`.) /// -/// * `_MM_EXCEPT_INEXACT`: An inexact-result exception occured (a.k.a. +/// * `_MM_EXCEPT_INEXACT`: An inexact-result exception occurred (a.k.a. /// precision exception). This means some precision was lost due to rounding. /// For example, the fraction `1/3` cannot be represented accurately in a /// 32 or 64 bit float and computing it would cause this exception to be @@ -1752,7 +1752,7 @@ pub const _MM_HINT_ET1: i32 = 6; #[rustc_legacy_const_generics(1)] #[stable(feature = "simd_x86", since = "1.27.0")] pub unsafe fn _mm_prefetch(p: *const i8) { - // We use the `llvm.prefetch` instrinsic with `cache type` = 1 (data cache). + // We use the `llvm.prefetch` intrinsic with `cache type` = 1 (data cache). // `locality` and `rw` are based on our `STRATEGY`. prefetch(p, (STRATEGY >> 2) & 1, STRATEGY & 3, 1); } diff --git a/library/stdarch/crates/core_arch/src/x86/sse41.rs b/library/stdarch/crates/core_arch/src/x86/sse41.rs index a8fe97fc02..7c59f2702f 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse41.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse41.rs @@ -8,7 +8,7 @@ use crate::{ #[cfg(test)] use stdarch_test::assert_instr; -// SSE4 rounding constans +// SSE4 rounding constants /// round to nearest #[stable(feature = "simd_x86", since = "1.27.0")] pub const _MM_FROUND_TO_NEAREST_INT: i32 = 0x00; @@ -155,11 +155,9 @@ pub unsafe fn _mm_blend_ps(a: __m128, b: __m128) -> __m128 { /// # #[target_feature(enable = "sse4.1")] /// # unsafe fn worker() { /// let mut float_store = vec![1.0, 1.0, 2.0, 3.0]; -/// unsafe { -/// let simd_floats = _mm_set_ps(2.5, 5.0, 7.5, 10.0); -/// let x: i32 = _mm_extract_ps::<2>(simd_floats); -/// float_store.push(f32::from_bits(x as u32)); -/// } +/// let simd_floats = _mm_set_ps(2.5, 5.0, 7.5, 10.0); +/// let x: i32 = _mm_extract_ps::<2>(simd_floats); +/// float_store.push(f32::from_bits(x as u32)); /// assert_eq!(float_store, vec![1.0, 1.0, 2.0, 3.0, 5.0]); /// # } /// # unsafe { worker() } @@ -832,7 +830,7 @@ pub unsafe fn _mm_round_sd(a: __m128d, b: __m128d) -> __m12 /// using the `ROUNDING` parameter, store the result as a single-precision /// floating-point element in the lower element of the intrinsic result, /// and copies the upper 3 packed elements from `a` to the upper elements -/// of the instrinsic result. +/// of the intrinsic result. /// Rounding is done according to the rounding parameter, which can be one of: /// /// ``` diff --git a/library/stdarch/crates/core_arch/src/x86/sse42.rs b/library/stdarch/crates/core_arch/src/x86/sse42.rs index 3aed5e7dde..fb3a22b519 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse42.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse42.rs @@ -146,7 +146,7 @@ pub unsafe fn _mm_cmpistrm(a: __m128i, b: __m128i) -> __m128i { /// # } /// ``` /// -/// The `_mm_cmpistri` intrinsic may also be used to find the existance of +/// The `_mm_cmpistri` intrinsic may also be used to find the existence of /// one or more of a given set of characters in the haystack. /// /// ``` diff --git a/library/stdarch/crates/core_arch/src/x86/sse4a.rs b/library/stdarch/crates/core_arch/src/x86/sse4a.rs index e6345d0da9..976c907cb2 100644 --- a/library/stdarch/crates/core_arch/src/x86/sse4a.rs +++ b/library/stdarch/crates/core_arch/src/x86/sse4a.rs @@ -32,7 +32,7 @@ extern "C" { /// If the length is zero, it is interpreted as `64`. If the length and index /// are zero, the lower 64 bits of `x` are extracted. /// -/// If `length == 0 && index > 0` or `lenght + index > 64` the result is +/// If `length == 0 && index > 0` or `length + index > 64` the result is /// undefined. #[inline] #[target_feature(enable = "sse4a")] diff --git a/library/stdarch/crates/core_arch/src/x86_64/bt.rs b/library/stdarch/crates/core_arch/src/x86_64/bt.rs index f2aa45d8ea..53da9d02f5 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/bt.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/bt.rs @@ -1,3 +1,4 @@ +use crate::arch::asm; #[cfg(test)] use stdarch_test::assert_instr; diff --git a/library/stdarch/crates/core_arch/src/x86_64/fxsr.rs b/library/stdarch/crates/core_arch/src/x86_64/fxsr.rs index 4274b4c476..d02702046e 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/fxsr.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/fxsr.rs @@ -1,4 +1,4 @@ -//! FXSR floating-point context fast save and restor. +//! FXSR floating-point context fast save and restore. #[cfg(test)] use stdarch_test::assert_instr; diff --git a/library/stdarch/crates/intrinsic-test/missing.txt b/library/stdarch/crates/intrinsic-test/missing.txt deleted file mode 100644 index fcc70935b6..0000000000 --- a/library/stdarch/crates/intrinsic-test/missing.txt +++ /dev/null @@ -1,115 +0,0 @@ -vmmlaq_s32 -vmmlaq_u32 -vrnd32x_f64 -vrnd32xq_f64 -vrnd32z_f64 -vrnd32zq_f64 -vrnd64x_f64 -vrnd64z_f64 -vrnd64zq_f64 -vsm3partw1q_u32 -vsm3partw2q_u32 -vsm3tt1bq_u32 -vsm3tt2aq_u32 -vsm3tt2bq_u32 -vsm4ekeyq_u32 -vsm4eq_u32 -vsudot_lane_s32 -vsudot_laneq_s32 -vsudotq_lane_s32 -vsudotq_laneq_s32 -vusdot_lane_s32 -vusdot_laneq_s32 -vusdot_s32 -vusdotq_lane_s32 -vusdotq_laneq_s32 -vusdotq_s32 -vcls_u16 -vcls_u32 -vcls_u8 -vclsq_u16 -vclsq_u32 -vclsq_u8 -vcreate_s16 -vcreate_u16 -vpaddq_s64 -vpaddq_u64 -vqshlu_n_s16 -vqshlu_n_s32 -vqshlu_n_s64 -vqshlu_n_s8 -vqshlub_n_s8 -vqshlud_n_s64 -vqshluh_n_s16 -vqshluq_n_s16 -vqshluq_n_s32 -vqshluq_n_s64 -vqshluq_n_s8 -vqshlus_n_s32 -vrax1q_u64 -vreinterpretq_p128_f32 -vreinterpretq_p128_f64 -vreinterpretq_p128_p16 -vreinterpretq_p128_p8 -vreinterpretq_p128_s16 -vreinterpretq_p128_s32 -vreinterpretq_p128_s64 -vreinterpretq_p128_s8 -vreinterpretq_p128_u16 -vreinterpretq_p128_u32 -vreinterpretq_p128_u64 -vreinterpretq_p128_u8 -vrnd32x_f32 -vrnd32xq_f32 -vrnd32z_f32 -vrnd32zq_f32 -vrnd64x_f32 -vrnd64xq_f32 -vrnd64xq_f64 -vrnd64z_f32 -vrnd64zq_f32 -vsha512h2q_u64 -vsha512hq_u64 -vsha512su0q_u64 -vsha512su1q_u64 -vslid_n_s64 -vslid_n_u64 -vsm3ss1q_u32 -vsm3tt1aq_u32 -vsrid_n_s64 -vsrid_n_u64 -vusmmlaq_s32 -vxarq_u64 -vadd_p16 -vadd_p64 -vadd_p8 -vaddq_p16 -vaddq_p64 -vaddq_p8 -vbcaxq_s16 -vbcaxq_s32 -vbcaxq_s64 -vbcaxq_s8 -vbcaxq_u16 -vbcaxq_u32 -vbcaxq_u64 -vbcaxq_u8 -veor3q_s16 -veor3q_s32 -veor3q_s64 -veor3q_s8 -veor3q_u16 -veor3q_u32 -veor3q_u64 -veor3q_u8 -vshld_s64 -vshld_u64 -vcopyq_laneq_u8 -vcopyq_laneq_s8 -vcopyq_laneq_p8 -vcopyq_lane_u8 -vcopyq_lane_s8 -vcopyq_lane_p8 -vcopy_laneq_u8 -vcopy_laneq_s8 -vcopy_laneq_p8 diff --git a/library/stdarch/crates/intrinsic-test/missing_aarch64.txt b/library/stdarch/crates/intrinsic-test/missing_aarch64.txt new file mode 100644 index 0000000000..b6ba2eab05 --- /dev/null +++ b/library/stdarch/crates/intrinsic-test/missing_aarch64.txt @@ -0,0 +1,133 @@ +# Not implemented in stdarch yet +vbfdot_f32 +vbfdot_lane_f32 +vbfdot_laneq_f32 +vbfdotq_f32 +vbfdotq_lane_f32 +vbfdotq_laneq_f32 +vbfmlalbq_f32 +vbfmlalbq_lane_f32 +vbfmlalbq_laneq_f32 +vbfmlaltq_f32 +vbfmlaltq_lane_f32 +vbfmlaltq_laneq_f32 +vbfmmlaq_f32 +vsudot_laneq_s32 +vsudot_lane_s32 +vsudotq_laneq_s32 +vsudotq_lane_s32 +vusdot_laneq_s32 +vusdot_lane_s32 +vusdotq_laneq_s32 +vusdotq_lane_s32 +vusdotq_s32 +vusdot_s32 + +# Implemented in Clang but missing from CSV +vcmla_f64 +vcmla_lane_f64 +vcmla_laneq_f64 +vcmlaq_lane_f64 +vcmlaq_laneq_f64 +vcmlaq_rot180_lane_f64 +vcmlaq_rot180_laneq_f64 +vcmlaq_rot270_lane_f64 +vcmlaq_rot270_laneq_f64 +vcmlaq_rot90_lane_f64 +vcmlaq_rot90_laneq_f64 +vcmla_rot180_f64 +vcmla_rot180_lane_f64 +vcmla_rot180_laneq_f64 +vcmla_rot270_f64 +vcmla_rot270_lane_f64 +vcmla_rot270_laneq_f64 +vcmla_rot90_f64 +vcmla_rot90_lane_f64 +vcmla_rot90_laneq_f64 + +# Implemented in Clang and stdarch but missing from CSV +vmov_n_p64 +vmovq_n_p64 +vreinterpret_f32_p64 +vreinterpret_p64_s64 +vreinterpretq_f32_p128 +vreinterpretq_f32_p64 +vreinterpretq_p128_p64 +vreinterpretq_p64_p128 +vtst_p16 +vtstq_p16 + +# Missing from both Clang and stdarch +vrnd32x_f64 +vrnd32xq_f64 +vrnd32z_f64 +vrnd32zq_f64 +vrnd64x_f64 +vrnd64xq_f64 +vrnd64z_f64 +vrnd64zq_f64 + +# Takes too long to compile tests +vcopyq_laneq_u8 +vcopyq_laneq_s8 +vcopyq_laneq_p8 +vcopyq_lane_u8 +vcopyq_lane_s8 +vcopyq_lane_p8 +vcopy_laneq_u8 +vcopy_laneq_s8 +vcopy_laneq_p8 +vcopy_lane_u8 +vcopy_lane_s8 +vcopy_lane_p8 + +# QEMU 6.0 doesn't support these instructions +vmmlaq_s32 +vmmlaq_u32 +vsm3partw1q_u32 +vsm3partw2q_u32 +vsm3ss1q_u32 +vsm3tt1aq_u32 +vsm3tt1bq_u32 +vsm3tt2aq_u32 +vsm3tt2bq_u32 +vsm4ekeyq_u32 +vsm4eq_u32 +vusmmlaq_s32 + +# LLVM select error in debug builds +vqshlu_n_s16 +vqshlu_n_s32 +vqshlu_n_s64 +vqshlu_n_s8 +vqshlub_n_s8 +vqshlud_n_s64 +vqshluh_n_s16 +vqshluq_n_s16 +vqshluq_n_s32 +vqshluq_n_s64 +vqshluq_n_s8 +vqshlus_n_s32 + +# These tests produce a different result from C but only in debug builds of +# stdarch. This likely both a bug in stdarch (expanding to a different LLVM +# intrinsic) and a bug in LLVM (incorrect optimization changing the behavior of +# integer operations). +vqrdmlah_lane_s16 +vqrdmlah_lane_s32 +vqrdmlah_laneq_s16 +vqrdmlah_laneq_s32 +vqrdmlah_s16 +vqrdmlah_s32 +vqrdmlahh_lane_s16 +vqrdmlahh_laneq_s16 +vqrdmlahh_s16 +vqrdmlahq_lane_s16 +vqrdmlahq_lane_s32 +vqrdmlahq_laneq_s16 +vqrdmlahq_laneq_s32 +vqrdmlahq_s16 +vqrdmlahq_s32 +vqrdmlahs_lane_s32 +vqrdmlahs_laneq_s32 +vqrdmlahs_s32 diff --git a/library/stdarch/crates/intrinsic-test/missing_arm.txt b/library/stdarch/crates/intrinsic-test/missing_arm.txt new file mode 100644 index 0000000000..bbc8de584f --- /dev/null +++ b/library/stdarch/crates/intrinsic-test/missing_arm.txt @@ -0,0 +1,334 @@ +# Not implemented in stdarch yet +vbfdot_f32 +vbfdot_lane_f32 +vbfdot_laneq_f32 +vbfdotq_f32 +vbfdotq_lane_f32 +vbfdotq_laneq_f32 +vbfmlalbq_f32 +vbfmlalbq_lane_f32 +vbfmlalbq_laneq_f32 +vbfmlaltq_f32 +vbfmlaltq_lane_f32 +vbfmlaltq_laneq_f32 +vbfmmlaq_f32 +vsudot_laneq_s32 +vsudot_lane_s32 +vsudotq_laneq_s32 +vsudotq_lane_s32 +vusdot_laneq_s32 +vusdot_lane_s32 +vusdotq_laneq_s32 +vusdotq_lane_s32 +vusdotq_s32 +vusdot_s32 + +# Implemented in Clang and stdarch but missing from CSV +vtst_p16 +vtstq_p16 + +# QEMU 6.0 doesn't support these instructions +vmmlaq_s32 +vmmlaq_u32 +vusmmlaq_s32 + +# Implemented in Clang and stdarch for A64 only even though CSV claims A32 support +__crc32d +__crc32cd +vaddq_p64 +vbsl_p64 +vbslq_p64 +vceq_p64 +vceqq_p64 +vceqz_p64 +vceqzq_p64 +vcombine_p64 +vcopy_lane_p64 +vcopy_laneq_p64 +vcopyq_lane_p64 +vcopyq_laneq_p64 +vcreate_p64 +vdup_lane_p64 +vdup_n_p64 +vdupq_lane_p64 +vdupq_n_p64 +vext_p64 +vextq_p64 +vget_high_p64 +vget_lane_p64 +vget_low_p64 +vgetq_lane_p64 +vmovn_high_s16 +vmovn_high_s32 +vmovn_high_s64 +vmovn_high_u16 +vmovn_high_u32 +vmovn_high_u64 +vmull_high_p64 +vmull_p64 +vreinterpret_p16_p64 +vreinterpret_p64_f32 +vreinterpret_p64_p16 +vreinterpret_p64_p8 +vreinterpret_p64_s16 +vreinterpret_p64_s32 +vreinterpret_p64_s8 +vreinterpret_p64_u16 +vreinterpret_p64_u32 +vreinterpret_p64_u64 +vreinterpret_p64_u8 +vreinterpret_p8_p64 +vreinterpretq_f64_u64 +vreinterpretq_p128_f32 +vreinterpretq_p128_p16 +vreinterpretq_p128_p8 +vreinterpretq_p128_s16 +vreinterpretq_p128_s32 +vreinterpretq_p128_s64 +vreinterpretq_p128_s8 +vreinterpretq_p128_u16 +vreinterpretq_p128_u32 +vreinterpretq_p128_u64 +vreinterpretq_p128_u8 +vreinterpretq_p16_p64 +vreinterpretq_p64_f32 +vreinterpretq_p64_p16 +vreinterpretq_p64_p8 +vreinterpretq_p64_s16 +vreinterpretq_p64_s32 +vreinterpretq_p64_s64 +vreinterpretq_p64_s8 +vreinterpretq_p64_u16 +vreinterpretq_p64_u32 +vreinterpretq_p64_u64 +vreinterpretq_p64_u8 +vreinterpretq_p8_p64 +vreinterpretq_s16_p64 +vreinterpretq_s32_p64 +vreinterpretq_s64_p64 +vreinterpretq_s8_p64 +vreinterpretq_u16_p64 +vreinterpretq_u32_p64 +vreinterpretq_u64_p64 +vreinterpretq_u8_p64 +vreinterpret_s16_p64 +vreinterpret_s32_p64 +vreinterpret_s64_p64 +vreinterpret_s8_p64 +vreinterpret_u16_p64 +vreinterpret_u32_p64 +vreinterpret_u64_p64 +vreinterpret_u8_p64 +vrndn_f64 +vrndnq_f64 +vset_lane_p64 +vsetq_lane_p64 +vsli_n_p64 +vsliq_n_p64 +vsri_n_p64 +vsriq_n_p64 +vtst_p64 +vtstq_p64 + +# Present in Clang header but triggers an ICE due to lack of backend support. +vcmla_f32 +vcmla_lane_f32 +vcmla_laneq_f32 +vcmla_rot180_f32 +vcmla_rot180_lane_f32 +vcmla_rot180_laneq_f32 +vcmla_rot270_f32 +vcmla_rot270_lane_f32 +vcmla_rot270_laneq_f32 +vcmla_rot90_f32 +vcmla_rot90_lane_f32 +vcmla_rot90_laneq_f32 +vcmlaq_f32 +vcmlaq_lane_f32 +vcmlaq_laneq_f32 +vcmlaq_rot180_f32 +vcmlaq_rot180_lane_f32 +vcmlaq_rot180_laneq_f32 +vcmlaq_rot270_f32 +vcmlaq_rot270_lane_f32 +vcmlaq_rot270_laneq_f32 +vcmlaq_rot90_f32 +vcmlaq_rot90_lane_f32 +vcmlaq_rot90_laneq_f32 + +# Implemented in stdarch for A64 only, Clang support both A32/A64 +vadd_s64 +vadd_u64 +vcaddq_rot270_f32 +vcaddq_rot90_f32 +vcadd_rot270_f32 +vcadd_rot90_f32 +vcombine_f32 +vcombine_p16 +vcombine_p8 +vcombine_s16 +vcombine_s32 +vcombine_s64 +vcombine_s8 +vcombine_u16 +vcombine_u32 +vcombine_u64 +vcombine_u8 +vcvtaq_s32_f32 +vcvtaq_u32_f32 +vcvta_s32_f32 +vcvta_u32_f32 +vcvtmq_s32_f32 +vcvtmq_u32_f32 +vcvtm_s32_f32 +vcvtm_u32_f32 +vcvtnq_s32_f32 +vcvtnq_u32_f32 +vcvtn_s32_f32 +vcvtn_u32_f32 +vcvtpq_s32_f32 +vcvtpq_u32_f32 +vcvtp_s32_f32 +vcvtp_u32_f32 +vdot_lane_s32 +vdot_lane_u32 +vdotq_lane_s32 +vdotq_lane_u32 +vdotq_s32 +vdotq_u32 +vdot_s32 +vdot_u32 +vqdmulh_lane_s16 +vqdmulh_lane_s32 +vqdmulhq_lane_s16 +vqdmulhq_lane_s32 +vrnda_f32 +vrnda_f32 +vrndaq_f32 +vrndaq_f32 +vrnd_f32 +vrnd_f32 +vrndi_f32 +vrndi_f32 +vrndiq_f32 +vrndiq_f32 +vrndm_f32 +vrndm_f32 +vrndmq_f32 +vrndmq_f32 +vrndns_f32 +vrndp_f32 +vrndpq_f32 +vrndq_f32 +vrndq_f32 +vrndx_f32 +vrndxq_f32 + +# LLVM select error in debug builds +vqrshrn_n_s16 +vqrshrn_n_s32 +vqrshrn_n_s64 +vqrshrn_n_u16 +vqrshrn_n_u32 +vqrshrn_n_u64 +vqrshrun_n_s16 +vqrshrun_n_s32 +vqrshrun_n_s64 +vqshrn_n_s16 +vqshrn_n_s32 +vqshrn_n_s64 +vqshrn_n_u16 +vqshrn_n_u32 +vqshrn_n_u64 +vqshrun_n_s16 +vqshrun_n_s32 +vqshrun_n_s64 +vrshrn_n_s16 +vrshrn_n_s32 +vrshrn_n_s64 +vrshrn_n_u16 +vrshrn_n_u32 +vrshrn_n_u64 +vshrq_n_u64 +vshr_n_u64 + +# Failing tests: stdarch has incorrect results compared to Clang +vqshlu_n_s16 +vqshlu_n_s32 +vqshlu_n_s64 +vqshlu_n_s8 +vqshluq_n_s16 +vqshluq_n_s32 +vqshluq_n_s64 +vqshluq_n_s8 +vsli_n_p16 +vsli_n_p8 +vsli_n_s16 +vsli_n_s32 +vsli_n_s64 +vsli_n_s8 +vsli_n_u16 +vsli_n_u32 +vsli_n_u64 +vsli_n_u8 +vsliq_n_p16 +vsliq_n_p8 +vsliq_n_s16 +vsliq_n_s32 +vsliq_n_s64 +vsliq_n_s8 +vsliq_n_u16 +vsliq_n_u32 +vsliq_n_u64 +vsliq_n_u8 +vsri_n_p16 +vsri_n_p8 +vsri_n_s16 +vsri_n_s32 +vsri_n_s64 +vsri_n_s8 +vsri_n_u16 +vsri_n_u32 +vsri_n_u64 +vsri_n_u8 +vsriq_n_p16 +vsriq_n_p8 +vsriq_n_s16 +vsriq_n_s32 +vsriq_n_s64 +vsriq_n_s8 +vsriq_n_u16 +vsriq_n_u32 +vsriq_n_u64 +vsriq_n_u8 + +# These produce a different result on Clang depending on the optimization level. +# This is definitely a bug in LLVM. +vadd_f32 +vaddq_f32 +vcvt_s32_f32 +vcvt_u32_f32 +vcvtq_s32_f32 +vcvtq_u32_f32 +vfma_f32 +vfma_n_f32 +vfmaq_f32 +vfmaq_n_f32 +vfms_f32 +vfmsq_f32 +vmla_f32 +vmla_lane_f32 +vmla_n_f32 +vmlaq_f32 +vmlaq_lane_f32 +vmlaq_n_f32 +vmls_f32 +vmls_lane_f32 +vmls_n_f32 +vmlsq_f32 +vmlsq_lane_f32 +vmlsq_n_f32 +vmul_lane_f32 +vmul_n_f32 +vmulq_lane_f32 +vmulq_n_f32 diff --git a/library/stdarch/crates/intrinsic-test/src/acle_csv_parser.rs b/library/stdarch/crates/intrinsic-test/src/acle_csv_parser.rs index f2179ff1d6..d7b0664851 100644 --- a/library/stdarch/crates/intrinsic-test/src/acle_csv_parser.rs +++ b/library/stdarch/crates/intrinsic-test/src/acle_csv_parser.rs @@ -82,11 +82,17 @@ impl Into for ACLEIntrinsicLine { }) .collect(); let arguments = ArgumentList { args }; + let a64_only = match &*self.supported_architectures { + "A64" => true, + "v7/A32/A64" | "A32/A64" => false, + _ => panic!("Invalid supported architectures"), + }; Intrinsic { name: name.to_string(), arguments, results, + a64_only, } } } diff --git a/library/stdarch/crates/intrinsic-test/src/argument.rs b/library/stdarch/crates/intrinsic-test/src/argument.rs index 9b02970f3f..f4cb77992a 100644 --- a/library/stdarch/crates/intrinsic-test/src/argument.rs +++ b/library/stdarch/crates/intrinsic-test/src/argument.rs @@ -55,7 +55,7 @@ pub struct ArgumentList { } impl ArgumentList { - /// Converts the argument list into the call paramters for a C function call. + /// Converts the argument list into the call parameters for a C function call. /// e.g. this would generate something like `a, &b, c` pub fn as_call_param_c(&self) -> String { self.args @@ -70,7 +70,7 @@ impl ArgumentList { .join(", ") } - /// Converts the argument list into the call paramters for a Rust function. + /// Converts the argument list into the call parameters for a Rust function. /// e.g. this would generate something like `a, b, c` pub fn as_call_param_rust(&self) -> String { self.args diff --git a/library/stdarch/crates/intrinsic-test/src/intrinsic.rs b/library/stdarch/crates/intrinsic-test/src/intrinsic.rs index 447c6db0bc..2b7130440f 100644 --- a/library/stdarch/crates/intrinsic-test/src/intrinsic.rs +++ b/library/stdarch/crates/intrinsic-test/src/intrinsic.rs @@ -8,11 +8,14 @@ pub struct Intrinsic { /// The function name of this intrinsic. pub name: String, - /// Any arguments for this intrinsinc. + /// Any arguments for this intrinsic. pub arguments: ArgumentList, /// The return type of this intrinsic. pub results: IntrinsicType, + + /// Whether this intrinsic is only available on A64. + pub a64_only: bool, } impl Intrinsic { diff --git a/library/stdarch/crates/intrinsic-test/src/main.rs b/library/stdarch/crates/intrinsic-test/src/main.rs index 9416456419..1b58da2fd7 100644 --- a/library/stdarch/crates/intrinsic-test/src/main.rs +++ b/library/stdarch/crates/intrinsic-test/src/main.rs @@ -72,12 +72,15 @@ fn generate_c_program(header_files: &[&str], intrinsic: &Intrinsic) -> String { #include #include #include + template T1 cast(T2 x) {{ static_assert(sizeof(T1) == sizeof(T2), "sizeof T1 and T2 must be the same"); T1 ret = 0; memcpy(&ret, &x, sizeof(T1)); return ret; }} + +#ifdef __aarch64__ std::ostream& operator<<(std::ostream& os, poly128_t value) {{ std::stringstream temp; do {{ @@ -90,6 +93,8 @@ std::ostream& operator<<(std::ostream& os, poly128_t value) {{ os << res; return os; }} +#endif + int main(int argc, char **argv) {{ {passes} return 0; @@ -133,7 +138,7 @@ fn gen_code_rust(intrinsic: &Intrinsic, constraints: &[&Argument], name: String) } } -fn generate_rust_program(intrinsic: &Intrinsic) -> String { +fn generate_rust_program(intrinsic: &Intrinsic, a32: bool) -> String { let constraints = intrinsic .arguments .iter() @@ -146,25 +151,26 @@ fn generate_rust_program(intrinsic: &Intrinsic) -> String { #![feature(stdsimd)] #![allow(overflowing_literals)] #![allow(non_upper_case_globals)] -use core_arch::arch::aarch64::*; +use core_arch::arch::{target_arch}::*; fn main() {{ {passes} }} "#, + target_arch = if a32 { "arm" } else { "aarch64" }, passes = gen_code_rust(intrinsic, &constraints, Default::default()) ) } -fn compile_c(c_filename: &str, intrinsic: &Intrinsic, compiler: &str) -> bool { +fn compile_c(c_filename: &str, intrinsic: &Intrinsic, compiler: &str, a32: bool) -> bool { let flags = std::env::var("CPPFLAGS").unwrap_or("".into()); let output = Command::new("sh") .arg("-c") .arg(format!( "{cpp} {cppflags} {arch_flags} -Wno-narrowing -O2 -target {target} -o c_programs/{intrinsic} {filename}", - target = "aarch64-unknown-linux-gnu", - arch_flags = "-march=armv8.6-a+crypto+sha3+crc+dotprod", + target = if a32 { "armv7-unknown-linux-gnueabihf" } else { "aarch64-unknown-linux-gnu" }, + arch_flags = if a32 { "-march=armv8.6-a+crypto+crc+dotprod" } else { "-march=armv8.6-a+crypto+sha3+crc+dotprod" }, filename = c_filename, intrinsic = intrinsic.name, cpp = compiler, @@ -175,19 +181,13 @@ fn compile_c(c_filename: &str, intrinsic: &Intrinsic, compiler: &str) -> bool { if output.status.success() { true } else { - let stderr = std::str::from_utf8(&output.stderr).unwrap_or(""); - if stderr.contains("error: use of undeclared identifier") { - warn!("Skipping intrinsic due to no support: {}", intrinsic.name); - true - } else { - error!( - "Failed to compile code for intrinsic: {}\n\nstdout:\n{}\n\nstderr:\n{}", - intrinsic.name, - std::str::from_utf8(&output.stdout).unwrap_or(""), - std::str::from_utf8(&output.stderr).unwrap_or("") - ); - false - } + error!( + "Failed to compile code for intrinsic: {}\n\nstdout:\n{}\n\nstderr:\n{}", + intrinsic.name, + std::str::from_utf8(&output.stdout).unwrap_or(""), + std::str::from_utf8(&output.stderr).unwrap_or("") + ); + false } } else { error!("Command failed: {:#?}", output); @@ -195,7 +195,7 @@ fn compile_c(c_filename: &str, intrinsic: &Intrinsic, compiler: &str) -> bool { } } -fn build_c(intrinsics: &Vec, compiler: &str) -> bool { +fn build_c(intrinsics: &Vec, compiler: &str, a32: bool) -> bool { let _ = std::fs::create_dir("c_programs"); intrinsics .par_iter() @@ -205,20 +205,20 @@ fn build_c(intrinsics: &Vec, compiler: &str) -> bool { let c_code = generate_c_program(&["arm_neon.h", "arm_acle.h"], &i); file.write_all(c_code.into_bytes().as_slice()).unwrap(); - compile_c(&c_filename, &i, compiler) + compile_c(&c_filename, &i, compiler, a32) }) .find_any(|x| !x) .is_none() } -fn build_rust(intrinsics: &Vec, toolchain: &str) -> bool { +fn build_rust(intrinsics: &Vec, toolchain: &str, a32: bool) -> bool { intrinsics.iter().for_each(|i| { let rust_dir = format!(r#"rust_programs/{}"#, i.name); let _ = std::fs::create_dir_all(&rust_dir); let rust_filename = format!(r#"{}/main.rs"#, rust_dir); let mut file = File::create(&rust_filename).unwrap(); - let c_code = generate_rust_program(&i); + let c_code = generate_rust_program(&i, a32); file.write_all(c_code.into_bytes().as_slice()).unwrap(); }); @@ -259,10 +259,15 @@ path = "{intrinsic}/main.rs""#, .current_dir("rust_programs") .arg("-c") .arg(format!( - "cargo {toolchain} build --release --target {target}", + "cargo {toolchain} build --target {target}", toolchain = toolchain, - target = "aarch64-unknown-linux-gnu", + target = if a32 { + "armv7-unknown-linux-gnueabihf" + } else { + "aarch64-unknown-linux-gnu" + }, )) + .env("RUSTFLAGS", "-Cdebuginfo=0") .output(); if let Ok(output) = output { if output.status.success() { @@ -317,6 +322,12 @@ fn main() { .long("skip") .help("Filename for a list of intrinsics to skip (one per line)"), ) + .arg( + Arg::with_name("A32") + .takes_value(false) + .long("a32") + .help("Run tests for A32 instrinsics instead of A64"), + ) .get_matches(); let filename = matches.value_of("INPUT").unwrap(); @@ -328,10 +339,15 @@ fn main() { let c_runner = matches.value_of("RUNNER").unwrap_or(""); let skip = if let Some(filename) = matches.value_of("SKIP") { let data = std::fs::read_to_string(&filename).expect("Failed to open file"); - data.lines().map(String::from).collect_vec() + data.lines() + .map(str::trim) + .filter(|s| !s.contains('#')) + .map(String::from) + .collect_vec() } else { Default::default() }; + let a32 = matches.is_present("A32"); let intrinsics = get_acle_intrinsics(filename); @@ -352,18 +368,19 @@ fn main() { .filter(|i| !i.arguments.iter().any(|a| a.is_ptr())) .filter(|i| !i.arguments.iter().any(|a| a.ty.inner_size() == 128)) .filter(|i| !skip.contains(&i.name)) + .filter(|i| !(a32 && i.a64_only)) .collect::>(); intrinsics.dedup(); - if !build_c(&intrinsics, cpp_compiler) { + if !build_c(&intrinsics, cpp_compiler, a32) { std::process::exit(2); } - if !build_rust(&intrinsics, &toolchain) { + if !build_rust(&intrinsics, &toolchain, a32) { std::process::exit(3); } - if !compare_outputs(&intrinsics, &toolchain, &c_runner) { + if !compare_outputs(&intrinsics, &toolchain, &c_runner, a32) { std::process::exit(1) } } @@ -374,7 +391,7 @@ enum FailureReason { Difference(String, String, String), } -fn compare_outputs(intrinsics: &Vec, toolchain: &str, runner: &str) -> bool { +fn compare_outputs(intrinsics: &Vec, toolchain: &str, runner: &str, a32: bool) -> bool { let intrinsics = intrinsics .par_iter() .filter_map(|intrinsic| { @@ -390,11 +407,16 @@ fn compare_outputs(intrinsics: &Vec, toolchain: &str, runner: &str) - .current_dir("rust_programs") .arg("-c") .arg(format!( - "cargo {toolchain} run --release --target {target} --bin {intrinsic}", + "cargo {toolchain} run --target {target} --bin {intrinsic}", intrinsic = intrinsic.name, toolchain = toolchain, - target = "aarch64-unknown-linux-gnu", + target = if a32 { + "armv7-unknown-linux-gnueabihf" + } else { + "aarch64-unknown-linux-gnu" + }, )) + .env("RUSTFLAGS", "-Cdebuginfo=0") .output(); let (c, rust) = match (c, rust) { diff --git a/library/stdarch/crates/intrinsic-test/src/types.rs b/library/stdarch/crates/intrinsic-test/src/types.rs index 89c9c95d5b..e51e616496 100644 --- a/library/stdarch/crates/intrinsic-test/src/types.rs +++ b/library/stdarch/crates/intrinsic-test/src/types.rs @@ -258,6 +258,9 @@ impl IntrinsicType { /// This is required for 8 bit types due to printing as the 8 bit types use /// a char and when using that in `std::cout` it will print as a character, /// which means value of 0 will be printed as a null byte. + /// + /// This is also needed for polynomial types because we want them to be + /// printed as unsigned integers to match Rust's `Debug` impl. pub fn c_promotion(&self) -> &str { match *self { IntrinsicType::Type { @@ -267,9 +270,21 @@ impl IntrinsicType { } if bit_len == 8 => match kind { TypeKind::Int => "(int)", TypeKind::UInt => "(unsigned int)", - TypeKind::Poly => "(unsigned int)", + TypeKind::Poly => "(unsigned int)(uint8_t)", _ => "", }, + IntrinsicType::Type { + kind: TypeKind::Poly, + bit_len: Some(bit_len), + .. + } => match bit_len { + 8 => unreachable!("handled above"), + 16 => "(uint16_t)", + 32 => "(uint32_t)", + 64 => "(uint64_t)", + 128 => "", + _ => panic!("invalid bit_len"), + }, _ => "", } } diff --git a/library/stdarch/crates/simd-test-macro/src/lib.rs b/library/stdarch/crates/simd-test-macro/src/lib.rs index 407c154475..9d81a4c5ea 100644 --- a/library/stdarch/crates/simd-test-macro/src/lib.rs +++ b/library/stdarch/crates/simd-test-macro/src/lib.rs @@ -64,6 +64,7 @@ pub fn simd_test( "i686" | "x86_64" | "i586" => "is_x86_feature_detected", "arm" | "armv7" => "is_arm_feature_detected", "aarch64" => "is_aarch64_feature_detected", + maybe_riscv if maybe_riscv.starts_with("riscv") => "is_riscv_feature_detected", "powerpc" | "powerpcle" => "is_powerpc_feature_detected", "powerpc64" | "powerpc64le" => "is_powerpc64_feature_detected", "mips" | "mipsel" | "mipsisa32r6" | "mipsisa32r6el" => { diff --git a/library/stdarch/crates/std_detect/src/detect/arch/aarch64.rs b/library/stdarch/crates/std_detect/src/detect/arch/aarch64.rs index 81979ba967..2f90555428 100644 --- a/library/stdarch/crates/std_detect/src/detect/arch/aarch64.rs +++ b/library/stdarch/crates/std_detect/src/detect/arch/aarch64.rs @@ -8,7 +8,7 @@ features! { /// Currently most features are only supported on linux-based platforms. /// /// This macro takes one argument which is a string literal of the feature being tested for. - /// The feature names are mostly taken from their FEAT_* definitiions in the [ARM Architecture + /// The feature names are mostly taken from their FEAT_* definitions in the [ARM Architecture /// Reference Manual][docs]. /// /// ## Supported arguments @@ -104,9 +104,9 @@ features! { @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] pauth: "pauth"; /// FEAT_PAuth (pointer authentication) @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] dpb: "dpb"; - /// FEAT_DPB (aka dcpop - data cache clean to point of persistance) + /// FEAT_DPB (aka dcpop - data cache clean to point of persistence) @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] dpb2: "dpb2"; - /// FEAT_DPB2 (aka dcpodp - data cache clean to point of deep persistance) + /// FEAT_DPB2 (aka dcpodp - data cache clean to point of deep persistence) @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] sve2: "sve2"; /// FEAT_SVE2 (Scalable Vector Extension 2) @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] sve2_aes: "sve2-aes"; diff --git a/library/stdarch/crates/std_detect/src/detect/arch/riscv.rs b/library/stdarch/crates/std_detect/src/detect/arch/riscv.rs new file mode 100644 index 0000000000..ac43b2c4dd --- /dev/null +++ b/library/stdarch/crates/std_detect/src/detect/arch/riscv.rs @@ -0,0 +1,205 @@ +//! Run-time feature detection on RISC-V. + +features! { + @TARGET: riscv; + @MACRO_NAME: is_riscv_feature_detected; + @MACRO_ATTRS: + /// A macro to test at *runtime* whether instruction sets are available on + /// RISC-V platforms. + /// + /// RISC-V standard defined the base sets and the extension sets. + /// The base sets are RV32I, RV64I, RV32E or RV128I. Any RISC-V platform + /// must support one base set and/or multiple extension sets. + /// + /// Any RISC-V standard instruction sets can be in state of either ratified, + /// frozen or draft. The version and status of current standard instruction + /// sets can be checked out from preface section of the [ISA manual]. + /// + /// Platform may define and support their own custom instruction sets with + /// ISA prefix X. These sets are highly platform specific and should be + /// detected with their own platform support crates. + /// + /// # Unprivileged Specification + /// + /// The supported ratified RISC-V instruction sets are as follows: + /// + /// * RV32I: `"rv32i"` + /// * Zifencei: `"zifencei"` + /// * Zihintpause: `"zihintpause"` + /// * RV64I: `"rv64i"` + /// * M: `"m"` + /// * A: `"a"` + /// * Zicsr: `"zicsr"` + /// * Zicntr: `"zicntr"` + /// * Zihpm: `"zihpm"` + /// * F: `"f"` + /// * D: `"d"` + /// * Q: `"q"` + /// * C: `"c"` + /// + /// There's also bases and extensions marked as standard instruction set, + /// but they are in frozen or draft state. These instruction sets are also + /// reserved by this macro and can be detected in the future platforms. + /// + /// Frozen RISC-V instruction sets: + /// + /// * Zfinx: `"zfinx"` + /// * Zdinx: `"zdinx"` + /// * Zhinx: `"zhinx"` + /// * Zhinxmin: `"zhinxmin"` + /// * Ztso: `"ztso"` + /// + /// Draft RISC-V instruction sets: + /// + /// * RV32E: `"rv32e"` + /// * RV128I: `"rv128i"` + /// * Zfh: `"zfh"` + /// * Zfhmin: `"zfhmin"` + /// * B: `"b"` + /// * J: `"j"` + /// * P: `"p"` + /// * V: `"v"` + /// * Zam: `"zam"` + /// + /// Defined by Privileged Specification: + /// + /// * Supervisor: `"s"` + /// * Svnapot: `"svnapot"` + /// * Svpbmt: `"svpbmt"` + /// * Svinval: `"svinval"` + /// * Hypervisor: `"h"` + /// + /// # RISC-V Bit-Manipulation ISA-extensions + /// + /// This document defined the following extensions: + /// + /// * Zba: `"zba"` + /// * Zbb: `"zbb"` + /// * Zbc: `"zbc"` + /// * Zbs: `"zbs"` + /// + /// # RISC-V Cryptography Extensions + /// + /// These extensions are defined in Volume I, Scalar & Entropy Source + /// Instructions: + /// + /// * Zbkb: `"zbkb"` + /// * Zbkc: `"zbkc"` + /// * Zbkx: `"zbkx"` + /// * Zknd: `"zknd"` + /// * Zkne: `"zkne"` + /// * Zknh: `"zknh"` + /// * Zksed: `"zksed"` + /// * Zksh: `"zksh"` + /// * Zkr: `"zkr"` + /// * Zkn: `"zkn"` + /// * Zks: `"zks"` + /// * Zk: `"zk"` + /// * Zkt: `"zkt"` + /// + /// [ISA manual]: https://github.com/riscv/riscv-isa-manual/ + #[unstable(feature = "stdsimd", issue = "27731")] + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] rv32i: "rv32i"; + /// RV32I Base Integer Instruction Set + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zifencei: "zifencei"; + /// "Zifencei" Instruction-Fetch Fence + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zihintpause: "zihintpause"; + /// "Zihintpause" Pause Hint + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] rv64i: "rv64i"; + /// RV64I Base Integer Instruction Set + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] m: "m"; + /// "M" Standard Extension for Integer Multiplication and Division + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] a: "a"; + /// "A" Standard Extension for Atomic Instructions + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zicsr: "zicsr"; + /// "Zicsr", Control and Status Register (CSR) Instructions + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zicntr: "zicntr"; + /// "Zicntr", Standard Extension for Base Counters and Timers + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zihpm: "zihpm"; + /// "Zihpm", Standard Extension for Hardware Performance Counters + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] f: "f"; + /// "F" Standard Extension for Single-Precision Floating-Point + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] d: "d"; + /// "D" Standard Extension for Double-Precision Floating-Point + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] q: "q"; + /// "Q" Standard Extension for Quad-Precision Floating-Point + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] c: "c"; + /// "C" Standard Extension for Compressed Instructions + + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zfinx: "zfinx"; + /// "Zfinx" Standard Extension for Single-Precision Floating-Point in Integer Registers + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zdinx: "zdinx"; + /// "Zdinx" Standard Extension for Double-Precision Floating-Point in Integer Registers + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zhinx: "zhinx"; + /// "Zhinx" Standard Extension for Half-Precision Floating-Point in Integer Registers + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zhinxmin: "zhinxmin"; + /// "Zhinxmin" Standard Extension for Minimal Half-Precision Floating-Point in Integer Registers + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] ztso: "ztso"; + /// "Ztso" Standard Extension for Total Store Ordering + + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] rv32e: "rv32e"; + /// RV32E Base Integer Instruction Set + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] rv128i: "rv128i"; + /// RV128I Base Integer Instruction Set + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zfh: "zfh"; + /// "Zfh" Standard Extension for 16-Bit Half-Precision Floating-Point + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zfhmin: "zfhmin"; + /// "Zfhmin" Standard Extension for Minimal Half-Precision Floating-Point Support + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] b: "b"; + /// "B" Standard Extension for Bit Manipulation + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] j: "j"; + /// "J" Standard Extension for Dynamically Translated Languages + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] p: "p"; + /// "P" Standard Extension for Packed-SIMD Instructions + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] v: "v"; + /// "V" Standard Extension for Vector Operations + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zam: "zam"; + /// "Zam" Standard Extension for Misaligned Atomics + + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] s: "s"; + /// Supervisor-Level ISA + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] svnapot: "svnapot"; + /// "Svnapot" Standard Extension for NAPOT Translation Contiguity + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] svpbmt: "svpbmt"; + /// "Svpbmt" Standard Extension for Page-Based Memory Types + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] svinval: "svinval"; + /// "Svinval" Standard Extension for Fine-Grained Address-Translation Cache Invalidation + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] h: "h"; + /// Hypervisor Extension + + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zba: "zba"; + /// "Zba" Standard Extension for Address Generation Instructions + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zbb: "zbb"; + /// "Zbb" Standard Extension for Basic Bit-Manipulation + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zbc: "zbc"; + /// "Zbc" Standard Extension for Carry-less Multiplication + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zbs: "zbs"; + /// "Zbs" Standard Extension for Single-Bit instructions + + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zbkb: "zbkb"; + /// "Zbkb" Standard Extension for Bitmanip instructions for Cryptography + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zbkc: "zbkc"; + /// "Zbkc" Standard Extension for Carry-less multiply instructions + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zbkx: "zbkx"; + /// "Zbkx" Standard Extension for Crossbar permutation instructions + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zknd: "zknd"; + /// "Zknd" Standard Extension for NIST Suite: AES Decryption + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zkne: "zkne"; + /// "Zkne" Standard Extension for NIST Suite: AES Encryption + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zknh: "zknh"; + /// "Zknh" Standard Extension for NIST Suite: Hash Function Instructions + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zksed: "zksed"; + /// "Zksed" Standard Extension for ShangMi Suite: SM4 Block Cipher Instructions + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zksh: "zksh"; + /// "Zksh" Standard Extension for ShangMi Suite: SM3 Hash Function Instructions + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zkr: "zkr"; + /// "Zkr" Standard Extension for Entropy Source Extension + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zkn: "zkn"; + /// "Zkn" Standard Extension for NIST Algorithm Suite + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zks: "zks"; + /// "Zks" Standard Extension for ShangMi Algorithm Suite + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zk: "zk"; + /// "Zk" Standard Extension for Standard scalar cryptography extension + @FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] zkt: "zkt"; + /// "Zkt" Standard Extension for Data Independent Execution Latency +} diff --git a/library/stdarch/crates/std_detect/src/detect/arch/x86.rs b/library/stdarch/crates/std_detect/src/detect/arch/x86.rs index f2df1fbcdf..22dbb98412 100644 --- a/library/stdarch/crates/std_detect/src/detect/arch/x86.rs +++ b/library/stdarch/crates/std_detect/src/detect/arch/x86.rs @@ -3,7 +3,7 @@ //! The features are detected using the `detect_features` function below. //! This function uses the CPUID instruction to read the feature flags from the //! CPU and encodes them in a `usize` where each bit position represents -//! whether a feature is available (bit is set) or unavaiable (bit is cleared). +//! whether a feature is available (bit is set) or unavailable (bit is cleared). //! //! The enum `Feature` is used to map bit positions to feature names, and the //! the `__crate::detect::check_for!` macro is used to map string literals (e.g., @@ -178,7 +178,7 @@ features! { @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] popcnt: "popcnt"; /// POPCNT (Population Count) @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] fxsr: "fxsr"; - /// FXSR (Floating-point context fast save and restor) + /// FXSR (Floating-point context fast save and restore) @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] xsave: "xsave"; /// XSAVE (Save Processor Extended States) @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] xsaveopt: "xsaveopt"; diff --git a/library/stdarch/crates/std_detect/src/detect/error_macros.rs b/library/stdarch/crates/std_detect/src/detect/error_macros.rs index 6769757ed9..1e70da486f 100644 --- a/library/stdarch/crates/std_detect/src/detect/error_macros.rs +++ b/library/stdarch/crates/std_detect/src/detect/error_macros.rs @@ -65,6 +65,27 @@ macro_rules! is_aarch64_feature_detected { }; } +/// Prevents compilation if `is_riscv_feature_detected` is used somewhere else +/// than `riscv32` or `riscv64` targets. +#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))] +#[macro_export] +#[unstable(feature = "stdsimd", issue = "27731")] +macro_rules! is_riscv_feature_detected { + ($t: tt) => { + compile_error!( + r#" + is_riscv_feature_detected can only be used on RISC-V targets. + You can prevent it from being used in other architectures by + guarding it behind a cfg(target_arch) as follows: + + #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] { + if is_riscv_feature_detected(...) { ... } + } + "# + ) + }; +} + /// Prevents compilation if `is_powerpc_feature_detected` is used somewhere else /// than `PowerPC` targets. #[cfg(not(target_arch = "powerpc"))] diff --git a/library/stdarch/crates/std_detect/src/detect/mod.rs b/library/stdarch/crates/std_detect/src/detect/mod.rs index 1b7768ae8f..e4eea72d45 100644 --- a/library/stdarch/crates/std_detect/src/detect/mod.rs +++ b/library/stdarch/crates/std_detect/src/detect/mod.rs @@ -38,6 +38,10 @@ cfg_if! { #[path = "arch/aarch64.rs"] #[macro_use] mod arch; + } else if #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] { + #[path = "arch/riscv.rs"] + #[macro_use] + mod arch; } else if #[cfg(target_arch = "powerpc")] { #[path = "arch/powerpc.rs"] #[macro_use] @@ -134,12 +138,15 @@ pub fn features() -> impl Iterator { target_arch = "x86_64", target_arch = "arm", target_arch = "aarch64", + target_arch = "riscv32", + target_arch = "riscv64", target_arch = "powerpc", target_arch = "powerpc64", target_arch = "mips", target_arch = "mips64", ))] { (0_u8..Feature::_last as u8).map(|discriminant: u8| { + #[allow(bindings_with_variant_name)] // RISC-V has Feature::f let f: Feature = unsafe { core::mem::transmute(discriminant) }; let name: &'static str = f.to_str(); let enabled: bool = check_for(f); diff --git a/library/stdarch/crates/std_detect/src/detect/os/freebsd/auxvec.rs b/library/stdarch/crates/std_detect/src/detect/os/freebsd/auxvec.rs index f12476adac..29fcc8cb0c 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/freebsd/auxvec.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/freebsd/auxvec.rs @@ -3,7 +3,8 @@ any( target_arch = "aarch64", target_arch = "arm", - target_arch = "powerpc64" + target_arch = "powerpc64", + target_arch = "riscv64" ), allow(dead_code) )] diff --git a/library/stdarch/crates/std_detect/src/detect/os/linux/auxvec.rs b/library/stdarch/crates/std_detect/src/detect/os/linux/auxvec.rs index 76908db314..e6447d0cde 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/linux/auxvec.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/linux/auxvec.rs @@ -63,7 +63,13 @@ pub(crate) fn auxv() -> Result { // Try to call a dynamically-linked getauxval function. if let Ok(hwcap) = getauxval(AT_HWCAP) { // Targets with only AT_HWCAP: - #[cfg(any(target_arch = "aarch64", target_arch = "mips", target_arch = "mips64"))] + #[cfg(any( + target_arch = "aarch64", + target_arch = "riscv32", + target_arch = "riscv64", + target_arch = "mips", + target_arch = "mips64" + ))] { if hwcap != 0 { return Ok(AuxVec { hwcap }); @@ -90,7 +96,13 @@ pub(crate) fn auxv() -> Result { #[cfg(not(feature = "std_detect_dlsym_getauxval"))] { // Targets with only AT_HWCAP: - #[cfg(any(target_arch = "aarch64", target_arch = "mips", target_arch = "mips64"))] + #[cfg(any( + target_arch = "aarch64", + target_arch = "riscv32", + target_arch = "riscv64", + target_arch = "mips", + target_arch = "mips64" + ))] { let hwcap = unsafe { libc::getauxval(AT_HWCAP as libc::c_ulong) as usize }; if hwcap != 0 { @@ -168,7 +180,13 @@ fn auxv_from_file(file: &str) -> Result { #[cfg(feature = "std_detect_file_io")] fn auxv_from_buf(buf: &[usize; 64]) -> Result { // Targets with only AT_HWCAP: - #[cfg(any(target_arch = "aarch64", target_arch = "mips", target_arch = "mips64"))] + #[cfg(any( + target_arch = "aarch64", + target_arch = "riscv32", + target_arch = "riscv64", + target_arch = "mips", + target_arch = "mips64", + ))] { for el in buf.chunks(2) { match el[0] { diff --git a/library/stdarch/crates/std_detect/src/detect/os/linux/cpuinfo.rs b/library/stdarch/crates/std_detect/src/detect/os/linux/cpuinfo.rs index 91279b9ed7..48a5c97286 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/linux/cpuinfo.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/linux/cpuinfo.rs @@ -212,6 +212,38 @@ CPU revision : 1"; assert!(cpuinfo.field("Features").has("asimd")); } + const RISCV_RV64GC: &str = r"processor : 0 +hart : 3 +isa : rv64imafdc +mmu : sv39 +uarch : sifive,u74-mc + +processor : 1 +hart : 1 +isa : rv64imafdc +mmu : sv39 +uarch : sifive,u74-mc + +processor : 2 +hart : 2 +isa : rv64imafdc +mmu : sv39 +uarch : sifive,u74-mc + +processor : 3 +hart : 4 +isa : rv64imafdc +mmu : sv39 +uarch : sifive,u74-mc"; + + #[test] + fn riscv_rv64gc() { + let cpuinfo = CpuInfo::from_str(RISCV_RV64GC).unwrap(); + assert_eq!(cpuinfo.field("isa"), "rv64imafdc"); + assert_eq!(cpuinfo.field("mmu"), "sv39"); + assert_eq!(cpuinfo.field("uarch"), "sifive,u74-mc"); + } + const POWER8E_POWERKVM: &str = r"processor : 0 cpu : POWER8E (raw), altivec supported clock : 3425.000000MHz diff --git a/library/stdarch/crates/std_detect/src/detect/os/linux/mod.rs b/library/stdarch/crates/std_detect/src/detect/os/linux/mod.rs index 4b6776e982..a49a72783d 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/linux/mod.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/linux/mod.rs @@ -45,7 +45,10 @@ cfg_if::cfg_if! { } else if #[cfg(target_arch = "arm")] { mod arm; pub(crate) use self::arm::detect_features; - } else if #[cfg(any(target_arch = "mips", target_arch = "mips64"))] { + } else if #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] { + mod riscv; + pub(crate) use self::riscv::detect_features; + } else if #[cfg(any(target_arch = "mips", target_arch = "mips64"))] { mod mips; pub(crate) use self::mips::detect_features; } else if #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] { diff --git a/library/stdarch/crates/std_detect/src/detect/os/linux/riscv.rs b/library/stdarch/crates/std_detect/src/detect/os/linux/riscv.rs new file mode 100644 index 0000000000..1ec06959a3 --- /dev/null +++ b/library/stdarch/crates/std_detect/src/detect/os/linux/riscv.rs @@ -0,0 +1,73 @@ +//! Run-time feature detection for RISC-V on Linux. + +use super::auxvec; +use crate::detect::{bit, cache, Feature}; + +/// Read list of supported features from the auxiliary vector. +pub(crate) fn detect_features() -> cache::Initializer { + let mut value = cache::Initializer::default(); + let enable_feature = |value: &mut cache::Initializer, feature, enable| { + if enable { + value.set(feature as u32); + } + }; + let enable_features = |value: &mut cache::Initializer, feature_slice: &[Feature], enable| { + if enable { + for feature in feature_slice { + value.set(*feature as u32); + } + } + }; + + // The values are part of the platform-specific [asm/hwcap.h][hwcap] + // + // [hwcap]: https://github.com/torvalds/linux/blob/master/arch/riscv/include/asm/hwcap.h + let auxv = auxvec::auxv().expect("read auxvec"); // should not fail on RISC-V platform + enable_feature( + &mut value, + Feature::a, + bit::test(auxv.hwcap, (b'a' - b'a').into()), + ); + enable_feature( + &mut value, + Feature::c, + bit::test(auxv.hwcap, (b'c' - b'a').into()), + ); + enable_features( + &mut value, + &[Feature::d, Feature::f, Feature::zicsr], + bit::test(auxv.hwcap, (b'd' - b'a').into()), + ); + enable_features( + &mut value, + &[Feature::f, Feature::zicsr], + bit::test(auxv.hwcap, (b'f' - b'a').into()), + ); + let has_i = bit::test(auxv.hwcap, (b'i' - b'a').into()); + // If future RV128I is supported, implement with `enable_feature` here + #[cfg(target_pointer_width = "64")] + enable_feature(&mut value, Feature::rv64i, has_i); + #[cfg(target_pointer_width = "32")] + enable_feature(&mut value, Feature::rv32i, has_i); + #[cfg(target_pointer_width = "32")] + enable_feature( + &mut value, + Feature::rv32e, + bit::test(auxv.hwcap, (b'e' - b'a').into()), + ); + enable_feature( + &mut value, + Feature::h, + bit::test(auxv.hwcap, (b'h' - b'a').into()), + ); + enable_feature( + &mut value, + Feature::m, + bit::test(auxv.hwcap, (b'm' - b'a').into()), + ); + // FIXME: Auxvec does not show supervisor feature support, but this mode may be useful + // to detect when Rust is used to write Linux kernel modules. + // These should be more than Auxvec way to detect supervisor features. + + value +} diff --git a/library/stdarch/crates/std_detect/src/lib.rs b/library/stdarch/crates/std_detect/src/lib.rs index a95af4145f..a17bd40e04 100644 --- a/library/stdarch/crates/std_detect/src/lib.rs +++ b/library/stdarch/crates/std_detect/src/lib.rs @@ -6,6 +6,7 @@ //! * `x86` and `x86_64`: [`is_x86_feature_detected`] //! * `arm`: [`is_arm_feature_detected`] //! * `aarch64`: [`is_aarch64_feature_detected`] +//! * `riscv`: [`is_riscv_feature_detected`] //! * `mips`: [`is_mips_feature_detected`] //! * `mips64`: [`is_mips64_feature_detected`] //! * `powerpc`: [`is_powerpc_feature_detected`] @@ -16,7 +17,6 @@ #![deny(rust_2018_idioms)] #![allow(clippy::shadow_reuse)] #![deny(clippy::missing_inline_in_public_items)] -#![cfg_attr(all(target_os = "freebsd", target_arch = "aarch64"), feature(asm))] #![cfg_attr(test, allow(unused_imports))] #![cfg_attr(feature = "std_detect_file_io", feature(vec_spare_capacity))] #![no_std] diff --git a/library/stdarch/crates/stdarch-gen/neon.spec b/library/stdarch/crates/stdarch-gen/neon.spec index 729602f724..c4a720aa35 100644 --- a/library/stdarch/crates/stdarch-gen/neon.spec +++ b/library/stdarch/crates/stdarch-gen/neon.spec @@ -56,7 +56,7 @@ // MAX - maximal value proper to overflow // // # validate -// Validates a and b aginst the expected result of the test. +// Validates a and b against the expected result of the test. // The special values 'TRUE' and 'FALSE' can be used to // represent the correct NEON representation of true or // false values. It too gets scaled to the type. @@ -411,7 +411,7 @@ aarch64 = cmtst generate int64x1_t:uint64x1_t, int64x2_t:uint64x2_t, poly64x1_t:uint64x1_t, poly64x2_t:uint64x2_t arm = vtst -generate int8x8_t:uint8x8_t, int8x16_t:uint8x16_t, int16x4_t:uint16x4_t, int16x8_t:uint16x8_t, int32x2_t:uint32x2_t, int32x4_t:uint32x4_t, poly8x8_t:uint8x8_t, poly8x16_t:uint8x16_t +generate int8x8_t:uint8x8_t, int8x16_t:uint8x16_t, int16x4_t:uint16x4_t, int16x8_t:uint16x8_t, int32x2_t:uint32x2_t, int32x4_t:uint32x4_t, poly8x8_t:uint8x8_t, poly8x16_t:uint8x16_t, poly16x4_t:uint16x4_t, poly16x8_t:uint16x8_t /// Unsigned compare bitwise Test bits nonzero name = vtst @@ -896,7 +896,7 @@ validate BITS_M1, BITS_M1, BITS_M1, BITS_M1, BITS_M1, BITS_M1, BITS_M1, BITS_M1, arm = vcls aarch64 = cls -generate uint*_t +generate uint8x8_t:int8x8_t, uint8x16_t:int8x16_t, uint16x4_t:int16x4_t, uint16x8_t:int16x8_t, uint32x2_t:int32x2_t, uint32x4_t:int32x4_t /// Count leading zero bits name = vclz @@ -2058,7 +2058,7 @@ generate int*_t /// Negate name = vneg -multi_fn = -a +multi_fn = a.wrapping_neg() a = 1 validate -1 @@ -4055,7 +4055,7 @@ generate float*_t /// Subtract name = vsub -multi_fn = a - b +multi_fn = a.wrapping_sub(b) a = 3 b = 2 validate 1 @@ -4065,7 +4065,7 @@ generate i64, u64 /// Add name = vadd -multi_fn = a + b +multi_fn = a.wrapping_add(b) a = 1 b = 2 validate 3 @@ -4685,7 +4685,7 @@ link-arm = vmaxs._EXT_ link-aarch64 = fmax._EXT_ generate float*_t -/// Floating-point Maximun Number (vector) +/// Floating-point Maximum Number (vector) name = vmaxnm a = 1.0, 2.0, 3.0, -4.0 b = 8.0, 16.0, -1.0, 6.0 @@ -4789,7 +4789,7 @@ link-arm = vmins._EXT_ link-aarch64 = fmin._EXT_ generate float*_t -/// Floating-point Minimun Number (vector) +/// Floating-point Minimum Number (vector) name = vminnm a = 1.0, 2.0, 3.0, -4.0 b = 8.0, 16.0, -1.0, 6.0 @@ -5894,7 +5894,7 @@ name = vqshl n-suffix constn = N multi_fn = static_assert_imm-out_bits_exp_len-N -multi_fn = vqshl-self-noext, a, {vdup-nself-noext, N.try_into().unwrap()} +multi_fn = vqshl-self-noext, a, {vdup-nself-noext, N as _} a = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 n = 2 validate 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60 @@ -5921,7 +5921,7 @@ name = vqshl n-suffix constn = N multi_fn = static_assert_imm-out_bits_exp_len-N -multi_fn = vqshl-self-noext, a, {vdup-nsigned-noext, N.try_into().unwrap()} +multi_fn = vqshl-self-noext, a, {vdup-nsigned-noext, N as _} a = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 n = 2 validate 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60 @@ -6480,7 +6480,7 @@ name = vrshr n-suffix constn = N multi_fn = static_assert-N-1-bits -multi_fn = vrshl-self-noext, a, {vdup-nself-noext, (-N).try_into().unwrap()} +multi_fn = vrshl-self-noext, a, {vdup-nself-noext, (-N) as _} a = 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64 n = 2 validate 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 @@ -6507,7 +6507,7 @@ name = vrshr n-suffix constn = N multi_fn = static_assert-N-1-bits -multi_fn = vrshl-self-noext, a, {vdup-nsigned-noext, (-N).try_into().unwrap()} +multi_fn = vrshl-self-noext, a, {vdup-nsigned-noext, (-N) as _} a = 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64 n = 2 validate 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 @@ -6613,7 +6613,7 @@ n-suffix constn = N multi_fn = static_assert-N-1-bits multi_fn = vrshr-nself-::, b:in_t, b -multi_fn = a + b +multi_fn = a.wrapping_add(b) a = 1 b = 4 n = 2 @@ -6628,7 +6628,7 @@ n-suffix constn = N multi_fn = static_assert-N-1-bits multi_fn = vrshr-nself-::, b:in_t, b -multi_fn = a + b +multi_fn = a.wrapping_add(b) a = 1 b = 4 n = 2 @@ -6804,7 +6804,7 @@ name = vshl n-suffix constn = N multi_fn = static_assert_imm-out_bits_exp_len-N -multi_fn = simd_shl, a, {vdup-nself-noext, N.try_into().unwrap()} +multi_fn = simd_shl, a, {vdup-nself-noext, N as _} a = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 n = 2 validate 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64 @@ -6818,7 +6818,7 @@ name = vshll n-suffix constn = N multi_fn = static_assert-N-0-bits -multi_fn = simd_shl, {simd_cast, a}, {vdup-nout-noext, N.try_into().unwrap()} +multi_fn = simd_shl, {simd_cast, a}, {vdup-nout-noext, N as _} a = 1, 2, 3, 4, 5, 6, 7, 8 n = 2 validate 4, 8, 12, 16, 20, 24, 28, 32 @@ -6851,7 +6851,7 @@ n-suffix constn = N multi_fn = static_assert-N-1-bits multi_fn = fix_right_shift_imm-N-bits -multi_fn = simd_shr, a, {vdup-nself-noext, n.try_into().unwrap()} +multi_fn = simd_shr, a, {vdup-nself-noext, n as _} a = 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64 n = 2 validate 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 @@ -6867,7 +6867,7 @@ name = vshrn_n no-q constn = N multi_fn = static_assert-N-1-halfbits -multi_fn = simd_cast, {simd_shr, a, {vdup-nself-noext, N.try_into().unwrap()}} +multi_fn = simd_cast, {simd_shr, a, {vdup-nself-noext, N as _}} a = 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64 n = 2 validate 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 @@ -7550,4 +7550,4 @@ n = 2 validate 510 aarch64 = sri -generate i64, u64 \ No newline at end of file +generate i64, u64 diff --git a/library/stdarch/crates/stdarch-gen/src/main.rs b/library/stdarch/crates/stdarch-gen/src/main.rs index 2142e7a5a0..39b4126946 100644 --- a/library/stdarch/crates/stdarch-gen/src/main.rs +++ b/library/stdarch/crates/stdarch-gen/src/main.rs @@ -1064,9 +1064,9 @@ fn gen_aarch64( }; let current_target = match target { Default => "neon", - ArmV7 => "v7", - Vfp4 => "vfp4", - FPArmV8 => "fp-armv8,v8", + ArmV7 => "neon", + Vfp4 => "neon", + FPArmV8 => "neon", AES => "neon,aes", FCMA => "neon,fcma", Dotprod => "neon,dotprod", @@ -1304,7 +1304,7 @@ fn gen_aarch64( }; format!( r#"{} - {}{}({}, {} as i64, a.cast())"#, + {}{}({}, {} as i64, a as _)"#, multi_calls, ext_c, current_fn, @@ -1327,7 +1327,7 @@ fn gen_aarch64( } } } else if link_aarch64.is_some() && matches!(fn_type, Fntype::Store) { - let cast = if is_vstx(&name) { ".cast()" } else { "" }; + let cast = if is_vstx(&name) { " as _" } else { "" }; match type_sub_len(in_t[1]) { 1 => format!(r#"{}{}(b, a{})"#, ext_c, current_fn, cast), 2 => format!(r#"{}{}(b.0, b.1, a{})"#, ext_c, current_fn, cast), @@ -1336,7 +1336,7 @@ fn gen_aarch64( _ => panic!("unsupported type: {}", in_t[1]), } } else if link_aarch64.is_some() && is_vldx(&name) { - format!(r#"{}{}(a.cast())"#, ext_c, current_fn,) + format!(r#"{}{}(a as _)"#, ext_c, current_fn,) } else { let trans: [&str; 2] = if link_t[3] != out_t { ["transmute(", ")"] @@ -1367,12 +1367,18 @@ fn gen_aarch64( } } }; + let stable = match target { + Default | ArmV7 | Vfp4 | FPArmV8 | AES => { + String::from("\n#[stable(feature = \"neon_intrinsics\", since = \"1.59.0\")]") + } + _ => String::new(), + }; let function = format!( r#" {} #[inline] #[target_feature(enable = "{}")] -#[cfg_attr(test, assert_instr({}{}))]{} +#[cfg_attr(test, assert_instr({}{}))]{}{} {}{{ {} }} @@ -1382,6 +1388,7 @@ fn gen_aarch64( current_aarch64, const_assert, const_legacy, + stable, fn_decl, call_params ); @@ -1553,7 +1560,7 @@ fn gen_store_test( let a: [{}; {}] = {}; let e: [{}; {}] = {}; let mut r: [{}; {}] = [0{}; {}]; - {}{}(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr().cast())); + {}{}(r.as_mut_ptr(), core::ptr::read_unaligned(a[1..].as_ptr() as _)); assert_eq!(r, e); "#, type_to_native_type(in_t[1]), @@ -2196,7 +2203,7 @@ fn gen_arm( _ => "", }; format!( - "{}(a.cast(), {}, {}, {})", + "{}(a as _, {}, {}, {})", current_fn, subs, constn.as_deref().unwrap(), @@ -2235,7 +2242,7 @@ fn gen_arm( } else if matches!(fn_type, Fntype::Store) { let (cast, size) = if is_vstx(&name) { ( - ".cast()", + " as _", format!(", {}", type_bits(&type_to_sub_type(in_t[1])) / 8), ) } else { @@ -2276,7 +2283,7 @@ fn gen_arm( _ => "", }; format!( - "{}({}, {} as i64, a.cast())", + "{}({}, {} as i64, a as _)", current_fn, subs, constn.as_deref().unwrap() @@ -2307,7 +2314,7 @@ fn gen_arm( _ => String::new(), } } else if matches!(fn_type, Fntype::Store) { - let cast = if is_vstx(&name) { ".cast()" } else { "" }; + let cast = if is_vstx(&name) { " as _" } else { "" }; match type_sub_len(in_t[1]) { 1 => format!("{}(b, a{})", current_fn, cast), 2 => format!("{}(b.0, b.1, a{})", current_fn, cast), @@ -2316,7 +2323,7 @@ fn gen_arm( _ => String::new(), } } else if link_aarch64.is_some() && is_vldx(&name) { - format!("{}(a.cast())", current_fn) + format!("{}(a as _)", current_fn) } else { String::new() }; @@ -2327,20 +2334,26 @@ fn gen_arm( fn_decl, multi_calls, ext_c_aarch64, aarch64_params ) }; + let stable_aarch64 = match target { + Default | ArmV7 | Vfp4 | FPArmV8 | AES => { + String::from("\n#[stable(feature = \"neon_intrinsics\", since = \"1.59.0\")]") + } + _ => String::new(), + }; format!( r#" {} #[inline] #[cfg(target_arch = "arm")] #[target_feature(enable = "neon,{}")] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr({}{}))]{} +#[cfg_attr(test, assert_instr({}{}))]{} {} {} #[inline] #[cfg(target_arch = "aarch64")] #[target_feature(enable = "{}")] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr({}{}))]{} +#[cfg_attr(test, assert_instr({}{}))]{}{} {} "#, current_comment, @@ -2354,6 +2367,7 @@ fn gen_arm( expand_intrinsic(¤t_aarch64, in_t[1]), const_assert, const_legacy, + stable_aarch64, call_aarch64, ) } else { @@ -2389,6 +2403,10 @@ fn gen_arm( String::new() } }; + let stable_aarch64 = match target { + Default | ArmV7 | Vfp4 | FPArmV8 | AES => String::from("\n#[cfg_attr(target_arch = \"aarch64\", stable(feature = \"neon_intrinsics\", since = \"1.59.0\"))]"), + _ => String::new(), + }; format!( r#" {} @@ -2396,7 +2414,7 @@ fn gen_arm( #[target_feature(enable = "{}")] #[cfg_attr(target_arch = "arm", target_feature(enable = "{}"))] #[cfg_attr(all(test, target_arch = "arm"), assert_instr({}{}))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr({}{}))]{} +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr({}{}))]{}{} {} "#, current_comment, @@ -2407,6 +2425,7 @@ fn gen_arm( expand_intrinsic(¤t_aarch64, in_t[1]), const_assert, const_legacy, + stable_aarch64, call, ) }; @@ -2787,7 +2806,7 @@ fn get_call( let s = ¶ms[i]; if s.starts_with('{') { let mut sub_fn = String::new(); - let mut paranthes = 0; + let mut parentheses = 0; while i < params.len() { if !sub_fn.is_empty() { sub_fn.push_str(", "); @@ -2796,19 +2815,19 @@ fn get_call( let l = params[i].len(); for j in 0..l { if ¶ms[i][j..j + 1] == "{" { - paranthes += 1; + parentheses += 1; } else { break; } } for j in 0..l { if ¶ms[i][l - j - 1..l - j] == "}" { - paranthes -= 1; + parentheses -= 1; } else { break; } } - if paranthes == 0 { + if parentheses == 0 { break; } i += 1; diff --git a/library/stdarch/crates/stdarch-verify/tests/arm.rs b/library/stdarch/crates/stdarch-verify/tests/arm.rs index a170ea4e62..6ce5ce05fd 100644 --- a/library/stdarch/crates/stdarch-verify/tests/arm.rs +++ b/library/stdarch/crates/stdarch-verify/tests/arm.rs @@ -594,6 +594,8 @@ fn verify_all_signatures() { "vclsq_u8", "vclsq_u16", "vclsq_u32", + "vtst_p16", + "vtstq_p16", "__dbg", ]; let arm = match map.get(rust.name) { diff --git a/library/stdarch/rustfmt.toml b/library/stdarch/rustfmt.toml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 2516f3452b..fad83094cd 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -13,20 +13,11 @@ // running tests while providing a base that other test frameworks may // build off of. -// N.B., this is also specified in this crate's Cargo.toml, but librustc_ast contains logic specific to -// this crate, which relies on this attribute (rather than the value of `--crate-name` passed by -// cargo) to detect this crate. - -#![crate_name = "test"] #![unstable(feature = "test", issue = "50297")] #![doc(test(attr(deny(warnings))))] -#![feature(libc)] -#![feature(rustc_private)] #![feature(nll)] -#![feature(available_parallelism)] #![feature(bench_black_box)] #![feature(internal_output_capture)] -#![feature(panic_unwind)] #![feature(staged_api)] #![feature(termination_trait_lib)] #![feature(test)] @@ -444,8 +435,8 @@ pub fn convert_benchmarks_to_tests(tests: Vec) -> Vec DynTestFn(Box::new(move || { - bench::run_once(|b| __rust_begin_short_backtrace(|| bench.run(b))) + DynBenchFn(benchfn) => DynTestFn(Box::new(move || { + bench::run_once(|b| __rust_begin_short_backtrace(|| benchfn(b))) })), StaticBenchFn(benchfn) => DynTestFn(Box::new(move || { bench::run_once(|b| __rust_begin_short_backtrace(|| benchfn(b))) @@ -544,11 +535,9 @@ pub fn run_test( TestRunOpts { strategy, nocapture: opts.nocapture, concurrency, time: opts.time_options }; match testfn { - DynBenchFn(bencher) => { + DynBenchFn(benchfn) => { // Benchmarks aren't expected to panic, so we run them all in-process. - crate::bench::benchmark(id, desc, monitor_ch, opts.nocapture, |harness| { - bencher.run(harness) - }); + crate::bench::benchmark(id, desc, monitor_ch, opts.nocapture, benchfn); None } StaticBenchFn(benchfn) => { diff --git a/library/test/src/stats.rs b/library/test/src/stats.rs index 45fae9c76b..40b05704b4 100644 --- a/library/test/src/stats.rs +++ b/library/test/src/stats.rs @@ -1,5 +1,4 @@ #![allow(missing_docs)] -#![allow(deprecated)] // Float use std::mem; diff --git a/library/test/src/types.rs b/library/test/src/types.rs index 3512a57e8e..37bb38fb0d 100644 --- a/library/test/src/types.rs +++ b/library/test/src/types.rs @@ -74,11 +74,6 @@ impl fmt::Display for TestName { } } -/// Represents a benchmark function. -pub trait TDynBenchFn: Send { - fn run(&self, harness: &mut Bencher); -} - // A function that runs a test. If the function returns successfully, // the test succeeds; if the function panics then the test fails. We // may need to come up with a more clever definition of test in order @@ -87,7 +82,7 @@ pub enum TestFn { StaticTestFn(fn()), StaticBenchFn(fn(&mut Bencher)), DynTestFn(Box), - DynBenchFn(Box), + DynBenchFn(Box), } impl TestFn { diff --git a/library/unwind/build.rs b/library/unwind/build.rs index 1d0b4a59a2..a3f5224151 100644 --- a/library/unwind/build.rs +++ b/library/unwind/build.rs @@ -17,6 +17,9 @@ fn main() { } else { println!("cargo:rustc-link-lib=gcc"); } + + // Android's unwinding library depends on dl_iterate_phdr in `libdl`. + println!("cargo:rustc-link-lib=dl"); } else if target.contains("freebsd") { println!("cargo:rustc-link-lib=gcc_s"); } else if target.contains("netbsd") { diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 1ce1f0b26d..b68b2163f8 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -44,11 +44,9 @@ libc = "0.2" serde = { version = "1.0.8", features = ["derive"] } serde_json = "1.0.2" toml = "0.5" -lazy_static = "1.3.0" time = "0.1" ignore = "0.4.10" opener = "0.5" -merge = "0.1.0" once_cell = "1.7.2" [target.'cfg(windows)'.dependencies.winapi] diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index ed53a98e9a..7105a2457e 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -15,6 +15,8 @@ //! switching compilers for the bootstrap and for build scripts will probably //! never get replaced. +include!("../dylib_util.rs"); + use std::env; use std::path::PathBuf; use std::process::{Child, Command}; @@ -50,11 +52,11 @@ fn main() { let rustc = env::var_os(rustc).unwrap_or_else(|| panic!("{:?} was not set", rustc)); let libdir = env::var_os(libdir).unwrap_or_else(|| panic!("{:?} was not set", libdir)); - let mut dylib_path = bootstrap::util::dylib_path(); + let mut dylib_path = dylib_path(); dylib_path.insert(0, PathBuf::from(&libdir)); let mut cmd = Command::new(rustc); - cmd.args(&args).env(bootstrap::util::dylib_path_var(), env::join_paths(&dylib_path).unwrap()); + cmd.args(&args).env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); // Get the name of the crate we're compiling, if any. let crate_name = @@ -161,7 +163,7 @@ fn main() { eprintln!( "{} command: {:?}={:?} {:?}", prefix, - bootstrap::util::dylib_path_var(), + dylib_path_var(), env::join_paths(&dylib_path).unwrap(), cmd, ); diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs index e4396d5301..ad3800834b 100644 --- a/src/bootstrap/bin/rustdoc.rs +++ b/src/bootstrap/bin/rustdoc.rs @@ -7,6 +7,8 @@ use std::ffi::OsString; use std::path::PathBuf; use std::process::Command; +include!("../dylib_util.rs"); + fn main() { let args = env::args_os().skip(1).collect::>(); let rustdoc = env::var_os("RUSTDOC_REAL").expect("RUSTDOC_REAL was not set"); @@ -20,14 +22,14 @@ fn main() { Err(_) => 0, }; - let mut dylib_path = bootstrap::util::dylib_path(); + let mut dylib_path = dylib_path(); dylib_path.insert(0, PathBuf::from(libdir.clone())); let mut cmd = Command::new(rustdoc); cmd.args(&args) .arg("--sysroot") .arg(&sysroot) - .env(bootstrap::util::dylib_path_var(), env::join_paths(&dylib_path).unwrap()); + .env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); // Force all crates compiled by this compiler to (a) be unstable and (b) // allow the `rustc_private` feature to link to other unstable crates @@ -59,7 +61,7 @@ fn main() { if verbose > 1 { eprintln!( "rustdoc command: {:?}={:?} {:?}", - bootstrap::util::dylib_path_var(), + dylib_path_var(), env::join_paths(&dylib_path).unwrap(), cmd, ); diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 22f2e405a1..7c36bb264c 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -13,7 +13,45 @@ import sys import tarfile import tempfile -from time import time +from time import time, sleep + +# Acquire a lock on the build directory to make sure that +# we don't cause a race condition while building +# Lock is created in `build_dir/lock.db` +def acquire_lock(build_dir): + try: + import sqlite3 + + path = os.path.join(build_dir, "lock.db") + try: + con = sqlite3.Connection(path, timeout=0) + curs = con.cursor() + curs.execute("BEGIN EXCLUSIVE") + # The lock is released when the cursor is dropped + return curs + # If the database is busy then lock has already been acquired + # so we wait for the lock. + # We retry every quarter second so that execution is passed back to python + # so that it can handle signals + except sqlite3.OperationalError: + del con + del curs + print("Waiting for lock on build directory") + con = sqlite3.Connection(path, timeout=0.25) + curs = con.cursor() + while True: + try: + curs.execute("BEGIN EXCLUSIVE") + break + except sqlite3.OperationalError: + pass + sleep(0.25) + return curs + except ImportError: + print("warning: sqlite3 not available in python, skipping build directory lock") + print("please file an issue on rust-lang/rust") + print("this is not a problem for non-concurrent x.py invocations") + return None def support_xz(): try: @@ -189,11 +227,11 @@ def default_build_triple(verbose): host = next(x for x in version.split('\n') if x.startswith("host: ")) triple = host.split("host: ")[1] if verbose: - print("detected default triple {}".format(triple)) + print("detected default triple {} from pre-installed rustc".format(triple)) return triple except Exception as e: if verbose: - print("rustup not detected: {}".format(e)) + print("pre-installed rustc not detected: {}".format(e)) print("falling back to auto-detect") required = sys.platform != 'win32' @@ -265,7 +303,7 @@ def default_build_triple(verbose): err = "unknown OS type: {}".format(ostype) sys.exit(err) - if cputype == 'powerpc' and ostype == 'unknown-freebsd': + if cputype in ['powerpc', 'riscv'] and ostype == 'unknown-freebsd': cputype = subprocess.check_output( ['uname', '-p']).strip().decode(default_encoding) cputype_mapper = { @@ -726,12 +764,15 @@ class RustBuild(object): status = subprocess.call(["git", "diff-index", "--quiet", commit, "--", compiler, library]) if status != 0: if download_rustc == "if-unchanged": + if self.verbose: + print("warning: saw changes to compiler/ or library/ since {}; " \ + "ignoring `download-rustc`".format(commit)) return None - print("warning: `download-rustc` is enabled, but there are changes to \ - compiler/ or library/") + print("warning: `download-rustc` is enabled, but there are changes to " \ + "compiler/ or library/") if self.verbose: - print("using downloaded stage1 artifacts from CI (commit {})".format(commit)) + print("using downloaded stage2 artifacts from CI (commit {})".format(commit)) self.rustc_commit = commit # FIXME: support downloading artifacts from the beta channel self.download_toolchain(False, "nightly") @@ -935,6 +976,7 @@ class RustBuild(object): def build_bootstrap(self): """Build bootstrap""" + print("Building rustbuild") build_dir = os.path.join(self.build_dir, "bootstrap") if self.clean and os.path.exists(build_dir): shutil.rmtree(build_dir) @@ -1094,7 +1136,7 @@ class RustBuild(object): recorded_submodules[data[3]] = data[2] for module in filtered_submodules: self.update_submodule(module[0], module[1], recorded_submodules) - print("Submodules updated in %.2f seconds" % (time() - start_time)) + print(" Submodules updated in %.2f seconds" % (time() - start_time)) def set_dist_environment(self, url): """Set download URL for normal environment""" @@ -1225,6 +1267,12 @@ def bootstrap(help_triggered): build.set_dist_environment(data["dist_server"]) build.build = args.build or build.build_triple() + + # Acquire the lock before doing any build actions + # The lock is released when `lock` is dropped + if not os.path.exists(build.build_dir): + os.makedirs(build.build_dir) + lock = acquire_lock(build.build_dir) build.update_submodules() # Fetch/build the bootstrap diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 6ba1b1b603..6ccf8b1d52 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -351,7 +351,6 @@ pub enum Kind { Check, Clippy, Fix, - Format, Test, Bench, Dist, @@ -399,7 +398,7 @@ impl<'a> Builder<'a> { native::Lld, native::CrtBeginEnd ), - Kind::Check | Kind::Clippy { .. } | Kind::Fix | Kind::Format => describe!( + Kind::Check | Kind::Clippy { .. } | Kind::Fix => describe!( check::Std, check::Rustc, check::Rustdoc, @@ -989,10 +988,20 @@ impl<'a> Builder<'a> { } }; - if use_new_symbol_mangling { - rustflags.arg("-Zsymbol-mangling-version=v0"); + // cfg(bootstrap) -- drop the compiler.stage == 0 branch. + if compiler.stage == 0 { + if use_new_symbol_mangling { + rustflags.arg("-Zsymbol-mangling-version=v0"); + } else { + rustflags.arg("-Zsymbol-mangling-version=legacy"); + } } else { - rustflags.arg("-Zsymbol-mangling-version=legacy"); + if use_new_symbol_mangling { + rustflags.arg("-Csymbol-mangling-version=v0"); + } else { + rustflags.arg("-Csymbol-mangling-version=legacy"); + rustflags.arg("-Zunstable-options"); + } } // FIXME: It might be better to use the same value for both `RUSTFLAGS` and `RUSTDOCFLAGS`, @@ -1176,6 +1185,7 @@ impl<'a> Builder<'a> { rustflags.arg("-Zosx-rpath-install-name"); Some("-Wl,-rpath,@loader_path/../lib") } else if !target.contains("windows") { + rustflags.arg("-Clink-args=-Wl,-z,origin"); Some("-Wl,-rpath,$ORIGIN/../lib") } else { None @@ -1578,11 +1588,11 @@ impl<'a> Builder<'a> { panic!("{}", out); } if let Some(out) = self.cache.get(&step) { - self.verbose(&format!("{}c {:?}", " ".repeat(stack.len()), step)); + self.verbose_than(1, &format!("{}c {:?}", " ".repeat(stack.len()), step)); return out; } - self.verbose(&format!("{}> {:?}", " ".repeat(stack.len()), step)); + self.verbose_than(1, &format!("{}> {:?}", " ".repeat(stack.len()), step)); stack.push(Box::new(step.clone())); } @@ -1605,7 +1615,7 @@ impl<'a> Builder<'a> { let cur_step = stack.pop().expect("step stack empty"); assert_eq!(cur_step.downcast_ref(), Some(&step)); } - self.verbose(&format!("{}< {:?}", " ".repeat(self.stack.borrow().len()), step)); + self.verbose_than(1, &format!("{}< {:?}", " ".repeat(self.stack.borrow().len()), step)); self.cache.put(step, out.clone()); out } diff --git a/src/bootstrap/cache.rs b/src/bootstrap/cache.rs index 0c16fae01b..fac5d8db51 100644 --- a/src/bootstrap/cache.rs +++ b/src/bootstrap/cache.rs @@ -13,7 +13,8 @@ use std::ops::Deref; use std::path::{Path, PathBuf}; use std::sync::Mutex; -use lazy_static::lazy_static; +// FIXME: replace with std::lazy after it gets stabilized and reaches beta +use once_cell::sync::Lazy; use crate::builder::Step; @@ -222,9 +223,7 @@ impl Interner { } } -lazy_static! { - pub static ref INTERNER: Interner = Interner::default(); -} +pub static INTERNER: Lazy = Lazy::new(Interner::default); /// This is essentially a `HashMap` which allows storing any type in its input and /// any type in its output. It is a write-once cache; values are never evicted, diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs index 3216c1af26..3b73dc1c7d 100644 --- a/src/bootstrap/clean.rs +++ b/src/bootstrap/clean.rs @@ -75,10 +75,10 @@ fn rm_rf(path: &Path) { do_op(path, "remove dir", |p| { fs::remove_dir(p).or_else(|e| { // Check for dir not empty on Windows + // FIXME: Once `ErrorKind::DirectoryNotEmpty` is stabilized, + // match on `e.kind()` instead. #[cfg(windows)] - if matches!(e.kind(), std::io::ErrorKind::Other) - && e.raw_os_error() == Some(145) - { + if e.raw_os_error() == Some(145) { return Ok(()); } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 007ca9f7f5..043b38ecec 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -28,6 +28,7 @@ use crate::dist; use crate::native; use crate::tool::SourceType; use crate::util::{exe, is_debug_info, is_dylib, symlink_dir}; +use crate::LLVM_TOOLS; use crate::{Compiler, DependencyType, GitRepo, Mode}; #[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)] @@ -661,6 +662,8 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS .env("CFG_VERSION", builder.rust_version()); let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib")); + let target_config = builder.config.target_config.get(&target); + cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative); if let Some(ref ver_date) = builder.rust_info.commit_date() { @@ -672,9 +675,15 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS if !builder.unstable_features() { cargo.env("CFG_DISABLE_UNSTABLE_FEATURES", "1"); } - if let Some(ref s) = builder.config.rustc_default_linker { + + // Prefer the current target's own default_linker, else a globally + // specified one. + if let Some(s) = target_config.and_then(|c| c.default_linker.as_ref()) { + cargo.env("CFG_DEFAULT_LINKER", s); + } else if let Some(ref s) = builder.config.rustc_default_linker { cargo.env("CFG_DEFAULT_LINKER", s); } + if builder.config.rustc_parallel { cargo.rustflag("--cfg=parallel_compiler"); cargo.rustdocflag("--cfg=parallel_compiler"); @@ -699,7 +708,6 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS } let llvm_config = builder.ensure(native::Llvm { target }); cargo.env("LLVM_CONFIG", &llvm_config); - let target_config = builder.config.target_config.get(&target); if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { cargo.env("CFG_LLVM_ROOT", s); } @@ -1135,7 +1143,6 @@ impl Step for Assemble { let libdir = builder.sysroot_libdir(target_compiler, target_compiler.host); let libdir_bin = libdir.parent().unwrap().join("bin"); t!(fs::create_dir_all(&libdir_bin)); - if let Some(lld_install) = lld_install { let src_exe = exe("lld", target_compiler.host); let dst_exe = exe("rust-lld", target_compiler.host); @@ -1153,17 +1160,26 @@ impl Step for Assemble { } } - // Similarly, copy `llvm-dwp` into libdir for Split DWARF. Only copy it when the LLVM - // backend is used to avoid unnecessarily building LLVM and because LLVM is not checked - // out by default when the LLVM backend is not enabled. if builder.config.rust_codegen_backends.contains(&INTERNER.intern_str("llvm")) { - let src_exe = exe("llvm-dwp", target_compiler.host); - let dst_exe = exe("rust-llvm-dwp", target_compiler.host); let llvm_config_bin = builder.ensure(native::Llvm { target: target_compiler.host }); if !builder.config.dry_run { let llvm_bin_dir = output(Command::new(llvm_config_bin).arg("--bindir")); let llvm_bin_dir = Path::new(llvm_bin_dir.trim()); - builder.copy(&llvm_bin_dir.join(&src_exe), &libdir_bin.join(&dst_exe)); + + // Since we've already built the LLVM tools, install them to the sysroot. + // This is the equivalent of installing the `llvm-tools-preview` component via + // rustup, and lets developers use a locally built toolchain to + // build projects that expect llvm tools to be present in the sysroot + // (e.g. the `bootimage` crate). + for tool in LLVM_TOOLS { + let tool_exe = exe(tool, target_compiler.host); + let src_path = llvm_bin_dir.join(&tool_exe); + // When using `donwload-ci-llvm`, some of the tools + // may not exist, so skip trying to copy them. + if src_path.exists() { + builder.copy(&src_path, &libdir_bin.join(&tool_exe)); + } + } } } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 68e20f90b7..5af9248583 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -18,7 +18,6 @@ pub use crate::flags::Subcommand; use crate::flags::{Color, Flags}; use crate::util::exe; use build_helper::t; -use merge::Merge; use serde::Deserialize; macro_rules! check_ci_llvm { @@ -294,6 +293,7 @@ pub struct Target { pub cxx: Option, pub ar: Option, pub ranlib: Option, + pub default_linker: Option, pub linker: Option, pub ndk: Option, pub sanitizers: Option, @@ -333,6 +333,10 @@ struct TomlConfig { profile: Option, } +trait Merge { + fn merge(&mut self, other: Self); +} + impl Merge for TomlConfig { fn merge( &mut self, @@ -356,105 +360,136 @@ impl Merge for TomlConfig { } } -/// TOML representation of various global build decisions. -#[derive(Deserialize, Default, Clone, Merge)] -#[serde(deny_unknown_fields, rename_all = "kebab-case")] -struct Build { - build: Option, - host: Option>, - target: Option>, - // This is ignored, the rust code always gets the build directory from the `BUILD_DIR` env variable - build_dir: Option, - cargo: Option, - rustc: Option, - rustfmt: Option, - docs: Option, - compiler_docs: Option, - docs_minification: Option, - submodules: Option, - fast_submodules: Option, - gdb: Option, - nodejs: Option, - npm: Option, - python: Option, - locked_deps: Option, - vendor: Option, - full_bootstrap: Option, - extended: Option, - tools: Option>, - verbose: Option, - sanitizers: Option, - profiler: Option, - cargo_native_static: Option, - low_priority: Option, - configure_args: Option>, - local_rebuild: Option, - print_step_timings: Option, - print_step_rusage: Option, - check_stage: Option, - doc_stage: Option, - build_stage: Option, - test_stage: Option, - install_stage: Option, - dist_stage: Option, - bench_stage: Option, - patch_binaries_for_nix: Option, +// We are using a decl macro instead of a derive proc macro here to reduce the compile time of +// rustbuild. +macro_rules! derive_merge { + ($(#[$attr:meta])* struct $name:ident { + $($field:ident: $field_ty:ty,)* + }) => { + $(#[$attr])* + struct $name { + $($field: $field_ty,)* + } + + impl Merge for $name { + fn merge(&mut self, other: Self) { + $( + if !self.$field.is_some() { + self.$field = other.$field; + } + )* + } + } + } } -/// TOML representation of various global install decisions. -#[derive(Deserialize, Default, Clone, Merge)] -#[serde(deny_unknown_fields, rename_all = "kebab-case")] -struct Install { - prefix: Option, - sysconfdir: Option, - docdir: Option, - bindir: Option, - libdir: Option, - mandir: Option, - datadir: Option, +derive_merge! { + /// TOML representation of various global build decisions. + #[derive(Deserialize, Default, Clone)] + #[serde(deny_unknown_fields, rename_all = "kebab-case")] + struct Build { + build: Option, + host: Option>, + target: Option>, + // This is ignored, the rust code always gets the build directory from the `BUILD_DIR` env variable + build_dir: Option, + cargo: Option, + rustc: Option, + rustfmt: Option, + docs: Option, + compiler_docs: Option, + docs_minification: Option, + submodules: Option, + fast_submodules: Option, + gdb: Option, + nodejs: Option, + npm: Option, + python: Option, + locked_deps: Option, + vendor: Option, + full_bootstrap: Option, + extended: Option, + tools: Option>, + verbose: Option, + sanitizers: Option, + profiler: Option, + cargo_native_static: Option, + low_priority: Option, + configure_args: Option>, + local_rebuild: Option, + print_step_timings: Option, + print_step_rusage: Option, + check_stage: Option, + doc_stage: Option, + build_stage: Option, + test_stage: Option, + install_stage: Option, + dist_stage: Option, + bench_stage: Option, + patch_binaries_for_nix: Option, + } } -/// TOML representation of how the LLVM build is configured. -#[derive(Deserialize, Default, Merge)] -#[serde(deny_unknown_fields, rename_all = "kebab-case")] -struct Llvm { - skip_rebuild: Option, - optimize: Option, - thin_lto: Option, - release_debuginfo: Option, - assertions: Option, - tests: Option, - plugins: Option, - ccache: Option, - version_check: Option, - static_libstdcpp: Option, - ninja: Option, - targets: Option, - experimental_targets: Option, - link_jobs: Option, - link_shared: Option, - version_suffix: Option, - clang_cl: Option, - cflags: Option, - cxxflags: Option, - ldflags: Option, - use_libcxx: Option, - use_linker: Option, - allow_old_toolchain: Option, - polly: Option, - clang: Option, - download_ci_llvm: Option, +derive_merge! { + /// TOML representation of various global install decisions. + #[derive(Deserialize, Default, Clone)] + #[serde(deny_unknown_fields, rename_all = "kebab-case")] + struct Install { + prefix: Option, + sysconfdir: Option, + docdir: Option, + bindir: Option, + libdir: Option, + mandir: Option, + datadir: Option, + } } -#[derive(Deserialize, Default, Clone, Merge)] -#[serde(deny_unknown_fields, rename_all = "kebab-case")] -struct Dist { - sign_folder: Option, - gpg_password_file: Option, - upload_addr: Option, - src_tarball: Option, - missing_tools: Option, - compression_formats: Option>, +derive_merge! { + /// TOML representation of how the LLVM build is configured. + #[derive(Deserialize, Default)] + #[serde(deny_unknown_fields, rename_all = "kebab-case")] + struct Llvm { + skip_rebuild: Option, + optimize: Option, + thin_lto: Option, + release_debuginfo: Option, + assertions: Option, + tests: Option, + plugins: Option, + ccache: Option, + version_check: Option, + static_libstdcpp: Option, + ninja: Option, + targets: Option, + experimental_targets: Option, + link_jobs: Option, + link_shared: Option, + version_suffix: Option, + clang_cl: Option, + cflags: Option, + cxxflags: Option, + ldflags: Option, + use_libcxx: Option, + use_linker: Option, + allow_old_toolchain: Option, + polly: Option, + clang: Option, + download_ci_llvm: Option, + } +} + +derive_merge! { + #[derive(Deserialize, Default, Clone)] + #[serde(deny_unknown_fields, rename_all = "kebab-case")] + struct Dist { + sign_folder: Option, + gpg_password_file: Option, + upload_addr: Option, + src_tarball: Option, + missing_tools: Option, + compression_formats: Option>, + } } #[derive(Deserialize)] @@ -470,79 +505,84 @@ impl Default for StringOrBool { } } -/// TOML representation of how the Rust build is configured. -#[derive(Deserialize, Default, Merge)] -#[serde(deny_unknown_fields, rename_all = "kebab-case")] -struct Rust { - optimize: Option, - debug: Option, - codegen_units: Option, - codegen_units_std: Option, - debug_assertions: Option, - debug_assertions_std: Option, - overflow_checks: Option, - overflow_checks_std: Option, - debug_logging: Option, - debuginfo_level: Option, - debuginfo_level_rustc: Option, - debuginfo_level_std: Option, - debuginfo_level_tools: Option, - debuginfo_level_tests: Option, - run_dsymutil: Option, - backtrace: Option, - incremental: Option, - parallel_compiler: Option, - default_linker: Option, - channel: Option, - description: Option, - musl_root: Option, - rpath: Option, - verbose_tests: Option, - optimize_tests: Option, - codegen_tests: Option, - ignore_git: Option, - dist_src: Option, - save_toolstates: Option, - codegen_backends: Option>, - lld: Option, - use_lld: Option, - llvm_tools: Option, - deny_warnings: Option, - backtrace_on_ice: Option, - verify_llvm_ir: Option, - thin_lto_import_instr_limit: Option, - remap_debuginfo: Option, - jemalloc: Option, - test_compare_mode: Option, - llvm_libunwind: Option, - control_flow_guard: Option, - new_symbol_mangling: Option, - profile_generate: Option, - profile_use: Option, - // ignored; this is set from an env var set by bootstrap.py - download_rustc: Option, +derive_merge! { + /// TOML representation of how the Rust build is configured. + #[derive(Deserialize, Default)] + #[serde(deny_unknown_fields, rename_all = "kebab-case")] + struct Rust { + optimize: Option, + debug: Option, + codegen_units: Option, + codegen_units_std: Option, + debug_assertions: Option, + debug_assertions_std: Option, + overflow_checks: Option, + overflow_checks_std: Option, + debug_logging: Option, + debuginfo_level: Option, + debuginfo_level_rustc: Option, + debuginfo_level_std: Option, + debuginfo_level_tools: Option, + debuginfo_level_tests: Option, + run_dsymutil: Option, + backtrace: Option, + incremental: Option, + parallel_compiler: Option, + default_linker: Option, + channel: Option, + description: Option, + musl_root: Option, + rpath: Option, + verbose_tests: Option, + optimize_tests: Option, + codegen_tests: Option, + ignore_git: Option, + dist_src: Option, + save_toolstates: Option, + codegen_backends: Option>, + lld: Option, + use_lld: Option, + llvm_tools: Option, + deny_warnings: Option, + backtrace_on_ice: Option, + verify_llvm_ir: Option, + thin_lto_import_instr_limit: Option, + remap_debuginfo: Option, + jemalloc: Option, + test_compare_mode: Option, + llvm_libunwind: Option, + control_flow_guard: Option, + new_symbol_mangling: Option, + profile_generate: Option, + profile_use: Option, + // ignored; this is set from an env var set by bootstrap.py + download_rustc: Option, + } } -/// TOML representation of how each build target is configured. -#[derive(Deserialize, Default, Merge)] -#[serde(deny_unknown_fields, rename_all = "kebab-case")] -struct TomlTarget { - cc: Option, - cxx: Option, - ar: Option, - ranlib: Option, - linker: Option, - llvm_config: Option, - llvm_filecheck: Option, - android_ndk: Option, - sanitizers: Option, - profiler: Option, - crt_static: Option, - musl_root: Option, - musl_libdir: Option, - wasi_root: Option, - qemu_rootfs: Option, - no_std: Option, +derive_merge! { + /// TOML representation of how each build target is configured. + #[derive(Deserialize, Default)] + #[serde(deny_unknown_fields, rename_all = "kebab-case")] + struct TomlTarget { + cc: Option, + cxx: Option, + ar: Option, + ranlib: Option, + default_linker: Option, + linker: Option, + llvm_config: Option, + llvm_filecheck: Option, + android_ndk: Option, + sanitizers: Option, + profiler: Option, + crt_static: Option, + musl_root: Option, + musl_libdir: Option, + wasi_root: Option, + qemu_rootfs: Option, + no_std: Option, + } } impl Config { @@ -1109,10 +1149,6 @@ impl Config { self.verbose > 0 } - pub fn very_verbose(&self) -> bool { - self.verbose > 1 - } - pub fn sanitizers_enabled(&self, target: TargetSelection) -> bool { self.target_config.get(&target).map(|t| t.sanitizers).flatten().unwrap_or(self.sanitizers) } diff --git a/src/bootstrap/defaults/config.tools.toml b/src/bootstrap/defaults/config.tools.toml index 182fb0fb06..88359fff19 100644 --- a/src/bootstrap/defaults/config.tools.toml +++ b/src/bootstrap/defaults/config.tools.toml @@ -11,6 +11,10 @@ incremental = true # This cuts compile times by almost 60x, but means you can't modify the compiler. download-rustc = "if-unchanged" +[build] +# Document with the in-tree rustdoc by default, since `download-rustc` makes it quick to compile. +doc-stage = 2 + [llvm] # Will download LLVM from CI if available on your platform. download-ci-llvm = "if-available" diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 09ea84a083..7d9b3da48e 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -398,12 +398,12 @@ impl Step for Rustc { // component for now. maybe_install_llvm_runtime(builder, host, image); - let src_dir = builder.sysroot_libdir(compiler, host).parent().unwrap().join("bin"); let dst_dir = image.join("lib/rustlib").join(&*host.triple).join("bin"); t!(fs::create_dir_all(&dst_dir)); // Copy over lld if it's there if builder.config.lld_enabled { + let src_dir = builder.sysroot_libdir(compiler, host).parent().unwrap().join("bin"); let rust_lld = exe("rust-lld", compiler.host); builder.copy(&src_dir.join(&rust_lld), &dst_dir.join(&rust_lld)); // for `-Z gcc-ld=lld` @@ -417,10 +417,6 @@ impl Step for Rustc { } } - // Copy over llvm-dwp if it's there - let exe = exe("rust-llvm-dwp", compiler.host); - builder.copy(&src_dir.join(&exe), &dst_dir.join(&exe)); - // Man pages t!(fs::create_dir_all(image.join("share/man/man1"))); let man_src = builder.src.join("src/doc/man"); @@ -1564,7 +1560,9 @@ impl Step for Extended { builder.install(&etc.join("gfx/rust-logo.ico"), &exe, 0o644); // Generate msi installer - let wix = PathBuf::from(env::var_os("WIX").unwrap()); + let wix_path = env::var_os("WIX") + .expect("`WIX` environment variable must be set for generating MSI installer(s)."); + let wix = PathBuf::from(wix_path); let heat = wix.join("bin/heat.exe"); let candle = wix.join("bin/candle.exe"); let light = wix.join("bin/light.exe"); @@ -2085,6 +2083,13 @@ impl Step for RustDev { ] { tarball.add_file(src_bindir.join(exe(bin, target)), "bin", 0o755); } + + // We don't build LLD on some platforms, so only add it if it exists + let lld_path = builder.lld_out(target).join("bin").join(exe("lld", target)); + if lld_path.exists() { + tarball.add_file(lld_path, "bin", 0o755); + } + tarball.add_file(&builder.llvm_filecheck(target), "bin", 0o755); // Copy the include directory as well; needed mostly to build diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp index 19e5fffcc2..ef635ee26d 100644 --- a/src/bootstrap/download-ci-llvm-stamp +++ b/src/bootstrap/download-ci-llvm-stamp @@ -1,4 +1,4 @@ Change this file to make users of the `download-ci-llvm` configuration download a new version of LLVM from CI, even if the LLVM submodule hasn’t changed. -Last change is for: https://github.com/rust-lang/rust/pull/88069 +Last change is for: https://github.com/rust-lang/rust/pull/91229 diff --git a/src/bootstrap/dylib_util.rs b/src/bootstrap/dylib_util.rs new file mode 100644 index 0000000000..6d75272c50 --- /dev/null +++ b/src/bootstrap/dylib_util.rs @@ -0,0 +1,28 @@ +// Various utilities for working with dylib paths. +// +// This file is meant to be included directly to avoid a dependency on the bootstrap library from +// the rustc and rustdoc wrappers. This improves compilation time by reducing the linking time. + +/// Returns the environment variable which the dynamic library lookup path +/// resides in for this platform. +pub fn dylib_path_var() -> &'static str { + if cfg!(target_os = "windows") { + "PATH" + } else if cfg!(target_os = "macos") { + "DYLD_LIBRARY_PATH" + } else if cfg!(target_os = "haiku") { + "LIBRARY_PATH" + } else { + "LD_LIBRARY_PATH" + } +} + +/// Parses the `dylib_path_var()` environment variable, returning a list of +/// paths that are members of this lookup path. +pub fn dylib_path() -> Vec { + let var = match env::var_os(dylib_path_var()) { + Some(v) => v, + None => return vec![], + }; + env::split_paths(&var).collect() +} diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 2fddda74a2..9180c5f03a 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -401,26 +401,19 @@ To learn more about a subcommand, run `./x.py -h`", "\n Arguments: This subcommand accepts a number of paths to directories to the crates - and/or artifacts to compile. For example: + and/or artifacts to compile. For example, for a quick build of a usable + compiler: - ./x.py build library/core - ./x.py build library/core library/proc_macro - ./x.py build library/std --stage 1 + ./x.py build --stage 1 library/std - If no arguments are passed then the complete artifacts for that stage are - also compiled. + This will build a compiler and standard library from the local source code. + Once this is done, build/$ARCH/stage1 contains a usable compiler. - ./x.py build - ./x.py build --stage 1 + If no arguments are passed then the default artifacts for that stage are + compiled. For example: - For a quick build of a usable compiler, you can pass: - - ./x.py build --stage 1 library/test - - This will first build everything once (like `--stage 0` without further - arguments would), and then use the compiler built in stage 0 to build - library/test and its dependencies. - Once this is done, build/$ARCH/stage1 contains a usable compiler.", + ./x.py build --stage 0 + ./x.py build ", ); } "check" | "c" => { @@ -430,14 +423,9 @@ Arguments: This subcommand accepts a number of paths to directories to the crates and/or artifacts to compile. For example: - ./x.py check library/core - ./x.py check library/core library/proc_macro + ./x.py check library/std - If no arguments are passed then the complete artifacts are compiled: std, test, and rustc. Note - also that since we use `cargo check`, by default this will automatically enable incremental - compilation, so there's no need to pass it separately, though it won't hurt. We also completely - ignore the stage passed, as there's no way to compile in non-stage 0 without actually building - the compiler.", + If no arguments are passed then many artifacts are checked.", ); } "clippy" => { diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 1667dfc3f8..8569089f70 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -110,7 +110,6 @@ use std::fs::{self, File, OpenOptions}; use std::io::{Read, Seek, SeekFrom, Write}; use std::path::{Path, PathBuf}; use std::process::{self, Command}; -use std::slice; use std::str; #[cfg(unix)] @@ -472,10 +471,6 @@ impl Build { build } - pub fn build_triple(&self) -> &[Interned] { - slice::from_ref(&self.build.triple) - } - // modified from `check_submodule` and `update_submodule` in bootstrap.py /// Given a path to the directory of a submodule, update it. /// @@ -1043,7 +1038,7 @@ impl Build { options[1] = Some(format!("-Clink-arg=-Wl,{}", threads)); } - std::array::IntoIter::new(options).flatten() + IntoIterator::into_iter(options).flatten() } /// Returns if this target should statically link the C runtime, if specified diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 37578e30f6..4a754e6da1 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -249,9 +249,14 @@ impl Step for Llvm { } } - if target.starts_with("riscv") { - // In RISC-V, using C++ atomics require linking to `libatomic` but the LLVM build - // system check cannot detect this. Therefore it is set manually here. + if !target.contains("freebsd") && target.starts_with("riscv") { + // RISC-V GCC erroneously requires linking against + // `libatomic` when using 1-byte and 2-byte C++ + // atomics but the LLVM build system check cannot + // detect this. Therefore it is set manually here. + // FreeBSD uses Clang as its system compiler and + // provides no libatomic in its base system so does + // not want this. if !builder.config.llvm_tools_enabled { cfg.define("CMAKE_EXE_LINKER_FLAGS", "-latomic"); } else { diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 57178aa382..ee58bedcc8 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -16,11 +16,6 @@ use build_helper::t; use crate::builder::Builder; use crate::config::{Config, TargetSelection}; -/// Returns the `name` as the filename of a static library for `target`. -pub fn staticlib(name: &str, target: TargetSelection) -> String { - if target.contains("windows") { format!("{}.lib", name) } else { format!("lib{}.a", name) } -} - /// Given an executable called `name`, return the filename for the /// executable for a particular target. pub fn exe(name: &str, target: TargetSelection) -> String { @@ -54,29 +49,7 @@ pub fn add_dylib_path(path: Vec, cmd: &mut Command) { cmd.env(dylib_path_var(), t!(env::join_paths(list))); } -/// Returns the environment variable which the dynamic library lookup path -/// resides in for this platform. -pub fn dylib_path_var() -> &'static str { - if cfg!(target_os = "windows") { - "PATH" - } else if cfg!(target_os = "macos") { - "DYLD_LIBRARY_PATH" - } else if cfg!(target_os = "haiku") { - "LIBRARY_PATH" - } else { - "LD_LIBRARY_PATH" - } -} - -/// Parses the `dylib_path_var()` environment variable, returning a list of -/// paths that are members of this lookup path. -pub fn dylib_path() -> Vec { - let var = match env::var_os(dylib_path_var()) { - Some(v) => v, - None => return vec![], - }; - env::split_paths(&var).collect() -} +include!("dylib_util.rs"); /// Adds a list of lookup paths to `cmd`'s link library lookup path. pub fn add_link_lib_path(path: Vec, cmd: &mut Command) { @@ -103,21 +76,6 @@ fn link_lib_path() -> Vec { env::split_paths(&var).collect() } -/// `push` all components to `buf`. On windows, append `.exe` to the last component. -pub fn push_exe_path(mut buf: PathBuf, components: &[&str]) -> PathBuf { - let (&file, components) = components.split_last().expect("at least one component required"); - let mut file = file.to_owned(); - - if cfg!(windows) { - file.push_str(".exe"); - } - - buf.extend(components); - buf.push(file); - - buf -} - pub struct TimeIt(bool, Instant); /// Returns an RAII structure that prints out how long it took to drop. diff --git a/src/ci/docker/host-x86_64/dist-aarch64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-aarch64-linux/Dockerfile index e6b6b6e53b..ab588ccc24 100644 --- a/src/ci/docker/host-x86_64/dist-aarch64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-aarch64-linux/Dockerfile @@ -1,5 +1,18 @@ +FROM ubuntu:20.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + curl \ + ca-certificates +WORKDIR /tmp +RUN curl -f https://curl.se/ca/cacert.pem -o cacert.pem + FROM ubuntu:16.04 +# The ca-certificates in ubuntu-16 is too old, so update the certificates +# with something more recent. +COPY --from=0 /tmp/cacert.pem /tmp/cacert.pem +ENV CURL_CA_BUNDLE /tmp/cacert.pem + COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh diff --git a/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile index 61cc000dca..ee4fd759b4 100644 --- a/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-arm-linux/Dockerfile @@ -1,5 +1,18 @@ +FROM ubuntu:20.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + curl \ + ca-certificates +WORKDIR /tmp +RUN curl -f https://curl.se/ca/cacert.pem -o cacert.pem + FROM ubuntu:16.04 +# The ca-certificates in ubuntu-16 is too old, so update the certificates +# with something more recent. +COPY --from=0 /tmp/cacert.pem /tmp/cacert.pem +ENV CURL_CA_BUNDLE /tmp/cacert.pem + COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh diff --git a/src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile index 66eb4137a8..b11a1d3feb 100644 --- a/src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile @@ -1,5 +1,18 @@ +FROM ubuntu:20.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + curl \ + ca-certificates +WORKDIR /tmp +RUN curl -f https://curl.se/ca/cacert.pem -o cacert.pem + FROM ubuntu:16.04 +# The ca-certificates in ubuntu-16 is too old, so update the certificates +# with something more recent. +COPY --from=0 /tmp/cacert.pem /tmp/cacert.pem +ENV CURL_CA_BUNDLE /tmp/cacert.pem + COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh diff --git a/src/ci/docker/host-x86_64/dist-armv7-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-armv7-linux/Dockerfile index c13f63911f..55ca23b293 100644 --- a/src/ci/docker/host-x86_64/dist-armv7-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-armv7-linux/Dockerfile @@ -1,5 +1,18 @@ +FROM ubuntu:20.04 +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + curl \ + ca-certificates +WORKDIR /tmp +RUN curl -f https://curl.se/ca/cacert.pem -o cacert.pem + FROM ubuntu:16.04 +# The ca-certificates in ubuntu-16 is too old, so update the certificates +# with something more recent. +COPY --from=0 /tmp/cacert.pem /tmp/cacert.pem +ENV CURL_CA_BUNDLE /tmp/cacert.pem + COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile index f71282a1b5..d4701a2561 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile @@ -72,7 +72,7 @@ ENV PATH="/node-v14.4.0-linux-x64/bin:${PATH}" # https://github.com/puppeteer/puppeteer/issues/375 # # We also specify the version in case we need to update it to go around cache limitations. -RUN npm install -g browser-ui-test@0.5.0 --unsafe-perm=true +RUN npm install -g browser-ui-test@0.5.3 --unsafe-perm=true ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ diff --git a/src/ci/docker/scripts/freebsd-toolchain.sh b/src/ci/docker/scripts/freebsd-toolchain.sh index de6b52a5e0..2f7c57bcdc 100755 --- a/src/ci/docker/scripts/freebsd-toolchain.sh +++ b/src/ci/docker/scripts/freebsd-toolchain.sh @@ -53,7 +53,7 @@ files_to_extract=( for lib in c cxxrt gcc_s m thr util; do files_to_extract=("${files_to_extract[@]}" "./lib/lib${lib}.*" "./usr/lib/lib${lib}.*") done -for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat kvm; do +for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat devstat kvm; do files_to_extract=("${files_to_extract[@]}" "./usr/lib/lib${lib}.*") done diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 96af401369..1617a74ad2 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -73,7 +73,7 @@ x--expand-yaml-anchors--remove: env: {} - &job-linux-xl - os: ubuntu-latest-xl + os: ubuntu-20.04-xl <<: *base-job - &job-macos-xl @@ -206,6 +206,10 @@ x--expand-yaml-anchors--remove: run: src/ci/scripts/verify-backported-commits.sh <<: *step + - name: ensure the stable version number is correct + run: src/ci/scripts/verify-stable-version-number.sh + <<: *step + - name: run the build run: src/ci/scripts/run-build-from-ci.sh env: @@ -548,7 +552,6 @@ jobs: env: SCRIPT: python x.py --stage 2 test src/tools/cargotest src/tools/cargo RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld - VCVARS_BAT: vcvars64.bat <<: *job-windows-xl - name: x86_64-msvc-tools diff --git a/src/ci/scripts/verify-stable-version-number.sh b/src/ci/scripts/verify-stable-version-number.sh new file mode 100755 index 0000000000..82eb3833cc --- /dev/null +++ b/src/ci/scripts/verify-stable-version-number.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# On the stable channel, check whether we're trying to build artifacts with the +# same version number of a release that's already been published, and fail the +# build if that's the case. +# +# It's a mistake whenever that happens: the release process won't start if it +# detects a duplicate version number, and the artifacts would have to be +# rebuilt anyway. + +set -euo pipefail +IFS=$'\n\t' + +if [[ "$(cat src/ci/channel)" != "stable" ]]; then + echo "This script only works on the stable channel. Skipping the check." + exit 0 +fi + +version="$(cat src/version)" +url="https://static.rust-lang.org/dist/channel-rust-${version}.toml" + +if curl --silent --fail "${url}" >/dev/null; then + echo "The version number ${version} matches an existing release." + echo + echo "If you're trying to prepare a point release, remember to change the" + echo "version number in the src/version file." + exit 1 +else + echo "The version number ${version} does not match any released version!" + exit 0 +fi diff --git a/src/doc/book/.github/workflows/main.yml b/src/doc/book/.github/workflows/main.yml index 53b59cf587..1acae0b6d2 100644 --- a/src/doc/book/.github/workflows/main.yml +++ b/src/doc/book/.github/workflows/main.yml @@ -12,12 +12,12 @@ jobs: - name: Install Rust run: | rustup set profile minimal - rustup toolchain install 1.55 -c rust-docs - rustup default 1.55 + rustup toolchain install 1.57 -c rust-docs + rustup default 1.57 - name: Install mdbook run: | mkdir bin - curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.12/mdbook-v0.4.12-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin + curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.14/mdbook-v0.4.14-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin echo "$(pwd)/bin" >> ${GITHUB_PATH} - name: Report versions run: | @@ -41,13 +41,21 @@ jobs: - name: Install mdbook run: | mkdir bin - curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.12/mdbook-v0.4.12-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin + curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.14/mdbook-v0.4.14-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin echo "$(pwd)/bin" >> ${GITHUB_PATH} + - name: Install aspell + run: sudo apt-get install aspell + - name: Install shellcheck + run: sudo apt-get install shellcheck - name: Report versions run: | rustup --version rustc -Vv mdbook --version + aspell --version + shellcheck --version + - name: Shellcheck + run: find . -name '*.sh' | xargs shellcheck - name: Spellcheck run: bash ci/spellcheck.sh list - name: Lint for local file paths diff --git a/src/doc/book/ADMIN_TASKS.md b/src/doc/book/ADMIN_TASKS.md index 6cef05fdf3..7c152577f1 100644 --- a/src/doc/book/ADMIN_TASKS.md +++ b/src/doc/book/ADMIN_TASKS.md @@ -1,7 +1,7 @@ # Administrative Tasks -This documentation is for Carol and Steve and anyone else managing the repo to -remember how to do occasional maintenance tasks. +This documentation is for anyone managing the repo to remember how to do +occasional maintenance tasks. ## Update the `rustc` version @@ -18,6 +18,11 @@ remember how to do occasional maintenance tasks. - Grep for `manual-regeneration` and follow the instructions in those places to update output that cannot be generated by a script +## Update the `edition` in all listings + +To update the `edition = "[year]"` metadata in all the listings' `Cargo.toml`s, +run the `./tools/update-editions.sh` script and commit the changes. + ## Release a new version of the listings We now make `.tar` files of complete projects containing every listing diff --git a/src/doc/book/README.md b/src/doc/book/README.md index 7b1236b451..91c64ce25d 100644 --- a/src/doc/book/README.md +++ b/src/doc/book/README.md @@ -71,7 +71,7 @@ $ mdbook test We'd love your help! Please see [CONTRIBUTING.md][contrib] to learn about the kinds of contributions we're looking for. -[contrib]: https://github.com/rust-lang/book/blob/master/CONTRIBUTING.md +[contrib]: https://github.com/rust-lang/book/blob/main/CONTRIBUTING.md Because the book is [printed](https://nostarch.com/rust), and because we want to keep the online version of the book close to the print version when diff --git a/src/doc/book/ci/dictionary.txt b/src/doc/book/ci/dictionary.txt index b4dbfa6312..c0f7848a9c 100644 --- a/src/doc/book/ci/dictionary.txt +++ b/src/doc/book/ci/dictionary.txt @@ -6,6 +6,7 @@ adaptor adaptors AddAssign Addr +adfb afdc aggregator AGraph @@ -13,6 +14,7 @@ aliasability alignof alloc allocator +AlwaysEqual Amir anotherusername APIs @@ -49,6 +51,7 @@ BitXorAssign Bjarne Boehm bool +boolean Boolean Booleans Bors @@ -61,6 +64,8 @@ Cagain callsite CamelCase cargodoc +centric +chacha ChangeColor ChangeColorMessage charset @@ -148,6 +153,7 @@ Enums eprintln Erlang ErrorKind +eval executables expr extern @@ -170,8 +176,11 @@ formatter formatters FrenchToast FromIterator +FromResidual frontend +getrandom getter +getters GGraph GitHub gitignore @@ -264,6 +273,7 @@ login lookup loopback lossy +Lukas lval macOS Matsakis @@ -332,6 +342,8 @@ OptionalNumber OsStr OsString other's +otherinstall +OtherError OutlinePrint overloadable overread @@ -392,6 +404,7 @@ representable request's resizes resizing +ReturnedError retweet rewordings rint @@ -421,6 +434,7 @@ ShrAssign shouldn Simula siphash +SipHash situps sizeof SliceIndex @@ -471,7 +485,6 @@ supertraits TcpListener TcpStream templating -test_harness test's TextField That'd @@ -543,6 +556,7 @@ WebSocket whitespace wildcard wildcards +Wirth workflow workspace workspaces @@ -550,6 +564,7 @@ Workspaces wouldn writeln WriteMessage +xcode xpression yyyy ZipImpl diff --git a/src/doc/book/ci/spellcheck.sh b/src/doc/book/ci/spellcheck.sh index f1c84a5f08..3d61e76a51 100755 --- a/src/doc/book/ci/spellcheck.sh +++ b/src/doc/book/ci/spellcheck.sh @@ -1,5 +1,7 @@ #!/bin/bash +set -eu + aspell --version # Checks project Markdown files for spelling mistakes. diff --git a/src/doc/book/ci/validate.sh b/src/doc/book/ci/validate.sh old mode 100644 new mode 100755 index 9e2cfdf10d..9d65bc1614 --- a/src/doc/book/ci/validate.sh +++ b/src/doc/book/ci/validate.sh @@ -1,4 +1,8 @@ +#!/bin/bash + +set -eu + for file in src/*.md ; do - echo Checking references in $file - cargo run --quiet --bin link2print < $file > /dev/null + echo Checking references in "$file" + cargo run --quiet --bin link2print < "$file" > /dev/null done \ No newline at end of file diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-01/Cargo.toml b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-01/Cargo.toml index 242309f93b..78c94fef95 100644 --- a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-01/Cargo.toml +++ b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-01/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "guessing_game" version = "0.1.0" -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml index 172ae61641..cc63f6f021 100644 --- a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml +++ b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "guessing_game" version = "0.1.0" -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.toml b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.toml index 172ae61641..cc63f6f021 100644 --- a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.toml +++ b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "guessing_game" version = "0.1.0" -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.toml b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.toml index 172ae61641..cc63f6f021 100644 --- a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.toml +++ b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "guessing_game" version = "0.1.0" -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.toml b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.toml index 172ae61641..cc63f6f021 100644 --- a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.toml +++ b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "guessing_game" version = "0.1.0" -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.toml b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.toml index 172ae61641..cc63f6f021 100644 --- a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.toml +++ b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "guessing_game" version = "0.1.0" -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/Cargo.toml b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/Cargo.toml index 242309f93b..78c94fef95 100644 --- a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/Cargo.toml +++ b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "guessing_game" version = "0.1.0" -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/Cargo.toml b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/Cargo.toml index 242309f93b..78c94fef95 100644 --- a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/Cargo.toml +++ b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "guessing_game" version = "0.1.0" -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.toml b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.toml index 172ae61641..cc63f6f021 100644 --- a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.toml +++ b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "guessing_game" version = "0.1.0" -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.toml b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.toml index 172ae61641..cc63f6f021 100644 --- a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.toml +++ b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "guessing_game" version = "0.1.0" -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.toml b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.toml index 172ae61641..cc63f6f021 100644 --- a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.toml +++ b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "guessing_game" version = "0.1.0" -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/doc/book/listings/ch03-common-programming-concepts/listing-03-01/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/listing-03-01/Cargo.toml index 10f40538b4..478b346fd5 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/listing-03-01/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/listing-03-01/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "functions" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/listing-03-02/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/listing-03-02/Cargo.toml index 71c3f86640..659645556b 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/listing-03-02/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/listing-03-02/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "branches" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/listing-03-03/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/listing-03-03/Cargo.toml index 9a198d7e1c..810e8bbc0a 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/listing-03-03/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/listing-03-03/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "loops" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/listing-03-04/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/listing-03-04/Cargo.toml index 9a198d7e1c..810e8bbc0a 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/listing-03-04/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/listing-03-04/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "loops" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/listing-03-05/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/listing-03-05/Cargo.toml index 9a198d7e1c..810e8bbc0a 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/listing-03-05/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/listing-03-05/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "loops" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/Cargo.toml index 91a7dd9bed..4da3b81504 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "variables" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-02-adding-mut/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-02-adding-mut/Cargo.toml index 91a7dd9bed..4da3b81504 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-02-adding-mut/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-02-adding-mut/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "variables" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-03-shadowing/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-03-shadowing/Cargo.toml index 91a7dd9bed..4da3b81504 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-03-shadowing/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-03-shadowing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "variables" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-04-shadowing-can-change-types/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-04-shadowing-can-change-types/Cargo.toml index 91a7dd9bed..4da3b81504 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-04-shadowing-can-change-types/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-04-shadowing-can-change-types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "variables" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-05-mut-cant-change-types/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-05-mut-cant-change-types/Cargo.toml index 91a7dd9bed..4da3b81504 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-05-mut-cant-change-types/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-05-mut-cant-change-types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "variables" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-06-floating-point/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-06-floating-point/Cargo.toml index 3f4af9c13f..83610e7561 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-06-floating-point/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-06-floating-point/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "floating-point" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-07-numeric-operations/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-07-numeric-operations/Cargo.toml index b1d25f207a..b4bea55e3d 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-07-numeric-operations/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-07-numeric-operations/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "numeric-operations" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-08-boolean/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-08-boolean/Cargo.toml index c0d2257675..47e42cef8a 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-08-boolean/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-08-boolean/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "boolean" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-09-char/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-09-char/Cargo.toml index 37fdd73a3d..a1ef3b537c 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-09-char/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-09-char/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "char" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-10-tuples/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-10-tuples/Cargo.toml index 01138c641d..9b0879c2c6 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-10-tuples/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-10-tuples/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tuples" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-11-destructuring-tuples/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-11-destructuring-tuples/Cargo.toml index 01138c641d..9b0879c2c6 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-11-destructuring-tuples/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-11-destructuring-tuples/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tuples" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-12-tuple-indexing/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-12-tuple-indexing/Cargo.toml index 01138c641d..9b0879c2c6 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-12-tuple-indexing/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-12-tuple-indexing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tuples" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-13-arrays/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-13-arrays/Cargo.toml index 61bd75847e..96be3e2b17 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-13-arrays/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-13-arrays/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "arrays" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-14-array-indexing/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-14-array-indexing/Cargo.toml index 61bd75847e..96be3e2b17 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-14-array-indexing/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-14-array-indexing/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "arrays" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-15-invalid-array-access/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-15-invalid-array-access/Cargo.toml index 61bd75847e..96be3e2b17 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-15-invalid-array-access/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-15-invalid-array-access/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "arrays" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-16-functions/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-16-functions/Cargo.toml index 10f40538b4..478b346fd5 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-16-functions/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-16-functions/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "functions" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-17-functions-with-parameters/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-17-functions-with-parameters/Cargo.toml index 10f40538b4..478b346fd5 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-17-functions-with-parameters/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-17-functions-with-parameters/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "functions" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-18-functions-with-multiple-parameters/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-18-functions-with-multiple-parameters/Cargo.toml index 10f40538b4..478b346fd5 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-18-functions-with-multiple-parameters/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-18-functions-with-multiple-parameters/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "functions" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/Cargo.toml index 10f40538b4..478b346fd5 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "functions" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/output.txt b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/output.txt index a3a52dbedf..b33f8bd4b3 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/output.txt +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-19-statements-vs-expressions/output.txt @@ -1,5 +1,13 @@ $ cargo run Compiling functions v0.1.0 (file:///projects/functions) +error: expected expression, found statement (`let`) + --> src/main.rs:2:14 + | +2 | let x = (let y = 6); + | ^^^^^^^^^ + | + = note: variable declaration using `let` is a statement + error[E0658]: `let` expressions in this position are experimental --> src/main.rs:2:14 | @@ -9,21 +17,18 @@ error[E0658]: `let` expressions in this position are experimental = note: see issue #53667 for more information = help: you can write `matches!(, )` instead of `let = ` -error: expected expression, found statement (`let`) - --> src/main.rs:2:14 - | -2 | let x = (let y = 6); - | ^^^^^^^^^ - | - = note: variable declaration using `let` is a statement - warning: unnecessary parentheses around assigned value --> src/main.rs:2:13 | 2 | let x = (let y = 6); - | ^^^^^^^^^^^ help: remove these parentheses + | ^ ^ | = note: `#[warn(unused_parens)]` on by default +help: remove these parentheses + | +2 - let x = (let y = 6); +2 + let x = let y = 6; + | For more information about this error, try `rustc --explain E0658`. warning: `functions` (bin "functions") generated 1 warning diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-20-blocks-are-expressions/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-20-blocks-are-expressions/Cargo.toml index 10f40538b4..478b346fd5 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-20-blocks-are-expressions/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-20-blocks-are-expressions/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "functions" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-21-function-return-values/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-21-function-return-values/Cargo.toml index 10f40538b4..478b346fd5 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-21-function-return-values/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-21-function-return-values/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "functions" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-22-function-parameter-and-return/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-22-function-parameter-and-return/Cargo.toml index 10f40538b4..478b346fd5 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-22-function-parameter-and-return/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-22-function-parameter-and-return/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "functions" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/Cargo.toml index 10f40538b4..478b346fd5 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "functions" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-24-comments-end-of-line/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-24-comments-end-of-line/Cargo.toml index 614cbebb0a..e0576b5dce 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-24-comments-end-of-line/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-24-comments-end-of-line/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "comments" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-25-comments-above-line/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-25-comments-above-line/Cargo.toml index 614cbebb0a..e0576b5dce 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-25-comments-above-line/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-25-comments-above-line/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "comments" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-26-if-true/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-26-if-true/Cargo.toml index 71c3f86640..659645556b 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-26-if-true/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-26-if-true/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "branches" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-27-if-false/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-27-if-false/Cargo.toml index 71c3f86640..659645556b 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-27-if-false/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-27-if-false/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "branches" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-28-if-condition-must-be-bool/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-28-if-condition-must-be-bool/Cargo.toml index 71c3f86640..659645556b 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-28-if-condition-must-be-bool/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-28-if-condition-must-be-bool/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "branches" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-29-if-not-equal-0/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-29-if-not-equal-0/Cargo.toml index 71c3f86640..659645556b 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-29-if-not-equal-0/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-29-if-not-equal-0/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "branches" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-30-else-if/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-30-else-if/Cargo.toml index 71c3f86640..659645556b 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-30-else-if/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-30-else-if/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "branches" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/Cargo.toml index 71c3f86640..659645556b 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-31-arms-must-return-same-type/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "branches" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-32-5-loop-labels/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-32-5-loop-labels/Cargo.toml index 9a198d7e1c..810e8bbc0a 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-32-5-loop-labels/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-32-5-loop-labels/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "loops" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-32-loop/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-32-loop/Cargo.toml index 9a198d7e1c..810e8bbc0a 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-32-loop/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-32-loop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "loops" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-33-return-value-from-loop/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-33-return-value-from-loop/Cargo.toml index 9a198d7e1c..810e8bbc0a 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-33-return-value-from-loop/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-33-return-value-from-loop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "loops" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-34-for-range/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-34-for-range/Cargo.toml index 9a198d7e1c..810e8bbc0a 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-34-for-range/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-34-for-range/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "loops" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch03-common-programming-concepts/output-only-01-no-type-annotations/Cargo.toml b/src/doc/book/listings/ch03-common-programming-concepts/output-only-01-no-type-annotations/Cargo.toml index b263d5b3ab..8ad4d5aa6b 100644 --- a/src/doc/book/listings/ch03-common-programming-concepts/output-only-01-no-type-annotations/Cargo.toml +++ b/src/doc/book/listings/ch03-common-programming-concepts/output-only-01-no-type-annotations/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "no_type_annotations" version = "0.1.0" -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/doc/book/listings/ch04-understanding-ownership/listing-04-01/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/listing-04-01/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/listing-04-01/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/listing-04-01/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/listing-04-02/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/listing-04-02/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/listing-04-02/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/listing-04-02/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/listing-04-03/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/listing-04-03/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/listing-04-03/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/listing-04-03/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/listing-04-04/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/listing-04-04/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/listing-04-04/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/listing-04-04/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/listing-04-05/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/listing-04-05/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/listing-04-05/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/listing-04-05/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/listing-04-06/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/listing-04-06/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/listing-04-06/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/listing-04-06/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/listing-04-06/output.txt b/src/doc/book/listings/ch04-understanding-ownership/listing-04-06/output.txt index 12db871131..1176f4e3ac 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/listing-04-06/output.txt +++ b/src/doc/book/listings/ch04-understanding-ownership/listing-04-06/output.txt @@ -6,7 +6,7 @@ error[E0596]: cannot borrow `*some_string` as mutable, as it is behind a `&` ref 7 | fn change(some_string: &String) { | ------- help: consider changing this to be a mutable reference: `&mut String` 8 | some_string.push_str(", world"); - | ^^^^^^^^^^^ `some_string` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `some_string` is a `&` reference, so the data it refers to cannot be borrowed as mutable For more information about this error, try `rustc --explain E0596`. error: could not compile `ownership` due to previous error diff --git a/src/doc/book/listings/ch04-understanding-ownership/listing-04-07/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/listing-04-07/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/listing-04-07/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/listing-04-07/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/listing-04-08/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/listing-04-08/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/listing-04-08/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/listing-04-08/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/listing-04-09/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/listing-04-09/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/listing-04-09/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/listing-04-09/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-01-can-mutate-string/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/no-listing-01-can-mutate-string/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-01-can-mutate-string/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-01-can-mutate-string/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-02-string-scope/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/no-listing-02-string-scope/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-02-string-scope/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-02-string-scope/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-03-string-move/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/no-listing-03-string-move/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-03-string-move/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-03-string-move/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-04-cant-use-after-move/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-05-clone/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/no-listing-05-clone/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-05-clone/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-05-clone/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-06-copy/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/no-listing-06-copy/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-06-copy/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-06-copy/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-07-reference/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/no-listing-07-reference/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-07-reference/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-07-reference/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-08-reference-with-annotations/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/no-listing-08-reference-with-annotations/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-08-reference-with-annotations/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-08-reference-with-annotations/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-09-fixes-listing-04-06/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/no-listing-09-fixes-listing-04-06/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-09-fixes-listing-04-06/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-09-fixes-listing-04-06/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-10-multiple-mut-not-allowed/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-11-muts-in-separate-scopes/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/no-listing-11-muts-in-separate-scopes/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-11-muts-in-separate-scopes/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-11-muts-in-separate-scopes/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-12-immutable-and-mutable-not-allowed/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/output.txt b/src/doc/book/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/output.txt index 35265dbc34..fddca683bd 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/output.txt +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-14-dangling-reference/output.txt @@ -10,7 +10,7 @@ error[E0106]: missing lifetime specifier help: consider using the `'static` lifetime | 5 | fn dangle() -> &'static String { - | ^^^^^^^^ + | ~~~~~~~~ For more information about this error, try `rustc --explain E0106`. error: could not compile `ownership` due to previous error diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-15-dangling-reference-annotated/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-16-no-dangle/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/no-listing-16-no-dangle/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-16-no-dangle/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-16-no-dangle/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-17-slice/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/no-listing-17-slice/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-17-slice/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-17-slice/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-18-first-word-slice/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/no-listing-18-first-word-slice/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-18-first-word-slice/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-18-first-word-slice/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch04-understanding-ownership/no-listing-19-slice-error/Cargo.toml b/src/doc/book/listings/ch04-understanding-ownership/no-listing-19-slice-error/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch04-understanding-ownership/no-listing-19-slice-error/Cargo.toml +++ b/src/doc/book/listings/ch04-understanding-ownership/no-listing-19-slice-error/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-01/Cargo.toml b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-01/Cargo.toml index 0f30eba901..3232b60653 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-01/Cargo.toml +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-01/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "structs" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-02/Cargo.toml b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-02/Cargo.toml index 0f30eba901..3232b60653 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-02/Cargo.toml +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-02/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "structs" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-02/src/main.rs b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-02/src/main.rs index 1831e65ff8..e0f7a6cd3c 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-02/src/main.rs +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-02/src/main.rs @@ -5,13 +5,13 @@ struct User { sign_in_count: u64, } +// ANCHOR: here fn main() { - // ANCHOR: here let user1 = User { email: String::from("someone@example.com"), username: String::from("someusername123"), active: true, sign_in_count: 1, }; - // ANCHOR_END: here } +// ANCHOR_END: here diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-03/Cargo.toml b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-03/Cargo.toml index 0f30eba901..3232b60653 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-03/Cargo.toml +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-03/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "structs" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-03/src/main.rs b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-03/src/main.rs index 8280c4aa8f..7a078e7e80 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-03/src/main.rs +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-03/src/main.rs @@ -5,8 +5,8 @@ struct User { sign_in_count: u64, } +// ANCHOR: here fn main() { - // ANCHOR: here let mut user1 = User { email: String::from("someone@example.com"), username: String::from("someusername123"), @@ -15,5 +15,5 @@ fn main() { }; user1.email = String::from("anotheremail@example.com"); - // ANCHOR_END: here } +// ANCHOR_END: here diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-04/Cargo.toml b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-04/Cargo.toml index 0f30eba901..3232b60653 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-04/Cargo.toml +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-04/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "structs" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-05/Cargo.toml b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-05/Cargo.toml index 0f30eba901..3232b60653 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-05/Cargo.toml +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-05/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "structs" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-06/Cargo.toml b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-06/Cargo.toml index 0f30eba901..3232b60653 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-06/Cargo.toml +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-06/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "structs" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-06/src/main.rs b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-06/src/main.rs index f42bccf769..15e7690e18 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-06/src/main.rs +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-06/src/main.rs @@ -5,20 +5,24 @@ struct User { sign_in_count: u64, } +// ANCHOR: here fn main() { + // --snip-- + // ANCHOR_END: here + let user1 = User { email: String::from("someone@example.com"), username: String::from("someusername123"), active: true, sign_in_count: 1, }; - // ANCHOR: here + let user2 = User { active: user1.active, username: user1.username, email: String::from("another@example.com"), sign_in_count: user1.sign_in_count, }; - // ANCHOR_END: here } +// ANCHOR_END: here diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-07/Cargo.toml b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-07/Cargo.toml index 0f30eba901..3232b60653 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-07/Cargo.toml +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-07/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "structs" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-07/src/main.rs b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-07/src/main.rs index 8754639106..008ad18f67 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-07/src/main.rs +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-07/src/main.rs @@ -5,18 +5,22 @@ struct User { sign_in_count: u64, } +// ANCHOR: here fn main() { + // --snip-- + // ANCHOR_END: here + let user1 = User { email: String::from("someone@example.com"), username: String::from("someusername123"), active: true, sign_in_count: 1, }; - // ANCHOR: here + let user2 = User { email: String::from("another@example.com"), ..user1 }; - // ANCHOR_END: here } +// ANCHOR_END: here diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-08/Cargo.toml b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-08/Cargo.toml index b204f7fca6..4a279a450d 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-08/Cargo.toml +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-08/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rectangles" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-09/Cargo.toml b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-09/Cargo.toml index b204f7fca6..4a279a450d 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-09/Cargo.toml +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-09/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rectangles" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-10/Cargo.toml b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-10/Cargo.toml index b204f7fca6..4a279a450d 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-10/Cargo.toml +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-10/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rectangles" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-11/Cargo.toml b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-11/Cargo.toml index b204f7fca6..4a279a450d 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-11/Cargo.toml +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-11/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rectangles" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-12/Cargo.toml b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-12/Cargo.toml index b204f7fca6..4a279a450d 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-12/Cargo.toml +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-12/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rectangles" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-13/Cargo.toml b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-13/Cargo.toml index b204f7fca6..4a279a450d 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-13/Cargo.toml +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-13/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rectangles" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-14/Cargo.toml b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-14/Cargo.toml index b204f7fca6..4a279a450d 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-14/Cargo.toml +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-14/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rectangles" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-15/Cargo.toml b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-15/Cargo.toml index b204f7fca6..4a279a450d 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-15/Cargo.toml +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-15/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rectangles" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-16/Cargo.toml b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-16/Cargo.toml index b204f7fca6..4a279a450d 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-16/Cargo.toml +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/listing-05-16/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rectangles" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/Cargo.toml b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/Cargo.toml index 0f30eba901..3232b60653 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/Cargo.toml +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "structs" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/src/main.rs b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/src/main.rs index 4c92c5d778..0d993162bf 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/src/main.rs +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/src/main.rs @@ -1,9 +1,7 @@ -fn main() { - // ANCHOR: here - struct Color(i32, i32, i32); - struct Point(i32, i32, i32); +struct Color(i32, i32, i32); +struct Point(i32, i32, i32); +fn main() { let black = Color(0, 0, 0); let origin = Point(0, 0, 0); - // ANCHOR_END: here } diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/Cargo.toml b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/Cargo.toml index 23f3b843bd..d36dbc1d34 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/Cargo.toml +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "structs" version = "0.1.0" -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/output.txt b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/output.txt index 304c1df607..e28da599c7 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/output.txt +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-02-reference-in-struct/output.txt @@ -8,9 +8,9 @@ error[E0106]: missing lifetime specifier | help: consider introducing a named lifetime parameter | -1 | struct User<'a> { +1 ~ struct User<'a> { 2 | active: bool, -3 | username: &'a str, +3 ~ username: &'a str, | error[E0106]: missing lifetime specifier @@ -21,10 +21,10 @@ error[E0106]: missing lifetime specifier | help: consider introducing a named lifetime parameter | -1 | struct User<'a> { +1 ~ struct User<'a> { 2 | active: bool, 3 | username: &str, -4 | email: &'a str, +4 ~ email: &'a str, | For more information about this error, try `rustc --explain E0106`. diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/Cargo.toml b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/Cargo.toml index b204f7fca6..4a279a450d 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/Cargo.toml +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-03-associated-functions/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rectangles" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/Cargo.toml b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/Cargo.toml index 0f30eba901..3232b60653 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/Cargo.toml +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "structs" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/src/main.rs b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/src/main.rs index ac93d27473..d48c94e99b 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/src/main.rs +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/src/main.rs @@ -1,7 +1,5 @@ -fn main() { - // ANCHOR: here - struct AlwaysEqual; +struct AlwaysEqual; +fn main() { let subject = AlwaysEqual; - // ANCHOR_END: here } diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/Cargo.toml b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/Cargo.toml index b204f7fca6..4a279a450d 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/Cargo.toml +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rectangles" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/Cargo.toml b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/Cargo.toml index b204f7fca6..4a279a450d 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/Cargo.toml +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rectangles" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/Cargo.toml b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/Cargo.toml index b204f7fca6..4a279a450d 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/Cargo.toml +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/output-only-01-debug/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rectangles" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/Cargo.toml b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/Cargo.toml index b204f7fca6..4a279a450d 100644 --- a/src/doc/book/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/Cargo.toml +++ b/src/doc/book/listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rectangles" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/listing-06-01/Cargo.toml b/src/doc/book/listings/ch06-enums-and-pattern-matching/listing-06-01/Cargo.toml index 673ea2b545..e959295f91 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/listing-06-01/Cargo.toml +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/listing-06-01/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "enums" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/listing-06-02/Cargo.toml b/src/doc/book/listings/ch06-enums-and-pattern-matching/listing-06-02/Cargo.toml index 673ea2b545..e959295f91 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/listing-06-02/Cargo.toml +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/listing-06-02/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "enums" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/listing-06-03/Cargo.toml b/src/doc/book/listings/ch06-enums-and-pattern-matching/listing-06-03/Cargo.toml index 673ea2b545..e959295f91 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/listing-06-03/Cargo.toml +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/listing-06-03/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "enums" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/listing-06-04/Cargo.toml b/src/doc/book/listings/ch06-enums-and-pattern-matching/listing-06-04/Cargo.toml index 673ea2b545..e959295f91 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/listing-06-04/Cargo.toml +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/listing-06-04/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "enums" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/listing-06-05/Cargo.toml b/src/doc/book/listings/ch06-enums-and-pattern-matching/listing-06-05/Cargo.toml index 673ea2b545..e959295f91 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/listing-06-05/Cargo.toml +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/listing-06-05/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "enums" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/listing-06-06/Cargo.toml b/src/doc/book/listings/ch06-enums-and-pattern-matching/listing-06-06/Cargo.toml index 673ea2b545..e959295f91 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/listing-06-06/Cargo.toml +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/listing-06-06/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "enums" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-01-defining-enums/Cargo.toml b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-01-defining-enums/Cargo.toml index 673ea2b545..e959295f91 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-01-defining-enums/Cargo.toml +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-01-defining-enums/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "enums" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-02-enum-with-data/Cargo.toml b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-02-enum-with-data/Cargo.toml index 673ea2b545..e959295f91 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-02-enum-with-data/Cargo.toml +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-02-enum-with-data/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "enums" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-03-variants-with-different-data/Cargo.toml b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-03-variants-with-different-data/Cargo.toml index 673ea2b545..e959295f91 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-03-variants-with-different-data/Cargo.toml +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-03-variants-with-different-data/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "enums" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-04-structs-similar-to-message-enum/Cargo.toml b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-04-structs-similar-to-message-enum/Cargo.toml index 673ea2b545..e959295f91 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-04-structs-similar-to-message-enum/Cargo.toml +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-04-structs-similar-to-message-enum/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "enums" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-05-methods-on-enums/Cargo.toml b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-05-methods-on-enums/Cargo.toml index 673ea2b545..e959295f91 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-05-methods-on-enums/Cargo.toml +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-05-methods-on-enums/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "enums" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-06-option-examples/Cargo.toml b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-06-option-examples/Cargo.toml index 673ea2b545..e959295f91 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-06-option-examples/Cargo.toml +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-06-option-examples/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "enums" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/Cargo.toml b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/Cargo.toml index 673ea2b545..e959295f91 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/Cargo.toml +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-07-cant-use-option-directly/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "enums" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-08-match-arm-multiple-lines/Cargo.toml b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-08-match-arm-multiple-lines/Cargo.toml index 673ea2b545..e959295f91 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-08-match-arm-multiple-lines/Cargo.toml +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-08-match-arm-multiple-lines/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "enums" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-09-variable-in-pattern/Cargo.toml b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-09-variable-in-pattern/Cargo.toml index 673ea2b545..e959295f91 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-09-variable-in-pattern/Cargo.toml +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-09-variable-in-pattern/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "enums" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/Cargo.toml b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/Cargo.toml index 673ea2b545..e959295f91 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/Cargo.toml +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-10-non-exhaustive-match/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "enums" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-12-if-let/Cargo.toml b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-12-if-let/Cargo.toml index 673ea2b545..e959295f91 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-12-if-let/Cargo.toml +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-12-if-let/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "enums" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-13-count-and-announce-match/Cargo.toml b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-13-count-and-announce-match/Cargo.toml index 673ea2b545..e959295f91 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-13-count-and-announce-match/Cargo.toml +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-13-count-and-announce-match/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "enums" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-14-count-and-announce-if-let-else/Cargo.toml b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-14-count-and-announce-if-let-else/Cargo.toml index 673ea2b545..e959295f91 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-14-count-and-announce-if-let-else/Cargo.toml +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-14-count-and-announce-if-let-else/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "enums" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-15-binding-catchall/Cargo.toml b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-15-binding-catchall/Cargo.toml index 673ea2b545..e959295f91 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-15-binding-catchall/Cargo.toml +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-15-binding-catchall/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "enums" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/Cargo.toml b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/Cargo.toml index 673ea2b545..e959295f91 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/Cargo.toml +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-16-underscore-catchall/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "enums" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/Cargo.toml b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/Cargo.toml index 673ea2b545..e959295f91 100644 --- a/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/Cargo.toml +++ b/src/doc/book/listings/ch06-enums-and-pattern-matching/no-listing-17-underscore-unit/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "enums" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-01/Cargo.toml b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-01/Cargo.toml index 5ea64de7b8..60cec7cb01 100644 --- a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-01/Cargo.toml +++ b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-01/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-03/Cargo.toml b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-03/Cargo.toml index 5ea64de7b8..60cec7cb01 100644 --- a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-03/Cargo.toml +++ b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-03/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-05/Cargo.toml b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-05/Cargo.toml index 5ea64de7b8..60cec7cb01 100644 --- a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-05/Cargo.toml +++ b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-05/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-07/Cargo.toml b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-07/Cargo.toml index 5ea64de7b8..60cec7cb01 100644 --- a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-07/Cargo.toml +++ b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-07/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-08/Cargo.toml b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-08/Cargo.toml index 5ea64de7b8..60cec7cb01 100644 --- a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-08/Cargo.toml +++ b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-08/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-09/Cargo.toml b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-09/Cargo.toml index 5ea64de7b8..60cec7cb01 100644 --- a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-09/Cargo.toml +++ b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-09/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-10/Cargo.toml b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-10/Cargo.toml index 5ea64de7b8..60cec7cb01 100644 --- a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-10/Cargo.toml +++ b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-10/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-11/Cargo.toml b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-11/Cargo.toml index 5ea64de7b8..60cec7cb01 100644 --- a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-11/Cargo.toml +++ b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-11/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-12/Cargo.toml b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-12/Cargo.toml index 5ea64de7b8..60cec7cb01 100644 --- a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-12/Cargo.toml +++ b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-12/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-13/Cargo.toml b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-13/Cargo.toml index 5ea64de7b8..60cec7cb01 100644 --- a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-13/Cargo.toml +++ b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-13/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-14/Cargo.toml b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-14/Cargo.toml index 5ea64de7b8..60cec7cb01 100644 --- a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-14/Cargo.toml +++ b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-14/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-15/Cargo.toml b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-15/Cargo.toml index 5ea64de7b8..60cec7cb01 100644 --- a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-15/Cargo.toml +++ b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-15/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-16/Cargo.toml b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-16/Cargo.toml index 5ea64de7b8..60cec7cb01 100644 --- a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-16/Cargo.toml +++ b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-16/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-17/Cargo.toml b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-17/Cargo.toml index 5ea64de7b8..60cec7cb01 100644 --- a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-17/Cargo.toml +++ b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-17/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-18/Cargo.toml b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-18/Cargo.toml index ca796231e8..15b3fffcab 100644 --- a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-18/Cargo.toml +++ b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-18/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "guessing_game" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] rand = "0.8.3" diff --git a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-19/Cargo.toml b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-19/Cargo.toml index 5ea64de7b8..60cec7cb01 100644 --- a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-19/Cargo.toml +++ b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-19/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-20/Cargo.toml b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-20/Cargo.toml index 5ea64de7b8..60cec7cb01 100644 --- a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-20/Cargo.toml +++ b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-20/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-21-and-22/Cargo.toml b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-21-and-22/Cargo.toml index 5ea64de7b8..60cec7cb01 100644 --- a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-21-and-22/Cargo.toml +++ b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-21-and-22/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.toml b/src/doc/book/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.toml index 172ae61641..cc63f6f021 100644 --- a/src/doc/book/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.toml +++ b/src/doc/book/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "guessing_game" version = "0.1.0" -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/doc/book/listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/Cargo.toml b/src/doc/book/listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/Cargo.toml index 5ea64de7b8..60cec7cb01 100644 --- a/src/doc/book/listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/Cargo.toml +++ b/src/doc/book/listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "restaurant" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-01/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-01/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-01/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-01/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-02/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-02/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-02/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-02/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-03/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-03/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-03/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-03/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-04/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-04/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-04/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-04/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-05/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-05/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-05/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-05/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-06/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-06/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-06/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-06/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-07/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-07/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-07/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-07/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-08/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-08/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-08/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-08/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-09/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-09/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-09/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-09/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-10/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-10/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-10/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-10/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-11/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-11/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-11/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-11/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-12/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-12/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-12/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-12/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-13/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-13/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-13/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-13/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-14/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-14/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-14/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-14/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-15/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-15/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-15/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-15/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-16/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-16/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-16/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-16/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-17/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-17/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-17/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-17/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-18/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-18/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-18/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-18/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-19/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-19/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-19/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-19/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-20/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-20/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-20/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-20/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-21/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-21/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-21/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-21/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-22/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-22/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-22/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-22/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-23/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-23/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-23/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-23/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-24/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-24/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-24/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-24/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-25/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-25/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-25/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-25/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-26/Cargo.toml b/src/doc/book/listings/ch08-common-collections/listing-08-26/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/listing-08-26/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/listing-08-26/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/no-listing-01-concat-multiple-strings/Cargo.toml b/src/doc/book/listings/ch08-common-collections/no-listing-01-concat-multiple-strings/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/no-listing-01-concat-multiple-strings/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/no-listing-01-concat-multiple-strings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/no-listing-02-format/Cargo.toml b/src/doc/book/listings/ch08-common-collections/no-listing-02-format/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/no-listing-02-format/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/no-listing-02-format/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/no-listing-03-iterate-over-hashmap/Cargo.toml b/src/doc/book/listings/ch08-common-collections/no-listing-03-iterate-over-hashmap/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/no-listing-03-iterate-over-hashmap/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/no-listing-03-iterate-over-hashmap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch08-common-collections/output-only-01-not-char-boundary/Cargo.toml b/src/doc/book/listings/ch08-common-collections/output-only-01-not-char-boundary/Cargo.toml index 25e89c8289..fe49598234 100644 --- a/src/doc/book/listings/ch08-common-collections/output-only-01-not-char-boundary/Cargo.toml +++ b/src/doc/book/listings/ch08-common-collections/output-only-01-not-char-boundary/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collections" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch09-error-handling/listing-09-01/Cargo.toml b/src/doc/book/listings/ch09-error-handling/listing-09-01/Cargo.toml index e7368bca41..660e2c819d 100644 --- a/src/doc/book/listings/ch09-error-handling/listing-09-01/Cargo.toml +++ b/src/doc/book/listings/ch09-error-handling/listing-09-01/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "panic" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch09-error-handling/listing-09-03/Cargo.toml b/src/doc/book/listings/ch09-error-handling/listing-09-03/Cargo.toml index 1e678575c1..c496db7834 100644 --- a/src/doc/book/listings/ch09-error-handling/listing-09-03/Cargo.toml +++ b/src/doc/book/listings/ch09-error-handling/listing-09-03/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch09-error-handling/listing-09-04/Cargo.toml b/src/doc/book/listings/ch09-error-handling/listing-09-04/Cargo.toml index 1e678575c1..c496db7834 100644 --- a/src/doc/book/listings/ch09-error-handling/listing-09-04/Cargo.toml +++ b/src/doc/book/listings/ch09-error-handling/listing-09-04/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch09-error-handling/listing-09-05/Cargo.toml b/src/doc/book/listings/ch09-error-handling/listing-09-05/Cargo.toml index 1e678575c1..c496db7834 100644 --- a/src/doc/book/listings/ch09-error-handling/listing-09-05/Cargo.toml +++ b/src/doc/book/listings/ch09-error-handling/listing-09-05/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch09-error-handling/listing-09-06/Cargo.toml b/src/doc/book/listings/ch09-error-handling/listing-09-06/Cargo.toml index 1e678575c1..c496db7834 100644 --- a/src/doc/book/listings/ch09-error-handling/listing-09-06/Cargo.toml +++ b/src/doc/book/listings/ch09-error-handling/listing-09-06/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch09-error-handling/listing-09-07/Cargo.toml b/src/doc/book/listings/ch09-error-handling/listing-09-07/Cargo.toml index 1e678575c1..c496db7834 100644 --- a/src/doc/book/listings/ch09-error-handling/listing-09-07/Cargo.toml +++ b/src/doc/book/listings/ch09-error-handling/listing-09-07/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch09-error-handling/listing-09-08/Cargo.toml b/src/doc/book/listings/ch09-error-handling/listing-09-08/Cargo.toml index 1e678575c1..c496db7834 100644 --- a/src/doc/book/listings/ch09-error-handling/listing-09-08/Cargo.toml +++ b/src/doc/book/listings/ch09-error-handling/listing-09-08/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch09-error-handling/listing-09-09/Cargo.toml b/src/doc/book/listings/ch09-error-handling/listing-09-09/Cargo.toml index 1e678575c1..c496db7834 100644 --- a/src/doc/book/listings/ch09-error-handling/listing-09-09/Cargo.toml +++ b/src/doc/book/listings/ch09-error-handling/listing-09-09/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch09-error-handling/listing-09-10/Cargo.toml b/src/doc/book/listings/ch09-error-handling/listing-09-10/Cargo.toml index 1e678575c1..c496db7834 100644 --- a/src/doc/book/listings/ch09-error-handling/listing-09-10/Cargo.toml +++ b/src/doc/book/listings/ch09-error-handling/listing-09-10/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch09-error-handling/listing-09-11/Cargo.toml b/src/doc/book/listings/ch09-error-handling/listing-09-11/Cargo.toml index 1e678575c1..c496db7834 100644 --- a/src/doc/book/listings/ch09-error-handling/listing-09-11/Cargo.toml +++ b/src/doc/book/listings/ch09-error-handling/listing-09-11/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch09-error-handling/listing-09-12/Cargo.toml b/src/doc/book/listings/ch09-error-handling/listing-09-12/Cargo.toml index 1e678575c1..c496db7834 100644 --- a/src/doc/book/listings/ch09-error-handling/listing-09-12/Cargo.toml +++ b/src/doc/book/listings/ch09-error-handling/listing-09-12/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch09-error-handling/listing-09-13/Cargo.toml b/src/doc/book/listings/ch09-error-handling/listing-09-13/Cargo.toml index ca796231e8..15b3fffcab 100644 --- a/src/doc/book/listings/ch09-error-handling/listing-09-13/Cargo.toml +++ b/src/doc/book/listings/ch09-error-handling/listing-09-13/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "guessing_game" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] rand = "0.8.3" diff --git a/src/doc/book/listings/ch09-error-handling/no-listing-01-panic/Cargo.toml b/src/doc/book/listings/ch09-error-handling/no-listing-01-panic/Cargo.toml index e7368bca41..660e2c819d 100644 --- a/src/doc/book/listings/ch09-error-handling/no-listing-01-panic/Cargo.toml +++ b/src/doc/book/listings/ch09-error-handling/no-listing-01-panic/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "panic" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch09-error-handling/no-listing-02-ask-compiler-for-type/Cargo.toml b/src/doc/book/listings/ch09-error-handling/no-listing-02-ask-compiler-for-type/Cargo.toml index 1e678575c1..c496db7834 100644 --- a/src/doc/book/listings/ch09-error-handling/no-listing-02-ask-compiler-for-type/Cargo.toml +++ b/src/doc/book/listings/ch09-error-handling/no-listing-02-ask-compiler-for-type/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch09-error-handling/no-listing-03-closures/Cargo.toml b/src/doc/book/listings/ch09-error-handling/no-listing-03-closures/Cargo.toml index 1e678575c1..c496db7834 100644 --- a/src/doc/book/listings/ch09-error-handling/no-listing-03-closures/Cargo.toml +++ b/src/doc/book/listings/ch09-error-handling/no-listing-03-closures/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch09-error-handling/no-listing-04-unwrap/Cargo.toml b/src/doc/book/listings/ch09-error-handling/no-listing-04-unwrap/Cargo.toml index 1e678575c1..c496db7834 100644 --- a/src/doc/book/listings/ch09-error-handling/no-listing-04-unwrap/Cargo.toml +++ b/src/doc/book/listings/ch09-error-handling/no-listing-04-unwrap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch09-error-handling/no-listing-05-expect/Cargo.toml b/src/doc/book/listings/ch09-error-handling/no-listing-05-expect/Cargo.toml index 1e678575c1..c496db7834 100644 --- a/src/doc/book/listings/ch09-error-handling/no-listing-05-expect/Cargo.toml +++ b/src/doc/book/listings/ch09-error-handling/no-listing-05-expect/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch09-error-handling/no-listing-08-unwrap-that-cant-fail/Cargo.toml b/src/doc/book/listings/ch09-error-handling/no-listing-08-unwrap-that-cant-fail/Cargo.toml index 1e678575c1..c496db7834 100644 --- a/src/doc/book/listings/ch09-error-handling/no-listing-08-unwrap-that-cant-fail/Cargo.toml +++ b/src/doc/book/listings/ch09-error-handling/no-listing-08-unwrap-that-cant-fail/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "error-handling" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.toml b/src/doc/book/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.toml index ca796231e8..15b3fffcab 100644 --- a/src/doc/book/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.toml +++ b/src/doc/book/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "guessing_game" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] rand = "0.8.3" diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-01/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-01/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-01/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-01/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-02/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-02/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-02/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-02/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-03/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-03/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-03/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-03/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-04/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-04/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-04/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-04/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/output.txt b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/output.txt index 0738325ac3..0530f54247 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/output.txt +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-05/output.txt @@ -11,7 +11,7 @@ error[E0369]: binary operation `>` cannot be applied to type `T` help: consider restricting type parameter `T` | 1 | fn largest(list: &[T]) -> T { - | ^^^^^^^^^^^^^^^^^^^^^^ + | ++++++++++++++++++++++ For more information about this error, try `rustc --explain E0369`. error: could not compile `chapter10` due to previous error diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-06/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-06/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-06/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-06/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-07/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-07/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-07/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-07/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-08/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-08/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-08/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-08/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-09/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-09/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-09/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-09/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-10/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-10/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-10/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-10/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-11/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-11/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-11/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-11/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-12/Cargo.lock b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-12/Cargo.lock index e8007a19be..2835471f04 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-12/Cargo.lock +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-12/Cargo.lock @@ -1,6 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "chapter10" -version = "0.1.0" +version = 3 +[[package]] +name = "aggregator" +version = "0.1.0" diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-12/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-12/Cargo.toml index a7adc3bc3c..46f46a7f44 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-12/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-12/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aggregator" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-13/Cargo.lock b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-13/Cargo.lock index e8007a19be..2835471f04 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-13/Cargo.lock +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-13/Cargo.lock @@ -1,6 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "chapter10" -version = "0.1.0" +version = 3 +[[package]] +name = "aggregator" +version = "0.1.0" diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-13/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-13/Cargo.toml index a7adc3bc3c..46f46a7f44 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-13/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-13/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aggregator" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-14/Cargo.lock b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-14/Cargo.lock index e8007a19be..2835471f04 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-14/Cargo.lock +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-14/Cargo.lock @@ -1,6 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "chapter10" -version = "0.1.0" +version = 3 +[[package]] +name = "aggregator" +version = "0.1.0" diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-14/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-14/Cargo.toml index a7adc3bc3c..46f46a7f44 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-14/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-14/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aggregator" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-15/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-15/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-15/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-15/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-16/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-17/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-18/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-18/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-18/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-18/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-19/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-20/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-20/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-20/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-20/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/output.txt b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/output.txt index a39351a6e9..534a984a63 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/output.txt +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-21/output.txt @@ -10,7 +10,7 @@ error[E0106]: missing lifetime specifier help: consider introducing a named lifetime parameter | 9 | fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { - | ^^^^ ^^^^^^^ ^^^^^^^ ^^^ + | ++++ ++ ++ ++ For more information about this error, try `rustc --explain E0106`. error: could not compile `chapter10` due to previous error diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-22/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-22/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-22/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-22/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-23/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-23/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-23/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-23/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/output.txt b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/output.txt index 6378f5a81c..7f31ce02c4 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/output.txt +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-24/output.txt @@ -4,7 +4,7 @@ error[E0597]: `string2` does not live long enough --> src/main.rs:6:44 | 6 | result = longest(string1.as_str(), string2.as_str()); - | ^^^^^^^ borrowed value does not live long enough + | ^^^^^^^^^^^^^^^^ borrowed value does not live long enough 7 | } | - `string2` dropped here while still borrowed 8 | println!("The longest string is {}", result); diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-25/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-26/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-26/Cargo.toml index 873f611c5c..e8847526dc 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-26/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/listing-10-26/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ownership" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/Cargo.toml index a7adc3bc3c..46f46a7f44 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-01-calling-trait-method/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aggregator" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/Cargo.lock b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/Cargo.lock index e8007a19be..2835471f04 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/Cargo.lock +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/Cargo.lock @@ -1,6 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "chapter10" -version = "0.1.0" +version = 3 +[[package]] +name = "aggregator" +version = "0.1.0" diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/Cargo.toml index a7adc3bc3c..46f46a7f44 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-02-calling-default-impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aggregator" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/Cargo.lock b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/Cargo.lock index e8007a19be..2835471f04 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/Cargo.lock +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/Cargo.lock @@ -1,6 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "chapter10" -version = "0.1.0" +version = 3 +[[package]] +name = "aggregator" +version = "0.1.0" diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/Cargo.toml index a7adc3bc3c..46f46a7f44 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-03-default-impl-calls-other-methods/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aggregator" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-04-traits-as-parameters/Cargo.lock b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-04-traits-as-parameters/Cargo.lock index e8007a19be..2835471f04 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-04-traits-as-parameters/Cargo.lock +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-04-traits-as-parameters/Cargo.lock @@ -1,6 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "chapter10" -version = "0.1.0" +version = 3 +[[package]] +name = "aggregator" +version = "0.1.0" diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-04-traits-as-parameters/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-04-traits-as-parameters/Cargo.toml index a7adc3bc3c..46f46a7f44 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-04-traits-as-parameters/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-04-traits-as-parameters/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aggregator" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-05-returning-impl-trait/Cargo.lock b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-05-returning-impl-trait/Cargo.lock index e8007a19be..2835471f04 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-05-returning-impl-trait/Cargo.lock +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-05-returning-impl-trait/Cargo.lock @@ -1,6 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "chapter10" -version = "0.1.0" +version = 3 +[[package]] +name = "aggregator" +version = "0.1.0" diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-05-returning-impl-trait/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-05-returning-impl-trait/Cargo.toml index a7adc3bc3c..46f46a7f44 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-05-returning-impl-trait/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-05-returning-impl-trait/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aggregator" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-06-impl-trait-returns-one-type/Cargo.lock b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-06-impl-trait-returns-one-type/Cargo.lock index e8007a19be..2835471f04 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-06-impl-trait-returns-one-type/Cargo.lock +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-06-impl-trait-returns-one-type/Cargo.lock @@ -1,6 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "chapter10" -version = "0.1.0" +version = 3 +[[package]] +name = "aggregator" +version = "0.1.0" diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-06-impl-trait-returns-one-type/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-06-impl-trait-returns-one-type/Cargo.toml index a7adc3bc3c..46f46a7f44 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-06-impl-trait-returns-one-type/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-06-impl-trait-returns-one-type/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aggregator" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-07-fixing-listing-10-05/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-08-only-one-reference-with-lifetime/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-08-only-one-reference-with-lifetime/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-08-only-one-reference-with-lifetime/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-08-only-one-reference-with-lifetime/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-09-unrelated-lifetime/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-09-unrelated-lifetime/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-09-unrelated-lifetime/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-09-unrelated-lifetime/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-09-unrelated-lifetime/output.txt b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-09-unrelated-lifetime/output.txt index 94645b2f47..0c628b6977 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-09-unrelated-lifetime/output.txt +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-09-unrelated-lifetime/output.txt @@ -1,13 +1,10 @@ $ cargo run Compiling chapter10 v0.1.0 (file:///projects/chapter10) -error[E0515]: cannot return value referencing local variable `result` +error[E0515]: cannot return reference to local variable `result` --> src/main.rs:11:5 | 11 | result.as_str() - | ------^^^^^^^^^ - | | - | returns a value referencing data owned by the current function - | `result` is borrowed here + | ^^^^^^^^^^^^^^^ returns a reference to data owned by the current function For more information about this error, try `rustc --explain E0515`. error: could not compile `chapter10` due to previous error diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-10-lifetimes-on-methods/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-10-lifetimes-on-methods/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-10-lifetimes-on-methods/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-10-lifetimes-on-methods/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-11-generics-traits-and-lifetimes/Cargo.toml b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-11-generics-traits-and-lifetimes/Cargo.toml index 6681ba2326..489f809672 100644 --- a/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-11-generics-traits-and-lifetimes/Cargo.toml +++ b/src/doc/book/listings/ch10-generic-types-traits-and-lifetimes/no-listing-11-generics-traits-and-lifetimes/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "chapter10" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-01/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-01/Cargo.toml index 03c641f3e4..e61cb12e3e 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-01/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-01/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "adder" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-03/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-03/Cargo.toml index 03c641f3e4..e61cb12e3e 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-03/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-03/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "adder" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-05/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-05/Cargo.toml index c9c0adfbe4..2447c67f51 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-05/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-05/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rectangle" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-06/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-06/Cargo.toml index c9c0adfbe4..2447c67f51 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-06/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-06/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rectangle" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-07/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-07/Cargo.toml index 03c641f3e4..e61cb12e3e 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-07/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-07/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "adder" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-08/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-08/Cargo.toml index b3a5ec1294..4e348c8d26 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-08/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-08/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "guessing_game" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-09/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-09/Cargo.toml index b3a5ec1294..4e348c8d26 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-09/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-09/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "guessing_game" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-10/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-10/Cargo.toml index 0a66321df6..f751864dec 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-10/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-10/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "silly-function" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-11/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-11/Cargo.toml index 03c641f3e4..e61cb12e3e 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-11/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-11/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "adder" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-12/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-12/Cargo.toml index 03c641f3e4..e61cb12e3e 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-12/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-12/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "adder" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-13/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-13/Cargo.toml index 03c641f3e4..e61cb12e3e 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-13/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-13/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "adder" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-01-changing-test-name/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-01-changing-test-name/Cargo.toml index 03c641f3e4..e61cb12e3e 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-01-changing-test-name/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-01-changing-test-name/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "adder" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-02-adding-another-rectangle-test/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-02-adding-another-rectangle-test/Cargo.toml index c9c0adfbe4..2447c67f51 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-02-adding-another-rectangle-test/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-02-adding-another-rectangle-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rectangle" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-03-introducing-a-bug/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-03-introducing-a-bug/Cargo.toml index c9c0adfbe4..2447c67f51 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-03-introducing-a-bug/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-03-introducing-a-bug/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rectangle" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-04-bug-in-add-two/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-04-bug-in-add-two/Cargo.toml index 03c641f3e4..e61cb12e3e 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-04-bug-in-add-two/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-04-bug-in-add-two/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "adder" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-05-greeter/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-05-greeter/Cargo.toml index 0225aa3ef9..90a826cf43 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-05-greeter/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-05-greeter/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "greeter" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-06-greeter-with-bug/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-06-greeter-with-bug/Cargo.toml index 0225aa3ef9..90a826cf43 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-06-greeter-with-bug/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-06-greeter-with-bug/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "greeter" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-07-custom-failure-message/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-07-custom-failure-message/Cargo.toml index 0225aa3ef9..90a826cf43 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-07-custom-failure-message/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-07-custom-failure-message/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "greeter" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-08-guess-with-bug/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-08-guess-with-bug/Cargo.toml index b3a5ec1294..4e348c8d26 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-08-guess-with-bug/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-08-guess-with-bug/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "guessing_game" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-09-guess-with-panic-msg-bug/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-09-guess-with-panic-msg-bug/Cargo.toml index b3a5ec1294..4e348c8d26 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-09-guess-with-panic-msg-bug/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-09-guess-with-panic-msg-bug/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "guessing_game" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-10-result-in-tests/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-10-result-in-tests/Cargo.toml index 03c641f3e4..e61cb12e3e 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-10-result-in-tests/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-10-result-in-tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "adder" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-11-ignore-a-test/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-11-ignore-a-test/Cargo.toml index 03c641f3e4..e61cb12e3e 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-11-ignore-a-test/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-11-ignore-a-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "adder" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-12-shared-test-code-problem/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-12-shared-test-code-problem/Cargo.toml index 03c641f3e4..e61cb12e3e 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-12-shared-test-code-problem/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-12-shared-test-code-problem/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "adder" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-13-fix-shared-test-code-problem/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-13-fix-shared-test-code-problem/Cargo.toml index 03c641f3e4..e61cb12e3e 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/no-listing-13-fix-shared-test-code-problem/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/no-listing-13-fix-shared-test-code-problem/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "adder" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/output-only-01-show-output/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/output-only-01-show-output/Cargo.toml index 0a66321df6..f751864dec 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/output-only-01-show-output/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/output-only-01-show-output/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "silly-function" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/output-only-02-single-test/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/output-only-02-single-test/Cargo.toml index 03c641f3e4..e61cb12e3e 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/output-only-02-single-test/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/output-only-02-single-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "adder" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/output-only-03-multiple-tests/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/output-only-03-multiple-tests/Cargo.toml index 03c641f3e4..e61cb12e3e 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/output-only-03-multiple-tests/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/output-only-03-multiple-tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "adder" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/output-only-04-running-ignored/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/output-only-04-running-ignored/Cargo.toml index 03c641f3e4..e61cb12e3e 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/output-only-04-running-ignored/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/output-only-04-running-ignored/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "adder" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch11-writing-automated-tests/output-only-05-single-integration/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/output-only-05-single-integration/Cargo.toml index 03c641f3e4..e61cb12e3e 100644 --- a/src/doc/book/listings/ch11-writing-automated-tests/output-only-05-single-integration/Cargo.toml +++ b/src/doc/book/listings/ch11-writing-automated-tests/output-only-05-single-integration/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "adder" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-01/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/listing-12-01/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-01/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-01/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-02/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/listing-12-02/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-02/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-02/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-03/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/listing-12-03/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-03/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-03/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-04/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/listing-12-04/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-04/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-04/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-05/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/listing-12-05/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-05/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-05/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-06/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/listing-12-06/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-06/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-06/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-07/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/listing-12-07/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-07/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-07/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-08/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/listing-12-08/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-08/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-08/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-09/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/listing-12-09/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-09/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-09/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-09/src/main.rs b/src/doc/book/listings/ch12-an-io-project/listing-12-09/src/main.rs index 8bee2544b8..83f46ee37f 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-09/src/main.rs +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-09/src/main.rs @@ -22,7 +22,7 @@ struct Config { // ANCHOR: here impl Config { - fn new(args: &[String]) -> Result { + fn new(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-10/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/listing-12-10/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-10/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-10/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-10/src/main.rs b/src/doc/book/listings/ch12-an-io-project/listing-12-10/src/main.rs index 2b8cac4255..c8aeb1d37e 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-10/src/main.rs +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-10/src/main.rs @@ -29,7 +29,7 @@ struct Config { } impl Config { - fn new(args: &[String]) -> Result { + fn new(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-11/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/listing-12-11/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-11/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-11/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-11/src/main.rs b/src/doc/book/listings/ch12-an-io-project/listing-12-11/src/main.rs index 15aa709e7c..974b503b72 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-11/src/main.rs +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-11/src/main.rs @@ -37,7 +37,7 @@ struct Config { } impl Config { - fn new(args: &[String]) -> Result { + fn new(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-12/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/listing-12-12/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-12/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-12/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-12/src/main.rs b/src/doc/book/listings/ch12-an-io-project/listing-12-12/src/main.rs index 337dac1cc9..f2e0e6b9f3 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-12/src/main.rs +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-12/src/main.rs @@ -38,7 +38,7 @@ struct Config { } impl Config { - fn new(args: &[String]) -> Result { + fn new(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-13/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/listing-12-13/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-13/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-13/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-13/src/lib.rs b/src/doc/book/listings/ch12-an-io-project/listing-12-13/src/lib.rs index 5a877fca1e..5b2850a5df 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-13/src/lib.rs +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-13/src/lib.rs @@ -8,7 +8,7 @@ pub struct Config { } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn new(args: &[String]) -> Result { // --snip-- // ANCHOR_END: here if args.len() < 3 { diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-14/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/listing-12-14/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-14/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-14/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-14/src/lib.rs b/src/doc/book/listings/ch12-an-io-project/listing-12-14/src/lib.rs index 40ee7cacbb..2ba2fd1961 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-14/src/lib.rs +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-14/src/lib.rs @@ -7,7 +7,7 @@ pub struct Config { } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn new(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-15/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/listing-12-15/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-15/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-15/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-15/src/lib.rs b/src/doc/book/listings/ch12-an-io-project/listing-12-15/src/lib.rs index a0f611a35b..c677188393 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-15/src/lib.rs +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-15/src/lib.rs @@ -7,7 +7,7 @@ pub struct Config { } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn new(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-16/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/listing-12-16/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-16/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-16/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-16/src/lib.rs b/src/doc/book/listings/ch12-an-io-project/listing-12-16/src/lib.rs index 4df625e083..8729c32f4d 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-16/src/lib.rs +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-16/src/lib.rs @@ -7,7 +7,7 @@ pub struct Config { } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn new(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-17/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/listing-12-17/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-17/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-17/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-17/src/lib.rs b/src/doc/book/listings/ch12-an-io-project/listing-12-17/src/lib.rs index e7ddee9953..0b094ce28a 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-17/src/lib.rs +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-17/src/lib.rs @@ -7,7 +7,7 @@ pub struct Config { } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn new(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-18/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/listing-12-18/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-18/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-18/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-18/src/lib.rs b/src/doc/book/listings/ch12-an-io-project/listing-12-18/src/lib.rs index 8984d1a887..c9d1f529da 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-18/src/lib.rs +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-18/src/lib.rs @@ -7,7 +7,7 @@ pub struct Config { } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn new(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-19/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/listing-12-19/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-19/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-19/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-19/src/lib.rs b/src/doc/book/listings/ch12-an-io-project/listing-12-19/src/lib.rs index 5a9e345b99..de8897b8d1 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-19/src/lib.rs +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-19/src/lib.rs @@ -7,7 +7,7 @@ pub struct Config { } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn new(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-20/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/listing-12-20/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-20/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-20/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-20/src/lib.rs b/src/doc/book/listings/ch12-an-io-project/listing-12-20/src/lib.rs index d36f151574..542d08874d 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-20/src/lib.rs +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-20/src/lib.rs @@ -7,7 +7,7 @@ pub struct Config { } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn new(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-21/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/listing-12-21/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-21/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-21/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-21/src/lib.rs b/src/doc/book/listings/ch12-an-io-project/listing-12-21/src/lib.rs index 79f166bc27..10f6dea094 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-21/src/lib.rs +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-21/src/lib.rs @@ -7,7 +7,7 @@ pub struct Config { } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn new(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-22/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/listing-12-22/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-22/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-22/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-22/src/lib.rs b/src/doc/book/listings/ch12-an-io-project/listing-12-22/src/lib.rs index 8feb1b1f81..3402a273f3 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-22/src/lib.rs +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-22/src/lib.rs @@ -10,7 +10,7 @@ pub struct Config { // ANCHOR_END: here impl Config { - pub fn new(args: &[String]) -> Result { + pub fn new(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-23/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/listing-12-23/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-23/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-23/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-23/src/lib.rs b/src/doc/book/listings/ch12-an-io-project/listing-12-23/src/lib.rs index 719d3fe03b..fa63a8c7be 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-23/src/lib.rs +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-23/src/lib.rs @@ -14,7 +14,7 @@ pub struct Config { // ANCHOR: here impl Config { - pub fn new(args: &[String]) -> Result { + pub fn new(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-24/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/listing-12-24/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-24/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-24/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/listing-12-24/src/lib.rs b/src/doc/book/listings/ch12-an-io-project/listing-12-24/src/lib.rs index d0d0eb385f..fe1dccf4ee 100644 --- a/src/doc/book/listings/ch12-an-io-project/listing-12-24/src/lib.rs +++ b/src/doc/book/listings/ch12-an-io-project/listing-12-24/src/lib.rs @@ -9,7 +9,7 @@ pub struct Config { } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn new(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } diff --git a/src/doc/book/listings/ch12-an-io-project/no-listing-01-handling-errors-in-main/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/no-listing-01-handling-errors-in-main/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/no-listing-01-handling-errors-in-main/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/no-listing-01-handling-errors-in-main/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/no-listing-01-handling-errors-in-main/src/main.rs b/src/doc/book/listings/ch12-an-io-project/no-listing-01-handling-errors-in-main/src/main.rs index e40109ce77..44bcfeab30 100644 --- a/src/doc/book/listings/ch12-an-io-project/no-listing-01-handling-errors-in-main/src/main.rs +++ b/src/doc/book/listings/ch12-an-io-project/no-listing-01-handling-errors-in-main/src/main.rs @@ -41,7 +41,7 @@ struct Config { } impl Config { - fn new(args: &[String]) -> Result { + fn new(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } diff --git a/src/doc/book/listings/ch12-an-io-project/no-listing-02-using-search-in-run/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/no-listing-02-using-search-in-run/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/no-listing-02-using-search-in-run/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/no-listing-02-using-search-in-run/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/no-listing-02-using-search-in-run/src/lib.rs b/src/doc/book/listings/ch12-an-io-project/no-listing-02-using-search-in-run/src/lib.rs index c3c5ffe14d..ede4eb49a0 100644 --- a/src/doc/book/listings/ch12-an-io-project/no-listing-02-using-search-in-run/src/lib.rs +++ b/src/doc/book/listings/ch12-an-io-project/no-listing-02-using-search-in-run/src/lib.rs @@ -7,7 +7,7 @@ pub struct Config { } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn new(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } diff --git a/src/doc/book/listings/ch12-an-io-project/output-only-01-with-args/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/output-only-01-with-args/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/output-only-01-with-args/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/output-only-01-with-args/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/output-only-02-missing-lifetimes/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/output-only-02-missing-lifetimes/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/output-only-02-missing-lifetimes/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/output-only-02-missing-lifetimes/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/output-only-02-missing-lifetimes/output.txt b/src/doc/book/listings/ch12-an-io-project/output-only-02-missing-lifetimes/output.txt index 33036173da..93116dd5ed 100644 --- a/src/doc/book/listings/ch12-an-io-project/output-only-02-missing-lifetimes/output.txt +++ b/src/doc/book/listings/ch12-an-io-project/output-only-02-missing-lifetimes/output.txt @@ -10,7 +10,7 @@ error[E0106]: missing lifetime specifier help: consider introducing a named lifetime parameter | 28 | pub fn search<'a>(query: &'a str, contents: &'a str) -> Vec<&'a str> { - | ^^^^ ^^^^^^^ ^^^^^^^ ^^^ + | ++++ ++ ++ ++ For more information about this error, try `rustc --explain E0106`. error: could not compile `minigrep` due to previous error diff --git a/src/doc/book/listings/ch12-an-io-project/output-only-02-missing-lifetimes/src/lib.rs b/src/doc/book/listings/ch12-an-io-project/output-only-02-missing-lifetimes/src/lib.rs index 97e41c8e83..65af968d95 100644 --- a/src/doc/book/listings/ch12-an-io-project/output-only-02-missing-lifetimes/src/lib.rs +++ b/src/doc/book/listings/ch12-an-io-project/output-only-02-missing-lifetimes/src/lib.rs @@ -7,7 +7,7 @@ pub struct Config { } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn new(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } diff --git a/src/doc/book/listings/ch12-an-io-project/output-only-03-multiple-matches/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/output-only-03-multiple-matches/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/output-only-03-multiple-matches/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/output-only-03-multiple-matches/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/output-only-03-multiple-matches/src/lib.rs b/src/doc/book/listings/ch12-an-io-project/output-only-03-multiple-matches/src/lib.rs index c3c5ffe14d..ede4eb49a0 100644 --- a/src/doc/book/listings/ch12-an-io-project/output-only-03-multiple-matches/src/lib.rs +++ b/src/doc/book/listings/ch12-an-io-project/output-only-03-multiple-matches/src/lib.rs @@ -7,7 +7,7 @@ pub struct Config { } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn new(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } diff --git a/src/doc/book/listings/ch12-an-io-project/output-only-04-no-matches/Cargo.toml b/src/doc/book/listings/ch12-an-io-project/output-only-04-no-matches/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch12-an-io-project/output-only-04-no-matches/Cargo.toml +++ b/src/doc/book/listings/ch12-an-io-project/output-only-04-no-matches/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch12-an-io-project/output-only-04-no-matches/src/lib.rs b/src/doc/book/listings/ch12-an-io-project/output-only-04-no-matches/src/lib.rs index c3c5ffe14d..ede4eb49a0 100644 --- a/src/doc/book/listings/ch12-an-io-project/output-only-04-no-matches/src/lib.rs +++ b/src/doc/book/listings/ch12-an-io-project/output-only-04-no-matches/src/lib.rs @@ -7,7 +7,7 @@ pub struct Config { } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn new(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } diff --git a/src/doc/book/listings/ch13-functional-features/listing-12-23-reproduced/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-12-23-reproduced/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-12-23-reproduced/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-12-23-reproduced/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-12-23-reproduced/src/lib.rs b/src/doc/book/listings/ch13-functional-features/listing-12-23-reproduced/src/lib.rs index 7721acd21e..7f0178dafc 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-12-23-reproduced/src/lib.rs +++ b/src/doc/book/listings/ch13-functional-features/listing-12-23-reproduced/src/lib.rs @@ -10,7 +10,7 @@ pub struct Config { // ANCHOR: ch13 impl Config { - pub fn new(args: &[String]) -> Result { + pub fn new(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } diff --git a/src/doc/book/listings/ch13-functional-features/listing-12-24-reproduced/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-12-24-reproduced/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-12-24-reproduced/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-12-24-reproduced/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-12-24-reproduced/src/lib.rs b/src/doc/book/listings/ch13-functional-features/listing-12-24-reproduced/src/lib.rs index d0d0eb385f..fe1dccf4ee 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-12-24-reproduced/src/lib.rs +++ b/src/doc/book/listings/ch13-functional-features/listing-12-24-reproduced/src/lib.rs @@ -9,7 +9,7 @@ pub struct Config { } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn new(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-01/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-01/Cargo.toml index 870e416e4e..f09a737d4d 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-01/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-01/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "workout-app" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-02/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-02/Cargo.toml index 870e416e4e..f09a737d4d 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-02/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-02/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "workout-app" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-03/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-03/Cargo.toml index 870e416e4e..f09a737d4d 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-03/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-03/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "workout-app" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-04/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-04/Cargo.toml index 870e416e4e..f09a737d4d 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-04/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-04/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "workout-app" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-05/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-05/Cargo.toml index 870e416e4e..f09a737d4d 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-05/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-05/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "workout-app" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-06/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-06/Cargo.toml index 870e416e4e..f09a737d4d 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-06/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-06/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "workout-app" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-07/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-07/Cargo.toml index 870e416e4e..f09a737d4d 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-07/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-07/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "workout-app" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-08/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-08/Cargo.toml index 2257cecdc7..914c4cfaa8 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-08/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-08/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "closure-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-08/output.txt b/src/doc/book/listings/ch13-functional-features/listing-13-08/output.txt index 30c51e12a0..37d83618a2 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-08/output.txt +++ b/src/doc/book/listings/ch13-functional-features/listing-13-08/output.txt @@ -4,10 +4,9 @@ error[E0308]: mismatched types --> src/main.rs:5:29 | 5 | let n = example_closure(5); - | ^ + | ^- help: try using a conversion method: `.to_string()` | | | expected struct `String`, found integer - | help: try using a conversion method: `5.to_string()` For more information about this error, try `rustc --explain E0308`. error: could not compile `closure-example` due to previous error diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-09/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-09/Cargo.toml index 5fe776c473..6b81ef92b4 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-09/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-09/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cacher" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-10/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-10/Cargo.toml index 5fe776c473..6b81ef92b4 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-10/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-10/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cacher" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-11/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-11/Cargo.toml index 870e416e4e..f09a737d4d 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-11/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-11/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "workout-app" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-12/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-12/Cargo.toml index fb3b804abd..ca73ff73d1 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-12/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-12/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "equal-to-x" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-13/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-13/Cargo.toml index a844ed1dc7..2652a8a1a4 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-13/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-13/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "iterators" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-14/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-14/Cargo.toml index a844ed1dc7..2652a8a1a4 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-14/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-14/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "iterators" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-15/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-15/Cargo.toml index a844ed1dc7..2652a8a1a4 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-15/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-15/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "iterators" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-16/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-16/Cargo.toml index a844ed1dc7..2652a8a1a4 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-16/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-16/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "iterators" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-17/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-17/Cargo.toml index a844ed1dc7..2652a8a1a4 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-17/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-17/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "iterators" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-18/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-18/Cargo.toml index a844ed1dc7..2652a8a1a4 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-18/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-18/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "iterators" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-19/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-19/Cargo.toml index 4e64dff447..cc803776b6 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-19/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-19/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "shoe_size" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-20/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-20/Cargo.toml index 4d881a627a..9e103f3eb3 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-20/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-20/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "counter" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-21/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-21/Cargo.toml index 4d881a627a..9e103f3eb3 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-21/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-21/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "counter" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-22/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-22/Cargo.toml index 4d881a627a..9e103f3eb3 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-22/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-22/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "counter" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-23/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-23/Cargo.toml index 4d881a627a..9e103f3eb3 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-23/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-23/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "counter" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-25/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-25/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-25/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-25/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-25/src/lib.rs b/src/doc/book/listings/ch13-functional-features/listing-13-25/src/lib.rs index d0d0eb385f..fe1dccf4ee 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-25/src/lib.rs +++ b/src/doc/book/listings/ch13-functional-features/listing-13-25/src/lib.rs @@ -9,7 +9,7 @@ pub struct Config { } impl Config { - pub fn new(args: &[String]) -> Result { + pub fn new(args: &[String]) -> Result { if args.len() < 3 { return Err("not enough arguments"); } diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-26/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-26/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-26/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-26/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-27/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-27/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-27/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-27/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/listing-13-29/Cargo.toml b/src/doc/book/listings/ch13-functional-features/listing-13-29/Cargo.toml index f4228aec21..64c2a3f520 100644 --- a/src/doc/book/listings/ch13-functional-features/listing-13-29/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/listing-13-29/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minigrep" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/no-listing-01-failing-cacher-test/Cargo.toml b/src/doc/book/listings/ch13-functional-features/no-listing-01-failing-cacher-test/Cargo.toml index 5fe776c473..6b81ef92b4 100644 --- a/src/doc/book/listings/ch13-functional-features/no-listing-01-failing-cacher-test/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/no-listing-01-failing-cacher-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cacher" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/no-listing-02-functions-cant-capture/Cargo.toml b/src/doc/book/listings/ch13-functional-features/no-listing-02-functions-cant-capture/Cargo.toml index fb3b804abd..ca73ff73d1 100644 --- a/src/doc/book/listings/ch13-functional-features/no-listing-02-functions-cant-capture/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/no-listing-02-functions-cant-capture/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "equal-to-x" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch13-functional-features/no-listing-03-move-closures/Cargo.toml b/src/doc/book/listings/ch13-functional-features/no-listing-03-move-closures/Cargo.toml index fb3b804abd..ca73ff73d1 100644 --- a/src/doc/book/listings/ch13-functional-features/no-listing-03-move-closures/Cargo.toml +++ b/src/doc/book/listings/ch13-functional-features/no-listing-03-move-closures/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "equal-to-x" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch14-more-about-cargo/listing-14-01/Cargo.toml b/src/doc/book/listings/ch14-more-about-cargo/listing-14-01/Cargo.toml index 3dab654eb0..c52da04129 100644 --- a/src/doc/book/listings/ch14-more-about-cargo/listing-14-01/Cargo.toml +++ b/src/doc/book/listings/ch14-more-about-cargo/listing-14-01/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "my_crate" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch14-more-about-cargo/listing-14-02/Cargo.toml b/src/doc/book/listings/ch14-more-about-cargo/listing-14-02/Cargo.toml index 3dab654eb0..c52da04129 100644 --- a/src/doc/book/listings/ch14-more-about-cargo/listing-14-02/Cargo.toml +++ b/src/doc/book/listings/ch14-more-about-cargo/listing-14-02/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "my_crate" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch14-more-about-cargo/listing-14-03/Cargo.toml b/src/doc/book/listings/ch14-more-about-cargo/listing-14-03/Cargo.toml index 30f96104bd..66ef4b532d 100644 --- a/src/doc/book/listings/ch14-more-about-cargo/listing-14-03/Cargo.toml +++ b/src/doc/book/listings/ch14-more-about-cargo/listing-14-03/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "art" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch14-more-about-cargo/listing-14-04/Cargo.toml b/src/doc/book/listings/ch14-more-about-cargo/listing-14-04/Cargo.toml index 30f96104bd..66ef4b532d 100644 --- a/src/doc/book/listings/ch14-more-about-cargo/listing-14-04/Cargo.toml +++ b/src/doc/book/listings/ch14-more-about-cargo/listing-14-04/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "art" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch14-more-about-cargo/listing-14-05/Cargo.toml b/src/doc/book/listings/ch14-more-about-cargo/listing-14-05/Cargo.toml index 30f96104bd..66ef4b532d 100644 --- a/src/doc/book/listings/ch14-more-about-cargo/listing-14-05/Cargo.toml +++ b/src/doc/book/listings/ch14-more-about-cargo/listing-14-05/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "art" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch14-more-about-cargo/listing-14-06/Cargo.toml b/src/doc/book/listings/ch14-more-about-cargo/listing-14-06/Cargo.toml index 30f96104bd..66ef4b532d 100644 --- a/src/doc/book/listings/ch14-more-about-cargo/listing-14-06/Cargo.toml +++ b/src/doc/book/listings/ch14-more-about-cargo/listing-14-06/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "art" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch14-more-about-cargo/listing-14-07/add/add-one/Cargo.toml b/src/doc/book/listings/ch14-more-about-cargo/listing-14-07/add/add-one/Cargo.toml index ab555f504b..0262902938 100644 --- a/src/doc/book/listings/ch14-more-about-cargo/listing-14-07/add/add-one/Cargo.toml +++ b/src/doc/book/listings/ch14-more-about-cargo/listing-14-07/add/add-one/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "add-one" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch14-more-about-cargo/listing-14-07/add/adder/Cargo.toml b/src/doc/book/listings/ch14-more-about-cargo/listing-14-07/add/adder/Cargo.toml index cae6ba5d2b..ea9e302eea 100644 --- a/src/doc/book/listings/ch14-more-about-cargo/listing-14-07/add/adder/Cargo.toml +++ b/src/doc/book/listings/ch14-more-about-cargo/listing-14-07/add/adder/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "adder" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch14-more-about-cargo/no-listing-01-workspace-with-adder-crate/add/adder/Cargo.toml b/src/doc/book/listings/ch14-more-about-cargo/no-listing-01-workspace-with-adder-crate/add/adder/Cargo.toml index 03c641f3e4..e61cb12e3e 100644 --- a/src/doc/book/listings/ch14-more-about-cargo/no-listing-01-workspace-with-adder-crate/add/adder/Cargo.toml +++ b/src/doc/book/listings/ch14-more-about-cargo/no-listing-01-workspace-with-adder-crate/add/adder/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "adder" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch14-more-about-cargo/no-listing-02-workspace-with-two-crates/add/add-one/Cargo.toml b/src/doc/book/listings/ch14-more-about-cargo/no-listing-02-workspace-with-two-crates/add/add-one/Cargo.toml index ab555f504b..0262902938 100644 --- a/src/doc/book/listings/ch14-more-about-cargo/no-listing-02-workspace-with-two-crates/add/add-one/Cargo.toml +++ b/src/doc/book/listings/ch14-more-about-cargo/no-listing-02-workspace-with-two-crates/add/add-one/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "add-one" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch14-more-about-cargo/no-listing-02-workspace-with-two-crates/add/adder/Cargo.toml b/src/doc/book/listings/ch14-more-about-cargo/no-listing-02-workspace-with-two-crates/add/adder/Cargo.toml index cae6ba5d2b..ea9e302eea 100644 --- a/src/doc/book/listings/ch14-more-about-cargo/no-listing-02-workspace-with-two-crates/add/adder/Cargo.toml +++ b/src/doc/book/listings/ch14-more-about-cargo/no-listing-02-workspace-with-two-crates/add/adder/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "adder" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/add-one/Cargo.toml b/src/doc/book/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/add-one/Cargo.toml index 22e2a51240..9e6905425e 100644 --- a/src/doc/book/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/add-one/Cargo.toml +++ b/src/doc/book/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/add-one/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "add-one" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] rand = "0.8.3" diff --git a/src/doc/book/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/adder/Cargo.toml b/src/doc/book/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/adder/Cargo.toml index cae6ba5d2b..ea9e302eea 100644 --- a/src/doc/book/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/adder/Cargo.toml +++ b/src/doc/book/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/adder/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "adder" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch14-more-about-cargo/no-listing-04-workspace-with-tests/add/add-one/Cargo.toml b/src/doc/book/listings/ch14-more-about-cargo/no-listing-04-workspace-with-tests/add/add-one/Cargo.toml index ab555f504b..0262902938 100644 --- a/src/doc/book/listings/ch14-more-about-cargo/no-listing-04-workspace-with-tests/add/add-one/Cargo.toml +++ b/src/doc/book/listings/ch14-more-about-cargo/no-listing-04-workspace-with-tests/add/add-one/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "add-one" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch14-more-about-cargo/no-listing-04-workspace-with-tests/add/adder/Cargo.toml b/src/doc/book/listings/ch14-more-about-cargo/no-listing-04-workspace-with-tests/add/adder/Cargo.toml index cae6ba5d2b..ea9e302eea 100644 --- a/src/doc/book/listings/ch14-more-about-cargo/no-listing-04-workspace-with-tests/add/adder/Cargo.toml +++ b/src/doc/book/listings/ch14-more-about-cargo/no-listing-04-workspace-with-tests/add/adder/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "adder" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch14-more-about-cargo/output-only-02-add-one/add/add-one/Cargo.toml b/src/doc/book/listings/ch14-more-about-cargo/output-only-02-add-one/add/add-one/Cargo.toml index 4266f6641c..1b19ca676a 100644 --- a/src/doc/book/listings/ch14-more-about-cargo/output-only-02-add-one/add/add-one/Cargo.toml +++ b/src/doc/book/listings/ch14-more-about-cargo/output-only-02-add-one/add/add-one/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "add-one" version = "0.1.0" -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/doc/book/listings/ch14-more-about-cargo/output-only-02-add-one/add/adder/Cargo.toml b/src/doc/book/listings/ch14-more-about-cargo/output-only-02-add-one/add/adder/Cargo.toml index cae6ba5d2b..ea9e302eea 100644 --- a/src/doc/book/listings/ch14-more-about-cargo/output-only-02-add-one/add/adder/Cargo.toml +++ b/src/doc/book/listings/ch14-more-about-cargo/output-only-02-add-one/add/adder/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "adder" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch14-more-about-cargo/output-only-03-use-rand/add/add-one/Cargo.toml b/src/doc/book/listings/ch14-more-about-cargo/output-only-03-use-rand/add/add-one/Cargo.toml index 22e2a51240..9e6905425e 100644 --- a/src/doc/book/listings/ch14-more-about-cargo/output-only-03-use-rand/add/add-one/Cargo.toml +++ b/src/doc/book/listings/ch14-more-about-cargo/output-only-03-use-rand/add/add-one/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "add-one" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] rand = "0.8.3" diff --git a/src/doc/book/listings/ch14-more-about-cargo/output-only-03-use-rand/add/adder/Cargo.toml b/src/doc/book/listings/ch14-more-about-cargo/output-only-03-use-rand/add/adder/Cargo.toml index cae6ba5d2b..ea9e302eea 100644 --- a/src/doc/book/listings/ch14-more-about-cargo/output-only-03-use-rand/add/adder/Cargo.toml +++ b/src/doc/book/listings/ch14-more-about-cargo/output-only-03-use-rand/add/adder/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "adder" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-01/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-01/Cargo.toml index 6d5c6832e4..690385c7a4 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-01/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-01/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "box-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-02/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-02/Cargo.toml index ca5c90b779..dce1515c3e 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-02/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-02/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cons-list" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-03/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-03/Cargo.toml index ca5c90b779..dce1515c3e 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-03/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-03/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cons-list" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-03/output.txt b/src/doc/book/listings/ch15-smart-pointers/listing-15-03/output.txt index e4180993a5..87e7b5766a 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-03/output.txt +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-03/output.txt @@ -11,7 +11,7 @@ error[E0072]: recursive type `List` has infinite size help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `List` representable | 2 | Cons(i32, Box), - | ^^^^ ^ + | ++++ + error[E0391]: cycle detected when computing drop-check constraints for `List` --> src/main.rs:1:1 @@ -19,7 +19,7 @@ error[E0391]: cycle detected when computing drop-check constraints for `List` 1 | enum List { | ^^^^^^^^^ | - = note: ...which again requires computing drop-check constraints for `List`, completing the cycle + = note: ...which immediately requires computing drop-check constraints for `List` again = note: cycle used when computing dropck types for `Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: List } }` Some errors have detailed explanations: E0072, E0391. diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-05/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-05/Cargo.toml index ca5c90b779..dce1515c3e 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-05/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-05/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cons-list" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-06/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-06/Cargo.toml index 330a2b3a1c..67ec198f74 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-06/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-06/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "deref-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-07/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-07/Cargo.toml index 330a2b3a1c..67ec198f74 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-07/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-07/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "deref-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-08/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-08/Cargo.toml index 330a2b3a1c..67ec198f74 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-08/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-08/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "deref-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-09/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-09/Cargo.toml index 330a2b3a1c..67ec198f74 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-09/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-09/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "deref-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-10/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-10/Cargo.toml index 330a2b3a1c..67ec198f74 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-10/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-10/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "deref-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-11/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-11/Cargo.toml index 330a2b3a1c..67ec198f74 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-11/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-11/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "deref-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-12/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-12/Cargo.toml index 330a2b3a1c..67ec198f74 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-12/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-12/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "deref-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-13/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-13/Cargo.toml index 330a2b3a1c..67ec198f74 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-13/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-13/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "deref-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-14/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-14/Cargo.toml index 32dbbdd327..1e4c994815 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-14/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-14/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "drop-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-15/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-15/Cargo.toml index 32dbbdd327..1e4c994815 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-15/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-15/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "drop-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-16/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-16/Cargo.toml index 32dbbdd327..1e4c994815 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-16/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-16/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "drop-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-17/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-17/Cargo.toml index ca5c90b779..dce1515c3e 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-17/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-17/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cons-list" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-18/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-18/Cargo.toml index ca5c90b779..dce1515c3e 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-18/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-18/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cons-list" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-19/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-19/Cargo.toml index ca5c90b779..dce1515c3e 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-19/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-19/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cons-list" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-20/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-20/Cargo.toml index 2b3ecf580b..98c3f537c6 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-20/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-20/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "limit-tracker" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-21/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-21/Cargo.toml index 2b3ecf580b..98c3f537c6 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-21/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-21/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "limit-tracker" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-21/output.txt b/src/doc/book/listings/ch15-smart-pointers/listing-15-21/output.txt index 9796bd7bf0..91a928ecba 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-21/output.txt +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-21/output.txt @@ -7,7 +7,7 @@ error[E0596]: cannot borrow `self.sent_messages` as mutable, as it is behind a ` | ----- help: consider changing that to be a mutable reference: `&mut self` ... 58 | self.sent_messages.push(String::from(message)); - | ^^^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable For more information about this error, try `rustc --explain E0596`. error: could not compile `limit-tracker` due to previous error diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-22/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-22/Cargo.toml index 2b3ecf580b..98c3f537c6 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-22/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-22/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "limit-tracker" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-23/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-23/Cargo.toml index 2b3ecf580b..98c3f537c6 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-23/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-23/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "limit-tracker" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-24/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-24/Cargo.toml index ca5c90b779..dce1515c3e 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-24/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-24/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cons-list" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-25/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-25/Cargo.toml index ca5c90b779..dce1515c3e 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-25/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-25/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cons-list" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-26/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-26/Cargo.toml index ca5c90b779..dce1515c3e 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-26/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-26/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cons-list" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-27/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-27/Cargo.toml index 9b981e540a..0bbf897d08 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-27/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-27/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tree" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-28/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-28/Cargo.toml index 9b981e540a..0bbf897d08 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-28/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-28/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tree" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/listing-15-29/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/listing-15-29/Cargo.toml index 9b981e540a..0bbf897d08 100644 --- a/src/doc/book/listings/ch15-smart-pointers/listing-15-29/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/listing-15-29/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tree" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/no-listing-01-cant-borrow-immutable-as-mutable/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/no-listing-01-cant-borrow-immutable-as-mutable/Cargo.toml index 9220706fc6..16f92447f6 100644 --- a/src/doc/book/listings/ch15-smart-pointers/no-listing-01-cant-borrow-immutable-as-mutable/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/no-listing-01-cant-borrow-immutable-as-mutable/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "borrowing" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/output-only-01-comparing-to-reference/Cargo.toml b/src/doc/book/listings/ch15-smart-pointers/output-only-01-comparing-to-reference/Cargo.toml index 330a2b3a1c..67ec198f74 100644 --- a/src/doc/book/listings/ch15-smart-pointers/output-only-01-comparing-to-reference/Cargo.toml +++ b/src/doc/book/listings/ch15-smart-pointers/output-only-01-comparing-to-reference/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "deref-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch15-smart-pointers/output-only-01-comparing-to-reference/output.txt b/src/doc/book/listings/ch15-smart-pointers/output-only-01-comparing-to-reference/output.txt index e9bbab0dbc..ed543708b6 100644 --- a/src/doc/book/listings/ch15-smart-pointers/output-only-01-comparing-to-reference/output.txt +++ b/src/doc/book/listings/ch15-smart-pointers/output-only-01-comparing-to-reference/output.txt @@ -4,7 +4,7 @@ error[E0277]: can't compare `{integer}` with `&{integer}` --> src/main.rs:6:5 | 6 | assert_eq!(5, y); - | ^^^^^^^^^^^^^^^^^ no implementation for `{integer} == &{integer}` + | ^^^^^^^^^^^^^^^^ no implementation for `{integer} == &{integer}` | = help: the trait `PartialEq<&{integer}>` is not implemented for `{integer}` = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-01/Cargo.toml b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-01/Cargo.toml index 86ef13c004..bd4edf7626 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-01/Cargo.toml +++ b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-01/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "threads" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-02/Cargo.toml b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-02/Cargo.toml index 86ef13c004..bd4edf7626 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-02/Cargo.toml +++ b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-02/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "threads" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-03/Cargo.toml b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-03/Cargo.toml index 86ef13c004..bd4edf7626 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-03/Cargo.toml +++ b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-03/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "threads" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-03/output.txt b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-03/output.txt index 23d3aaf278..321bf59d70 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-03/output.txt +++ b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-03/output.txt @@ -19,7 +19,7 @@ note: function requires argument type to outlive `'static` help: to force the closure to take ownership of `v` (and any other referenced variables), use the `move` keyword | 6 | let handle = thread::spawn(move || { - | ^^^^^^^ + | ++++ For more information about this error, try `rustc --explain E0373`. error: could not compile `threads` due to previous error diff --git a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-04/Cargo.toml b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-04/Cargo.toml index 86ef13c004..bd4edf7626 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-04/Cargo.toml +++ b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-04/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "threads" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-05/Cargo.toml b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-05/Cargo.toml index 86ef13c004..bd4edf7626 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-05/Cargo.toml +++ b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-05/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "threads" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-06/Cargo.toml b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-06/Cargo.toml index 078faf4d0b..24bd2ee7b4 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-06/Cargo.toml +++ b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-06/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "message-passing" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-07/Cargo.toml b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-07/Cargo.toml index 078faf4d0b..24bd2ee7b4 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-07/Cargo.toml +++ b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-07/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "message-passing" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-08/Cargo.toml b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-08/Cargo.toml index 078faf4d0b..24bd2ee7b4 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-08/Cargo.toml +++ b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-08/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "message-passing" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-09/Cargo.toml b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-09/Cargo.toml index 078faf4d0b..24bd2ee7b4 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-09/Cargo.toml +++ b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-09/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "message-passing" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-10/Cargo.toml b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-10/Cargo.toml index 078faf4d0b..24bd2ee7b4 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-10/Cargo.toml +++ b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-10/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "message-passing" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-11/Cargo.toml b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-11/Cargo.toml index 078faf4d0b..24bd2ee7b4 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-11/Cargo.toml +++ b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-11/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "message-passing" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-12/Cargo.toml b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-12/Cargo.toml index eaaec49577..da297eaba1 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-12/Cargo.toml +++ b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-12/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "shared-state" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-13/Cargo.toml b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-13/Cargo.toml index eaaec49577..da297eaba1 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-13/Cargo.toml +++ b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-13/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "shared-state" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-14/Cargo.toml b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-14/Cargo.toml index eaaec49577..da297eaba1 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-14/Cargo.toml +++ b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-14/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "shared-state" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-14/output.txt b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-14/output.txt index ffdd0674b8..9546e1e489 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-14/output.txt +++ b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-14/output.txt @@ -15,6 +15,7 @@ error[E0277]: `Rc>` cannot be sent between threads safely | = help: within `[closure@src/main.rs:11:36: 15:10]`, the trait `Send` is not implemented for `Rc>` = note: required because it appears within the type `[closure@src/main.rs:11:36: 15:10]` +note: required by a bound in `spawn` For more information about this error, try `rustc --explain E0277`. error: could not compile `shared-state` due to previous error diff --git a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-15/Cargo.toml b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-15/Cargo.toml index eaaec49577..da297eaba1 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/listing-16-15/Cargo.toml +++ b/src/doc/book/listings/ch16-fearless-concurrency/listing-16-15/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "shared-state" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch16-fearless-concurrency/no-listing-01-join-too-early/Cargo.toml b/src/doc/book/listings/ch16-fearless-concurrency/no-listing-01-join-too-early/Cargo.toml index 86ef13c004..bd4edf7626 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/no-listing-01-join-too-early/Cargo.toml +++ b/src/doc/book/listings/ch16-fearless-concurrency/no-listing-01-join-too-early/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "threads" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch16-fearless-concurrency/no-listing-02-no-loop-to-understand-error/Cargo.toml b/src/doc/book/listings/ch16-fearless-concurrency/no-listing-02-no-loop-to-understand-error/Cargo.toml index eaaec49577..da297eaba1 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/no-listing-02-no-loop-to-understand-error/Cargo.toml +++ b/src/doc/book/listings/ch16-fearless-concurrency/no-listing-02-no-loop-to-understand-error/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "shared-state" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch16-fearless-concurrency/output-only-01-move-drop/Cargo.toml b/src/doc/book/listings/ch16-fearless-concurrency/output-only-01-move-drop/Cargo.toml index 86ef13c004..bd4edf7626 100644 --- a/src/doc/book/listings/ch16-fearless-concurrency/output-only-01-move-drop/Cargo.toml +++ b/src/doc/book/listings/ch16-fearless-concurrency/output-only-01-move-drop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "threads" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch17-oop/listing-17-01/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-01/Cargo.toml index 1a64077d11..aed614e939 100644 --- a/src/doc/book/listings/ch17-oop/listing-17-01/Cargo.toml +++ b/src/doc/book/listings/ch17-oop/listing-17-01/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "averaged-collection" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch17-oop/listing-17-02/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-02/Cargo.toml index 1a64077d11..aed614e939 100644 --- a/src/doc/book/listings/ch17-oop/listing-17-02/Cargo.toml +++ b/src/doc/book/listings/ch17-oop/listing-17-02/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "averaged-collection" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch17-oop/listing-17-03/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-03/Cargo.toml index 06f8902623..9b816e7661 100644 --- a/src/doc/book/listings/ch17-oop/listing-17-03/Cargo.toml +++ b/src/doc/book/listings/ch17-oop/listing-17-03/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gui" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch17-oop/listing-17-04/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-04/Cargo.toml index 06f8902623..9b816e7661 100644 --- a/src/doc/book/listings/ch17-oop/listing-17-04/Cargo.toml +++ b/src/doc/book/listings/ch17-oop/listing-17-04/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gui" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch17-oop/listing-17-05/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-05/Cargo.toml index 06f8902623..9b816e7661 100644 --- a/src/doc/book/listings/ch17-oop/listing-17-05/Cargo.toml +++ b/src/doc/book/listings/ch17-oop/listing-17-05/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gui" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch17-oop/listing-17-06/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-06/Cargo.toml index 06f8902623..9b816e7661 100644 --- a/src/doc/book/listings/ch17-oop/listing-17-06/Cargo.toml +++ b/src/doc/book/listings/ch17-oop/listing-17-06/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gui" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch17-oop/listing-17-07/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-07/Cargo.toml index 06f8902623..9b816e7661 100644 --- a/src/doc/book/listings/ch17-oop/listing-17-07/Cargo.toml +++ b/src/doc/book/listings/ch17-oop/listing-17-07/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gui" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch17-oop/listing-17-08/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-08/Cargo.toml index 06f8902623..9b816e7661 100644 --- a/src/doc/book/listings/ch17-oop/listing-17-08/Cargo.toml +++ b/src/doc/book/listings/ch17-oop/listing-17-08/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gui" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch17-oop/listing-17-09/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-09/Cargo.toml index 06f8902623..9b816e7661 100644 --- a/src/doc/book/listings/ch17-oop/listing-17-09/Cargo.toml +++ b/src/doc/book/listings/ch17-oop/listing-17-09/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gui" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch17-oop/listing-17-10/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-10/Cargo.toml index 06f8902623..9b816e7661 100644 --- a/src/doc/book/listings/ch17-oop/listing-17-10/Cargo.toml +++ b/src/doc/book/listings/ch17-oop/listing-17-10/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gui" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch17-oop/listing-17-11/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-11/Cargo.toml index 706689ab91..1619af5c64 100644 --- a/src/doc/book/listings/ch17-oop/listing-17-11/Cargo.toml +++ b/src/doc/book/listings/ch17-oop/listing-17-11/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "blog" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch17-oop/listing-17-12/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-12/Cargo.toml index 706689ab91..1619af5c64 100644 --- a/src/doc/book/listings/ch17-oop/listing-17-12/Cargo.toml +++ b/src/doc/book/listings/ch17-oop/listing-17-12/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "blog" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch17-oop/listing-17-13/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-13/Cargo.toml index 706689ab91..1619af5c64 100644 --- a/src/doc/book/listings/ch17-oop/listing-17-13/Cargo.toml +++ b/src/doc/book/listings/ch17-oop/listing-17-13/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "blog" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch17-oop/listing-17-14/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-14/Cargo.toml index 706689ab91..1619af5c64 100644 --- a/src/doc/book/listings/ch17-oop/listing-17-14/Cargo.toml +++ b/src/doc/book/listings/ch17-oop/listing-17-14/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "blog" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch17-oop/listing-17-15/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-15/Cargo.toml index 706689ab91..1619af5c64 100644 --- a/src/doc/book/listings/ch17-oop/listing-17-15/Cargo.toml +++ b/src/doc/book/listings/ch17-oop/listing-17-15/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "blog" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch17-oop/listing-17-16/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-16/Cargo.toml index 706689ab91..1619af5c64 100644 --- a/src/doc/book/listings/ch17-oop/listing-17-16/Cargo.toml +++ b/src/doc/book/listings/ch17-oop/listing-17-16/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "blog" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch17-oop/listing-17-17/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-17/Cargo.toml index 706689ab91..1619af5c64 100644 --- a/src/doc/book/listings/ch17-oop/listing-17-17/Cargo.toml +++ b/src/doc/book/listings/ch17-oop/listing-17-17/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "blog" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch17-oop/listing-17-18/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-18/Cargo.toml index 706689ab91..1619af5c64 100644 --- a/src/doc/book/listings/ch17-oop/listing-17-18/Cargo.toml +++ b/src/doc/book/listings/ch17-oop/listing-17-18/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "blog" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch17-oop/listing-17-19/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-19/Cargo.toml index 706689ab91..1619af5c64 100644 --- a/src/doc/book/listings/ch17-oop/listing-17-19/Cargo.toml +++ b/src/doc/book/listings/ch17-oop/listing-17-19/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "blog" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch17-oop/listing-17-20/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-20/Cargo.toml index 706689ab91..1619af5c64 100644 --- a/src/doc/book/listings/ch17-oop/listing-17-20/Cargo.toml +++ b/src/doc/book/listings/ch17-oop/listing-17-20/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "blog" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch17-oop/listing-17-21/Cargo.toml b/src/doc/book/listings/ch17-oop/listing-17-21/Cargo.toml index 706689ab91..1619af5c64 100644 --- a/src/doc/book/listings/ch17-oop/listing-17-21/Cargo.toml +++ b/src/doc/book/listings/ch17-oop/listing-17-21/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "blog" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch17-oop/no-listing-01-trait-object-of-clone/Cargo.toml b/src/doc/book/listings/ch17-oop/no-listing-01-trait-object-of-clone/Cargo.toml index 06f8902623..9b816e7661 100644 --- a/src/doc/book/listings/ch17-oop/no-listing-01-trait-object-of-clone/Cargo.toml +++ b/src/doc/book/listings/ch17-oop/no-listing-01-trait-object-of-clone/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gui" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-01/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-01/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-01/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-01/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-02/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-02/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-02/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-02/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-03/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-03/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-03/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-03/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-04/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-04/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-04/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-04/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-05/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-05/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-05/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-05/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-06/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-06/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-06/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-06/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-07/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-07/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-07/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-07/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-08/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-08/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-08/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-08/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-09/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-09/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-09/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-09/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-10/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-10/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-10/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-10/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-10/output.txt b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-10/output.txt index b527311bb1..702d10a23f 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-10/output.txt +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-10/output.txt @@ -1,12 +1,10 @@ $ cargo run Compiling patterns v0.1.0 (file:///projects/patterns) warning: irrefutable `if let` pattern - --> src/main.rs:2:5 + --> src/main.rs:2:8 | -2 | / if let x = 5 { -3 | | println!("{}", x); -4 | | }; - | |_____^ +2 | if let x = 5 { + | ^^^^^^^^^ | = note: `#[warn(irrefutable_let_patterns)]` on by default = note: this pattern will always match, so the `if let` is useless diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-11/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-11/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-11/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-11/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-12/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-12/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-12/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-12/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-13/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-13/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-13/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-13/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-14/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-14/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-14/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-14/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-15/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-15/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-15/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-15/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-16/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-16/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-16/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-16/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-17/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-17/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-17/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-17/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-18/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-18/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-18/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-18/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-19/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-19/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-19/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-19/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-20/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-20/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-20/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-20/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-21/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-21/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-21/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-21/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-22/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-22/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-22/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-22/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-23/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-23/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-23/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-23/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-24/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-24/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-24/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-24/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-25/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-25/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-25/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-25/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-26/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-26/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-26/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-26/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-27/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-27/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-27/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-27/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-28/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-28/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-28/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-28/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-29/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-29/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-29/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-29/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/no-listing-01-literals/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/no-listing-01-literals/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/no-listing-01-literals/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/no-listing-01-literals/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/no-listing-02-multiple-patterns/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/no-listing-02-multiple-patterns/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/no-listing-02-multiple-patterns/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/no-listing-02-multiple-patterns/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/no-listing-03-ranges/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/no-listing-03-ranges/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/no-listing-03-ranges/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/no-listing-03-ranges/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/no-listing-04-ranges-of-char/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/no-listing-04-ranges-of-char/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/no-listing-04-ranges-of-char/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/no-listing-04-ranges-of-char/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch18-patterns-and-matching/no-listing-05-destructuring-structs-and-tuples/Cargo.toml b/src/doc/book/listings/ch18-patterns-and-matching/no-listing-05-destructuring-structs-and-tuples/Cargo.toml index 1ea5a1c005..82fe057bbc 100644 --- a/src/doc/book/listings/ch18-patterns-and-matching/no-listing-05-destructuring-structs-and-tuples/Cargo.toml +++ b/src/doc/book/listings/ch18-patterns-and-matching/no-listing-05-destructuring-structs-and-tuples/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "patterns" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-13-21-reproduced/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-13-21-reproduced/Cargo.toml index 4d881a627a..9e103f3eb3 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-13-21-reproduced/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-13-21-reproduced/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "counter" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-01/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-01/Cargo.toml index 940d4ab820..3e8a292013 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-01/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-01/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-02/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-02/Cargo.toml index 940d4ab820..3e8a292013 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-02/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-02/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-03/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-03/Cargo.toml index 940d4ab820..3e8a292013 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-03/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-03/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-04/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-04/Cargo.toml index 940d4ab820..3e8a292013 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-04/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-04/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-05/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-05/Cargo.toml index 940d4ab820..3e8a292013 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-05/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-05/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-06/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-06/Cargo.toml index 940d4ab820..3e8a292013 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-06/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-06/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-07/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-07/Cargo.toml index 940d4ab820..3e8a292013 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-07/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-07/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-08/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-08/Cargo.toml index 940d4ab820..3e8a292013 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-08/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-08/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-09/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-09/Cargo.toml index 940d4ab820..3e8a292013 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-09/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-09/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-10/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-10/Cargo.toml index 940d4ab820..3e8a292013 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-10/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-10/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-11/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-11/Cargo.toml index 940d4ab820..3e8a292013 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-11/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-11/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-12/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-12/Cargo.toml index 0fad0cdf04..52395a5873 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-12/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-12/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-13/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-13/Cargo.toml index 0fad0cdf04..52395a5873 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-13/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-13/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-14/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-14/Cargo.toml index 0fad0cdf04..52395a5873 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-14/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-14/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-15/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-15/Cargo.toml index 0fad0cdf04..52395a5873 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-15/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-15/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-16/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-16/Cargo.toml index 0fad0cdf04..52395a5873 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-16/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-16/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-17/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-17/Cargo.toml index 0fad0cdf04..52395a5873 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-17/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-17/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-18/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-18/Cargo.toml index 0fad0cdf04..52395a5873 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-18/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-18/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-19/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-19/Cargo.toml index 0fad0cdf04..52395a5873 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-19/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-19/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-20/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-20/Cargo.toml index 0fad0cdf04..52395a5873 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-20/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-20/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-21/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-21/Cargo.toml index 0fad0cdf04..52395a5873 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-21/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-21/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-22/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-22/Cargo.toml index 0fad0cdf04..52395a5873 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-22/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-22/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-23/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-23/Cargo.toml index 0fad0cdf04..52395a5873 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-23/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-23/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-24/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-24/Cargo.toml index ce5f9eadc2..a2ae20c77c 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-24/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-24/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "types-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-25/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-25/Cargo.toml index ce5f9eadc2..a2ae20c77c 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-25/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-25/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "types-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-27/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-27/Cargo.toml index 51b8b14f99..b196f35b55 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-27/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-27/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "functions-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-28/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-28/Cargo.toml index b9af9c6d62..9218091c89 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-28/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-28/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "macros-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-30/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-30/Cargo.toml index 4c4e6f898b..c6fb920877 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-30/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-30/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello_macro" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-31/hello_macro/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-31/hello_macro/Cargo.toml index 4c4e6f898b..c6fb920877 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-31/hello_macro/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-31/hello_macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello_macro" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/Cargo.toml index 80cada3ef0..aa076ac48b 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-31/hello_macro/hello_macro_derive/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "hello_macro_derive" version = "0.1.0" -edition = "2018" +edition = "2021" [lib] proc-macro = true diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-33/hello_macro/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-33/hello_macro/Cargo.toml index 4c4e6f898b..c6fb920877 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-33/hello_macro/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-33/hello_macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello_macro" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/listing-19-33/hello_macro/hello_macro_derive/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/listing-19-33/hello_macro/hello_macro_derive/Cargo.toml index 80cada3ef0..aa076ac48b 100644 --- a/src/doc/book/listings/ch19-advanced-features/listing-19-33/hello_macro/hello_macro_derive/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/listing-19-33/hello_macro/hello_macro_derive/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "hello_macro_derive" version = "0.1.0" -edition = "2018" +edition = "2021" [lib] proc-macro = true diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-01-unsafe-fn/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/no-listing-01-unsafe-fn/Cargo.toml index 940d4ab820..3e8a292013 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-01-unsafe-fn/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-01-unsafe-fn/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/Cargo.toml index 0fad0cdf04..52395a5873 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/output.txt b/src/doc/book/listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/output.txt index 1264ce7470..0991f10faa 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/output.txt +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-02-impl-outlineprint-for-point/output.txt @@ -3,14 +3,16 @@ $ cargo run error[E0277]: `Point` doesn't implement `std::fmt::Display` --> src/main.rs:20:6 | -3 | trait OutlinePrint: fmt::Display { - | ------------ required by this bound in `OutlinePrint` -... 20 | impl OutlinePrint for Point {} | ^^^^^^^^^^^^ `Point` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `Point` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `OutlinePrint` + --> src/main.rs:3:21 + | +3 | trait OutlinePrint: fmt::Display { + | ^^^^^^^^^^^^ required by this bound in `OutlinePrint` For more information about this error, try `rustc --explain E0277`. error: could not compile `traits-example` due to previous error diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-03-impl-display-for-point/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/no-listing-03-impl-display-for-point/Cargo.toml index 0fad0cdf04..52395a5873 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-03-impl-display-for-point/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-03-impl-display-for-point/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-04-kilometers-alias/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/no-listing-04-kilometers-alias/Cargo.toml index ce5f9eadc2..a2ae20c77c 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-04-kilometers-alias/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-04-kilometers-alias/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "types-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-05-write-trait/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/no-listing-05-write-trait/Cargo.toml index 0fad0cdf04..52395a5873 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-05-write-trait/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-05-write-trait/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-06-result-alias/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/no-listing-06-result-alias/Cargo.toml index 0fad0cdf04..52395a5873 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-06-result-alias/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-06-result-alias/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-07-never-type/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/no-listing-07-never-type/Cargo.toml index 0fad0cdf04..52395a5873 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-07-never-type/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-07-never-type/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "traits-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-08-match-arms-different-types/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/no-listing-08-match-arms-different-types/Cargo.toml index ce5f9eadc2..a2ae20c77c 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-08-match-arms-different-types/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-08-match-arms-different-types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "types-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-09-unwrap-definition/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/no-listing-09-unwrap-definition/Cargo.toml index ce5f9eadc2..a2ae20c77c 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-09-unwrap-definition/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-09-unwrap-definition/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "types-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-10-loop-returns-never/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/no-listing-10-loop-returns-never/Cargo.toml index ce5f9eadc2..a2ae20c77c 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-10-loop-returns-never/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-10-loop-returns-never/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "types-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-11-cant-create-str/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/no-listing-11-cant-create-str/Cargo.toml index ce5f9eadc2..a2ae20c77c 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-11-cant-create-str/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-11-cant-create-str/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "types-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-12-generic-fn-definition/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/no-listing-12-generic-fn-definition/Cargo.toml index ce5f9eadc2..a2ae20c77c 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-12-generic-fn-definition/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-12-generic-fn-definition/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "types-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-13-generic-implicit-sized-bound/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/no-listing-13-generic-implicit-sized-bound/Cargo.toml index ce5f9eadc2..a2ae20c77c 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-13-generic-implicit-sized-bound/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-13-generic-implicit-sized-bound/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "types-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-14-generic-maybe-sized/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/no-listing-14-generic-maybe-sized/Cargo.toml index ce5f9eadc2..a2ae20c77c 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-14-generic-maybe-sized/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-14-generic-maybe-sized/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "types-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-15-map-closure/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/no-listing-15-map-closure/Cargo.toml index 51b8b14f99..b196f35b55 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-15-map-closure/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-15-map-closure/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "functions-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-16-map-function/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/no-listing-16-map-function/Cargo.toml index 51b8b14f99..b196f35b55 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-16-map-function/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-16-map-function/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "functions-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-17-map-initializer/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/no-listing-17-map-initializer/Cargo.toml index 51b8b14f99..b196f35b55 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-17-map-initializer/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-17-map-initializer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "functions-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-18-returns-closure/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/no-listing-18-returns-closure/Cargo.toml index 51b8b14f99..b196f35b55 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-18-returns-closure/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-18-returns-closure/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "functions-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-18-returns-closure/output.txt b/src/doc/book/listings/ch19-advanced-features/no-listing-18-returns-closure/output.txt index 9811fcde09..d6fffc9678 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-18-returns-closure/output.txt +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-18-returns-closure/output.txt @@ -10,7 +10,7 @@ error[E0746]: return type cannot have an unboxed trait object help: use `impl Fn(i32) -> i32` as the return type, as all return paths are of type `[closure@src/lib.rs:2:5: 2:14]`, which implements `Fn(i32) -> i32` | 1 | fn returns_closure() -> impl Fn(i32) -> i32 { - | ^^^^^^^^^^^^^^^^^^^ + | ~~~~~~~~~~~~~~~~~~~ For more information about this error, try `rustc --explain E0746`. error: could not compile `functions-example` due to previous error diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-19-returns-closure-trait-object/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/no-listing-19-returns-closure-trait-object/Cargo.toml index 51b8b14f99..b196f35b55 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-19-returns-closure-trait-object/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-19-returns-closure-trait-object/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "functions-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/hello_macro/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/hello_macro/Cargo.toml index 4c4e6f898b..c6fb920877 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/hello_macro/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/hello_macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello_macro" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/pancakes/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/pancakes/Cargo.toml index b941d527be..3ad910862a 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/pancakes/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-20-impl-hellomacro-for-pancakes/pancakes/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "pancakes" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] hello_macro = { path = "../hello_macro" } \ No newline at end of file diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/Cargo.toml index 4c4e6f898b..c6fb920877 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello_macro" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/Cargo.toml index 80cada3ef0..aa076ac48b 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-21-pancakes/hello_macro/hello_macro_derive/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "hello_macro_derive" version = "0.1.0" -edition = "2018" +edition = "2021" [lib] proc-macro = true diff --git a/src/doc/book/listings/ch19-advanced-features/no-listing-21-pancakes/pancakes/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/no-listing-21-pancakes/pancakes/Cargo.toml index f150aec0aa..cb3a98c3a8 100644 --- a/src/doc/book/listings/ch19-advanced-features/no-listing-21-pancakes/pancakes/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/no-listing-21-pancakes/pancakes/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "pancakes" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] hello_macro = { path = "../hello_macro" } diff --git a/src/doc/book/listings/ch19-advanced-features/output-only-01-missing-unsafe/Cargo.toml b/src/doc/book/listings/ch19-advanced-features/output-only-01-missing-unsafe/Cargo.toml index 940d4ab820..3e8a292013 100644 --- a/src/doc/book/listings/ch19-advanced-features/output-only-01-missing-unsafe/Cargo.toml +++ b/src/doc/book/listings/ch19-advanced-features/output-only-01-missing-unsafe/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "unsafe-example" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/listing-20-01/Cargo.toml b/src/doc/book/listings/ch20-web-server/listing-20-01/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-01/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/listing-20-01/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/listing-20-02/Cargo.toml b/src/doc/book/listings/ch20-web-server/listing-20-02/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-02/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/listing-20-02/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/listing-20-03/Cargo.toml b/src/doc/book/listings/ch20-web-server/listing-20-03/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-03/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/listing-20-03/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/listing-20-04/Cargo.toml b/src/doc/book/listings/ch20-web-server/listing-20-04/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-04/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/listing-20-04/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/listing-20-05/Cargo.toml b/src/doc/book/listings/ch20-web-server/listing-20-05/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-05/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/listing-20-05/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/listing-20-06/Cargo.toml b/src/doc/book/listings/ch20-web-server/listing-20-06/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-06/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/listing-20-06/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/listing-20-07/Cargo.toml b/src/doc/book/listings/ch20-web-server/listing-20-07/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-07/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/listing-20-07/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/listing-20-08/Cargo.toml b/src/doc/book/listings/ch20-web-server/listing-20-08/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-08/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/listing-20-08/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/listing-20-09/Cargo.toml b/src/doc/book/listings/ch20-web-server/listing-20-09/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-09/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/listing-20-09/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/listing-20-10/Cargo.toml b/src/doc/book/listings/ch20-web-server/listing-20-10/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-10/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/listing-20-10/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/listing-20-11/Cargo.toml b/src/doc/book/listings/ch20-web-server/listing-20-11/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-11/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/listing-20-11/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/listing-20-12/Cargo.toml b/src/doc/book/listings/ch20-web-server/listing-20-12/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-12/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/listing-20-12/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/listing-20-13/Cargo.toml b/src/doc/book/listings/ch20-web-server/listing-20-13/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-13/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/listing-20-13/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/listing-20-14/Cargo.toml b/src/doc/book/listings/ch20-web-server/listing-20-14/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-14/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/listing-20-14/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/listing-20-15/Cargo.toml b/src/doc/book/listings/ch20-web-server/listing-20-15/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-15/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/listing-20-15/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/listing-20-16/Cargo.toml b/src/doc/book/listings/ch20-web-server/listing-20-16/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-16/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/listing-20-16/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/listing-20-17/Cargo.toml b/src/doc/book/listings/ch20-web-server/listing-20-17/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-17/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/listing-20-17/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/listing-20-18/Cargo.toml b/src/doc/book/listings/ch20-web-server/listing-20-18/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-18/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/listing-20-18/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/listing-20-19/Cargo.toml b/src/doc/book/listings/ch20-web-server/listing-20-19/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-19/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/listing-20-19/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/listing-20-20/Cargo.toml b/src/doc/book/listings/ch20-web-server/listing-20-20/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-20/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/listing-20-20/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/listing-20-21/Cargo.toml b/src/doc/book/listings/ch20-web-server/listing-20-21/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-21/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/listing-20-21/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/listing-20-22/Cargo.toml b/src/doc/book/listings/ch20-web-server/listing-20-22/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-22/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/listing-20-22/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/listing-20-23/Cargo.toml b/src/doc/book/listings/ch20-web-server/listing-20-23/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-23/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/listing-20-23/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/listing-20-24/Cargo.toml b/src/doc/book/listings/ch20-web-server/listing-20-24/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-24/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/listing-20-24/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/listing-20-25/Cargo.toml b/src/doc/book/listings/ch20-web-server/listing-20-25/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/listing-20-25/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/listing-20-25/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/no-listing-01-define-threadpool-struct/Cargo.toml b/src/doc/book/listings/ch20-web-server/no-listing-01-define-threadpool-struct/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/no-listing-01-define-threadpool-struct/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/no-listing-01-define-threadpool-struct/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/no-listing-02-impl-threadpool-new/Cargo.toml b/src/doc/book/listings/ch20-web-server/no-listing-02-impl-threadpool-new/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/no-listing-02-impl-threadpool-new/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/no-listing-02-impl-threadpool-new/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/no-listing-03-define-execute/Cargo.toml b/src/doc/book/listings/ch20-web-server/no-listing-03-define-execute/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/no-listing-03-define-execute/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/no-listing-03-define-execute/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/no-listing-04-update-worker-definition/Cargo.toml b/src/doc/book/listings/ch20-web-server/no-listing-04-update-worker-definition/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/no-listing-04-update-worker-definition/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/no-listing-04-update-worker-definition/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/no-listing-05-fix-worker-new/Cargo.toml b/src/doc/book/listings/ch20-web-server/no-listing-05-fix-worker-new/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/no-listing-05-fix-worker-new/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/no-listing-05-fix-worker-new/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/no-listing-06-fix-threadpool-drop/Cargo.toml b/src/doc/book/listings/ch20-web-server/no-listing-06-fix-threadpool-drop/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/no-listing-06-fix-threadpool-drop/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/no-listing-06-fix-threadpool-drop/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/no-listing-07-define-message-enum/Cargo.toml b/src/doc/book/listings/ch20-web-server/no-listing-07-define-message-enum/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/no-listing-07-define-message-enum/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/no-listing-07-define-message-enum/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/listings/ch20-web-server/no-listing-08-final-code/Cargo.toml b/src/doc/book/listings/ch20-web-server/no-listing-08-final-code/Cargo.toml index faf0baeab6..fe619478a6 100644 --- a/src/doc/book/listings/ch20-web-server/no-listing-08-final-code/Cargo.toml +++ b/src/doc/book/listings/ch20-web-server/no-listing-08-final-code/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hello" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] diff --git a/src/doc/book/nostarch/chapter05.md b/src/doc/book/nostarch/chapter05.md index fc88ee89be..d280447a04 100644 --- a/src/doc/book/nostarch/chapter05.md +++ b/src/doc/book/nostarch/chapter05.md @@ -3,25 +3,29 @@ # Using Structs to Structure Related Data -A *struct*, or *structure*, is a custom data type that lets you name and -package together multiple related values that make up a meaningful group. If +A *struct*, or *structure*, is a custom data type that lets you package +together and name multiple related values that make up a meaningful group. If you’re familiar with an object-oriented language, a *struct* is like an object’s data attributes. In this chapter, we’ll compare and contrast tuples -with structs. We’ll demonstrate how to define and instantiate structs. We’ll -discuss how to define associated functions, especially the kind of associated -functions called *methods*, to specify behavior associated with a struct type. -Structs and enums (discussed in Chapter 6) are the building blocks for creating -new types in your program’s domain to take full advantage of Rust’s compile -time type checking. +with structs to build on what you already know and demonstrate when structs are +a better way to group data. + + +We’ll demonstrate how to define and instantiate structs. We’ll discuss how to +define associated functions, especially the kind of associated functions called +*methods*, to specify behavior associated with a struct type. Structs and enums +(discussed in Chapter 6) are the building blocks for creating new types in your +program’s domain to take full advantage of Rust’s compile time type checking. ## Defining and Instantiating Structs -Structs are similar to tuples, which were discussed in “The Tuple Type” -section. Like tuples, the pieces of a struct can be different types. Unlike -with tuples, you’ll name each piece of data so it’s clear what the values mean. -As a result of these names, structs are more flexible than tuples: you don’t -have to rely on the order of the data to specify or access the values of an -instance. +Structs are similar to tuples, discussed in “The Tuple Type” section, in that +both hold multiple related values. Like tuples, the pieces of a struct can be +different types. Unlike with tuples, in a struct you’ll name each piece of data +so it’s clear what the values mean. Adding these names means that structs are +more flexible than tuples: you don’t have to rely on the order of the data to +specify or access the values of an instance. To define a struct, we enter the keyword `struct` and name the entire struct. A struct’s name should describe the significance of the pieces of data being @@ -51,31 +55,35 @@ in that template with particular data to create values of the type. For example, we can declare a particular user as shown in Listing 5-2. ``` -let user1 = User { - email: String::from("someone@example.com"), - username: String::from("someusername123"), - active: true, - sign_in_count: 1, -}; +fn main() { + let user1 = User { + email: String::from("someone@example.com"), + username: String::from("someusername123"), + active: true, + sign_in_count: 1, + }; +} ``` Listing 5-2: Creating an instance of the `User` struct -To get a specific value from a struct, we can use dot notation. If we wanted +To get a specific value from a struct, we use dot notation. If we wanted just this user’s email address, we could use `user1.email` wherever we wanted to use this value. If the instance is mutable, we can change a value by using the dot notation and assigning into a particular field. Listing 5-3 shows how to change the value in the `email` field of a mutable `User` instance. ``` -let mut user1 = User { - email: String::from("someone@example.com"), - username: String::from("someusername123"), - active: true, - sign_in_count: 1, -}; +fn main() { + let mut user1 = User { + email: String::from("someone@example.com"), + username: String::from("someusername123"), + active: true, + sign_in_count: 1, + }; -user1.email = String::from("anotheremail@example.com"); + user1.email = String::from("anotheremail@example.com"); +} ``` Listing 5-3: Changing the value in the `email` field of a `User` instance @@ -108,7 +116,7 @@ fields, but having to repeat the `email` and `username` field names and variables is a bit tedious. If the struct had more fields, repeating each name would get even more annoying. Luckily, there’s a convenient shorthand! -### Using the Field Init Shorthand when Variables and Fields Have the Same Name +### Using the Field Init Shorthand Because the parameter names and the struct field names are exactly the same in Listing 5-4, we can use the *field init shorthand* syntax to rewrite @@ -137,21 +145,25 @@ than `email: email`. ### Creating Instances From Other Instances With Struct Update Syntax -It’s often useful to create a new instance of a struct that uses most of an old -instance’s values but changes some. You can do this using *struct update -syntax*. +It’s often useful to create a new instance of a struct that includes most of +the values from another instance, but changes some. You can do this using +*struct update syntax*. -First, Listing 5-6 shows how we create a new `User` instance in `user2` without -the update syntax. We set a new value for `email` but otherwise use the same -values from `user1` that we created in Listing 5-2. +First, in Listing 5-6 we show how to create a new `User` instance in `user2` +regularly, without the update syntax. We set a new value for `email` but +otherwise use the same values from `user1` that we created in Listing 5-2. ``` -let user2 = User { - active: user1.active, - username: user1.username, - email: String::from("another@example.com"), - sign_in_count: user1.sign_in_count, -}; +fn main() { + // --snip-- + + let user2 = User { + active: user1.active, + username: user1.username, + email: String::from("another@example.com"), + sign_in_count: user1.sign_in_count, + }; +} ``` Listing 5-6: Creating a new `User` instance using one of the values from `user1` @@ -161,10 +173,14 @@ shown in Listing 5-7. The syntax `..` specifies that the remaining fields not explicitly set should have the same value as the fields in the given instance. ``` -let user2 = User { - email: String::from("another@example.com"), - ..user1 -}; +fn main() { + // --snip-- + + let user2 = User { + email: String::from("another@example.com"), + ..user1 + }; +} ``` Listing 5-7: Using struct update syntax to set a new `email` value for a `User` @@ -178,35 +194,38 @@ corresponding fields in `user1`, but we can choose to specify values for as many fields as we want in any order, regardless of the order of the fields in the struct’s definition. -Note that the struct update syntax is like assignment with `=` because it moves -the data, just as we saw in the “Ways Variables and Data Interact: Move” -section. In this example, we can no longer use `user1` after creating `user2` -because the `String` in the `username` field of `user1` was moved into `user2`. -If we had given `user2` new `String` values for both `email` and `username`, -and thus only used the `active` and `sign_in_count` values from `user1`, then -`user1` would still be valid after creating `user2`. The types of `active` and -`sign_in_count` are types that implement the `Copy` trait, so the behavior we -discussed in the “Stack-Only Data: Copy” section would apply. +Note that the struct update syntax uses `=` like an assignment; this is +because it moves the data, just as we saw in the “Ways Variables and Data +Interact: Move” section. In this example, we can no longer use `user1` after +creating `user2` because the `String` in the `username` field of `user1` was +moved into `user2`. If we had given `user2` new `String` values for both +`email` and `username`, and thus only used the `active` and `sign_in_count` +values from `user1`, then `user1` would still be valid after creating `user2`. +The types of `active` and `sign_in_count` are types that implement the `Copy` +trait, so the behavior we discussed in the “Stack-Only Data: Copy” section +would apply. ### Using Tuple Structs without Named Fields to Create Different Types -You can also define structs that look similar to tuples, called *tuple +Rust also supports structs that look similar to tuples, called *tuple structs*. Tuple structs have the added meaning the struct name provides but don’t have names associated with their fields; rather, they just have the types of the fields. Tuple structs are useful when you want to give the whole tuple a -name and make the tuple be a different type from other tuples, and naming each +name and make the tuple a different type from other tuples, and when naming each field as in a regular struct would be verbose or redundant. To define a tuple struct, start with the `struct` keyword and the struct name -followed by the types in the tuple. For example, here are definitions and -usages of two tuple structs named `Color` and `Point`: +followed by the types in the tuple. For example, here we define and use +two tuple structs named `Color` and `Point`: ``` struct Color(i32, i32, i32); struct Point(i32, i32, i32); -let black = Color(0, 0, 0); -let origin = Point(0, 0, 0); +fn main() { + let black = Color(0, 0, 0); + let origin = Point(0, 0, 0); +} ``` Note that the `black` and `origin` values are different types, because they’re @@ -222,40 +241,41 @@ individual value, and so on. You can also define structs that don’t have any fields! These are called *unit-like structs* because they behave similarly to `()`, the unit type that -we mentioned in “The Tuple Type” section. Unit-like structs can be useful in -situations in which you need to implement a trait on some type but don’t have -any data that you want to store in the type itself. We’ll discuss traits in -Chapter 10. Here’s an example of declaring and instantiating a unit struct -named `AlwaysEqual`: +we mentioned in “The Tuple Type” section. Unit-like structs can be useful when +you need to implement a trait on some type but don’t have any data that you +want to store in the type itself. We’ll discuss traits in Chapter 10. Here’s an +example of declaring and instantiating a unit struct named `AlwaysEqual`: ``` struct AlwaysEqual; -let subject = AlwaysEqual; +fn main() { + let subject = AlwaysEqual; +} ``` To define `AlwaysEqual`, we use the `struct` keyword, the name we want, then a semicolon. No need for curly brackets or parentheses! Then we can get an instance of `AlwaysEqual` in the `subject` variable in a similar way: using the -name we defined, without any curly brackets or parentheses. Imagine we’ll be -implementing behavior for this type that every instance is always equal to -every instance of every other type, perhaps to have a known result for testing -purposes. We wouldn’t need any data to implement that behavior! You’ll see in -Chapter 10 how to define traits and implement them on any type, including -unit-like structs. +name we defined, without any curly brackets or parentheses. Imagine that later +we’ll implement behavior for this type such that every instance of +`AlwaysEqual` is always equal to every instance of any other type, perhaps to +have a known result for testing purposes. We wouldn’t need any data to +implement that behavior! You’ll see in Chapter 10 how to define traits and +implement them on any type, including unit-like structs. > ### Ownership of Struct Data > > In the `User` struct definition in Listing 5-1, we used the owned `String` > type rather than the `&str` string slice type. This is a deliberate choice -> because we want instances of this struct to own all of its data and for that -> data to be valid for as long as the entire struct is valid. +> because we want each instance of this struct to own all of its data and for +> that data to be valid for as long as the entire struct is valid. > -> It’s possible for structs to store references to data owned by something else, -> but to do so requires the use of *lifetimes*, a Rust feature that we’ll +> It’s also possible for structs to store references to data owned by something +> else, but to do so requires the use of *lifetimes*, a Rust feature that we’ll > discuss in Chapter 10. Lifetimes ensure that the data referenced by a struct > is valid for as long as the struct is. Let’s say you try to store a reference -> in a struct without specifying lifetimes, like this, which won’t work: +> in a struct without specifying lifetimes, like the following; this won’t work: > > Filename: src/main.rs > @@ -282,29 +302,31 @@ unit-like structs. > ``` > $ cargo run > Compiling structs v0.1.0 (file:///projects/structs) -> errorE0106: missing lifetime specifier -> --> src/main.rs:2:15 +> error[E0106]: missing lifetime specifier +> --> src/main.rs:3:15 > | -> 2 | username: &str, +> 3 | username: &str, > | ^ expected named lifetime parameter > | > help: consider introducing a named lifetime parameter > | -> 1 | struct User<'a> { -> 2 | username: &'a str, +> 1 ~ struct User<'a> { +> 2 | active: bool, +> 3 ~ username: &'a str, > | > -> errorE0106: missing lifetime specifier -> --> src/main.rs:3:12 +> error[E0106]: missing lifetime specifier +> --> src/main.rs:4:12 > | -> 3 | email: &str, +> 4 | email: &str, > | ^ expected named lifetime parameter > | > help: consider introducing a named lifetime parameter > | -> 1 | struct User<'a> { -> 2 | username: &str, -> 3 | email: &'a str, +> 1 ~ struct User<'a> { +> 2 | active: bool, +> 3 | username: &str, +> 4 ~ email: &'a str, > | > ``` > @@ -315,8 +337,8 @@ unit-like structs. ## An Example Program Using Structs To understand when we might want to use structs, let’s write a program that -calculates the area of a rectangle. We’ll start with single variables, and then -refactor the program until we’re using structs instead. +calculates the area of a rectangle. We’ll start by using single variables, and +then refactor the program until we’re using structs instead. Let’s make a new binary project with Cargo called *rectangles* that will take the width and height of a rectangle specified in pixels and calculate the area @@ -354,10 +376,12 @@ $ cargo run The area of the rectangle is 1500 square pixels. ``` -Even though Listing 5-8 works and figures out the area of the rectangle by -calling the `area` function with each dimension, we can do better. The width -and the height are related to each other because together they describe one -rectangle. +This code succeeds in figuring out the area of the rectangle by calling the +`area` function with each dimension, but we can do more to make this code clear +and readable. + + The issue with this code is evident in the signature of `area`: @@ -366,8 +390,8 @@ fn area(width: u32, height: u32) -> u32 { ``` The `area` function is supposed to calculate the area of one rectangle, but the -function we wrote has two parameters. The parameters are related, but that’s -not expressed anywhere in our program. It would be more readable and more +function we wrote has two parameters, and it's not clear anywhere in our +program that the parameters are related. It would be more readable and more manageable to group width and height together. We’ve already discussed one way we might do that in “The Tuple Type” section of Chapter 3: by using tuples. @@ -396,21 +420,20 @@ Listing 5-9: Specifying the width and height of the rectangle with a tuple In one way, this program is better. Tuples let us add a bit of structure, and we’re now passing just one argument. But in another way, this version is less -clear: tuples don’t name their elements, so our calculation has become more -confusing because we have to index into the parts of the tuple. +clear: tuples don’t name their elements, so we have to index into the parts of +the tuple, making our calculation less obvious. -It doesn’t matter if we mix up width and height for the area calculation, but -if we want to draw the rectangle on the screen, it would matter! We would have -to keep in mind that `width` is the tuple index `0` and `height` is the tuple -index `1`. If someone else worked on this code, they would have to figure this -out and keep it in mind as well. It would be easy to forget or mix up these -values and cause errors, because we haven’t conveyed the meaning of our data in -our code. +Mixing up the width and height wouldn’t matter for the area calculation, but if +we want to draw the rectangle on the screen, it would matter! We would have to +keep in mind that `width` is the tuple index `0` and `height` is the tuple +index `1`. This would be even harder for someone else to figure out and keep in +mind if they were to use our code. Because we haven’t conveyed the meaning of +our data in our code, it’s now easier to introduce errors. ### Refactoring with Structs: Adding More Meaning We use structs to add meaning by labeling the data. We can transform the tuple -we’re using into a data type with a name for the whole as well as names for the +we’re using into a struct with a name for the whole as well as names for the parts, as shown in Listing 5-10. Filename: src/main.rs @@ -461,7 +484,7 @@ and `1`. This is a win for clarity. ### Adding Useful Functionality with Derived Traits -It’d be nice to be able to print an instance of `Rectangle` while we’re +It’d be useful to be able to print an instance of `Rectangle` while we’re debugging our program and see the values for all its fields. Listing 5-11 tries using the `println!` macro as we have used in previous chapters. This won’t work, however. @@ -501,7 +524,7 @@ a `1` or any other primitive type to a user. But with structs, the way display possibilities: Do you want commas or not? Do you want to print the curly brackets? Should all the fields be shown? Due to this ambiguity, Rust doesn’t try to guess what we want, and structs don’t have a provided -implementation of `Display`. +implementation of `Display` to use with `println!` and the `{}` placeholder. If we continue reading the errors, we’ll find this helpful note: @@ -571,7 +594,7 @@ Nice! It’s not the prettiest output, but it shows the values of all the fields for this instance, which would definitely help during debugging. When we have larger structs, it’s useful to have output that’s a bit easier to read; in those cases, we can use `{:#?}` instead of `{:?}` in the `println!` string. -When we use the `{:#?}` style in the example, the output will look like this: +In this example, using the `{:#?}` style will output: ``` $ cargo run @@ -584,17 +607,23 @@ rect1 is Rectangle { } ``` -Another way to print out a value using the `Debug` format is by using the -`dbg!` macro. The `dbg!` macro takes ownership of an expression, prints the -file and line number of where that `dbg!` macro call occurs in your code along -with the resulting value of that expression, and returns ownership of the -value. Calling the `dbg!` macro prints to the standard error console stream -(`stderr`), as opposed to `println!` which prints to the standard output -console stream (`stdout`). We’ll talk more about `stderr` and `stdout` in the -“Writing Error Messages to Standard Error Instead of Standard Output” section -in Chapter 12. Here’s an example where we’re interested in the value that gets -assigned to the `width` field, as well as the value of the whole struct in -`rect1`: +Another way to print out a value using the `Debug` format is to use the `dbg!` +macro, which takes ownership of an expression, prints the file and line number +of where that `dbg!` macro call occurs in your code along with the resulting +value of that expression, and returns ownership of the value. + + + +> Note: Calling the `dbg!` macro prints to the standard error console stream +> (`stderr`), as opposed to `println!` which prints to the standard output +> console stream (`stdout`). We’ll talk more about `stderr` and `stdout` in the +> “Writing Error Messages to Standard Error Instead of Standard Output” section +> in Chapter 12. + +Here’s an example where we’re interested in the value that gets assigned to the +`width` field, as well as the value of the whole struct in `rect1`: ``` #[derive(Debug)] @@ -656,13 +685,13 @@ continue to refactor this code by turning the `area` function into an `area` ## Method Syntax -*Methods* are similar to functions: they’re declared with the `fn` keyword and -their name, they can have parameters and a return value, and they contain some -code that is run when they’re called from somewhere else. However, methods are -different from functions in that they’re defined within the context of a struct -(or an enum or a trait object, which we cover in Chapters 6 and 17, -respectively), and their first parameter is always `self`, which represents the -instance of the struct the method is being called on. +*Methods* are similar to functions: we declare them with the `fn` keyword and a +name, they can have parameters and a return value, and they contain some code +that’s run when the method is called from somewhere else. Unlike functions, +methods are defined within the context of a struct (or an enum or a trait +object, which we cover in Chapters 6 and 17, respectively), and their first +parameter is always `self`, which represents the instance of the struct the +method is being called on. ### Defining Methods @@ -729,7 +758,7 @@ instance by using just `self` as the first parameter is rare; this technique is usually used when the method transforms `self` into something else and you want to prevent the caller from using the original instance after the transformation. -The main benefit of using methods instead of functions, in addition to using +The main reason for using methods instead of functions, in addition to providing method syntax and not having to repeat the type of `self` in every method’s signature, is for organization. We’ve put all the things we can do with an instance of a type in one `impl` block rather than making future users of our @@ -760,21 +789,20 @@ fn main() { } ``` -Here, we’re choosing to make the behavior of the `width` method be that it -returns `true` if the value in the instance’s `width` field is greater than 0, -and `false` if the value is 0: we can use a field within a method of the same -name for any purpose. In `main`, when we follow `rect1.width` with parentheses, -Rust knows we mean the method `width`. When we don’t use parentheses, Rust -knows we mean the field `width`. +Here, we’re choosing to make the `width` method return `true` if the value in +the instance’s `width` field is greater than 0, and `false` if the value is 0: +we can use a field within a method of the same name for any purpose. In `main`, +when we follow `rect1.width` with parentheses, Rust knows we mean the method +`width`. When we don’t use parentheses, Rust knows we mean the field `width`. -Often, but not always, methods with the same name as a field will be defined to -only return the value in the field and do nothing else. Methods like this are -called *getters*, and Rust does not implement them automatically for struct -fields as some other languages do. Getters are useful because you can make the -field private but the method public and thus enable read-only access to that -field as part of the type’s public API. We will be discussing what public and -private are and how to designate a field or method as public or private in -Chapter 7. +Often, but not always, when we give methods with the same name as a field we +want it to only return the value in the field and do nothing else. Methods like +this are called *getters*, and Rust does not implement them automatically for +struct fields as some other languages do. Getters are useful because you can +make the field private but the method public and thus enable read-only access +to that field as part of the type’s public API. We will be discussing what +public and private are and how to designate a field or method as public or +private in Chapter 7. > ### Where’s the `->` Operator? > @@ -810,9 +838,11 @@ Chapter 7. Let’s practice using methods by implementing a second method on the `Rectangle` struct. This time, we want an instance of `Rectangle` to take another instance of `Rectangle` and return `true` if the second `Rectangle` can fit completely -within `self`; otherwise it should return `false`. That is, we want to be able -to write the program shown in Listing 5-14, once we’ve defined the `can_hold` -method. +within `self` (the first `Rectangle`); + + +otherwise it should return `false`. That is, once we’ve defined the `can_hold` +method, we want to be able to write the program shown in Listing 5-14. Filename: src/main.rs @@ -889,7 +919,7 @@ All functions defined within an `impl` block are called *associated functions* because they’re associated with the type named after the `impl`. We can define associated functions that don’t have `self` as their first parameter (and thus are not methods) because they don’t need an instance of the type to work with. -We’ve already used one function like this, the `String::from` function, that’s +We’ve already used one function like this: the `String::from` function that’s defined on the `String` type. Associated functions that aren’t methods are often used for constructors that diff --git a/src/doc/book/nostarch/chapter06.md b/src/doc/book/nostarch/chapter06.md index 4256c74464..47ca417010 100644 --- a/src/doc/book/nostarch/chapter06.md +++ b/src/doc/book/nostarch/chapter06.md @@ -10,25 +10,35 @@ data. Next, we’ll explore a particularly useful enum, called `Option`, which expresses that a value can be either something or nothing. Then we’ll look at how pattern matching in the `match` expression makes it easy to run different code for different values of an enum. Finally, we’ll cover how the `if let` -construct is another convenient and concise idiom available to you to handle -enums in your code. +construct is another convenient and concise idiom available to handle enums in +your code. Enums are a feature in many languages, but their capabilities differ in each language. Rust’s enums are most similar to *algebraic data types* in functional languages, such as F#, OCaml, and Haskell. ## Defining an Enum - -Let’s look at a situation we might want to express in code and see why enums -are useful and more appropriate than structs in this case. Say we need to work -with IP addresses. Currently, two major standards are used for IP addresses: -version four and version six. These are the only possibilities for an IP -address that our program will come across: we can *enumerate* all possible -variants, which is where enumeration gets its name. + + +Enums are a way of defining custom data types in a different way than you do +with structs. Let’s look at a situation we might want to express in code and +see why enums are useful and more appropriate than structs in this case. Say we +need to work with IP addresses. Currently, two major standards are used for IP +addresses: version four and version six. Because these are the only +possibilities for an IP address that our program will come across, we can +*enumerate* all possible variants, which is where enumeration gets its name. Any IP address can be either a version four or a version six address, but not both at the same time. That property of IP addresses makes the enum data -structure appropriate, because enum values can only be one of its variants. +structure appropriate, because an enum value can only be one of its variants. Both version four and version six addresses are still fundamentally IP addresses, so they should be treated as the same type when the code is handling situations that apply to any kind of IP address. @@ -56,10 +66,9 @@ let six = IpAddrKind::V6; ``` Note that the variants of the enum are namespaced under its identifier, and we -use a double colon to separate the two. The reason this is useful is that now -both values `IpAddrKind::V4` and `IpAddrKind::V6` are of the same type: -`IpAddrKind`. We can then, for instance, define a function that takes any -`IpAddrKind`: +use a double colon to separate the two. This is useful because now both values +`IpAddrKind::V4` and `IpAddrKind::V6` are of the same type: `IpAddrKind`. We +can then, for instance, define a function that takes any `IpAddrKind`: ``` fn route(ip_kind: IpAddrKind) {} @@ -75,7 +84,8 @@ route(IpAddrKind::V6); Using enums has even more advantages. Thinking more about our IP address type, at the moment we don’t have a way to store the actual IP address *data*; we only know what *kind* it is. Given that you just learned about structs in -Chapter 5, you might tackle this problem as shown in Listing 6-1. +Chapter 5, you might be tempted to tackle this problem with structs as shown in +Listing 6-1. ``` enum IpAddrKind { @@ -104,15 +114,15 @@ Listing 6-1: Storing the data and `IpAddrKind` variant of an IP address using a Here, we’ve defined a struct `IpAddr` that has two fields: a `kind` field that is of type `IpAddrKind` (the enum we defined previously) and an `address` field -of type `String`. We have two instances of this struct. The first, `home`, has -the value `IpAddrKind::V4` as its `kind` with associated address data of -`127.0.0.1`. The second instance, `loopback`, has the other variant of -`IpAddrKind` as its `kind` value, `V6`, and has address `::1` associated with -it. We’ve used a struct to bundle the `kind` and `address` values together, so -now the variant is associated with the value. +of type `String`. We have two instances of this struct. The first is `home`, +and it has the value `IpAddrKind::V4` as its `kind` with associated address +data of `127.0.0.1`. The second instance is `loopback`. It has the other +variant of `IpAddrKind` as its `kind` value, `V6`, and has address `::1` +associated with it. We’ve used a struct to bundle the `kind` and `address` +values together, so now the variant is associated with the value. -We can represent the same concept in a more concise way using just an enum, -rather than an enum inside a struct, by putting data directly into each enum +However, representing the same concept using just an enum is more concise: +rather than an enum inside a struct, we can put data directly into each enum variant. This new definition of the `IpAddr` enum says that both `V4` and `V6` variants will have associated `String` values: @@ -253,15 +263,18 @@ useful: `Option`. ### The `Option` Enum and Its Advantages Over Null Values -In the previous section, we looked at how the `IpAddr` enum let us use Rust’s -type system to encode more information than just the data into our program. This section explores a case study of `Option`, which is another enum defined -by the standard library. The `Option` type is used in many places because it -encodes the very common scenario in which a value could be something or it -could be nothing. Expressing this concept in terms of the type system means the -compiler can check whether you’ve handled all the cases you should be handling; -this functionality can prevent bugs that are extremely common in other -programming languages. +by the standard library. The `Option` type encodes the very common scenario in +which a value could be something or it could be nothing. + +For example, if you request the first of a list containing items, you would get +a value. If you request the first item of an empty list, you would get nothing. +Expressing this concept in terms of the type system means the compiler can +check whether you’ve handled all the cases you should be handling; this +functionality can prevent bugs that are extremely common in other programming +languages. Programming language design is often thought of in terms of which features you include, but the features you exclude are important too. Rust doesn’t have the @@ -302,10 +315,10 @@ enum Option { ``` The `Option` enum is so useful that it’s even included in the prelude; you -don’t need to bring it into scope explicitly. In addition, so are its variants: -you can use `Some` and `None` directly without the `Option::` prefix. The -`Option` enum is still just a regular enum, and `Some(T)` and `None` are -still variants of type `Option`. +don’t need to bring it into scope explicitly. Its variants are also included in +the prelude: you can use `Some` and `None` directly without the `Option::` +prefix. The `Option` enum is still just a regular enum, and `Some(T)` and +`None` are still variants of type `Option`. The `` syntax is a feature of Rust we haven’t talked about yet. It’s a generic type parameter, and we’ll cover generics in more detail in Chapter 10. @@ -375,7 +388,7 @@ perform `T` operations with it. Generally, this helps catch one of the most common issues with null: assuming that something isn’t null when it actually is. -Not having to worry about incorrectly assuming a not-null value helps you to be +Eliminating the risk of incorrectly assuming a not-null value helps you to be more confident in your code. In order to have a value that can possibly be null, you must explicitly opt in by making the type of that value `Option`. Then, when you use that value, you are required to explicitly handle the case @@ -399,9 +412,9 @@ just this when used with enums: it will run different code depending on which variant of the enum it has, and that code can use the data inside the matching value. -## The `match` Control Flow Operator +## The `match` Control Flow Construct -Rust has an extremely powerful control flow operator called `match` that allows +Rust has an extremely powerful control flow construct called `match` that allows you to compare a value against a series of patterns and then execute code based on which pattern matches. Patterns can be made up of literal values, variable names, wildcards, and many other things; Chapter 18 covers all the different @@ -415,13 +428,15 @@ the first hole it encounters that it fits into. In the same way, values go through each pattern in a `match`, and at the first pattern the value “fits,” the value falls into the associated code block to be used during execution. -Because we just mentioned coins, let’s use them as an example using `match`! We -can write a function that can take an unknown United States coin and, in a -similar way as the counting machine, determine which coin it is and return its + + +Speaking of coins, let’s use them as an example using `match`! We +can write a function that takes an unknown United States coin and, in a +similar way as the counting machine, determines which coin it is and return its value in cents, as shown here in Listing 6-3. ``` -enum Coin { +[1]enum Coin { Penny, Nickel, Dime, @@ -445,8 +460,8 @@ Let’s break down the `match` in the `value_in_cents` function. First, we list the `match` keyword followed by an expression, which in this case is the value `coin`. This seems very similar to an expression used with `if`, but there’s a big difference: with `if`, the expression needs to return a Boolean value, but -here, it can be any type. The type of `coin` in this example is the `Coin` enum -that we defined on line 1. +here, it can return any type. The type of `coin` in this example is the `Coin` +enum that we defined at [1]. Next are the `match` arms. An arm has two parts: a pattern and some code. The first arm here has a pattern that is the value `Coin::Penny` and then the `=>` @@ -463,11 +478,11 @@ The code associated with each arm is an expression, and the resulting value of the expression in the matching arm is the value that gets returned for the entire `match` expression. -Curly brackets typically aren’t used if the match arm code is short, as it is +We don't typically use curly brackets if the match arm code is short, as it is in Listing 6-3 where each arm just returns a value. If you want to run multiple -lines of code in a match arm, you can use curly brackets. For example, the -following code would print “Lucky penny!” every time the method was called with -a `Coin::Penny` but would still return the last value of the block, `1`: +lines of code in a match arm, you must use curly brackets. For example, the +following code prints “Lucky penny!” every time the method is called with a +`Coin::Penny`, but still returns the last value of the block, `1`: ``` fn value_in_cents(coin: Coin) -> u8 { @@ -515,10 +530,10 @@ enum Coin { Listing 6-4: A `Coin` enum in which the `Quarter` variant also holds a `UsState` value -Let’s imagine that a friend of ours is trying to collect all 50 state quarters. -While we sort our loose change by coin type, we’ll also call out the name of -the state associated with each quarter so if it’s one our friend doesn’t have, -they can add it to their collection. +Let’s imagine that a friend is trying to collect all 50 state quarters. While +we sort our loose change by coin type, we’ll also call out the name of the +state associated with each quarter so if it’s one our friend doesn’t have, they +can add it to their collection. In the match expression for this code, we add a variable called `state` to the pattern that matches values of the variant `Coin::Quarter`. When a @@ -615,9 +630,11 @@ once you get used to it, you’ll wish you had it in all languages. It’s consistently a user favorite. ### Matches Are Exhaustive - -There’s one other aspect of `match` we need to discuss. Consider this version -of our `plus_one` function that has a bug and won’t compile: + + +There’s one other aspect of `match` we need to discuss: the arms’ patterns must +cover all possibilities. Consider this version of our `plus_one` function, +which has a bug and won’t compile: ``` fn plus_one(x: Option) -> Option { @@ -653,15 +670,15 @@ have null, thus making the billion-dollar mistake discussed earlier impossible. ### Catch-all Patterns and the `_` Placeholder -Let’s look at an example where we want to take special actions for a few -particular values, but for all other values take one default action. Imagine -we’re implementing a game where if you get a value of 3 on a dice roll, your -player doesn’t move, but instead gets a new fancy hat. If you roll a 7, your -player loses a fancy hat. For all other values, your player moves that number -of spaces on the game board. Here’s a `match` that implements that logic, with -the result of the dice roll hardcoded rather than a random value, and all other -logic represented by functions without bodies because actually implementing -them is out of scope for this example: +Using enums, we can also take special actions for a few particular values, but +for all other values take one default action. Imagine we’re implementing a game +where, if you roll a 3 on a dice roll, your player doesn’t move, but instead +gets a new fancy hat. If you roll a 7, your player loses a fancy hat. For all +other values, your player moves that number of spaces on the game board. Here’s +a `match` that implements that logic, with the result of the dice roll +hardcoded rather than a random value, and all other logic represented by +functions without bodies because actually implementing them is out of scope for +this example: ``` let dice_roll = 9; @@ -685,17 +702,17 @@ This code compiles, even though we haven’t listed all the possible values a `u8` can have, because the last pattern will match all values not specifically listed. This catch-all pattern meets the requirement that `match` must be exhaustive. Note that we have to put the catch-all arm last because the -patterns are evaluated in order. Rust will warn us if we add arms after a -catch-all because those later arms would never match! +patterns are evaluated in order. If we put the catch-all arm earlier, the other +arms would never run, so Rust will warn us if we add arms after a catch-all! -Rust also has a pattern we can use when we don’t want to use the value in the -catch-all pattern: `_`, which is a special pattern that matches any value and -does not bind to that value. This tells Rust we aren’t going to use the value, -so Rust won’t warn us about an unused variable. +Rust also has a pattern we can use when we want a catch-all but don’t want to +*use* the value in the catch-all pattern: `_` is a special pattern that matches +any value and does not bind to that value. This tells Rust we aren’t going to +use the value, so Rust won’t warn us about an unused variable. -Let’s change the rules of the game to be that if you roll anything other than -a 3 or a 7, you must roll again. We don’t need to use the value in that case, -so we can change our code to use `_` instead of the variable named `other`: +Let’s change the rules of the game: now, if you roll anything other than a 3 or +a 7, you must roll again. We no longer need to use the catch-all value, so we +can change our code to use `_` instead of the variable named `other`: ``` let dice_roll = 9; @@ -713,10 +730,10 @@ fn reroll() {} This example also meets the exhaustiveness requirement because we’re explicitly ignoring all other values in the last arm; we haven’t forgotten anything. -If we change the rules of the game one more time, so that nothing else happens -on your turn if you roll anything other than a 3 or a 7, we can express that by -using the unit value (the empty tuple type we mentioned in “The Tuple Type” -section) as the code that goes with the `_` arm: +Finally, we'll change the rules of the game one more time, so that nothing else +happens on your turn if you roll anything other than a 3 or a 7. We can express +that by using the unit value (the empty tuple type we mentioned in “The Tuple +Type” section) as the code that goes with the `_` arm: ``` let dice_roll = 9; @@ -756,11 +773,11 @@ match config_max { Listing 6-6: A `match` that only cares about executing code when the value is `Some` -If the value is `Some`, we want to print out the value in the `Some` variant, -which we do by binding the value to the variable `max` in the pattern. -We don’t want to do anything with the `None` value. To satisfy the `match` -expression, we have to add `_ => ()` after processing just one variant, which -is annoying boilerplate code to add. +If the value is `Some`, we print out the value in the `Some` variant by binding +the value to the variable `max` in the pattern. We don’t want to do anything +with the `None` value. To satisfy the `match` expression, we have to add `_ => +()` after processing just one variant, which is annoying boilerplate code to +add. Instead, we could write this in a shorter way using `if let`. The following code behaves the same as the `match` in Listing 6-6: diff --git a/src/doc/book/nostarch/chapter08.md b/src/doc/book/nostarch/chapter08.md index ed37b3c41e..89618120f6 100644 --- a/src/doc/book/nostarch/chapter08.md +++ b/src/doc/book/nostarch/chapter08.md @@ -222,7 +222,7 @@ programs from ending up in that situation. > Note: For more on the implementation details of the `Vec` type, see “The > Rustonomicon” at *https://doc.rust-lang.org/nomicon/vec/vec.html*. -### Iterating over the Values in a Vector +### Iterating Over the Values in a Vector If we want to access each element in a vector in turn, we can iterate through all of the elements rather than use indices to access one at a time. Listing diff --git a/src/doc/book/nostarch/chapter11.md b/src/doc/book/nostarch/chapter11.md new file mode 100644 index 0000000000..78a88cc827 --- /dev/null +++ b/src/doc/book/nostarch/chapter11.md @@ -0,0 +1,1499 @@ + +[TOC] + +# Writing Automated Tests + +In his 1972 essay “The Humble Programmer,” Edsger W. Dijkstra said that +“Program testing can be a very effective way to show the presence of bugs, but +it is hopelessly inadequate for showing their absence.” That doesn’t mean we +shouldn’t try to test as much as we can! + +Correctness in our programs is the extent to which our code does what we intend +it to do. Rust is designed with a high degree of concern about the correctness +of programs, but correctness is complex and not easy to prove. Rust’s type +system shoulders a huge part of this burden, but the type system cannot catch +every kind of incorrectness. As such, Rust includes support for writing +automated software tests within the language. + +As an example, say we write a function called `add_two` that adds 2 to whatever +number is passed to it. This function’s signature accepts an integer as a +parameter and returns an integer as a result. When we implement and compile +that function, Rust does all the type checking and borrow checking that you’ve +learned so far to ensure that, for instance, we aren’t passing a `String` value +or an invalid reference to this function. But Rust *can’t* check that this +function will do precisely what we intend, which is return the parameter plus 2 +rather than, say, the parameter plus 10 or the parameter minus 50! That’s where +tests come in. + +We can write tests that assert, for example, that when we pass `3` to the +`add_two` function, the returned value is `5`. We can run these tests whenever +we make changes to our code to make sure any existing correct behavior has not +changed. + +Testing is a complex skill: although we can’t cover every detail about how to +write good tests in one chapter, we’ll discuss the mechanics of Rust’s testing +facilities. We’ll talk about the annotations and macros available to you when +writing your tests, the default behavior and options provided for running your +tests, and how to organize tests into unit tests and integration tests. + +## How to Write Tests + +Tests are Rust functions that verify that the non-test code is functioning in +the expected manner. The bodies of test functions typically perform these three +actions: + +1. Set up any needed data or state. +2. Run the code you want to test. +3. Assert the results are what you expect. + +Let’s look at the features Rust provides specifically for writing tests that +take these actions, which include the `test` attribute, a few macros, and the +`should_panic` attribute. + +### The Anatomy of a Test Function + +At its simplest, a test in Rust is a function that’s annotated with the `test` +attribute. Attributes are metadata about pieces of Rust code; one example is +the `derive` attribute we used with structs in Chapter 5. To change a function +into a test function, add `#[test]` on the line before `fn`. When you run your +tests with the `cargo test` command, Rust builds a test runner binary that runs +the functions annotated with the `test` attribute and reports on whether each +test function passes or fails. + +When we make a new library project with Cargo, a test module with a test +function in it is automatically generated for us. This module helps you start +writing your tests so you don’t have to look up the exact structure and syntax +of test functions every time you start a new project. You can add as many +additional test functions and as many test modules as you want! + +We’ll explore some aspects of how tests work by experimenting with the template +test generated for us without actually testing any code. Then we’ll write some +real-world tests that call some code that we’ve written and assert that its +behavior is correct. + +Let’s create a new library project called `adder`: + +``` +$ cargo new adder --lib + Created library `adder` project +$ cd adder +``` + +The contents of the *src/lib.rs* file in your `adder` library should look like +Listing 11-1. + +Filename: src/lib.rs + +``` +#[cfg(test)] +mod tests { +[1] #[test] + fn it_works() { + [2] assert_eq!(2 + 2, 4); + } +} +``` + +Listing 11-1: The test module and function generated automatically by `cargo +new` + +For now, let’s ignore the top two lines and focus on the function to see how it +works. Note the `#[test]` annotation [1]: this attribute indicates this is a +test function, so the test runner knows to treat this function as a test. We +could also have non-test functions in the `tests` module to help set up common +scenarios or perform common operations, so we need to indicate which functions +are tests by using the `#[test]` attribute. + +The function body uses the `assert_eq!` macro [2] to assert that 2 + 2 equals +4. This assertion serves as an example of the format for a typical test. Let’s +run it to see that this test passes. + +The `cargo test` command runs all tests in our project, as shown in Listing +11-2. + +``` +$ cargo test + Compiling adder v0.1.0 (file:///projects/adder) + Finished test [unoptimized + debuginfo] target(s) in 0.57s + Running unittests (target/debug/deps/adder-92948b65e88960b4) + +[1] running 1 test +[2] test tests::it_works ... ok + +[3] test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s + +[4] Doc-tests adder + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s + +``` + +Listing 11-2: The output from running the automatically generated test + +Cargo compiled and ran the test. After the `Compiling`, `Finished`, and +`Running` lines is the line `running 1 test` [1]. The next line shows the name +of the generated test function, called `it_works`, and the result of running +that test, `ok` [2]. The overall summary of running the tests appears next. The +text `test result: ok.` [3] means that all the tests passed, and the portion +that reads `1 passed; 0 failed` totals the number of tests that passed or +failed. + +Because we don’t have any tests we’ve marked as ignored, the summary shows `0 +ignored`. We also haven’t filtered the tests being run, so the end of the +summary shows `0 filtered out`. We’ll talk about ignoring and filtering out +tests in the next section, “Controlling How Tests Are +Run.” + +The `0 measured` statistic is for benchmark tests that measure performance. +Benchmark tests are, as of this writing, only available in nightly Rust. See +the documentation about benchmark tests at +*https://doc.rust-lang.org/unstable-book/library-features/test.html* to learn +more. + +The next part of the test output, which starts with `Doc-tests adder` [4], is +for the results of any documentation tests. We don’t have any documentation +tests yet, but Rust can compile any code examples that appear in our API +documentation. This feature helps us keep our docs and our code in sync! We’ll +discuss how to write documentation tests in the “Documentation Comments as +Tests” section of Chapter 14. For now, we’ll ignore the `Doc-tests` output. + +Let’s change the name of our test to see how that changes the test output. +Change the `it_works` function to a different name, such as `exploration`, like +so: + +Filename: src/lib.rs + +``` +#[cfg(test)] +mod tests { + #[test] + fn exploration() { + assert_eq!(2 + 2, 4); + } +} +``` + +Then run `cargo test` again. The output now shows `exploration` instead of +`it_works`: + +``` +running 1 test +test tests::exploration ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; +``` + +Let’s add another test, but this time we’ll make a test that fails! Tests fail +when something in the test function panics. Each test is run in a new thread, +and when the main thread sees that a test thread has died, the test is marked +as failed. We talked about the simplest way to cause a panic in Chapter 9, +which is to call the `panic!` macro. Enter the new test, `another`, so your +*src/lib.rs* file looks like Listing 11-3. + +Filename: src/lib.rs + +``` +#[cfg(test)] +mod tests { + #[test] + fn exploration() { + assert_eq!(2 + 2, 4); + } + + #[test] + fn another() { + panic!("Make this test fail"); + } +} +``` + +Listing 11-3: Adding a second test that will fail because we call the `panic!` +macro + +Run the tests again using `cargo test`. The output should look like Listing +11-4, which shows that our `exploration` test passed and `another` failed. + +``` +running 2 tests +test tests::exploration ... ok +[1] test tests::another ... FAILED + +[2] failures: + +---- tests::another stdout ---- +thread 'main' panicked at 'Make this test fail', src/lib.rs:10:9 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace + +[3] failures: + tests::another + +[4] test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s + +error: test failed, to rerun pass '--lib' +``` + +Listing 11-4: Test results when one test passes and one test fails + +Instead of `ok`, the line `test tests::another` shows `FAILED` [1]. Two new +sections appear between the individual results and the summary: the first +section [2] displays the detailed reason for each test failure. In this case, +`another` failed because it `panicked at 'Make this test fail'`, which happened +on line 10 in the *src/lib.rs* file. The next section [3] lists just the names +of all the failing tests, which is useful when there are lots of tests and lots +of detailed failing test output. We can use the name of a failing test to run +just that test to more easily debug it; we’ll talk more about ways to run tests +in the “Controlling How Tests Are Run” section. + +The summary line displays at the end [4]: overall, our test result is `FAILED`. +We had one test pass and one test fail. + +Now that you’ve seen what the test results look like in different scenarios, +let’s look at some macros other than `panic!` that are useful in tests. + +### Checking Results with the `assert!` Macro + +The `assert!` macro, provided by the standard library, is useful when you want +to ensure that some condition in a test evaluates to `true`. We give the +`assert!` macro an argument that evaluates to a Boolean. If the value is +`true`, `assert!` does nothing and the test passes. If the value is `false`, +the `assert!` macro calls the `panic!` macro, which causes the test to fail. +Using the `assert!` macro helps us check that our code is functioning in the +way we intend. + +In Chapter 5, Listing 5-15, we used a `Rectangle` struct and a `can_hold` +method, which are repeated here in Listing 11-5. Let’s put this code in the +*src/lib.rs* file and write some tests for it using the `assert!` macro. + +Filename: src/lib.rs + +``` +#[derive(Debug)] +struct Rectangle { + width: u32, + height: u32, +} + +impl Rectangle { + fn can_hold(&self, other: &Rectangle) -> bool { + self.width > other.width && self.height > other.height + } +} +``` + +Listing 11-5: Using the `Rectangle` struct and its `can_hold` method from +Chapter 5 + +The `can_hold` method returns a Boolean, which means it’s a perfect use case +for the `assert!` macro. In Listing 11-6, we write a test that exercises the +`can_hold` method by creating a `Rectangle` instance that has a width of 8 and +a height of 7 and asserting that it can hold another `Rectangle` instance that +has a width of 5 and a height of 1. + +Filename: src/lib.rs + +``` +#[cfg(test)] +mod tests { +[1] use super::*; + + #[test] +[2] fn larger_can_hold_smaller() { + [3] let larger = Rectangle { + width: 8, + height: 7, + }; + let smaller = Rectangle { + width: 5, + height: 1, + }; + + [4] assert!(larger.can_hold(&smaller)); + } +} +``` + +Listing 11-6: A test for `can_hold` that checks whether a larger rectangle can +indeed hold a smaller rectangle + +Note that we’ve added a new line inside the `tests` module: `use super::*;` +[1]. The `tests` module is a regular module that follows the usual visibility +rules we covered in Chapter 7 in the “Paths for Referring to an Item in the +Module Tree” section. Because the `tests` module is an inner module, we need to +bring the code under test in the outer module into the scope of the inner +module. We use a glob here so anything we define in the outer module is +available to this `tests` module. + +We’ve named our test `larger_can_hold_smaller` [2], and we’ve created the two +`Rectangle` instances that we need [3]. Then we called the `assert!` macro and +passed it the result of calling `larger.can_hold(&smaller)` [4]. This +expression is supposed to return `true`, so our test should pass. Let’s find +out! + +``` +running 1 test +test tests::larger_can_hold_smaller ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s +``` + +It does pass! Let’s add another test, this time asserting that a smaller +rectangle cannot hold a larger rectangle: + +Filename: src/lib.rs + +``` +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn larger_can_hold_smaller() { + // --snip-- + } + + #[test] + fn smaller_cannot_hold_larger() { + let larger = Rectangle { + width: 8, + height: 7, + }; + let smaller = Rectangle { + width: 5, + height: 1, + }; + + assert!(!smaller.can_hold(&larger)); + } +} +``` + +Because the correct result of the `can_hold` function in this case is `false`, +we need to negate that result before we pass it to the `assert!` macro. As a +result, our test will pass if `can_hold` returns `false`: + +``` +running 2 tests +test tests::larger_can_hold_smaller ... ok +test tests::smaller_cannot_hold_larger ... ok + +test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s +``` + +Two tests that pass! Now let’s see what happens to our test results when we +introduce a bug in our code. Let’s change the implementation of the `can_hold` +method by replacing the greater than sign with a less than sign when it +compares the widths: + +``` +// --snip-- +impl Rectangle { + fn can_hold(&self, other: &Rectangle) -> bool { + self.width < other.width && self.height > other.height + } +} +``` + +Running the tests now produces the following: + +``` +running 2 tests +test tests::smaller_cannot_hold_larger ... ok +test tests::larger_can_hold_smaller ... FAILED + +failures: + +---- tests::larger_can_hold_smaller stdout ---- +thread 'main' panicked at 'assertion failed: larger.can_hold(&smaller)', src/lib.rs:28:9 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace + + +failures: + tests::larger_can_hold_smaller + +test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s +``` + +Our tests caught the bug! Because `larger.width` is 8 and `smaller.width` is +5, the comparison of the widths in `can_hold` now returns `false`: 8 is not +less than 5. + +### Testing Equality with the `assert_eq!` and `assert_ne!` Macros + +A common way to test functionality is to compare the result of the code under +test to the value you expect the code to return to make sure they’re equal. You +could do this using the `assert!` macro and passing it an expression using the +`==` operator. However, this is such a common test that the standard library +provides a pair of macros—`assert_eq!` and `assert_ne!`—to perform this test +more conveniently. These macros compare two arguments for equality or +inequality, respectively. They’ll also print the two values if the assertion +fails, which makes it easier to see *why* the test failed; conversely, the +`assert!` macro only indicates that it got a `false` value for the `==` +expression, not the values that led to the `false` value. + +In Listing 11-7, we write a function named `add_two` that adds `2` to its +parameter and returns the result. Then we test this function using the +`assert_eq!` macro. + +Filename: src/lib.rs + +``` +pub fn add_two(a: i32) -> i32 { + a + 2 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_adds_two() { + assert_eq!(4, add_two(2)); + } +} +``` + +Listing 11-7: Testing the function `add_two` using the `assert_eq!` macro + +Let’s check that it passes! + +``` +running 1 test +test tests::it_adds_two ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s +``` + +The first argument we gave to the `assert_eq!` macro, `4`, is equal to the +result of calling `add_two(2)`. The line for this test is `test +tests::it_adds_two ... ok`, and the `ok` text indicates that our test passed! + +Let’s introduce a bug into our code to see what it looks like when a test that +uses `assert_eq!` fails. Change the implementation of the `add_two` function to +instead add `3`: + +``` +pub fn add_two(a: i32) -> i32 { + a + 3 +} +``` + +Run the tests again: + +``` +running 1 test +test tests::it_adds_two ... FAILED + +failures: + +---- tests::it_adds_two stdout ---- +[1] thread 'main' panicked at 'assertion failed: `(left == right)` +[2] left: `4`, +[3] right: `5`', src/lib.rs:11:9 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace + +failures: + tests::it_adds_two + +test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s +``` + +Our test caught the bug! The `it_adds_two` test failed, displaying the message +`` assertion failed: `(left == right)` `` [1] and showing that `left` was `4` +[2] and `right` was `5` [3]. This message is useful and helps us start +debugging: it means the `left` argument to `assert_eq!` was `4` but the `right` +argument, where we had `add_two(2)`, was `5`. + +Note that in some languages and test frameworks, the parameters to the +functions that assert two values are equal are called `expected` and `actual`, +and the order in which we specify the arguments matters. However, in Rust, +they’re called `left` and `right`, and the order in which we specify the value +we expect and the value that the code under test produces doesn’t matter. We +could write the assertion in this test as `assert_eq!(add_two(2), 4)`, which +would result in a failure message that displays `` assertion failed: `(left == +right)` `` and that `left` was `5` and `right` was `4`. + +The `assert_ne!` macro will pass if the two values we give it are not equal and +fail if they’re equal. This macro is most useful for cases when we’re not sure +what a value *will* be, but we know what the value definitely *won’t* be if our +code is functioning as we intend. For example, if we’re testing a function that +is guaranteed to change its input in some way, but the way in which the input +is changed depends on the day of the week that we run our tests, the best thing +to assert might be that the output of the function is not equal to the input. + +Under the surface, the `assert_eq!` and `assert_ne!` macros use the operators +`==` and `!=`, respectively. When the assertions fail, these macros print their +arguments using debug formatting, which means the values being compared must +implement the `PartialEq` and `Debug` traits. All the primitive types and most +of the standard library types implement these traits. For structs and enums +that you define, you’ll need to implement `PartialEq` to assert that values of +those types are equal or not equal. You’ll need to implement `Debug` to print +the values when the assertion fails. Because both traits are derivable traits, +as mentioned in Listing 5-12 in Chapter 5, this is usually as straightforward +as adding the `#[derive(PartialEq, Debug)]` annotation to your struct or enum +definition. See Appendix C, “Derivable Traits,” for more details about these +and other derivable traits. + +### Adding Custom Failure Messages + +You can also add a custom message to be printed with the failure message as +optional arguments to the `assert!`, `assert_eq!`, and `assert_ne!` macros. Any +arguments specified after the one required argument to `assert!` or the two +required arguments to `assert_eq!` and `assert_ne!` are passed along to the +`format!` macro (discussed in Chapter 8 in the “Concatenation with the `+` +Operator or the `format!` Macro” section), so you can pass a format string that +contains `{}` placeholders and values to go in those placeholders. Custom +messages are useful to document what an assertion means; when a test fails, +you’ll have a better idea of what the problem is with the code. + +For example, let’s say we have a function that greets people by name and we +want to test that the name we pass into the function appears in the output: + +Filename: src/lib.rs + +``` +pub fn greeting(name: &str) -> String { + format!("Hello {}!", name) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn greeting_contains_name() { + let result = greeting("Carol"); + assert!(result.contains("Carol")); + } +} +``` + +The requirements for this program haven’t been agreed upon yet, and we’re +pretty sure the `Hello` text at the beginning of the greeting will change. We +decided we don’t want to have to update the test when the requirements change, +so instead of checking for exact equality to the value returned from the +`greeting` function, we’ll just assert that the output contains the text of the +input parameter. + +Let’s introduce a bug into this code by changing `greeting` to not include +`name` to see what this test failure looks like: + +``` +pub fn greeting(name: &str) -> String { + String::from("Hello!") +} +``` + +Running this test produces the following: + +``` +running 1 test +test tests::greeting_contains_name ... FAILED + +failures: + +---- tests::greeting_contains_name stdout ---- +thread 'main' panicked at 'assertion failed: result.contains(\"Carol\")', src/lib.rs:12:9 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace + + +failures: + tests::greeting_contains_name +``` + +This result just indicates that the assertion failed and which line the +assertion is on. A more useful failure message in this case would print the +value we got from the `greeting` function. Let’s change the test function, +giving it a custom failure message made from a format string with a placeholder +filled in with the actual value we got from the `greeting` function: + +``` +#[test] +fn greeting_contains_name() { + let result = greeting("Carol"); + assert!( + result.contains("Carol"), + "Greeting did not contain name, value was `{}`", + result + ); +} +``` + +Now when we run the test, we’ll get a more informative error message: + +``` +---- tests::greeting_contains_name stdout ---- +thread 'main' panicked at 'Greeting did not contain name, value was `Hello!`', src/lib.rs:12:9 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +``` + +We can see the value we actually got in the test output, which would help us +debug what happened instead of what we were expecting to happen. + +### Checking for Panics with `should_panic` + +In addition to checking that our code returns the correct values we expect, +it’s also important to check that our code handles error conditions as we +expect. For example, consider the `Guess` type that we created in Chapter 9, +Listing 9-13. Other code that uses `Guess` depends on the guarantee that `Guess` +instances will contain only values between 1 and 100. We can write a test that +ensures that attempting to create a `Guess` instance with a value outside that +range panics. + +We do this by adding another attribute, `should_panic`, to our test function. +This attribute makes a test pass if the code inside the function panics; the +test will fail if the code inside the function doesn’t panic. + +Listing 11-8 shows a test that checks that the error conditions of `Guess::new` +happen when we expect them to. + +Filename: src/lib.rs + +``` +pub struct Guess { + value: i32, +} + +impl Guess { + pub fn new(value: i32) -> Guess { + if value < 1 || value > 100 { + panic!("Guess value must be between 1 and 100, got {}.", value); + } + + Guess { value } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[should_panic] + fn greater_than_100() { + Guess::new(200); + } +} +``` + +Listing 11-8: Testing that a condition will cause a `panic!` + +We place the `#[should_panic]` attribute after the `#[test]` attribute and +before the test function it applies to. Let’s look at the result when this test +passes: + +``` +running 1 test +test tests::greater_than_100 - should panic ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s +``` + +Looks good! Now let’s introduce a bug in our code by removing the condition +that the `new` function will panic if the value is greater than 100: + +``` +// --snip-- +impl Guess { + pub fn new(value: i32) -> Guess { + if value < 1 { + panic!("Guess value must be between 1 and 100, got {}.", value); + } + + Guess { value } + } +} +``` + +When we run the test in Listing 11-8, it will fail: + +``` +running 1 test +test tests::greater_than_100 - should panic ... FAILED + +failures: + +---- tests::greater_than_100 stdout ---- +note: test did not panic as expected + +failures: + tests::greater_than_100 + +test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s +``` + +We don’t get a very helpful message in this case, but when we look at the test +function, we see that it’s annotated with `#[should_panic]`. The failure we got +means that the code in the test function did not cause a panic. + +Tests that use `should_panic` can be imprecise because they only indicate that +the code has caused some panic. A `should_panic` test would pass even if the +test panics for a different reason from the one we were expecting to happen. To +make `should_panic` tests more precise, we can add an optional `expected` +parameter to the `should_panic` attribute. The test harness will make sure that +the failure message contains the provided text. For example, consider the +modified code for `Guess` in Listing 11-9 where the `new` function panics with +different messages depending on whether the value is too small or too large. + +Filename: src/lib.rs + +``` +// --snip-- + +impl Guess { + pub fn new(value: i32) -> Guess { + if value < 1 { + panic!( + "Guess value must be greater than or equal to 1, got {}.", + value + ); + } else if value > 100 { + panic!( + "Guess value must be less than or equal to 100, got {}.", + value + ); + } + + Guess { value } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[should_panic(expected = "Guess value must be less than or equal to 100")] + fn greater_than_100() { + Guess::new(200); + } +} +``` + +Listing 11-9: Testing that a condition will cause a `panic!` with a particular +panic message + +This test will pass because the value we put in the `should_panic` attribute’s +`expected` parameter is a substring of the message that the `Guess::new` +function panics with. We could have specified the entire panic message that we +expect, which in this case would be `Guess value must be less than or equal to +100, got 200.` What you choose to specify in the expected parameter for +`should_panic` depends on how much of the panic message is unique or dynamic +and how precise you want your test to be. In this case, a substring of the +panic message is enough to ensure that the code in the test function executes +the `else if value > 100` case. + +To see what happens when a `should_panic` test with an `expected` message +fails, let’s again introduce a bug into our code by swapping the bodies of the +`if value < 1` and the `else if value > 100` blocks: + +``` +if value < 1 { + panic!("Guess value must be less than or equal to 100, got {}.", value); +} else if value > 100 { + panic!("Guess value must be greater than or equal to 1, got {}.", value); +} +``` + +This time when we run the `should_panic` test, it will fail: + +``` +running 1 test +test tests::greater_than_100 - should panic ... FAILED + +failures: + +---- tests::greater_than_100 stdout ---- +thread 'main' panicked at 'Guess value must be greater than or equal to 1, got 200.', src/lib.rs:13:13 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +note: panic did not contain expected string + panic message: `"Guess value must be greater than or equal to 1, got 200."`, + expected substring: `"Guess value must be less than or equal to 100"` + +failures: + tests::greater_than_100 + +test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s +``` + +The failure message indicates that this test did indeed panic as we expected, +but the panic message did not include the expected string `'Guess value must be +less than or equal to 100'`. The panic message that we did get in this case was +`Guess value must be greater than or equal to 1, got 200.` Now we can start +figuring out where our bug is! + +### Using `Result` in Tests + +So far, we’ve written tests that panic when they fail. We can also write tests +that use `Result`! Here’s the test from Listing 11-1, rewritten to use +`Result` and return an `Err` instead of panicking: + +``` +#[cfg(test)] +mod tests { + #[test] + fn it_works() -> Result<(), String> { + if 2 + 2 == 4 { + Ok(()) + } else { + Err(String::from("two plus two does not equal four")) + } + } +} +``` + +The `it_works` function now has a return type, `Result<(), String>`. In the +body of the function, rather than calling the `assert_eq!` macro, we return +`Ok(())` when the test passes and an `Err` with a `String` inside when the test +fails. + +Writing tests so they return a `Result` enables you to use the question +mark operator in the body of tests, which can be a convenient way to write +tests that should fail if any operation within them returns an `Err` variant. + +You can’t use the `#[should_panic]` annotation on tests that use `Result`. To assert that an operation returns an `Err` variant, *don’t* use the +question mark operator on the `Result` value. Instead, use +`assert!(value.is_err())`. + +Now that you know several ways to write tests, let’s look at what is happening +when we run our tests and explore the different options we can use with `cargo +test`. + +## Controlling How Tests Are Run + +Just as `cargo run` compiles your code and then runs the resulting binary, +`cargo test` compiles your code in test mode and runs the resulting test +binary. You can specify command line options to change the default behavior of +`cargo test`. For example, the default behavior of the binary produced by +`cargo test` is to run all the tests in parallel and capture output generated +during test runs, preventing the output from being displayed and making it +easier to read the output related to the test results. + +Some command line options go to `cargo test`, and some go to the resulting test +binary. To separate these two types of arguments, you list the arguments that +go to `cargo test` followed by the separator `--` and then the ones that go to +the test binary. Running `cargo test --help` displays the options you can use +with `cargo test`, and running `cargo test -- --help` displays the options you +can use after the separator `--`. + +### Running Tests in Parallel or Consecutively + +When you run multiple tests, by default they run in parallel using threads. +This means the tests will finish running faster so you can get feedback quicker +on whether or not your code is working. Because the tests are running at the +same time, make sure your tests don’t depend on each other or on any shared +state, including a shared environment, such as the current working directory or +environment variables. + +For example, say each of your tests runs some code that creates a file on disk +named *test-output.txt* and writes some data to that file. Then each test reads +the data in that file and asserts that the file contains a particular value, +which is different in each test. Because the tests run at the same time, one +test might overwrite the file between when another test writes and reads the +file. The second test will then fail, not because the code is incorrect but +because the tests have interfered with each other while running in parallel. +One solution is to make sure each test writes to a different file; another +solution is to run the tests one at a time. + +If you don’t want to run the tests in parallel or if you want more fine-grained +control over the number of threads used, you can send the `--test-threads` flag +and the number of threads you want to use to the test binary. Take a look at +the following example: + +``` +$ cargo test -- --test-threads=1 +``` + +We set the number of test threads to `1`, telling the program not to use any +parallelism. Running the tests using one thread will take longer than running +them in parallel, but the tests won’t interfere with each other if they share +state. + +### Showing Function Output + +By default, if a test passes, Rust’s test library captures anything printed to +standard output. For example, if we call `println!` in a test and the test +passes, we won’t see the `println!` output in the terminal; we’ll see only the +line that indicates the test passed. If a test fails, we’ll see whatever was +printed to standard output with the rest of the failure message. + +As an example, Listing 11-10 has a silly function that prints the value of its +parameter and returns 10, as well as a test that passes and a test that fails. + +Filename: src/lib.rs + +``` +fn prints_and_returns_10(a: i32) -> i32 { + println!("I got the value {}", a); + 10 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn this_test_will_pass() { + let value = prints_and_returns_10(4); + assert_eq!(10, value); + } + + #[test] + fn this_test_will_fail() { + let value = prints_and_returns_10(8); + assert_eq!(5, value); + } +} +``` + +Listing 11-10: Tests for a function that calls `println!` + +When we run these tests with `cargo test`, we’ll see the following output: + +``` +running 2 tests +test tests::this_test_will_pass ... ok +test tests::this_test_will_fail ... FAILED + +failures: + +---- tests::this_test_will_fail stdout ---- +[1] I got the value 8 +thread 'main' panicked at 'assertion failed: `(left == right)` + left: `5`, + right: `10`', src/lib.rs:19:9 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace + +failures: + tests::this_test_will_fail + +test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s +``` + +Note that nowhere in this output do we see `I got the value 4`, which is what +is printed when the test that passes runs. That output has been captured. The +output from the test that failed, `I got the value 8` [1], appears in the +section of the test summary output, which also shows the cause of the test +failure. + +If we want to see printed values for passing tests as well, we can tell Rust +to also show the output of successful tests at the end with `--show-output`. + +``` +$ cargo test -- --show-output +``` + +When we run the tests in Listing 11-10 again with the `--show-output` flag, we +see the following output: + +``` +running 2 tests +test tests::this_test_will_pass ... ok +test tests::this_test_will_fail ... FAILED + +successes: + +---- tests::this_test_will_pass stdout ---- +I got the value 4 + + +successes: + tests::this_test_will_pass + +failures: + +---- tests::this_test_will_fail stdout ---- +I got the value 8 +thread 'main' panicked at 'assertion failed: `(left == right)` + left: `5`, + right: `10`', src/lib.rs:19:9 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace + +failures: + tests::this_test_will_fail + +test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s +``` + +### Running a Subset of Tests by Name + +Sometimes, running a full test suite can take a long time. If you’re working on +code in a particular area, you might want to run only the tests pertaining to +that code. You can choose which tests to run by passing `cargo test` the name +or names of the test(s) you want to run as an argument. + +To demonstrate how to run a subset of tests, we’ll create three tests for our +`add_two` function, as shown in Listing 11-11, and choose which ones to run. + +Filename: src/lib.rs + +``` +pub fn add_two(a: i32) -> i32 { + a + 2 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn add_two_and_two() { + assert_eq!(4, add_two(2)); + } + + #[test] + fn add_three_and_two() { + assert_eq!(5, add_two(3)); + } + + #[test] + fn one_hundred() { + assert_eq!(102, add_two(100)); + } +} +``` + +Listing 11-11: Three tests with three different names + +If we run the tests without passing any arguments, as we saw earlier, all the +tests will run in parallel: + +``` +running 3 tests +test tests::add_three_and_two ... ok +test tests::add_two_and_two ... ok +test tests::one_hundred ... ok + +test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s +``` + +#### Running Single Tests + +We can pass the name of any test function to `cargo test` to run only that test: + +``` +$ cargo test one_hundred + Compiling adder v0.1.0 (file:///projects/adder) + Finished test [unoptimized + debuginfo] target(s) in 0.69s + Running unittests (target/debug/deps/adder-92948b65e88960b4) + +running 1 test +test tests::one_hundred ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 2 filtered out; finished in 0.00s +``` + +Only the test with the name `one_hundred` ran; the other two tests didn’t match +that name. The test output lets us know we had more tests than what this +command ran by displaying `2 filtered out` at the end of the summary line. + +We can’t specify the names of multiple tests in this way; only the first value +given to `cargo test` will be used. But there is a way to run multiple tests. + +#### Filtering to Run Multiple Tests + +We can specify part of a test name, and any test whose name matches that value +will be run. For example, because two of our tests’ names contain `add`, we can +run those two by running `cargo test add`: + +``` +$ cargo test add + Compiling adder v0.1.0 (file:///projects/adder) + Finished test [unoptimized + debuginfo] target(s) in 0.61s + Running unittests (target/debug/deps/adder-92948b65e88960b4) + +running 2 tests +test tests::add_three_and_two ... ok +test tests::add_two_and_two ... ok + +test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out; finished in 0.00s +``` + +This command ran all tests with `add` in the name and filtered out the test +named `one_hundred`. Also note that the module in which a test appears becomes +part of the test’s name, so we can run all the tests in a module by filtering +on the module’s name. + +### Ignoring Some Tests Unless Specifically Requested + +Sometimes a few specific tests can be very time-consuming to execute, so you +might want to exclude them during most runs of `cargo test`. Rather than +listing as arguments all tests you do want to run, you can instead annotate the +time-consuming tests using the `ignore` attribute to exclude them, as shown +here: + +Filename: src/lib.rs + +``` +#[test] +fn it_works() { + assert_eq!(2 + 2, 4); +} + +#[test] +#[ignore] +fn expensive_test() { + // code that takes an hour to run +} +``` + +After `#[test]` we add the `#[ignore]` line to the test we want to exclude. Now +when we run our tests, `it_works` runs, but `expensive_test` doesn’t: + +``` +$ cargo test + Compiling adder v0.1.0 (file:///projects/adder) + Finished test [unoptimized + debuginfo] target(s) in 0.60s + Running unittests (target/debug/deps/adder-92948b65e88960b4) + +running 2 tests +test expensive_test ... ignored +test it_works ... ok + +test result: ok. 1 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 0.00s +``` + +The `expensive_test` function is listed as `ignored`. If we want to run only +the ignored tests, we can use `cargo test -- --ignored`: + +``` +$ cargo test -- --ignored + Finished test [unoptimized + debuginfo] target(s) in 0.61s + Running unittests (target/debug/deps/adder-92948b65e88960b4) + +running 1 test +test expensive_test ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out; finished in 0.00s +``` + +By controlling which tests run, you can make sure your `cargo test` results +will be fast. When you’re at a point where it makes sense to check the results +of the `ignored` tests and you have time to wait for the results, you can run +`cargo test -- --ignored` instead. If you want to run all tests whether they’re +ignored or not, you can run `cargo test -- --include-ignored`. + +## Test Organization + +As mentioned at the start of the chapter, testing is a complex discipline, and +different people use different terminology and organization. The Rust community +thinks about tests in terms of two main categories: *unit tests* and +*integration tests*. Unit tests are small and more focused, testing one module +in isolation at a time, and can test private interfaces. Integration tests are +entirely external to your library and use your code in the same way any other +external code would, using only the public interface and potentially exercising +multiple modules per test. + +Writing both kinds of tests is important to ensure that the pieces of your +library are doing what you expect them to, separately and together. + +### Unit Tests + +The purpose of unit tests is to test each unit of code in isolation from the +rest of the code to quickly pinpoint where code is and isn’t working as +expected. You’ll put unit tests in the *src* directory in each file with the +code that they’re testing. The convention is to create a module named `tests` +in each file to contain the test functions and to annotate the module with +`cfg(test)`. + +#### The Tests Module and `#[cfg(test)]` + +The `#[cfg(test)]` annotation on the tests module tells Rust to compile and run +the test code only when you run `cargo test`, not when you run `cargo build`. +This saves compile time when you only want to build the library and saves space +in the resulting compiled artifact because the tests are not included. You’ll +see that because integration tests go in a different directory, they don’t need +the `#[cfg(test)]` annotation. However, because unit tests go in the same files +as the code, you’ll use `#[cfg(test)]` to specify that they shouldn’t be +included in the compiled result. + +Recall that when we generated the new `adder` project in the first section of +this chapter, Cargo generated this code for us: + +Filename: src/lib.rs + +``` +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } +} +``` + +This code is the automatically generated test module. The attribute `cfg` +stands for *configuration* and tells Rust that the following item should only +be included given a certain configuration option. In this case, the +configuration option is `test`, which is provided by Rust for compiling and +running tests. By using the `cfg` attribute, Cargo compiles our test code only +if we actively run the tests with `cargo test`. This includes any helper +functions that might be within this module, in addition to the functions +annotated with `#[test]`. + +#### Testing Private Functions + +There’s debate within the testing community about whether or not private +functions should be tested directly, and other languages make it difficult or +impossible to test private functions. Regardless of which testing ideology you +adhere to, Rust’s privacy rules do allow you to test private functions. +Consider the code in Listing 11-12 with the private function `internal_adder`. + +Filename: src/lib.rs + +``` +pub fn add_two(a: i32) -> i32 { + internal_adder(a, 2) +} + +fn internal_adder(a: i32, b: i32) -> i32 { + a + b +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn internal() { + assert_eq!(4, internal_adder(2, 2)); + } +} +``` + +Listing 11-12: Testing a private function + +Note that the `internal_adder` function is not marked as `pub`. Tests are just +Rust code, and the `tests` module is just another module. As we discussed in +the “Paths for Referring to an Item in the Module Tree” section, items in child +modules can use the items in their ancestor modules. In this test, we bring all +of the `test` module’s parent’s items into scope with `use super::*`, and then +the test can call `internal_adder`. If you don’t think private functions should +be tested, there’s nothing in Rust that will compel you to do so. + +### Integration Tests + +In Rust, integration tests are entirely external to your library. They use your +library in the same way any other code would, which means they can only call +functions that are part of your library’s public API. Their purpose is to test +whether many parts of your library work together correctly. Units of code that +work correctly on their own could have problems when integrated, so test +coverage of the integrated code is important as well. To create integration +tests, you first need a *tests* directory. + +#### The *tests* Directory + +We create a *tests* directory at the top level of our project directory, next +to *src*. Cargo knows to look for integration test files in this directory. We +can then make as many test files as we want to in this directory, and Cargo +will compile each of the files as an individual crate. + +Let’s create an integration test. With the code in Listing 11-12 still in the +*src/lib.rs* file, make a *tests* directory, create a new file named +*tests/integration_test.rs*, and enter the code in Listing 11-13. + +Filename: tests/integration_test.rs + +``` +use adder; + +#[test] +fn it_adds_two() { + assert_eq!(4, adder::add_two(2)); +} +``` + +Listing 11-13: An integration test of a function in the `adder` crate + +We’ve added `use adder` at the top of the code, which we didn’t need in the +unit tests. The reason is that each file in the `tests` directory is a separate +crate, so we need to bring our library into each test crate’s scope. + +We don’t need to annotate any code in *tests/integration_test.rs* with +`#[cfg(test)]`. Cargo treats the `tests` directory specially and compiles files +in this directory only when we run `cargo test`. Run `cargo test` now: + +``` +$ cargo test + Compiling adder v0.1.0 (file:///projects/adder) + Finished test [unoptimized + debuginfo] target(s) in 1.31s + Running unittests (target/debug/deps/adder-1082c4b063a8fbe6) + +[1] running 1 test +test tests::internal ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s + + [2] Running tests/integration_test.rs (target/debug/deps/integration_test-1082c4b063a8fbe6) + +running 1 test +[3] test it_adds_two ... ok + +[4] test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s + + Doc-tests adder + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s +``` + +The three sections of output include the unit tests, the integration test, and +the doc tests. The first section for the unit tests [1] is the same as we’ve +been seeing: one line for each unit test (one named `internal` that we added in +Listing 11-12) and then a summary line for the unit tests. + +The integration tests section starts with the line `Running +tests/integration_test.rs` [2]. Next, there is a line for each test function in +that integration test [3] and a summary line for the results of the integration +test [4] just before the `Doc-tests adder` section starts. + +Similarly to how adding more unit test functions adds more result lines to the +unit tests section, adding more test functions to the integration test file +adds more result lines to this integration test file’s section. Each +integration test file has its own section, so if we add more files in the +*tests* directory, there will be more integration test sections. + +We can still run a particular integration test function by specifying the test +function’s name as an argument to `cargo test`. To run all the tests in a +particular integration test file, use the `--test` argument of `cargo test` +followed by the name of the file: + +``` +$ cargo test --test integration_test + Finished test [unoptimized + debuginfo] target(s) in 0.64s + Running tests/integration_test.rs (target/debug/deps/integration_test-82e7799c1bc62298) + +running 1 test +test it_adds_two ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s +``` + +This command runs only the tests in the *tests/integration_test.rs* file. + +#### Submodules in Integration Tests + +As you add more integration tests, you might want to make more than one file in +the *tests* directory to help organize them; for example, you can group the +test functions by the functionality they’re testing. As mentioned earlier, each +file in the *tests* directory is compiled as its own separate crate. + +Treating each integration test file as its own crate is useful to create +separate scopes that are more like the way end users will be using your crate. +However, this means files in the *tests* directory don’t share the same +behavior as files in *src* do, as you learned in Chapter 7 regarding how to +separate code into modules and files. + +The different behavior of files in the *tests* directory is most noticeable +when you have a set of helper functions that would be useful in multiple +integration test files and you try to follow the steps in the “Separating +Modules into Different Files” section of Chapter 7 to extract them into a +common module. For example, if we create *tests/common.rs* and place a function +named `setup` in it, we can add some code to `setup` that we want to call from +multiple test functions in multiple test files: + +Filename: tests/common.rs + +``` +pub fn setup() { + // setup code specific to your library's tests would go here +} +``` + +When we run the tests again, we’ll see a new section in the test output for the +*common.rs* file, even though this file doesn’t contain any test functions nor +did we call the `setup` function from anywhere: + +``` +running 1 test +test tests::internal ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s + + Running tests/common.rs (target/debug/deps/common-92948b65e88960b4) + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s + + Running tests/integration_test.rs (target/debug/deps/integration_test-92948b65e88960b4) + +running 1 test +test it_adds_two ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s + + Doc-tests adder + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s +``` + +Having `common` appear in the test results with `running 0 tests` displayed for +it is not what we wanted. We just wanted to share some code with the other +integration test files. + +To avoid having `common` appear in the test output, instead of creating +*tests/common.rs*, we’ll create *tests/common/mod.rs*. This is an alternate +naming convention that Rust also understands. Naming the file this way tells +Rust not to treat the `common` module as an integration test file. When we move +the `setup` function code into *tests/common/mod.rs* and delete the +*tests/common.rs* file, the section in the test output will no longer appear. +Files in subdirectories of the *tests* directory don’t get compiled as separate +crates or have sections in the test output. + +After we’ve created *tests/common/mod.rs*, we can use it from any of the +integration test files as a module. Here’s an example of calling the `setup` +function from the `it_adds_two` test in *tests/integration_test.rs*: + +Filename: tests/integration_test.rs + +``` +use adder; + +mod common; + +#[test] +fn it_adds_two() { + common::setup(); + assert_eq!(4, adder::add_two(2)); +} +``` + +Note that the `mod common;` declaration is the same as the module declaration +we demonstrated in Listing 7-21. Then in the test function, we can call the +`common::setup()` function. + +#### Integration Tests for Binary Crates + +If our project is a binary crate that only contains a *src/main.rs* file and +doesn’t have a *src/lib.rs* file, we can’t create integration tests in the +*tests* directory and bring functions defined in the *src/main.rs* file into +scope with a `use` statement. Only library crates expose functions that other +crates can use; binary crates are meant to be run on their own. + +This is one of the reasons Rust projects that provide a binary have a +straightforward *src/main.rs* file that calls logic that lives in the +*src/lib.rs* file. Using that structure, integration tests *can* test the +library crate with `use` to make the important functionality available. +If the important functionality works, the small amount of code in the +*src/main.rs* file will work as well, and that small amount of code doesn’t +need to be tested. + +## Summary + +Rust’s testing features provide a way to specify how code should function to +ensure it continues to work as you expect, even as you make changes. Unit tests +exercise different parts of a library separately and can test private +implementation details. Integration tests check that many parts of the library +work together correctly, and they use the library’s public API to test the code +in the same way external code will use it. Even though Rust’s type system and +ownership rules help prevent some kinds of bugs, tests are still important to +reduce logic bugs having to do with how your code is expected to behave. + +Let’s combine the knowledge you learned in this chapter and in previous +chapters to work on a project! diff --git a/src/doc/book/nostarch/chapter12.md b/src/doc/book/nostarch/chapter12.md new file mode 100644 index 0000000000..49d58039d5 --- /dev/null +++ b/src/doc/book/nostarch/chapter12.md @@ -0,0 +1,1672 @@ + +[TOC] + +# An I/O Project: Building a Command Line Program + +This chapter is a recap of the many skills you’ve learned so far and an +exploration of a few more standard library features. We’ll build a command line +tool that interacts with file and command line input/output to practice some of +the Rust concepts you now have under your belt. + +Rust’s speed, safety, single binary output, and cross-platform support make it +an ideal language for creating command line tools, so for our project, we’ll +make our own version of the classic command line tool `grep` (**g**lobally +search a **r**egular **e**xpression and **p**rint). In the simplest use case, +`grep` searches a specified file for a specified string. To do so, `grep` takes +as its arguments a filename and a string. Then it reads the file, finds lines +in that file that contain the string argument, and prints those lines. + +Along the way, we’ll show how to make our command line tool use features of the +terminal that many command line tools use. We’ll read the value of an +environment variable to allow the user to configure the behavior of our tool. +We’ll also print error messages to the standard error console stream (`stderr`) +instead of standard output (`stdout`), so, for example, the user can redirect +successful output to a file while still seeing error messages onscreen. + +One Rust community member, Andrew Gallant, has already created a fully +featured, very fast version of `grep`, called `ripgrep`. By comparison, our +version of `grep` will be fairly simple, but this chapter will give you some of +the background knowledge you need to understand a real-world project such as +`ripgrep`. + +Our `grep` project will combine a number of concepts you’ve learned so far: + +* Organizing code (using what you learned about modules in Chapter 7) +* Using vectors and strings (collections, Chapter 8) +* Handling errors (Chapter 9) +* Using traits and lifetimes where appropriate (Chapter 10) +* Writing tests (Chapter 11) + +We’ll also briefly introduce closures, iterators, and trait objects, which +Chapters 13 and 17 will cover in detail. + +## Accepting Command Line Arguments + +Let’s create a new project with, as always, `cargo new`. We’ll call our project +`minigrep` to distinguish it from the `grep` tool that you might already have +on your system. + +``` +$ cargo new minigrep + Created binary (application) `minigrep` project +$ cd minigrep +``` + +The first task is to make `minigrep` accept its two command line arguments: the +filename and a string to search for. That is, we want to be able to run our +program with `cargo run`, a string to search for, and a path to a file to +search in, like so: + +``` +$ cargo run searchstring example-filename.txt +``` + +Right now, the program generated by `cargo new` cannot process arguments we +give it. Some existing libraries on *https://crates.io/* can help with writing +a program that accepts command line arguments, but because you’re just learning +this concept, let’s implement this capability ourselves. + +### Reading the Argument Values + +To enable `minigrep` to read the values of command line arguments we pass to +it, we’ll need a function provided in Rust’s standard library, which is +`std::env::args`. This function returns an iterator of the command line +arguments that were given to `minigrep`. We’ll cover iterators fully in Chapter +13. For now, you only need to know two details about iterators: iterators +produce a series of values, and we can call the `collect` method on an iterator +to turn it into a collection, such as a vector, containing all the elements the +iterator produces. + +Use the code in Listing 12-1 to allow your `minigrep` program to read any +command line arguments passed to it and then collect the values into a vector. + +Filename: src/main.rs + +``` +use std::env; + +fn main() { + let args: Vec = env::args().collect(); + println!("{:?}", args); +} +``` + +Listing 12-1: Collecting the command line arguments into a vector and printing +them + +First, we bring the `std::env` module into scope with a `use` statement so we +can use its `args` function. Notice that the `std::env::args` function is +nested in two levels of modules. As we discussed in Chapter 7, in cases where +the desired function is nested in more than one module, it’s conventional to +bring the parent module into scope rather than the function. By doing so, we +can easily use other functions from `std::env`. It’s also less ambiguous than +adding `use std::env::args` and then calling the function with just `args`, +because `args` might easily be mistaken for a function that’s defined in the +current module. + +> ### The `args` Function and Invalid Unicode +> +> Note that `std::env::args` will panic if any argument contains invalid +> Unicode. If your program needs to accept arguments containing invalid +> Unicode, use `std::env::args_os` instead. That function returns an iterator +> that produces `OsString` values instead of `String` values. We’ve chosen to +> use `std::env::args` here for simplicity, because `OsString` values differ +> per platform and are more complex to work with than `String` values. + +On the first line of `main`, we call `env::args`, and we immediately use +`collect` to turn the iterator into a vector containing all the values produced +by the iterator. We can use the `collect` function to create many kinds of +collections, so we explicitly annotate the type of `args` to specify that we +want a vector of strings. Although we very rarely need to annotate types in +Rust, `collect` is one function you do often need to annotate because Rust +isn’t able to infer the kind of collection you want. + +Finally, we print the vector using the debug formatter, `:?`. Let’s try running +the code first with no arguments and then with two arguments: + +``` +$ cargo run +--snip-- +["target/debug/minigrep"] +``` + +``` +$ cargo run needle haystack +--snip-- +["target/debug/minigrep", "needle", "haystack"] +``` + +Notice that the first value in the vector is `"target/debug/minigrep"`, which +is the name of our binary. This matches the behavior of the arguments list in +C, letting programs use the name by which they were invoked in their execution. +It’s often convenient to have access to the program name in case you want to +print it in messages or change behavior of the program based on what command +line alias was used to invoke the program. But for the purposes of this +chapter, we’ll ignore it and save only the two arguments we need. + +### Saving the Argument Values in Variables + +Printing the value of the vector of arguments illustrated that the program is +able to access the values specified as command line arguments. Now we need to +save the values of the two arguments in variables so we can use the values +throughout the rest of the program. We do that in Listing 12-2. + +Filename: src/main.rs + +``` +use std::env; + +fn main() { + let args: Vec = env::args().collect(); + + let query = &args[1]; + let filename = &args[2]; + + println!("Searching for {}", query); + println!("In file {}", filename); +} +``` + +Listing 12-2: Creating variables to hold the query argument and filename +argument + +As we saw when we printed the vector, the program’s name takes up the first +value in the vector at `args[0]`, so we’re starting at index `1`. The first +argument `minigrep` takes is the string we’re searching for, so we put a +reference to the first argument in the variable `query`. The second argument +will be the filename, so we put a reference to the second argument in the +variable `filename`. + +We temporarily print the values of these variables to prove that the code is +working as we intend. Let’s run this program again with the arguments `test` +and `sample.txt`: + +``` +$ cargo run test sample.txt + Compiling minigrep v0.1.0 (file:///projects/minigrep) + Finished dev [unoptimized + debuginfo] target(s) in 0.0s + Running `target/debug/minigrep test sample.txt` +Searching for test +In file sample.txt +``` + +Great, the program is working! The values of the arguments we need are being +saved into the right variables. Later we’ll add some error handling to deal +with certain potential erroneous situations, such as when the user provides no +arguments; for now, we’ll ignore that situation and work on adding file-reading +capabilities instead. + +## Reading a File + +Now we’ll add functionality to read the file that is specified in the +`filename` command line argument. First, we need a sample file to test it with: +the best kind of file to use to make sure `minigrep` is working is one with a +small amount of text over multiple lines with some repeated words. Listing 12-3 +has an Emily Dickinson poem that will work well! Create a file called +*poem.txt* at the root level of your project, and enter the poem “I’m Nobody! +Who are you?” + +Filename: poem.txt + +``` +I'm nobody! Who are you? +Are you nobody, too? +Then there's a pair of us - don't tell! +They'd banish us, you know. + +How dreary to be somebody! +How public, like a frog +To tell your name the livelong day +To an admiring bog! +``` + +Listing 12-3: A poem by Emily Dickinson makes a good test case + +With the text in place, edit *src/main.rs* and add code to read the file, as +shown in Listing 12-4. + +Filename: src/main.rs + +``` +use std::env; +[1] use std::fs; + +fn main() { + // --snip-- + println!("In file {}", filename); + + [2] let contents = fs::read_to_string(filename) + .expect("Something went wrong reading the file"); + + [3] println!("With text:\n{}", contents); +} +``` + +Listing 12-4: Reading the contents of the file specified by the second argument + +First, we add another `use` statement to bring in a relevant part of the +standard library: we need `std::fs` to handle files [1]. + +In `main`, we’ve added a new statement: `fs::read_to_string` takes the +`filename`, opens that file, and returns a `Result` of the file’s +contents [2]. + +After that statement, we’ve again added a temporary `println!` statement that +prints the value of `contents` after the file is read, so we can check that the +program is working so far [3]. + +Let’s run this code with any string as the first command line argument (because +we haven’t implemented the searching part yet) and the *poem.txt* file as the +second argument: + +``` +$ cargo run the poem.txt + Compiling minigrep v0.1.0 (file:///projects/minigrep) + Finished dev [unoptimized + debuginfo] target(s) in 0.0s + Running `target/debug/minigrep the poem.txt` +Searching for the +In file poem.txt +With text: +I'm nobody! Who are you? +Are you nobody, too? +Then there's a pair of us - don't tell! +They'd banish us, you know. + +How dreary to be somebody! +How public, like a frog +To tell your name the livelong day +To an admiring bog! +``` + +Great! The code read and then printed the contents of the file. But the code +has a few flaws. The `main` function has multiple responsibilities: generally, +functions are clearer and easier to maintain if each function is responsible +for only one idea. The other problem is that we’re not handling errors as well +as we could. The program is still small, so these flaws aren’t a big problem, +but as the program grows, it will be harder to fix them cleanly. It’s good +practice to begin refactoring early on when developing a program, because it’s +much easier to refactor smaller amounts of code. We’ll do that next. + +## Refactoring to Improve Modularity and Error Handling + +To improve our program, we’ll fix four problems that have to do with the +program’s structure and how it’s handling potential errors. + +First, our `main` function now performs two tasks: it parses arguments and +reads files. For such a small function, this isn’t a major problem. However, if +we continue to grow our program inside `main`, the number of separate tasks the +`main` function handles will increase. As a function gains responsibilities, it +becomes more difficult to reason about, harder to test, and harder to change +without breaking one of its parts. It’s best to separate functionality so each +function is responsible for one task. + +This issue also ties into the second problem: although `query` and `filename` +are configuration variables to our program, variables like `contents` are used +to perform the program’s logic. The longer `main` becomes, the more variables +we’ll need to bring into scope; the more variables we have in scope, the harder +it will be to keep track of the purpose of each. It’s best to group the +configuration variables into one structure to make their purpose clear. + +The third problem is that we’ve used `expect` to print an error message when +reading the file fails, but the error message just prints `Something went wrong +reading the file`. Reading a file can fail in a number of ways: for example, +the file could be missing, or we might not have permission to open it. Right +now, regardless of the situation, we’d print the `Something went wrong reading +the file` error message, which wouldn’t give the user any information! + +Fourth, we use `expect` repeatedly to handle different errors, and if the user +runs our program without specifying enough arguments, they’ll get an `index out +of bounds` error from Rust that doesn’t clearly explain the problem. It would +be best if all the error-handling code were in one place so future maintainers +had only one place to consult in the code if the error-handling logic needed to +change. Having all the error-handling code in one place will also ensure that +we’re printing messages that will be meaningful to our end users. + +Let’s address these four problems by refactoring our project. + +### Separation of Concerns for Binary Projects + +The organizational problem of allocating responsibility for multiple tasks to +the `main` function is common to many binary projects. As a result, the Rust +community has developed a process to use as a guideline for splitting the +separate concerns of a binary program when `main` starts getting large. The +process has the following steps: + +* Split your program into a *main.rs* and a *lib.rs* and move your program’s + logic to *lib.rs*. +* As long as your command line parsing logic is small, it can remain in + *main.rs*. +* When the command line parsing logic starts getting complicated, extract it + from *main.rs* and move it to *lib.rs*. + +The responsibilities that remain in the `main` function after this process +should be limited to the following: + +* Calling the command line parsing logic with the argument values +* Setting up any other configuration +* Calling a `run` function in *lib.rs* +* Handling the error if `run` returns an error + +This pattern is about separating concerns: *main.rs* handles running the +program, and *lib.rs* handles all the logic of the task at hand. Because you +can’t test the `main` function directly, this structure lets you test all of +your program’s logic by moving it into functions in *lib.rs*. The only code +that remains in *main.rs* will be small enough to verify its correctness by +reading it. Let’s rework our program by following this process. + +#### Extracting the Argument Parser + +We’ll extract the functionality for parsing arguments into a function that +`main` will call to prepare for moving the command line parsing logic to +*src/lib.rs*. Listing 12-5 shows the new start of `main` that calls a new +function `parse_config`, which we’ll define in *src/main.rs* for the moment. + +Filename: src/main.rs + +``` +fn main() { + let args: Vec = env::args().collect(); + + let (query, filename) = parse_config(&args); + + // --snip-- +} + +fn parse_config(args: &[String]) -> (&str, &str) { + let query = &args[1]; + let filename = &args[2]; + + (query, filename) +} +``` + +Listing 12-5: Extracting a `parse_config` function from `main` + +We’re still collecting the command line arguments into a vector, but instead of +assigning the argument value at index 1 to the variable `query` and the +argument value at index 2 to the variable `filename` within the `main` +function, we pass the whole vector to the `parse_config` function. The +`parse_config` function then holds the logic that determines which argument +goes in which variable and passes the values back to `main`. We still create +the `query` and `filename` variables in `main`, but `main` no longer has the +responsibility of determining how the command line arguments and variables +correspond. + +This rework may seem like overkill for our small program, but we’re refactoring +in small, incremental steps. After making this change, run the program again to +verify that the argument parsing still works. It’s good to check your progress +often, to help identify the cause of problems when they occur. + +#### Grouping Configuration Values + +We can take another small step to improve the `parse_config` function further. +At the moment, we’re returning a tuple, but then we immediately break that +tuple into individual parts again. This is a sign that perhaps we don’t have +the right abstraction yet. + +Another indicator that shows there’s room for improvement is the `config` part +of `parse_config`, which implies that the two values we return are related and +are both part of one configuration value. We’re not currently conveying this +meaning in the structure of the data other than by grouping the two values into +a tuple; we could put the two values into one struct and give each of the +struct fields a meaningful name. Doing so will make it easier for future +maintainers of this code to understand how the different values relate to each +other and what their purpose is. + +Listing 12-6 shows the improvements to the `parse_config` function. + +Filename: src/main.rs + +``` +fn main() { + let args: Vec = env::args().collect(); + + [1] let config = parse_config(&args); + + println!("Searching for {}", config.query[2]); + println!("In file {}", config.filename[3]); + + let contents = fs::read_to_string(config.filename[4]) + .expect("Something went wrong reading the file"); + + // --snip-- +} + +[5] struct Config { + query: String, + filename: String, +} + +[6] fn parse_config(args: &[String]) -> Config { + [7] let query = args[1].clone(); + [8] let filename = args[2].clone(); + + Config { query, filename } +} +``` + +Listing 12-6: Refactoring `parse_config` to return an instance of a `Config` +struct + +We’ve added a struct named `Config` defined to have fields named `query` and +`filename` [5]. The signature of `parse_config` now indicates that it returns a +`Config` value [6]. In the body of `parse_config`, where we used to return +string slices that reference `String` values in `args`, we now define `Config` +to contain owned `String` values. The `args` variable in `main` is the owner of +the argument values and is only letting the `parse_config` function borrow +them, which means we’d violate Rust’s borrowing rules if `Config` tried to take +ownership of the values in `args`. + +We could manage the `String` data in a number of different ways, but the +easiest, though somewhat inefficient, route is to call the `clone` method on +the values [7][8]. This will make a full copy of the data for the `Config` +instance to own, which takes more time and memory than storing a reference to +the string data. However, cloning the data also makes our code very +straightforward because we don’t have to manage the lifetimes of the +references; in this circumstance, giving up a little performance to gain +simplicity is a worthwhile trade-off. + +> ### The Trade-Offs of Using `clone` +> +> There’s a tendency among many Rustaceans to avoid using `clone` to fix +> ownership problems because of its runtime cost. In +> Chapter 13, you’ll learn how to use more efficient +> methods in this type of situation. But for now, it’s okay to copy a few +> strings to continue making progress because you’ll make these copies only +> once and your filename and query string are very small. It’s better to have +> a working program that’s a bit inefficient than to try to hyperoptimize code +> on your first pass. As you become more experienced with Rust, it’ll be +> easier to start with the most efficient solution, but for now, it’s +> perfectly acceptable to call `clone`. + +We’ve updated `main` so it places the instance of `Config` returned by +`parse_config` into a variable named `config` [1], and we updated the code that +previously used the separate `query` and `filename` variables so it now uses +the fields on the `Config` struct instead [2][3][4]. + +Now our code more clearly conveys that `query` and `filename` are related and +that their purpose is to configure how the program will work. Any code that +uses these values knows to find them in the `config` instance in the fields +named for their purpose. + +#### Creating a Constructor for `Config` + +So far, we’ve extracted the logic responsible for parsing the command line +arguments from `main` and placed it in the `parse_config` function. Doing so +helped us to see that the `query` and `filename` values were related and that +relationship should be conveyed in our code. We then added a `Config` struct to +name the related purpose of `query` and `filename` and to be able to return the +values’ names as struct field names from the `parse_config` function. + +So now that the purpose of the `parse_config` function is to create a `Config` +instance, we can change `parse_config` from a plain function to a function +named `new` that is associated with the `Config` struct. Making this change +will make the code more idiomatic. We can create instances of types in the +standard library, such as `String`, by calling `String::new`. Similarly, by +changing `parse_config` into a `new` function associated with `Config`, we’ll +be able to create instances of `Config` by calling `Config::new`. Listing 12-7 +shows the changes we need to make. + +Filename: src/main.rs + +``` +fn main() { + let args: Vec = env::args().collect(); + + [1] let config = Config::new(&args); + + // --snip-- +} + +// --snip-- + +[2] impl Config { + [3] fn new(args: &[String]) -> Config { + let query = args[1].clone(); + let filename = args[2].clone(); + + Config { query, filename } + } +} +``` + +Listing 12-7: Changing `parse_config` into `Config::new` + +We’ve updated `main` where we were calling `parse_config` to instead call +`Config::new` [1]. We’ve changed the name of `parse_config` to `new` [3] and +moved it within an `impl` block [2], which associates the `new` function with +`Config`. Try compiling this code again to make sure it works. + +### Fixing the Error Handling + +Now we’ll work on fixing our error handling. Recall that attempting to access +the values in the `args` vector at index 1 or index 2 will cause the program to +panic if the vector contains fewer than three items. Try running the program +without any arguments; it will look like this: + +``` +$ cargo run + Compiling minigrep v0.1.0 (file:///projects/minigrep) + Finished dev [unoptimized + debuginfo] target(s) in 0.0s + Running `target/debug/minigrep` +thread 'main' panicked at 'index out of bounds: the len is 1 but the index is 1', src/main.rs:27:21 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +``` + +The line `index out of bounds: the len is 1 but the index is 1` is an error +message intended for programmers. It won’t help our end users understand what +happened and what they should do instead. Let’s fix that now. + +#### Improving the Error Message + +In Listing 12-8, we add a check in the `new` function that will verify that the +slice is long enough before accessing index 1 and 2. If the slice isn’t long +enough, the program panics and displays a better error message than the `index +out of bounds` message. + +Filename: src/main.rs + +``` +// --snip-- +fn new(args: &[String]) -> Config { + if args.len() < 3 { + panic!("not enough arguments"); + } + // --snip-- +``` + +Listing 12-8: Adding a check for the number of arguments + +This code is similar to the `Guess::new` function we wrote in Listing 9-10, +where we called `panic!` when the `value` argument was out of the range of +valid values. Instead of checking for a range of values here, we’re checking +that the length of `args` is at least 3 and the rest of the function can +operate under the assumption that this condition has been met. If `args` has +fewer than three items, this condition will be true, and we call the `panic!` +macro to end the program immediately. + +With these extra few lines of code in `new`, let’s run the program without any +arguments again to see what the error looks like now: + +``` +$ cargo run + Compiling minigrep v0.1.0 (file:///projects/minigrep) + Finished dev [unoptimized + debuginfo] target(s) in 0.0s + Running `target/debug/minigrep` +thread 'main' panicked at 'not enough arguments', src/main.rs:26:13 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace +``` + +This output is better: we now have a reasonable error message. However, we also +have extraneous information we don’t want to give to our users. Perhaps using +the technique we used in Listing 9-13 isn’t the best to use here: a call to +`panic!` is more appropriate for a programming problem than a usage problem, as +discussed in Chapter 9. Instead, we can use the other technique you learned +about in Chapter 9—returning a `Result` that indicates either success or an +error. + +#### Returning a `Result` from `new` Instead of Calling `panic!` + +We can instead return a `Result` value that will contain a `Config` instance in +the successful case and will describe the problem in the error case. When +`Config::new` is communicating to `main`, we can use the `Result` type to +signal there was a problem. Then we can change `main` to convert an `Err` +variant into a more practical error for our users without the surrounding text +about `thread 'main'` and `RUST_BACKTRACE` that a call to `panic!` causes. + +Listing 12-9 shows the changes we need to make to the return value of +`Config::new` and the body of the function needed to return a `Result`. Note +that this won’t compile until we update `main` as well, which we’ll do in the +next listing. + +Filename: src/main.rs + +``` +impl Config { + fn new(args: &[String]) -> Result { + if args.len() < 3 { + return Err("not enough arguments"); + } + + let query = args[1].clone(); + let filename = args[2].clone(); + + Ok(Config { query, filename }) + } +} +``` + +Listing 12-9: Returning a `Result` from `Config::new` + +Our `new` function now returns a `Result` with a `Config` instance in the +success case and a `&'static str` in the error case. Our error values will +always be string literals that have the `'static` lifetime. + +We’ve made two changes in the body of the `new` function: instead of calling +`panic!` when the user doesn’t pass enough arguments, we now return an `Err` +value, and we’ve wrapped the `Config` return value in an `Ok`. These changes +make the function conform to its new type signature. + +Returning an `Err` value from `Config::new` allows the `main` function to +handle the `Result` value returned from the `new` function and exit the process +more cleanly in the error case. + +#### Calling `Config::new` and Handling Errors + +To handle the error case and print a user-friendly message, we need to update +`main` to handle the `Result` being returned by `Config::new`, as shown in +Listing 12-10. We’ll also take the responsibility of exiting the command line +tool with a nonzero error code from `panic!` and implement it by hand. A +nonzero exit status is a convention to signal to the process that called our +program that the program exited with an error state. + +Filename: src/main.rs + +``` +[1] use std::process; + +fn main() { + let args: Vec = env::args().collect(); + + [2] let config = Config::new(&args).unwrap_or_else([3]|err[4]| { + [5] println!("Problem parsing arguments: {}", err); + [6] process::exit(1); + }); + + // --snip-- +``` + +Listing 12-10: Exiting with an error code if creating a new `Config` fails + +In this listing, we’ve used a method we haven’t covered in detail yet: +`unwrap_or_else`, which is defined on `Result` by the standard library +[2]. Using `unwrap_or_else` allows us to define some custom, non-`panic!` error +handling. If the `Result` is an `Ok` value, this method’s behavior is similar +to `unwrap`: it returns the inner value `Ok` is wrapping. However, if the value +is an `Err` value, this method calls the code in the *closure*, which is an +anonymous function we define and pass as an argument to `unwrap_or_else` [3]. +We’ll cover closures in more detail in Chapter 13. For now, you just need to +know that `unwrap_or_else` will pass the inner value of the `Err`, which in +this case is the static string `"not enough arguments"` that we added in +Listing 12-9, to our closure in the argument `err` that appears between the +vertical pipes [4]. The code in the closure can then use the `err` value when +it runs. + +We’ve added a new `use` line to bring `process` from the standard library into +scope [1]. The code in the closure that will be run in the error case is only +two lines: we print the `err` value [5] and then call `process::exit` [6]. The +`process::exit` function will stop the program immediately and return the +number that was passed as the exit status code. This is similar to the +`panic!`-based handling we used in Listing 12-8, but we no longer get all the +extra output. Let’s try it: + +``` +$ cargo run + Compiling minigrep v0.1.0 (file:///projects/minigrep) + Finished dev [unoptimized + debuginfo] target(s) in 0.48s + Running `target/debug/minigrep` +Problem parsing arguments: not enough arguments +``` + +Great! This output is much friendlier for our users. + +### Extracting Logic from `main` + +Now that we’ve finished refactoring the configuration parsing, let’s turn to +the program’s logic. As we stated in “Separation of Concerns for Binary +Projects”, we’ll extract a function named `run` that will hold all the logic +currently in the `main` function that isn’t involved with setting up +configuration or handling errors. When we’re done, `main` will be concise and +easy to verify by inspection, and we’ll be able to write tests for all the +other logic. + +Listing 12-11 shows the extracted `run` function. For now, we’re just making +the small, incremental improvement of extracting the function. We’re still +defining the function in *src/main.rs*. + +Filename: src/main.rs + +``` +fn main() { + // --snip-- + + println!("Searching for {}", config.query); + println!("In file {}", config.filename); + + run(config); +} + +fn run(config: Config) { + let contents = fs::read_to_string(config.filename) + .expect("Something went wrong reading the file"); + + println!("With text:\n{}", contents); +} + +// --snip-- +``` + +Listing 12-11: Extracting a `run` function containing the rest of the program +logic + +The `run` function now contains all the remaining logic from `main`, starting +from reading the file. The `run` function takes the `Config` instance as an +argument. + +#### Returning Errors from the `run` Function + +With the remaining program logic separated into the `run` function, we can +improve the error handling, as we did with `Config::new` in Listing 12-9. +Instead of allowing the program to panic by calling `expect`, the `run` +function will return a `Result` when something goes wrong. This will let +us further consolidate into `main` the logic around handling errors in a +user-friendly way. Listing 12-12 shows the changes we need to make to the +signature and body of `run`. + +Filename: src/main.rs + +``` +[1] use std::error::Error; + +// --snip-- + +[2] fn run(config: Config) -> Result<(), Box> { + let contents = fs::read_to_string(config.filename)?[3]; + + println!("With text:\n{}", contents); + + [4] Ok(()) +} +``` + +Listing 12-12: Changing the `run` function to return `Result` + +We’ve made three significant changes here. First, we changed the return type of +the `run` function to `Result<(), Box>` [2]. This function previously +returned the unit type, `()`, and we keep that as the value returned in the +`Ok` case. + +For the error type, we used the *trait object* `Box` (and we’ve +brought `std::error::Error` into scope with a `use` statement at the top [1]). +We’ll cover trait objects in Chapter 17. For now, just know that `Box` means the function will return a type that implements the `Error` +trait, but we don’t have to specify what particular type the return value will +be. This gives us flexibility to return error values that may be of different +types in different error cases. The `dyn` keyword is short for “dynamic.” + +Second, we’ve removed the call to `expect` in favor of the `?` operator [3], as +we talked about in Chapter 9. Rather than `panic!` on an error, `?` will return +the error value from the current function for the caller to handle. + +Third, the `run` function now returns an `Ok` value in the success case [4]. +We’ve declared the `run` function’s success type as `()` in the signature, +which means we need to wrap the unit type value in the `Ok` value. This +`Ok(())` syntax might look a bit strange at first, but using `()` like this is +the idiomatic way to indicate that we’re calling `run` for its side effects +only; it doesn’t return a value we need. + +When you run this code, it will compile but will display a warning: + +``` +warning: unused `Result` that must be used + --> src/main.rs:19:5 + | +19 | run(config); + | ^^^^^^^^^^^^ + | + = note: `#[warn(unused_must_use)]` on by default + = note: this `Result` may be an `Err` variant, which should be handled +``` + +Rust tells us that our code ignored the `Result` value and the `Result` value +might indicate that an error occurred. But we’re not checking to see whether or +not there was an error, and the compiler reminds us that we probably meant to +have some error-handling code here! Let’s rectify that problem now. + +#### Handling Errors Returned from `run` in `main` + +We’ll check for errors and handle them using a technique similar to one we used +with `Config::new` in Listing 12-10, but with a slight difference: + +Filename: src/main.rs + +``` +fn main() { + // --snip-- + + println!("Searching for {}", config.query); + println!("In file {}", config.filename); + + if let Err(e) = run(config) { + println!("Application error: {}", e); + + process::exit(1); + } +} +``` + +We use `if let` rather than `unwrap_or_else` to check whether `run` returns an +`Err` value and call `process::exit(1)` if it does. The `run` function doesn’t +return a value that we want to `unwrap` in the same way that `Config::new` +returns the `Config` instance. Because `run` returns `()` in the success case, +we only care about detecting an error, so we don’t need `unwrap_or_else` to +return the unwrapped value because it would only be `()`. + +The bodies of the `if let` and the `unwrap_or_else` functions are the same in +both cases: we print the error and exit. + +### Splitting Code into a Library Crate + +Our `minigrep` project is looking good so far! Now we’ll split the +*src/main.rs* file and put some code into the *src/lib.rs* file so we can test +it and have a *src/main.rs* file with fewer responsibilities. + +Let’s move all the code that isn’t the `main` function from *src/main.rs* to +*src/lib.rs*: + +* The `run` function definition +* The relevant `use` statements +* The definition of `Config` +* The `Config::new` function definition + +The contents of *src/lib.rs* should have the signatures shown in Listing 12-13 +(we’ve omitted the bodies of the functions for brevity). Note that this won’t +compile until we modify *src/main.rs* in Listing 12-14. + +Filename: src/lib.rs + +``` +use std::error::Error; +use std::fs; + +pub struct Config { + pub query: String, + pub filename: String, +} + +impl Config { + pub fn new(args: &[String]) -> Result { + // --snip-- + } +} + +pub fn run(config: Config) -> Result<(), Box> { + // --snip-- +} +``` + +Listing 12-13: Moving `Config` and `run` into *src/lib.rs* + +We’ve made liberal use of the `pub` keyword: on `Config`, on its fields and its +`new` method, and on the `run` function. We now have a library crate that has a +public API that we can test! + +Now we need to bring the code we moved to *src/lib.rs* into the scope of the +binary crate in *src/main.rs*, as shown in Listing 12-14. + +Filename: src/main.rs + +``` +use std::env; +use std::process; + +use minigrep::Config; + +fn main() { + // --snip-- + if let Err(e) = minigrep::run(config) { + // --snip-- + } +} +``` + +Listing 12-14: Using the `minigrep` library crate in *src/main.rs* + +We add a `use minigrep::Config` line to bring the `Config` type from the +library crate into the binary crate’s scope, and we prefix the `run` function +with our crate name. Now all the functionality should be connected and should +work. Run the program with `cargo run` and make sure everything works +correctly. + +Whew! That was a lot of work, but we’ve set ourselves up for success in the +future. Now it’s much easier to handle errors, and we’ve made the code more +modular. Almost all of our work will be done in *src/lib.rs* from here on out. + +Let’s take advantage of this newfound modularity by doing something that would +have been difficult with the old code but is easy with the new code: we’ll +write some tests! + +## Developing the Library’s Functionality with Test-Driven Development + +Now that we’ve extracted the logic into *src/lib.rs* and left the argument +collecting and error handling in *src/main.rs*, it’s much easier to write tests +for the core functionality of our code. We can call functions directly with +various arguments and check return values without having to call our binary +from the command line. + +In this section, we’ll add the searching logic to the `minigrep` program by +using the Test-driven development (TDD) process. This software development +technique follows these steps: + +1. Write a test that fails and run it to make sure it fails for the reason you + expect. +2. Write or modify just enough code to make the new test pass. +3. Refactor the code you just added or changed and make sure the tests + continue to pass. +4. Repeat from step 1! + +This process is just one of many ways to write software, but TDD can help drive +code design as well. Writing the test before you write the code that makes the +test pass helps to maintain high test coverage throughout the process. + +We’ll test drive the implementation of the functionality that will actually do +the searching for the query string in the file contents and produce a list of +lines that match the query. We’ll add this functionality in a function called +`search`. + +### Writing a Failing Test + +Because we don’t need them anymore, let’s remove the `println!` statements from +*src/lib.rs* and *src/main.rs* that we used to check the program’s behavior. +Then, in *src/lib.rs*, we’ll add a `tests` module with a test function, as we +did in Chapter 11. The test function specifies the behavior we want the +`search` function to have: it will take a query and the text to search for the +query in, and it will return only the lines from the text that contain the +query. Listing 12-15 shows this test, which won’t compile yet. + +Filename: src/lib.rs + +``` +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn one_result() { + let query = "duct"; + let contents = "\ +Rust: +safe, fast, productive. +Pick three."; + + assert_eq!(vec!["safe, fast, productive."], search(query, contents)); + } +} +``` + +Listing 12-15: Creating a failing test for the `search` function we wish we had + +This test searches for the string `"duct"`. The text we’re searching is three +lines, only one of which contains `"duct"` (Note that the backslash after the +opening double quote tells Rust not to put a newline character at the beginning +of the contents of this string literal). We assert that the value returned from +the `search` function contains only the line we expect. + +We aren’t able to run this test and watch it fail because the test doesn’t even +compile: the `search` function doesn’t exist yet! So now we’ll add just enough +code to get the test to compile and run by adding a definition of the `search` +function that always returns an empty vector, as shown in Listing 12-16. Then +the test should compile and fail because an empty vector doesn’t match a vector +containing the line `"safe, fast, productive."` + +Filename: src/lib.rs + +``` +pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { + vec![] +} +``` + +Listing 12-16: Defining just enough of the `search` function so our test will +compile + +Notice that we need an explicit lifetime `'a` defined in the signature of +`search` and used with the `contents` argument and the return value. Recall in +Chapter 10 that the lifetime parameters specify which argument lifetime is +connected to the lifetime of the return value. In this case, we indicate that +the returned vector should contain string slices that reference slices of the +argument `contents` (rather than the argument `query`). + +In other words, we tell Rust that the data returned by the `search` function +will live as long as the data passed into the `search` function in the +`contents` argument. This is important! The data referenced *by* a slice needs +to be valid for the reference to be valid; if the compiler assumes we’re making +string slices of `query` rather than `contents`, it will do its safety checking +incorrectly. + +If we forget the lifetime annotations and try to compile this function, we’ll +get this error: + +``` +error[E0106]: missing lifetime specifier + --> src/lib.rs:28:51 + | +28 | pub fn search(query: &str, contents: &str) -> Vec<&str> { + | ---- ---- ^ expected named lifetime parameter + | + = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `query` or `contents` +help: consider introducing a named lifetime parameter + | +28 | pub fn search<'a>(query: &'a str, contents: &'a str) -> Vec<&'a str> { + | ++++ ++ ++ ++ +``` + +Rust can’t possibly know which of the two arguments we need, so we need to tell +it. Because `contents` is the argument that contains all of our text and we +want to return the parts of that text that match, we know `contents` is the +argument that should be connected to the return value using the lifetime syntax. + +Other programming languages don’t require you to connect arguments to return +values in the signature. Although this might seem strange, it will get easier +over time. You might want to compare this example with the “Validating +References with Lifetimes” section in Chapter 10. + +Now let’s run the test: + +``` +$ cargo test + Compiling minigrep v0.1.0 (file:///projects/minigrep) + Finished test [unoptimized + debuginfo] target(s) in 0.97s + Running unittests (target/debug/deps/minigrep-9cd200e5fac0fc94) + +running 1 test +test tests::one_result ... FAILED + +failures: + +---- tests::one_result stdout ---- +thread 'main' panicked at 'assertion failed: `(left == right)` + left: `["safe, fast, productive."]`, + right: `[]`', src/lib.rs:44:9 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace + + +failures: + tests::one_result + +test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s + +error: test failed, to rerun pass '--lib' +``` + +Great, the test fails, exactly as we expected. Let’s get the test to pass! + +### Writing Code to Pass the Test + +Currently, our test is failing because we always return an empty vector. To fix +that and implement `search`, our program needs to follow these steps: + +* Iterate through each line of the contents. +* Check whether the line contains our query string. +* If it does, add it to the list of values we’re returning. +* If it doesn’t, do nothing. +* Return the list of results that match. + +Let’s work through each step, starting with iterating through lines. + +#### Iterating Through Lines with the `lines` Method + +Rust has a helpful method to handle line-by-line iteration of strings, +conveniently named `lines`, that works as shown in Listing 12-17. Note this +won’t compile yet. + +Filename: src/lib.rs + +``` +pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { + for line in contents.lines() { + // do something with line + } +} +``` + +Listing 12-17: Iterating through each line in `contents` + +The `lines` method returns an iterator. We’ll talk about iterators in depth in +Chapter 13, but recall that you saw this way of using an iterator in Listing +3-5, where we used a `for` loop with an iterator to run some code on each item +in a collection. + +#### Searching Each Line for the Query + +Next, we’ll check whether the current line contains our query string. +Fortunately, strings have a helpful method named `contains` that does this for +us! Add a call to the `contains` method in the `search` function, as shown in +Listing 12-18. Note this still won’t compile yet. + +Filename: src/lib.rs + +``` +pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { + for line in contents.lines() { + if line.contains(query) { + // do something with line + } + } +} +``` + +Listing 12-18: Adding functionality to see whether the line contains the string +in `query` + +#### Storing Matching Lines + +We also need a way to store the lines that contain our query string. For that, +we can make a mutable vector before the `for` loop and call the `push` method +to store a `line` in the vector. After the `for` loop, we return the vector, as +shown in Listing 12-19. + +Filename: src/lib.rs + +``` +pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> { + let mut results = Vec::new(); + + for line in contents.lines() { + if line.contains(query) { + results.push(line); + } + } + + results +} +``` + +Listing 12-19: Storing the lines that match so we can return them + +Now the `search` function should return only the lines that contain `query`, +and our test should pass. Let’s run the test: + +``` +$ cargo test +--snip-- +running 1 test +test tests::one_result ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s +``` + +Our test passed, so we know it works! + +At this point, we could consider opportunities for refactoring the +implementation of the search function while keeping the tests passing to +maintain the same functionality. The code in the search function isn’t too bad, +but it doesn’t take advantage of some useful features of iterators. We’ll +return to this example in Chapter 13, where we’ll explore iterators in detail, +and look at how to improve it. + +#### Using the `search` Function in the `run` Function + +Now that the `search` function is working and tested, we need to call `search` +from our `run` function. We need to pass the `config.query` value and the +`contents` that `run` reads from the file to the `search` function. Then `run` +will print each line returned from `search`: + +Filename: src/lib.rs + +``` +pub fn run(config: Config) -> Result<(), Box> { + let contents = fs::read_to_string(config.filename)?; + + for line in search(&config.query, &contents) { + println!("{}", line); + } + + Ok(()) +} +``` + +We’re still using a `for` loop to return each line from `search` and print it. + +Now the entire program should work! Let’s try it out, first with a word that +should return exactly one line from the Emily Dickinson poem, “frog”: + +``` +$ cargo run frog poem.txt + Compiling minigrep v0.1.0 (file:///projects/minigrep) + Finished dev [unoptimized + debuginfo] target(s) in 0.38s + Running `target/debug/minigrep frog poem.txt` +How public, like a frog +``` + +Cool! Now let’s try a word that will match multiple lines, like “body”: + +``` +$ cargo run body poem.txt + Finished dev [unoptimized + debuginfo] target(s) in 0.0s + Running `target/debug/minigrep body poem.txt` +I'm nobody! Who are you? +Are you nobody, too? +How dreary to be somebody! +``` + +And finally, let’s make sure that we don’t get any lines when we search for a +word that isn’t anywhere in the poem, such as “monomorphization”: + +``` +$ cargo run monomorphization poem.txt + Finished dev [unoptimized + debuginfo] target(s) in 0.0s + Running `target/debug/minigrep monomorphization poem.txt` +``` + +Excellent! We’ve built our own mini version of a classic tool and learned a lot +about how to structure applications. We’ve also learned a bit about file input +and output, lifetimes, testing, and command line parsing. + +To round out this project, we’ll briefly demonstrate how to work with +environment variables and how to print to standard error, both of which are +useful when you’re writing command line programs. + +## Working with Environment Variables + +We’ll improve `minigrep` by adding an extra feature: an option for +case-insensitive searching that the user can turn on via an environment +variable. We could make this feature a command line option and require that +users enter it each time they want it to apply, but instead we’ll use an +environment variable. Doing so allows our users to set the environment variable +once and have all their searches be case insensitive in that terminal session. + +### Writing a Failing Test for the Case-Insensitive `search` Function + +We want to add a new `search_case_insensitive` function that we’ll call when +the environment variable is on. We’ll continue to follow the TDD process, so +the first step is again to write a failing test. We’ll add a new test for the +new `search_case_insensitive` function and rename our old test from +`one_result` to `case_sensitive` to clarify the differences between the two +tests, as shown in Listing 12-20. + +Filename: src/lib.rs + +``` +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn case_sensitive() { + let query = "duct"; + let contents = "\ +Rust: +safe, fast, productive. +Pick three. +Duct tape."; + + assert_eq!(vec!["safe, fast, productive."], search(query, contents)); + } + + #[test] + fn case_insensitive() { + let query = "rUsT"; + let contents = "\ +Rust: +safe, fast, productive. +Pick three. +Trust me."; + + assert_eq!( + vec!["Rust:", "Trust me."], + search_case_insensitive(query, contents) + ); + } +} +``` + +Listing 12-20: Adding a new failing test for the case-insensitive function +we’re about to add + +Note that we’ve edited the old test’s `contents` too. We’ve added a new line +with the text `"Duct tape."` using a capital D that shouldn’t match the query +`"duct"` when we’re searching in a case-sensitive manner. Changing the old test +in this way helps ensure that we don’t accidentally break the case-sensitive +search functionality that we’ve already implemented. This test should pass now +and should continue to pass as we work on the case-insensitive search. + +The new test for the case-*insensitive* search uses `"rUsT"` as its query. In +the `search_case_insensitive` function we’re about to add, the query `"rUsT"` +should match the line containing `"Rust:"` with a capital R and match the line +`"Trust me."` even though both have different casing from the query. This is +our failing test, and it will fail to compile because we haven’t yet defined +the `search_case_insensitive` function. Feel free to add a skeleton +implementation that always returns an empty vector, similar to the way we did +for the `search` function in Listing 12-16 to see the test compile and fail. + +### Implementing the `search_case_insensitive` Function + +The `search_case_insensitive` function, shown in Listing 12-21, will be almost +the same as the `search` function. The only difference is that we’ll lowercase +the `query` and each `line` so whatever the case of the input arguments, +they’ll be the same case when we check whether the line contains the query. + +Filename: src/lib.rs + +``` +pub fn search_case_insensitive<'a>( + query: &str, + contents: &'a str, +) -> Vec<&'a str> { + [1] let query = query.to_lowercase(); + let mut results = Vec::new(); + + for line in contents.lines() { + if line.to_lowercase()[2].contains(&query[3]) { + results.push(line); + } + } + + results +} +``` + +Listing 12-21: Defining the `search_case_insensitive` function to lowercase the +query and the line before comparing them + +First, we lowercase the `query` string and store it in a shadowed variable with +the same name [1]. Calling `to_lowercase` on the query is necessary so no +matter whether the user’s query is `"rust"`, `"RUST"`, `"Rust"`, or `"rUsT"`, +we’ll treat the query as if it were `"rust"` and be insensitive to the case. +While `to_lowercase` will handle basic Unicode, it won’t be 100% accurate. If +we were writing a real application, we’d want to do a bit more work here, but +this section is about environment variables, not Unicode, so we’ll leave it at +that here. + +Note that `query` is now a `String` rather than a string slice, because calling +`to_lowercase` creates new data rather than referencing existing data. Say the +query is `"rUsT"`, as an example: that string slice doesn’t contain a lowercase +`u` or `t` for us to use, so we have to allocate a new `String` containing +`"rust"`. When we pass `query` as an argument to the `contains` method now, we +need to add an ampersand [3] because the signature of `contains` is defined to +take a string slice. + +Next, we add a call to `to_lowercase` on each `line` before we check whether it +contains `query` to lowercase all characters [2]. Now that we’ve converted +`line` and `query` to lowercase, we’ll find matches no matter what the case of +the query is. + +Let’s see if this implementation passes the tests: + +``` +running 2 tests +test tests::case_insensitive ... ok +test tests::case_sensitive ... ok + +test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s +``` + +Great! They passed. Now, let’s call the new `search_case_insensitive` function +from the `run` function. First, we’ll add a configuration option to the +`Config` struct to switch between case-sensitive and case-insensitive search. +Adding this field will cause compiler errors because we aren’t initializing +this field anywhere yet: + +Filename: src/lib.rs + +``` +pub struct Config { + pub query: String, + pub filename: String, + pub case_sensitive: bool, +} +``` + +Note that we added the `case_sensitive` field that holds a Boolean. Next, we +need the `run` function to check the `case_sensitive` field’s value and use +that to decide whether to call the `search` function or the +`search_case_insensitive` function, as shown in Listing 12-22. Note this still +won’t compile yet. + +Filename: src/lib.rs + +``` +pub fn run(config: Config) -> Result<(), Box> { + let contents = fs::read_to_string(config.filename)?; + + let results = if config.case_sensitive { + search(&config.query, &contents) + } else { + search_case_insensitive(&config.query, &contents) + }; + + for line in results { + println!("{}", line); + } + + Ok(()) +} +``` + +Listing 12-22: Calling either `search` or `search_case_insensitive` based on +the value in `config.case_sensitive` + +Finally, we need to check for the environment variable. The functions for +working with environment variables are in the `env` module in the standard +library, so we want to bring that module into scope with a `use std::env;` line +at the top of *src/lib.rs*. Then we’ll use the `var` function from the `env` +module to check for an environment variable named `CASE_INSENSITIVE`, as shown +in Listing 12-23. + +Filename: src/lib.rs + +``` +use std::env; +// --snip-- + +impl Config { + pub fn new(args: &[String]) -> Result { + if args.len() < 3 { + return Err("not enough arguments"); + } + + let query = args[1].clone(); + let filename = args[2].clone(); + + let case_sensitive = env::var("CASE_INSENSITIVE").is_err(); + + Ok(Config { + query, + filename, + case_sensitive, + }) + } +} +``` + +Listing 12-23: Checking for an environment variable named `CASE_INSENSITIVE` + +Here, we create a new variable `case_sensitive`. To set its value, we call the +`env::var` function and pass it the name of the `CASE_INSENSITIVE` environment +variable. The `env::var` function returns a `Result` that will be the +successful `Ok` variant that contains the value of the environment variable if +the environment variable is set. It will return the `Err` variant if the +environment variable is not set. + +We’re using the `is_err` method on the `Result` to check whether it’s an error +and therefore unset, which means it *should* do a case-sensitive search. If the +`CASE_INSENSITIVE` environment variable is set to anything, `is_err` will +return false and the program will perform a case-insensitive search. We don’t +care about the *value* of the environment variable, just whether it’s set or +unset, so we’re checking `is_err` rather than using `unwrap`, `expect`, or any +of the other methods we’ve seen on `Result`. + +We pass the value in the `case_sensitive` variable to the `Config` instance so +the `run` function can read that value and decide whether to call `search` or +`search_case_insensitive`, as we implemented in Listing 12-22. + +Let’s give it a try! First, we’ll run our program without the environment +variable set and with the query `to`, which should match any line that contains +the word “to” in all lowercase: + +``` +$ cargo run to poem.txt + Compiling minigrep v0.1.0 (file:///projects/minigrep) + Finished dev [unoptimized + debuginfo] target(s) in 0.0s + Running `target/debug/minigrep to poem.txt` +Are you nobody, too? +How dreary to be somebody! +``` + +Looks like that still works! Now, let’s run the program with `CASE_INSENSITIVE` +set to `1` but with the same query `to`. + +If you’re using PowerShell, you will need to set the environment variable and +run the program as separate commands: + +``` +PS> $Env:CASE_INSENSITIVE=1; cargo run to poem.txt +``` + +This will make `CASE_INSENSITIVE` persist for the remainder of your shell +session. It can be unset with the `Remove-Item` cmdlet: + +``` +PS> Remove-Item Env:CASE_INSENSITIVE +``` + +We should get lines that contain “to” that might have uppercase letters: + +``` +$ CASE_INSENSITIVE=1 cargo run to poem.txt + Finished dev [unoptimized + debuginfo] target(s) in 0.0s + Running `target/debug/minigrep to poem.txt` +Are you nobody, too? +How dreary to be somebody! +To tell your name the livelong day +To an admiring bog! +``` + +Excellent, we also got lines containing “To”! Our `minigrep` program can now do +case-insensitive searching controlled by an environment variable. Now you know +how to manage options set using either command line arguments or environment +variables. + +Some programs allow arguments *and* environment variables for the same +configuration. In those cases, the programs decide that one or the other takes +precedence. For another exercise on your own, try controlling case +insensitivity through either a command line argument or an environment +variable. Decide whether the command line argument or the environment variable +should take precedence if the program is run with one set to case sensitive and +one set to case insensitive. + +The `std::env` module contains many more useful features for dealing with +environment variables: check out its documentation to see what is available. + +## Writing Error Messages to Standard Error Instead of Standard Output + +At the moment, we’re writing all of our output to the terminal using the +`println!` macro. In most terminals, there are two kinds of output: *standard +output* (`stdout`) for general information and *standard error* (`stderr`) for +error messages. This distinction enables users to choose to direct the +successful output of a program to a file but still print error messages to the +screen. + +The `println!` macro is only capable of printing to standard output, so we +have to use something else to print to standard error. + +### Checking Where Errors Are Written + +First, let’s observe how the content printed by `minigrep` is currently being +written to standard output, including any error messages we want to write to +standard error instead. We’ll do that by redirecting the standard output stream +to a file while also intentionally causing an error. We won’t redirect the +standard error stream, so any content sent to standard error will continue to +display on the screen. + +Command line programs are expected to send error messages to the standard error +stream so we can still see error messages on the screen even if we redirect the +standard output stream to a file. Our program is not currently well-behaved: +we’re about to see that it saves the error message output to a file instead! + +The way to demonstrate this behavior is by running the program with `>` and the +filename, *output.txt*, that we want to redirect the standard output stream to. +We won’t pass any arguments, which should cause an error: + +``` +$ cargo run > output.txt +``` + +The `>` syntax tells the shell to write the contents of standard output to +*output.txt* instead of the screen. We didn’t see the error message we were +expecting printed to the screen, so that means it must have ended up in the +file. This is what *output.txt* contains: + +``` +Problem parsing arguments: not enough arguments +``` + +Yup, our error message is being printed to standard output. It’s much more +useful for error messages like this to be printed to standard error so only +data from a successful run ends up in the file. We’ll change that. + +### Printing Errors to Standard Error + +We’ll use the code in Listing 12-24 to change how error messages are printed. +Because of the refactoring we did earlier in this chapter, all the code that +prints error messages is in one function, `main`. The standard library provides +the `eprintln!` macro that prints to the standard error stream, so let’s change +the two places we were calling `println!` to print errors to use `eprintln!` +instead. + +Filename: src/main.rs + +``` +fn main() { + let args: Vec = env::args().collect(); + + let config = Config::new(&args).unwrap_or_else(|err| { + eprintln!("Problem parsing arguments: {}", err); + process::exit(1); + }); + + if let Err(e) = minigrep::run(config) { + eprintln!("Application error: {}", e); + + process::exit(1); + } +} +``` + +Listing 12-24: Writing error messages to standard error instead of standard +output using `eprintln!` + +After changing `println!` to `eprintln!`, let’s run the program again in the +same way, without any arguments and redirecting standard output with `>`: + +``` +$ cargo run > output.txt +Problem parsing arguments: not enough arguments +``` + +Now we see the error onscreen and *output.txt* contains nothing, which is the +behavior we expect of command line programs. + +Let’s run the program again with arguments that don’t cause an error but still +redirect standard output to a file, like so: + +``` +$ cargo run to poem.txt > output.txt +``` + +We won’t see any output to the terminal, and *output.txt* will contain our +results: + +Filename: output.txt + +``` +Are you nobody, too? +How dreary to be somebody! +``` + +This demonstrates that we’re now using standard output for successful output +and standard error for error output as appropriate. + +## Summary + +This chapter recapped some of the major concepts you’ve learned so far and +covered how to perform common I/O operations in Rust. By using command line +arguments, files, environment variables, and the `eprintln!` macro for printing +errors, you’re now prepared to write command line applications. By using the +concepts in previous chapters, your code will be well organized, store data +effectively in the appropriate data structures, handle errors nicely, and be +well tested. + +Next, we’ll explore some Rust features that were influenced by functional +languages: closures and iterators. diff --git a/src/doc/book/rust-toolchain b/src/doc/book/rust-toolchain index 67fc7ad0d6..c88cb2a7b1 100644 --- a/src/doc/book/rust-toolchain +++ b/src/doc/book/rust-toolchain @@ -1 +1 @@ -1.55 +1.57 diff --git a/src/doc/book/src/SUMMARY.md b/src/doc/book/src/SUMMARY.md index 22c11ca78b..f0483544c0 100644 --- a/src/doc/book/src/SUMMARY.md +++ b/src/doc/book/src/SUMMARY.md @@ -32,7 +32,7 @@ - [Enums and Pattern Matching](ch06-00-enums.md) - [Defining an Enum](ch06-01-defining-an-enum.md) - - [The `match` Control Flow Operator](ch06-02-match.md) + - [The `match` Control Flow Construct](ch06-02-match.md) - [Concise Control Flow with `if let`](ch06-03-if-let.md) ## Basic Rust Literacy diff --git a/src/doc/book/src/appendix-04-useful-development-tools.md b/src/doc/book/src/appendix-04-useful-development-tools.md index 2909559af4..4f1f3ca953 100644 --- a/src/doc/book/src/appendix-04-useful-development-tools.md +++ b/src/doc/book/src/appendix-04-useful-development-tools.md @@ -158,26 +158,25 @@ For more information on Clippy, see [its documentation][clippy]. [clippy]: https://github.com/rust-lang/rust-clippy -### IDE Integration Using the Rust Language Server +### IDE Integration Using `rust-analyzer` -To help IDE integration, the Rust project distributes the *Rust Language -Server* (`rls`). This tool speaks the [Language Server -Protocol][lsp], which is a specification for IDEs and programming -languages to communicate with each other. Different clients can use the `rls`, -such as [the Rust plug-in for Visual Studio Code][vscode]. +To help IDE integration, the Rust community recommends using +[`rust-analyzer`][rust-analyzer]. This tool is a set of compiler-centric +utilities that speaks the [Language Server Protocol][lsp], which is a +specification for IDEs and programming languages to communicate with each +other. Different clients can use `rust-analyzer`, such as [the Rust analyzer +plug-in for Visual Studio Code][vscode]. [lsp]: http://langserver.org/ -[vscode]: https://marketplace.visualstudio.com/items?itemName=rust-lang.rust +[vscode]: https://marketplace.visualstudio.com/items?itemName=matklad.rust-analyzer -To install the `rls`, enter the following: +Visit the `rust-analyzer` project’s [home page][rust-analyzer] for installation +instructions, then install the language server support in your particular IDE. +Your IDE will gain abilities such as autocompletion, jump to definition, and +inline errors. -```console -$ rustup component add rls -``` +For more information on `rust-analyzer`, see [its +documentation][rust-analyzer-manual]. -Then install the language server support in your particular IDE; you’ll gain -abilities such as autocompletion, jump to definition, and inline errors. - -For more information on the `rls`, see [its documentation][rls]. - -[rls]: https://github.com/rust-lang/rls +[rust-analyzer]: https://rust-analyzer.github.io +[rust-analyzer-manual]: https://rust-analyzer.github.io/manual.html diff --git a/src/doc/book/src/appendix-05-editions.md b/src/doc/book/src/appendix-05-editions.md index db98ecc5ee..90828ebbaf 100644 --- a/src/doc/book/src/appendix-05-editions.md +++ b/src/doc/book/src/appendix-05-editions.md @@ -24,8 +24,8 @@ Editions serve different purposes for different people: * For those developing Rust, a new edition provides a rallying point for the project as a whole. -At the time of this writing, two Rust editions are available: Rust 2015 and -Rust 2018. This book is written using Rust 2018 edition idioms. +At the time of this writing, three Rust editions are available: Rust 2015, Rust +2018, and Rust 2021. This book is written using Rust 2021 edition idioms. The `edition` key in *Cargo.toml* indicates which edition the compiler should use for your code. If the key doesn’t exist, Rust uses `2015` as the edition diff --git a/src/doc/book/src/appendix-06-translation.md b/src/doc/book/src/appendix-06-translation.md index af7d614106..2986a958f9 100644 --- a/src/doc/book/src/appendix-06-translation.md +++ b/src/doc/book/src/appendix-06-translation.md @@ -11,7 +11,7 @@ For resources in languages other than English. Most are still in progress; see - [正體中文](https://github.com/rust-tw/book-tw) - [Українська](https://github.com/pavloslav/rust-book-uk-ua) - [Español](https://github.com/thecodix/book), [alternate](https://github.com/ManRR/rust-book-es) -- [Italiano](https://github.com/AgeOfWar/rust-book-it) +- [Italiano](https://github.com/Ciro-Fusco/book_it) - [Русский](https://github.com/rust-lang-ru/book) - [한국어](https://github.com/rinthel/rust-lang-book-ko) - [日本語](https://github.com/rust-lang-ja/book-ja) diff --git a/src/doc/book/src/ch00-00-introduction.md b/src/doc/book/src/ch00-00-introduction.md index 2a1b7745c0..5319698a7d 100644 --- a/src/doc/book/src/ch00-00-introduction.md +++ b/src/doc/book/src/ch00-00-introduction.md @@ -187,4 +187,4 @@ doesn’t compile. The source files from which this book is generated can be found on [GitHub][book]. -[book]: https://github.com/rust-lang/book/tree/master/src +[book]: https://github.com/rust-lang/book/tree/main/src diff --git a/src/doc/book/src/ch01-03-hello-cargo.md b/src/doc/book/src/ch01-03-hello-cargo.md index 2c018a04da..a6284499df 100644 --- a/src/doc/book/src/ch01-03-hello-cargo.md +++ b/src/doc/book/src/ch01-03-hello-cargo.md @@ -39,7 +39,7 @@ $ cargo new hello_cargo $ cd hello_cargo ``` -The first command creates a new directory called *hello_cargo*. We’ve named +The first command created a new directory called *hello_cargo*. We’ve named our project *hello_cargo*, and Cargo creates its files in a directory of the same name. @@ -64,7 +64,7 @@ code in Listing 1-2. [package] name = "hello_cargo" version = "0.1.0" -edition = "2018" +edition = "2021" [dependencies] ``` @@ -100,7 +100,7 @@ fn main() { Cargo has generated a “Hello, world!” program for you, just like the one we wrote in Listing 1-1! So far, the differences between our previous project and -the project Cargo generates are that Cargo placed the code in the *src* +the project Cargo generated are that Cargo placed the code in the *src* directory, and we have a *Cargo.toml* configuration file in the top directory. Cargo expects your source files to live inside the *src* directory. The diff --git a/src/doc/book/src/ch02-00-guessing-game-tutorial.md b/src/doc/book/src/ch02-00-guessing-game-tutorial.md index 234f7a3540..d709dbad26 100644 --- a/src/doc/book/src/ch02-00-guessing-game-tutorial.md +++ b/src/doc/book/src/ch02-00-guessing-game-tutorial.md @@ -221,9 +221,10 @@ we pass to it, but it also returns a value—in this case, an `Result` in its standard library: a generic [`Result`][result] as well as specific versions for submodules, such as `io::Result`. The `Result` types are [*enumerations*][enums], often referred to as *enums*, -which can have a fixed set of possibilites known as *variants*. Enums are often -used with `match`, a conditional that makes it convenient to execute different -code based on which variant an enum value is when the conditional is evaluated. +which can have a fixed set of possibilities known as *variants*. Enums are +often used with `match`, a conditional that makes it convenient to execute +different code based on which variant an enum value is when the conditional is +evaluated. Chapter 6 will cover enums in more detail. The purpose of these `Result` types is to encode error-handling information. @@ -469,7 +470,7 @@ $ cargo update Updating rand v0.8.3 -> v0.8.4 ``` -Cargo ignores the `0.9.0` releaese. At this point, you would also notice a +Cargo ignores the `0.9.0` release. At this point, you would also notice a change in your *Cargo.lock* file noting that the version of the `rand` crate you are now using is `0.8.4`. To use `rand` version `0.9.0` or any version in the `0.9.x` series, you’d have to update the *Cargo.toml* file to look like @@ -628,7 +629,7 @@ strong, static type system. However, it also has type inference. When we wrote a `String` and didn’t make us write the type. The `secret_number`, on the other hand, is a number type. A few of Rust’s number types can have a value between 1 and 100: `i32`, a 32-bit number; `u32`, an unsigned 32-bit number; `i64`, a -64-bit number; as well as others. Unless otherwise speceified, Rust defaults to +64-bit number; as well as others. Unless otherwise specified, Rust defaults to an `i32`, which is the type of `secret_number` unless you add type information elsewhere that would cause Rust to infer a different numerical type. The reason for the error is that Rust cannot compare a string and a number type. diff --git a/src/doc/book/src/ch03-01-variables-and-mutability.md b/src/doc/book/src/ch03-01-variables-and-mutability.md index 261279fb6d..d4d8b54016 100644 --- a/src/doc/book/src/ch03-01-variables-and-mutability.md +++ b/src/doc/book/src/ch03-01-variables-and-mutability.md @@ -69,7 +69,7 @@ When we run the program now, we get this: {{#include ../listings/ch03-common-programming-concepts/no-listing-02-adding-mut/output.txt}} ``` -We’re allowed to change the value that `x` binds to from `5` to `6` when `mut` +We’re allowed to change the value bound to `x` from `5` to `6` when `mut` is used. There are multiple trade-offs to consider in addition to the prevention of bugs. For example, in cases where you’re using large data structures, mutating an instance in place may be faster than copying and diff --git a/src/doc/book/src/ch03-03-how-functions-work.md b/src/doc/book/src/ch03-03-how-functions-work.md index 76aa243ab2..fea2248e82 100644 --- a/src/doc/book/src/ch03-03-how-functions-work.md +++ b/src/doc/book/src/ch03-03-how-functions-work.md @@ -179,12 +179,12 @@ Keep this in mind as you explore function return values and expressions next. ### Functions with Return Values Functions can return values to the code that calls them. We don’t name return -values, but we do declare their type after an arrow (`->`). In Rust, the return -value of the function is synonymous with the value of the final expression in -the block of the body of a function. You can return early from a function by -using the `return` keyword and specifying a value, but most functions return -the last expression implicitly. Here’s an example of a function that returns a -value: +values, but we must declare their type after an arrow (`->`). In Rust, the +return value of the function is synonymous with the value of the final +expression in the block of the body of a function. You can return early from a +function by using the `return` keyword and specifying a value, but most +functions return the last expression implicitly. Here’s an example of a +function that returns a value: Filename: src/main.rs diff --git a/src/doc/book/src/ch04-02-references-and-borrowing.md b/src/doc/book/src/ch04-02-references-and-borrowing.md index 82b7a7b31d..7c24d87315 100644 --- a/src/doc/book/src/ch04-02-references-and-borrowing.md +++ b/src/doc/book/src/ch04-02-references-and-borrowing.md @@ -165,7 +165,7 @@ through the last time that reference is used. For instance, this code will compile because the last usage of the immutable references, the `println!`, occurs before the mutable reference is introduced: -```rust,edition2018 +```rust,edition2021 {{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-13-reference-scope-ends/src/main.rs:here}} ``` diff --git a/src/doc/book/src/ch05-00-structs.md b/src/doc/book/src/ch05-00-structs.md index 3ef04c3d02..abf9b3040d 100644 --- a/src/doc/book/src/ch05-00-structs.md +++ b/src/doc/book/src/ch05-00-structs.md @@ -1,12 +1,13 @@ # Using Structs to Structure Related Data -A *struct*, or *structure*, is a custom data type that lets you name and -package together multiple related values that make up a meaningful group. If +A *struct*, or *structure*, is a custom data type that lets you package +together and name multiple related values that make up a meaningful group. If you’re familiar with an object-oriented language, a *struct* is like an object’s data attributes. In this chapter, we’ll compare and contrast tuples -with structs. We’ll demonstrate how to define and instantiate structs. We’ll -discuss how to define associated functions, especially the kind of associated -functions called *methods*, to specify behavior associated with a struct type. -Structs and enums (discussed in Chapter 6) are the building blocks for creating -new types in your program’s domain to take full advantage of Rust’s compile -time type checking. +with structs to build on what you already know and demonstrate when structs are +a better way to group data. We’ll demonstrate how to define and instantiate +structs. We’ll discuss how to define associated functions, especially the kind +of associated functions called *methods*, to specify behavior associated with a +struct type. Structs and enums (discussed in Chapter 6) are the building blocks +for creating new types in your program’s domain to take full advantage of +Rust’s compile time type checking. diff --git a/src/doc/book/src/ch05-01-defining-structs.md b/src/doc/book/src/ch05-01-defining-structs.md index ab405a4fb9..945d67f284 100644 --- a/src/doc/book/src/ch05-01-defining-structs.md +++ b/src/doc/book/src/ch05-01-defining-structs.md @@ -1,11 +1,11 @@ ## Defining and Instantiating Structs -Structs are similar to tuples, which were discussed in [“The Tuple -Type”][tuples] section. Like tuples, the pieces of a struct can -be different types. Unlike with tuples, you’ll name each piece of data so it’s -clear what the values mean. As a result of these names, structs are more -flexible than tuples: you don’t have to rely on the order of the data to -specify or access the values of an instance. +Structs are similar to tuples, discussed in [“The Tuple Type”][tuples] section, in that both hold multiple related values. Like tuples, the +pieces of a struct can be different types. Unlike with tuples, in a struct +you’ll name each piece of data so it’s clear what the values mean. Adding these +names means that structs are more flexible than tuples: you don’t have to rely +on the order of the data to specify or access the values of an instance. To define a struct, we enter the keyword `struct` and name the entire struct. A struct’s name should describe the significance of the pieces of data being @@ -36,7 +36,7 @@ example, we can declare a particular user as shown in Listing 5-2. Listing 5-2: Creating an instance of the `User` struct -To get a specific value from a struct, we can use dot notation. If we wanted +To get a specific value from a struct, we use dot notation. If we wanted just this user’s email address, we could use `user1.email` wherever we wanted to use this value. If the instance is mutable, we can change a value by using the dot notation and assigning into a particular field. Listing 5-3 shows how @@ -70,7 +70,8 @@ fields, but having to repeat the `email` and `username` field names and variables is a bit tedious. If the struct had more fields, repeating each name would get even more annoying. Luckily, there’s a convenient shorthand! -### Using the Field Init Shorthand when Variables and Fields Have the Same Name + +### Using the Field Init Shorthand Because the parameter names and the struct field names are exactly the same in Listing 5-4, we can use the *field init shorthand* syntax to rewrite @@ -93,13 +94,13 @@ than `email: email`. ### Creating Instances From Other Instances With Struct Update Syntax -It’s often useful to create a new instance of a struct that uses most of an old -instance’s values but changes some. You can do this using *struct update -syntax*. +It’s often useful to create a new instance of a struct that includes most of +the values from another instance, but changes some. You can do this using +*struct update syntax*. -First, Listing 5-6 shows how we create a new `User` instance in `user2` without -the update syntax. We set a new value for `email` but otherwise use the same -values from `user1` that we created in Listing 5-2. +First, in Listing 5-6 we show how to create a new `User` instance in `user2` +regularly, without the update syntax. We set a new value for `email` but +otherwise use the same values from `user1` that we created in Listing 5-2. ```rust {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/listing-05-06/src/main.rs:here}} @@ -128,32 +129,32 @@ corresponding fields in `user1`, but we can choose to specify values for as many fields as we want in any order, regardless of the order of the fields in the struct’s definition. -Note that the struct update syntax is like assignment with `=` because it moves -the data, just as we saw in the [“Ways Variables and Data Interact: Move” -section][move]. In this example, we can no longer use `user1` -after creating `user2` because the `String` in the `username` field of `user1` -was moved into `user2`. If we had given `user2` new `String` values for both -`email` and `username`, and thus only used the `active` and `sign_in_count` -values from `user1`, then `user1` would still be valid after creating `user2`. -The types of `active` and `sign_in_count` are types that implement the `Copy` -trait, so the behavior we discussed in the [“Stack-Only Data: Copy” -section][copy] would apply. +Note that the struct update syntax uses `=` like an assignment; this is +because it moves the data, just as we saw in the [“Ways Variables and Data +Interact: Move”][move] section. In this example, we can no +longer use `user1` after creating `user2` because the `String` in the +`username` field of `user1` was moved into `user2`. If we had given `user2` new +`String` values for both `email` and `username`, and thus only used the +`active` and `sign_in_count` values from `user1`, then `user1` would still be +valid after creating `user2`. The types of `active` and `sign_in_count` are +types that implement the `Copy` trait, so the behavior we discussed in the +[“Stack-Only Data: Copy”][copy] section would apply. ### Using Tuple Structs without Named Fields to Create Different Types -You can also define structs that look similar to tuples, called *tuple +Rust also supports structs that look similar to tuples, called *tuple structs*. Tuple structs have the added meaning the struct name provides but don’t have names associated with their fields; rather, they just have the types of the fields. Tuple structs are useful when you want to give the whole tuple a -name and make the tuple be a different type from other tuples, and naming each +name and make the tuple a different type from other tuples, and when naming each field as in a regular struct would be verbose or redundant. To define a tuple struct, start with the `struct` keyword and the struct name -followed by the types in the tuple. For example, here are definitions and -usages of two tuple structs named `Color` and `Point`: +followed by the types in the tuple. For example, here we define and use +two tuple structs named `Color` and `Point`: ```rust -{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/src/main.rs:here}} +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/no-listing-01-tuple-structs/src/main.rs}} ``` Note that the `black` and `origin` values are different types, because they’re @@ -170,37 +171,37 @@ individual value, and so on. You can also define structs that don’t have any fields! These are called *unit-like structs* because they behave similarly to `()`, the unit type that we mentioned in [“The Tuple Type”][tuples] section. Unit-like -structs can be useful in situations in which you need to implement a trait on -some type but don’t have any data that you want to store in the type itself. -We’ll discuss traits in Chapter 10. Here’s an example of declaring and -instantiating a unit struct named `AlwaysEqual`: +structs can be useful when you need to implement a trait on some type but don’t +have any data that you want to store in the type itself. We’ll discuss traits +in Chapter 10. Here’s an example of declaring and instantiating a unit struct +named `AlwaysEqual`: ```rust -{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/src/main.rs:here}} +{{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/no-listing-04-unit-like-structs/src/main.rs}} ``` To define `AlwaysEqual`, we use the `struct` keyword, the name we want, then a semicolon. No need for curly brackets or parentheses! Then we can get an instance of `AlwaysEqual` in the `subject` variable in a similar way: using the -name we defined, without any curly brackets or parentheses. Imagine we’ll be -implementing behavior for this type that every instance is always equal to -every instance of every other type, perhaps to have a known result for testing -purposes. We wouldn’t need any data to implement that behavior! You’ll see in -Chapter 10 how to define traits and implement them on any type, including -unit-like structs. +name we defined, without any curly brackets or parentheses. Imagine that later +we’ll implement behavior for this type such that every instance of +`AlwaysEqual` is always equal to every instance of any other type, perhaps to +have a known result for testing purposes. We wouldn’t need any data to +implement that behavior! You’ll see in Chapter 10 how to define traits and +implement them on any type, including unit-like structs. > ### Ownership of Struct Data > > In the `User` struct definition in Listing 5-1, we used the owned `String` > type rather than the `&str` string slice type. This is a deliberate choice -> because we want instances of this struct to own all of its data and for that -> data to be valid for as long as the entire struct is valid. +> because we want each instance of this struct to own all of its data and for +> that data to be valid for as long as the entire struct is valid. > -> It’s possible for structs to store references to data owned by something else, -> but to do so requires the use of *lifetimes*, a Rust feature that we’ll +> It’s also possible for structs to store references to data owned by something +> else, but to do so requires the use of *lifetimes*, a Rust feature that we’ll > discuss in Chapter 10. Lifetimes ensure that the data referenced by a struct > is valid for as long as the struct is. Let’s say you try to store a reference -> in a struct without specifying lifetimes, like this, which won’t work: +> in a struct without specifying lifetimes, like the following; this won’t work: > > Filename: src/main.rs > @@ -208,10 +209,10 @@ unit-like structs. > > ```rust,ignore,does_not_compile > struct User { +> active: bool, > username: &str, > email: &str, > sign_in_count: u64, -> active: bool, > } > > fn main() { @@ -230,36 +231,34 @@ unit-like structs. > $ cargo run > Compiling structs v0.1.0 (file:///projects/structs) > error[E0106]: missing lifetime specifier -> --> src/main.rs:2:15 +> --> src/main.rs:3:15 > | -> 2 | username: &str, +> 3 | username: &str, > | ^ expected named lifetime parameter > | > help: consider introducing a named lifetime parameter > | -> 1 | struct User<'a> { -> 2 | username: &'a str, +> 1 ~ struct User<'a> { +> 2 | active: bool, +> 3 ~ username: &'a str, > | > > error[E0106]: missing lifetime specifier -> --> src/main.rs:3:12 +> --> src/main.rs:4:12 > | -> 3 | email: &str, +> 4 | email: &str, > | ^ expected named lifetime parameter > | > help: consider introducing a named lifetime parameter > | -> 1 | struct User<'a> { -> 2 | username: &str, -> 3 | email: &'a str, +> 1 ~ struct User<'a> { +> 2 | active: bool, +> 3 | username: &str, +> 4 ~ email: &'a str, > | > -> error: aborting due to 2 previous errors -> > For more information about this error, try `rustc --explain E0106`. -> error: could not compile `structs` -> -> To learn more, run the command again with --verbose. +> error: could not compile `structs` due to 2 previous errors > ``` > > In Chapter 10, we’ll discuss how to fix these errors so you can store diff --git a/src/doc/book/src/ch05-02-example-structs.md b/src/doc/book/src/ch05-02-example-structs.md index ff7640f093..c737e508c8 100644 --- a/src/doc/book/src/ch05-02-example-structs.md +++ b/src/doc/book/src/ch05-02-example-structs.md @@ -1,8 +1,8 @@ ## An Example Program Using Structs To understand when we might want to use structs, let’s write a program that -calculates the area of a rectangle. We’ll start with single variables, and then -refactor the program until we’re using structs instead. +calculates the area of a rectangle. We’ll start by using single variables, and +then refactor the program until we’re using structs instead. Let’s make a new binary project with Cargo called *rectangles* that will take the width and height of a rectangle specified in pixels and calculate the area @@ -24,10 +24,9 @@ Now, run this program using `cargo run`: {{#include ../listings/ch05-using-structs-to-structure-related-data/listing-05-08/output.txt}} ``` -Even though Listing 5-8 works and figures out the area of the rectangle by -calling the `area` function with each dimension, we can do better. The width -and the height are related to each other because together they describe one -rectangle. +This code succeeds in figuring out the area of the rectangle by calling the +`area` function with each dimension, but we can do more to make this code clear +and readable. The issue with this code is evident in the signature of `area`: @@ -36,8 +35,8 @@ The issue with this code is evident in the signature of `area`: ``` The `area` function is supposed to calculate the area of one rectangle, but the -function we wrote has two parameters. The parameters are related, but that’s -not expressed anywhere in our program. It would be more readable and more +function we wrote has two parameters, and it’s not clear anywhere in our +program that the parameters are related. It would be more readable and more manageable to group width and height together. We’ve already discussed one way we might do that in [“The Tuple Type”][the-tuple-type] section of Chapter 3: by using tuples. @@ -57,21 +56,20 @@ rectangle with a tuple In one way, this program is better. Tuples let us add a bit of structure, and we’re now passing just one argument. But in another way, this version is less -clear: tuples don’t name their elements, so our calculation has become more -confusing because we have to index into the parts of the tuple. +clear: tuples don’t name their elements, so we have to index into the parts of +the tuple, making our calculation less obvious. -It doesn’t matter if we mix up width and height for the area calculation, but -if we want to draw the rectangle on the screen, it would matter! We would have -to keep in mind that `width` is the tuple index `0` and `height` is the tuple -index `1`. If someone else worked on this code, they would have to figure this -out and keep it in mind as well. It would be easy to forget or mix up these -values and cause errors, because we haven’t conveyed the meaning of our data in -our code. +Mixing up the width and height wouldn’t matter for the area calculation, but if +we want to draw the rectangle on the screen, it would matter! We would have to +keep in mind that `width` is the tuple index `0` and `height` is the tuple +index `1`. This would be even harder for someone else to figure out and keep in +mind if they were to use our code. Because we haven’t conveyed the meaning of +our data in our code, it’s now easier to introduce errors. ### Refactoring with Structs: Adding More Meaning We use structs to add meaning by labeling the data. We can transform the tuple -we’re using into a data type with a name for the whole as well as names for the +we’re using into a struct with a name for the whole as well as names for the parts, as shown in Listing 5-10. Filename: src/main.rs @@ -103,7 +101,7 @@ and `1`. This is a win for clarity. ### Adding Useful Functionality with Derived Traits -It’d be nice to be able to print an instance of `Rectangle` while we’re +It’d be useful to be able to print an instance of `Rectangle` while we’re debugging our program and see the values for all its fields. Listing 5-11 tries using the [`println!` macro][println] as we have used in previous chapters. This won’t work, however. @@ -132,7 +130,7 @@ a `1` or any other primitive type to a user. But with structs, the way display possibilities: Do you want commas or not? Do you want to print the curly brackets? Should all the fields be shown? Due to this ambiguity, Rust doesn’t try to guess what we want, and structs don’t have a provided -implementation of `Display`. +implementation of `Display` to use with `println!` and the `{}` placeholder. If we continue reading the errors, we’ll find this helpful note: @@ -183,23 +181,25 @@ Nice! It’s not the prettiest output, but it shows the values of all the fields for this instance, which would definitely help during debugging. When we have larger structs, it’s useful to have output that’s a bit easier to read; in those cases, we can use `{:#?}` instead of `{:?}` in the `println!` string. -When we use the `{:#?}` style in the example, the output will look like this: +In this example, using the `{:#?}` style will output: ```console {{#include ../listings/ch05-using-structs-to-structure-related-data/output-only-02-pretty-debug/output.txt}} ``` -Another way to print out a value using the `Debug` format is by using the -[`dbg!` macro][dbg] . The `dbg!` macro takes ownership of an -expression, prints the file and line number of where that `dbg!` macro call -occurs in your code along with the resulting value of that expression, and -returns ownership of the value. Calling the `dbg!` macro prints to the standard -error console stream (`stderr`), as opposed to `println!` which prints to the -standard output console stream (`stdout`). We’ll talk more about `stderr` and -`stdout` in the [“Writing Error Messages to Standard Error Instead of Standard -Output” section in Chapter 12][err]. Here’s an example where -we’re interested in the value that gets assigned to the `width` field, as well -as the value of the whole struct in `rect1`: +Another way to print out a value using the `Debug` format is to use the [`dbg!` +macro][dbg], which takes ownership of an expression, prints the +file and line number of where that `dbg!` macro call occurs in your code along +with the resulting value of that expression, and returns ownership of the value. + +> Note: Calling the `dbg!` macro prints to the standard error console stream +> (`stderr`), as opposed to `println!` which prints to the standard output +> console stream (`stdout`). We’ll talk more about `stderr` and `stdout` in the +> “[“Writing Error Messages to Standard Error Instead of Standard +> Output” section in Chapter 12][err]. + +Here’s an example where we’re interested in the value that gets assigned to the +`width` field, as well as the value of the whole struct in `rect1`: ```rust {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/no-listing-05-dbg-macro/src/main.rs}} @@ -208,7 +208,7 @@ as the value of the whole struct in `rect1`: We can put `dbg!` around the expression `30 * scale` and, because `dbg!` returns ownership of the expression’s value, the `width` field will get the same value as if we didn’t have the `dbg!` call there. We don’t want `dbg!` to -take ownership of `rect1`, so we use a reference to `dbg!` in the next call. +take ownership of `rect1`, so we use a reference to `rect1` in the next call. Here’s what the output of this example looks like: ```console diff --git a/src/doc/book/src/ch05-03-method-syntax.md b/src/doc/book/src/ch05-03-method-syntax.md index a9de20df3b..6e4416cb93 100644 --- a/src/doc/book/src/ch05-03-method-syntax.md +++ b/src/doc/book/src/ch05-03-method-syntax.md @@ -1,12 +1,12 @@ ## Method Syntax -*Methods* are similar to functions: they’re declared with the `fn` keyword and -their name, they can have parameters and a return value, and they contain some -code that is run when they’re called from somewhere else. However, methods are -different from functions in that they’re defined within the context of a struct -(or an enum or a trait object, which we cover in Chapters 6 and 17, -respectively), and their first parameter is always `self`, which represents the -instance of the struct the method is being called on. +*Methods* are similar to functions: we declare them with the `fn` keyword and a +name, they can have parameters and a return value, and they contain some code +that’s run when the method is called from somewhere else. Unlike functions, +methods are defined within the context of a struct (or an enum or a trait +object, which we cover in Chapters 6 and 17, respectively), and their first +parameter is always `self`, which represents the instance of the struct the +method is being called on. ### Defining Methods @@ -52,7 +52,7 @@ instance by using just `self` as the first parameter is rare; this technique is usually used when the method transforms `self` into something else and you want to prevent the caller from using the original instance after the transformation. -The main benefit of using methods instead of functions, in addition to using +The main reason for using methods instead of functions, in addition to providing method syntax and not having to repeat the type of `self` in every method’s signature, is for organization. We’ve put all the things we can do with an instance of a type in one `impl` block rather than making future users of our @@ -68,21 +68,20 @@ fields. For example, we can define a method on `Rectangle` also named `width`: {{#rustdoc_include ../listings/ch05-using-structs-to-structure-related-data/no-listing-06-method-field-interaction/src/main.rs:here}} ``` -Here, we’re choosing to make the behavior of the `width` method be that it -returns `true` if the value in the instance’s `width` field is greater than 0, -and `false` if the value is 0: we can use a field within a method of the same -name for any purpose. In `main`, when we follow `rect1.width` with parentheses, -Rust knows we mean the method `width`. When we don’t use parentheses, Rust -knows we mean the field `width`. +Here, we’re choosing to make the `width` method return `true` if the value in +the instance’s `width` field is greater than 0, and `false` if the value is 0: +we can use a field within a method of the same name for any purpose. In `main`, +when we follow `rect1.width` with parentheses, Rust knows we mean the method +`width`. When we don’t use parentheses, Rust knows we mean the field `width`. -Often, but not always, methods with the same name as a field will be defined to -only return the value in the field and do nothing else. Methods like this are -called *getters*, and Rust does not implement them automatically for struct -fields as some other languages do. Getters are useful because you can make the -field private but the method public and thus enable read-only access to that -field as part of the type’s public API. We will be discussing what public and -private are and how to designate a field or method as public or private in -Chapter 7. +Often, but not always, when we give methods with the same name as a field we +want it to only return the value in the field and do nothing else. Methods like +this are called *getters*, and Rust does not implement them automatically for +struct fields as some other languages do. Getters are useful because you can +make the field private but the method public and thus enable read-only access +to that field as part of the type’s public API. We will be discussing what +public and private are and how to designate a field or method as public or +private in Chapter 7. > ### Where’s the `->` Operator? > @@ -134,9 +133,9 @@ Chapter 7. Let’s practice using methods by implementing a second method on the `Rectangle` struct. This time, we want an instance of `Rectangle` to take another instance of `Rectangle` and return `true` if the second `Rectangle` can fit completely -within `self`; otherwise it should return `false`. That is, we want to be able -to write the program shown in Listing 5-14, once we’ve defined the `can_hold` -method. +within `self` (the first `Rectangle`); otherwise it should return `false`. That +is, once we’ve defined the `can_hold` method, we want to be able to write the +program shown in Listing 5-14. Filename: src/main.rs @@ -190,7 +189,7 @@ All functions defined within an `impl` block are called *associated functions* because they’re associated with the type named after the `impl`. We can define associated functions that don’t have `self` as their first parameter (and thus are not methods) because they don’t need an instance of the type to work with. -We’ve already used one function like this, the `String::from` function, that’s +We’ve already used one function like this: the `String::from` function that’s defined on the `String` type. Associated functions that aren’t methods are often used for constructors that diff --git a/src/doc/book/src/ch06-00-enums.md b/src/doc/book/src/ch06-00-enums.md index cf7ea67f60..7fdfc2ccbc 100644 --- a/src/doc/book/src/ch06-00-enums.md +++ b/src/doc/book/src/ch06-00-enums.md @@ -7,8 +7,8 @@ data. Next, we’ll explore a particularly useful enum, called `Option`, which expresses that a value can be either something or nothing. Then we’ll look at how pattern matching in the `match` expression makes it easy to run different code for different values of an enum. Finally, we’ll cover how the `if let` -construct is another convenient and concise idiom available to you to handle -enums in your code. +construct is another convenient and concise idiom available to handle enums in +your code. Enums are a feature in many languages, but their capabilities differ in each language. Rust’s enums are most similar to *algebraic data types* in functional diff --git a/src/doc/book/src/ch06-01-defining-an-enum.md b/src/doc/book/src/ch06-01-defining-an-enum.md index ce581642f0..33bf8eaa26 100644 --- a/src/doc/book/src/ch06-01-defining-an-enum.md +++ b/src/doc/book/src/ch06-01-defining-an-enum.md @@ -1,15 +1,16 @@ ## Defining an Enum -Let’s look at a situation we might want to express in code and see why enums -are useful and more appropriate than structs in this case. Say we need to work -with IP addresses. Currently, two major standards are used for IP addresses: -version four and version six. These are the only possibilities for an IP -address that our program will come across: we can *enumerate* all possible -variants, which is where enumeration gets its name. +Enums are a way of defining custom data types in a different way than you do +with structs. Let’s look at a situation we might want to express in code and +see why enums are useful and more appropriate than structs in this case. Say we +need to work with IP addresses. Currently, two major standards are used for IP +addresses: version four and version six. Because these are the only +possibilities for an IP address that our program will come across, we can +*enumerate* all possible variants, which is where enumeration gets its name. Any IP address can be either a version four or a version six address, but not both at the same time. That property of IP addresses makes the enum data -structure appropriate, because enum values can only be one of its variants. +structure appropriate, because an enum value can only be one of its variants. Both version four and version six addresses are still fundamentally IP addresses, so they should be treated as the same type when the code is handling situations that apply to any kind of IP address. @@ -33,10 +34,9 @@ We can create instances of each of the two variants of `IpAddrKind` like this: ``` Note that the variants of the enum are namespaced under its identifier, and we -use a double colon to separate the two. The reason this is useful is that now -both values `IpAddrKind::V4` and `IpAddrKind::V6` are of the same type: -`IpAddrKind`. We can then, for instance, define a function that takes any -`IpAddrKind`: +use a double colon to separate the two. This is useful because now both values +`IpAddrKind::V4` and `IpAddrKind::V6` are of the same type: `IpAddrKind`. We +can then, for instance, define a function that takes any `IpAddrKind`: ```rust {{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-01-defining-enums/src/main.rs:fn}} @@ -51,7 +51,8 @@ And we can call this function with either variant: Using enums has even more advantages. Thinking more about our IP address type, at the moment we don’t have a way to store the actual IP address *data*; we only know what *kind* it is. Given that you just learned about structs in -Chapter 5, you might tackle this problem as shown in Listing 6-1. +Chapter 5, you might be tempted to tackle this problem with structs as shown in +Listing 6-1. ```rust {{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-01/src/main.rs:here}} @@ -62,15 +63,15 @@ an IP address using a `struct` Here, we’ve defined a struct `IpAddr` that has two fields: a `kind` field that is of type `IpAddrKind` (the enum we defined previously) and an `address` field -of type `String`. We have two instances of this struct. The first, `home`, has -the value `IpAddrKind::V4` as its `kind` with associated address data of -`127.0.0.1`. The second instance, `loopback`, has the other variant of -`IpAddrKind` as its `kind` value, `V6`, and has address `::1` associated with -it. We’ve used a struct to bundle the `kind` and `address` values together, so -now the variant is associated with the value. +of type `String`. We have two instances of this struct. The first is `home`, +and it has the value `IpAddrKind::V4` as its `kind` with associated address +data of `127.0.0.1`. The second instance is `loopback`. It has the other +variant of `IpAddrKind` as its `kind` value, `V6`, and has address `::1` +associated with it. We’ve used a struct to bundle the `kind` and `address` +values together, so now the variant is associated with the value. -We can represent the same concept in a more concise way using just an enum, -rather than an enum inside a struct, by putting data directly into each enum +However, representing the same concept using just an enum is more concise: +rather than an enum inside a struct, we can put data directly into each enum variant. This new definition of the `IpAddr` enum says that both `V4` and `V6` variants will have associated `String` values: @@ -106,8 +107,6 @@ we’ve defined and used, but it embeds the address data inside the variants in the form of two different structs, which are defined differently for each variant: -[IpAddr]: ../std/net/enum.IpAddr.html - ```rust struct Ipv4Addr { // --snip-- @@ -182,15 +181,14 @@ useful: `Option`. ### The `Option` Enum and Its Advantages Over Null Values -In the previous section, we looked at how the `IpAddr` enum let us use Rust’s -type system to encode more information than just the data into our program. This section explores a case study of `Option`, which is another enum defined -by the standard library. The `Option` type is used in many places because it -encodes the very common scenario in which a value could be something or it -could be nothing. Expressing this concept in terms of the type system means the -compiler can check whether you’ve handled all the cases you should be handling; -this functionality can prevent bugs that are extremely common in other -programming languages. +by the standard library. The `Option` type encodes the very common scenario in +which a value could be something or it could be nothing. For example, if you +request the first of a list containing items, you would get a value. If you +request the first item of an empty list, you would get nothing. Expressing this +concept in terms of the type system means the compiler can check whether you’ve +handled all the cases you should be handling; this functionality can prevent +bugs that are extremely common in other programming languages. Programming language design is often thought of in terms of which features you include, but the features you exclude are important too. Rust doesn’t have the @@ -223,8 +221,6 @@ that can encode the concept of a value being present or absent. This enum is `Option`, and it is [defined by the standard library][option] as follows: -[option]: ../std/option/enum.Option.html - ```rust enum Option { None, @@ -233,10 +229,10 @@ enum Option { ``` The `Option` enum is so useful that it’s even included in the prelude; you -don’t need to bring it into scope explicitly. In addition, so are its variants: -you can use `Some` and `None` directly without the `Option::` prefix. The -`Option` enum is still just a regular enum, and `Some(T)` and `None` are -still variants of type `Option`. +don’t need to bring it into scope explicitly. Its variants are also included in +the prelude: you can use `Some` and `None` directly without the `Option::` +prefix. The `Option` enum is still just a regular enum, and `Some(T)` and +`None` are still variants of type `Option`. The `` syntax is a feature of Rust we haven’t talked about yet. It’s a generic type parameter, and we’ll cover generics in more detail in Chapter 10. @@ -292,7 +288,7 @@ perform `T` operations with it. Generally, this helps catch one of the most common issues with null: assuming that something isn’t null when it actually is. -Not having to worry about incorrectly assuming a not-null value helps you to be +Eliminating the risk of incorrectly assuming a not-null value helps you to be more confident in your code. In order to have a value that can possibly be null, you must explicitly opt in by making the type of that value `Option`. Then, when you use that value, you are required to explicitly handle the case @@ -307,8 +303,6 @@ number of methods that are useful in a variety of situations; you can check them out in [its documentation][docs]. Becoming familiar with the methods on `Option` will be extremely useful in your journey with Rust. -[docs]: ../std/option/enum.Option.html - In general, in order to use an `Option` value, you want to have code that will handle each variant. You want some code that will run only when you have a `Some(T)` value, and this code is allowed to use the inner `T`. You want some @@ -317,3 +311,7 @@ value available. The `match` expression is a control flow construct that does just this when used with enums: it will run different code depending on which variant of the enum it has, and that code can use the data inside the matching value. + +[IpAddr]: ../std/net/enum.IpAddr.html +[option]: ../std/option/enum.Option.html +[docs]: ../std/option/enum.Option.html diff --git a/src/doc/book/src/ch06-02-match.md b/src/doc/book/src/ch06-02-match.md index d2baa0c914..a6056e0739 100644 --- a/src/doc/book/src/ch06-02-match.md +++ b/src/doc/book/src/ch06-02-match.md @@ -1,6 +1,7 @@ -## The `match` Control Flow Operator + +## The `match` Control Flow Construct -Rust has an extremely powerful control flow operator called `match` that allows +Rust has an extremely powerful control flow construct called `match` that allows you to compare a value against a series of patterns and then execute code based on which pattern matches. Patterns can be made up of literal values, variable names, wildcards, and many other things; Chapter 18 covers all the different @@ -13,11 +14,10 @@ down a track with variously sized holes along it, and each coin falls through the first hole it encounters that it fits into. In the same way, values go through each pattern in a `match`, and at the first pattern the value “fits,” the value falls into the associated code block to be used during execution. - -Because we just mentioned coins, let’s use them as an example using `match`! We -can write a function that can take an unknown United States coin and, in a -similar way as the counting machine, determine which coin it is and return its -value in cents, as shown here in Listing 6-3. +Speaking of coins, let’s use them as an example using `match`! We can write a +function that takes an unknown United States coin and, in a similar way as the +counting machine, determines which coin it is and return its value in cents, as +shown here in Listing 6-3. ```rust {{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/listing-06-03/src/main.rs:here}} @@ -30,8 +30,8 @@ Let’s break down the `match` in the `value_in_cents` function. First, we list the `match` keyword followed by an expression, which in this case is the value `coin`. This seems very similar to an expression used with `if`, but there’s a big difference: with `if`, the expression needs to return a Boolean value, but -here, it can be any type. The type of `coin` in this example is the `Coin` enum -that we defined on line 1. +here, it can return any type. The type of `coin` in this example is the `Coin` +enum that we defined on the first line. Next are the `match` arms. An arm has two parts: a pattern and some code. The first arm here has a pattern that is the value `Coin::Penny` and then the `=>` @@ -48,11 +48,11 @@ The code associated with each arm is an expression, and the resulting value of the expression in the matching arm is the value that gets returned for the entire `match` expression. -Curly brackets typically aren’t used if the match arm code is short, as it is +We don't typically use curly brackets if the match arm code is short, as it is in Listing 6-3 where each arm just returns a value. If you want to run multiple -lines of code in a match arm, you can use curly brackets. For example, the -following code would print “Lucky penny!” every time the method was called with -a `Coin::Penny` but would still return the last value of the block, `1`: +lines of code in a match arm, you must use curly brackets. For example, the +following code prints “Lucky penny!” every time the method is called with a +`Coin::Penny`, but still returns the last value of the block, `1`: ```rust {{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-08-match-arm-multiple-lines/src/main.rs:here}} @@ -78,10 +78,10 @@ inside it, which we’ve done here in Listing 6-4. Listing 6-4: A `Coin` enum in which the `Quarter` variant also holds a `UsState` value -Let’s imagine that a friend of ours is trying to collect all 50 state quarters. -While we sort our loose change by coin type, we’ll also call out the name of -the state associated with each quarter so if it’s one our friend doesn’t have, -they can add it to their collection. +Let’s imagine that a friend is trying to collect all 50 state quarters. While +we sort our loose change by coin type, we’ll also call out the name of the +state associated with each quarter so if it’s one our friend doesn’t have, they +can add it to their collection. In the match expression for this code, we add a variable called `state` to the pattern that matches values of the variant `Coin::Quarter`. When a @@ -185,15 +185,15 @@ have null, thus making the billion-dollar mistake discussed earlier impossible. ### Catch-all Patterns and the `_` Placeholder -Let’s look at an example where we want to take special actions for a few -particular values, but for all other values take one default action. Imagine -we’re implementing a game where if you get a value of 3 on a dice roll, your -player doesn’t move, but instead gets a new fancy hat. If you roll a 7, your -player loses a fancy hat. For all other values, your player moves that number -of spaces on the game board. Here’s a `match` that implements that logic, with -the result of the dice roll hardcoded rather than a random value, and all other -logic represented by functions without bodies because actually implementing -them is out of scope for this example: +Using enums, we can also take special actions for a few particular values, but +for all other values take one default action. Imagine we’re implementing a game +where, if you roll a 3 on a dice roll, your player doesn’t move, but instead +gets a new fancy hat. If you roll a 7, your player loses a fancy hat. For all +other values, your player moves that number of spaces on the game board. Here’s +a `match` that implements that logic, with the result of the dice roll +hardcoded rather than a random value, and all other logic represented by +functions without bodies because actually implementing them is out of scope for +this example: ```rust {{#rustdoc_include ../listings/ch06-enums-and-pattern-matching/no-listing-15-binding-catchall/src/main.rs:here}} diff --git a/src/doc/book/src/ch06-03-if-let.md b/src/doc/book/src/ch06-03-if-let.md index c78c3ee89b..07634e1620 100644 --- a/src/doc/book/src/ch06-03-if-let.md +++ b/src/doc/book/src/ch06-03-if-let.md @@ -12,11 +12,11 @@ variable but only wants to execute code if the value is the `Some` variant. Listing 6-6: A `match` that only cares about executing code when the value is `Some` -If the value is `Some`, we want to print out the value in the `Some` variant, -which we do by binding the value to the variable `max` in the pattern. -We don’t want to do anything with the `None` value. To satisfy the `match` -expression, we have to add `_ => ()` after processing just one variant, which -is annoying boilerplate code to add. +If the value is `Some`, we print out the value in the `Some` variant by binding +the value to the variable `max` in the pattern. We don’t want to do anything +with the `None` value. To satisfy the `match` expression, we have to add `_ => +()` after processing just one variant, which is annoying boilerplate code to +add. Instead, we could write this in a shorter way using `if let`. The following code behaves the same as the `match` in Listing 6-6: diff --git a/src/doc/book/src/ch07-01-packages-and-crates.md b/src/doc/book/src/ch07-01-packages-and-crates.md index 7292726128..d4411a06ad 100644 --- a/src/doc/book/src/ch07-01-packages-and-crates.md +++ b/src/doc/book/src/ch07-01-packages-and-crates.md @@ -37,7 +37,7 @@ or binary. Here, we have a package that only contains *src/main.rs*, meaning it only contains a binary crate named `my-project`. If a package contains *src/main.rs* -and *src/lib.rs*, it has two crates: a library and a binary, both with the same +and *src/lib.rs*, it has two crates: a binary and a library, both with the same name as the package. A package can have multiple binary crates by placing files in the *src/bin* directory: each file will be a separate binary crate. diff --git a/src/doc/book/src/ch08-01-vectors.md b/src/doc/book/src/ch08-01-vectors.md index c629cc5aab..15cf84db5e 100644 --- a/src/doc/book/src/ch08-01-vectors.md +++ b/src/doc/book/src/ch08-01-vectors.md @@ -165,7 +165,7 @@ programs from ending up in that situation. > Note: For more on the implementation details of the `Vec` type, see [“The > Rustonomicon”][nomicon]. -### Iterating over the Values in a Vector +### Iterating Over the Values in a Vector If we want to access each element in a vector in turn, we can iterate through all of the elements rather than use indices to access one at a time. Listing diff --git a/src/doc/book/src/ch11-01-writing-tests.md b/src/doc/book/src/ch11-01-writing-tests.md index 0c41f4a1c1..08cc5dbcaf 100644 --- a/src/doc/book/src/ch11-01-writing-tests.md +++ b/src/doc/book/src/ch11-01-writing-tests.md @@ -520,8 +520,9 @@ mark operator in the body of tests, which can be a convenient way to write tests that should fail if any operation within them returns an `Err` variant. You can’t use the `#[should_panic]` annotation on tests that use `Result`. Instead, you should return an `Err` value directly when the test should -fail. +E>`. To assert that an operation returns an `Err` variant, *don’t* use the +question mark operator on the `Result` value. Instead, use +`assert!(value.is_err())`. Now that you know several ways to write tests, let’s look at what is happening when we run our tests and explore the different options we can use with `cargo diff --git a/src/doc/book/src/ch11-02-running-tests.md b/src/doc/book/src/ch11-02-running-tests.md index c33280e349..1d176fbf6a 100644 --- a/src/doc/book/src/ch11-02-running-tests.md +++ b/src/doc/book/src/ch11-02-running-tests.md @@ -180,4 +180,5 @@ the ignored tests, we can use `cargo test -- --ignored`: By controlling which tests run, you can make sure your `cargo test` results will be fast. When you’re at a point where it makes sense to check the results of the `ignored` tests and you have time to wait for the results, you can run -`cargo test -- --ignored` instead. +`cargo test -- --ignored` instead. If you want to run all tests whether they’re +ignored or not, you can run `cargo test -- --include-ignored`. diff --git a/src/doc/book/src/ch12-03-improving-error-handling-and-modularity.md b/src/doc/book/src/ch12-03-improving-error-handling-and-modularity.md index b8a91623f7..75aa4fb39f 100644 --- a/src/doc/book/src/ch12-03-improving-error-handling-and-modularity.md +++ b/src/doc/book/src/ch12-03-improving-error-handling-and-modularity.md @@ -112,9 +112,6 @@ struct fields a meaningful name. Doing so will make it easier for future maintainers of this code to understand how the different values relate to each other and what their purpose is. -> Note: Using primitive values when a complex type would be more appropriate is -> an anti-pattern known as *primitive obsession*. - Listing 12-6 shows the improvements to the `parse_config` function. Filename: src/main.rs @@ -269,7 +266,7 @@ next listing. Filename: src/main.rs -```rust,ignore +```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch12-an-io-project/listing-12-09/src/main.rs:here}} ``` @@ -277,7 +274,8 @@ next listing. `Config::new` Our `new` function now returns a `Result` with a `Config` instance in the -success case and a `&str` in the error case. +success case and a `&'static str` in the error case. Our error values will +always be string literals that have the `'static` lifetime. We’ve made two changes in the body of the `new` function: instead of calling `panic!` when the user doesn’t pass enough arguments, we now return an `Err` @@ -458,7 +456,7 @@ compile until we modify *src/main.rs* in Listing 12-14. Filename: src/lib.rs -```rust,ignore +```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch12-an-io-project/listing-12-13/src/lib.rs:here}} ``` diff --git a/src/doc/book/src/ch12-04-testing-the-librarys-functionality.md b/src/doc/book/src/ch12-04-testing-the-librarys-functionality.md index bf3e4f1f52..38ac639250 100644 --- a/src/doc/book/src/ch12-04-testing-the-librarys-functionality.md +++ b/src/doc/book/src/ch12-04-testing-the-librarys-functionality.md @@ -4,8 +4,7 @@ Now that we’ve extracted the logic into *src/lib.rs* and left the argument collecting and error handling in *src/main.rs*, it’s much easier to write tests for the core functionality of our code. We can call functions directly with various arguments and check return values without having to call our binary -from the command line. Feel free to write some tests for the functionality in -the `Config::new` and `run` functions on your own. +from the command line. In this section, we’ll add the searching logic to the `minigrep` program by using the Test-driven development (TDD) process. This software development diff --git a/src/doc/book/src/ch12-06-writing-to-stderr-instead-of-stdout.md b/src/doc/book/src/ch12-06-writing-to-stderr-instead-of-stdout.md index 0d6a45a6cc..dabfeeaa11 100644 --- a/src/doc/book/src/ch12-06-writing-to-stderr-instead-of-stdout.md +++ b/src/doc/book/src/ch12-06-writing-to-stderr-instead-of-stdout.md @@ -1,9 +1,9 @@ ## Writing Error Messages to Standard Error Instead of Standard Output At the moment, we’re writing all of our output to the terminal using the -`println!` macro. Most terminals provide two kinds of output: *standard -output* (`stdout`) for general information and *standard error* (`stderr`) -for error messages. This distinction enables users to choose to direct the +`println!` macro. In most terminals, there are two kinds of output: *standard +output* (`stdout`) for general information and *standard error* (`stderr`) for +error messages. This distinction enables users to choose to direct the successful output of a program to a file but still print error messages to the screen. diff --git a/src/doc/book/src/ch13-03-improving-our-io-project.md b/src/doc/book/src/ch13-03-improving-our-io-project.md index 28a494500f..c9e29dbe6a 100644 --- a/src/doc/book/src/ch13-03-improving-our-io-project.md +++ b/src/doc/book/src/ch13-03-improving-our-io-project.md @@ -56,7 +56,7 @@ well. Filename: src/main.rs -```rust,ignore +```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch13-functional-features/listing-13-25/src/main.rs:here}} ``` @@ -75,7 +75,7 @@ body. Filename: src/lib.rs -```rust,ignore +```rust,ignore,does_not_compile {{#rustdoc_include ../listings/ch13-functional-features/listing-13-26/src/lib.rs:here}} ``` @@ -89,16 +89,6 @@ signature of the `Config::new` function so the parameter `args` has the type `args` and we’ll be mutating `args` by iterating over it, we can add the `mut` keyword into the specification of the `args` parameter to make it mutable. -We also needed to specify that the string slice error type can now only have -the `'static` lifetime. Because we’re only ever returning string literals, this -was true before. However, when we had a reference in the parameters, there was -the possibility that the reference in the return type could have had the same -lifetime as the reference in the parameters. The rules that we discussed in the -[“Lifetime Elision”][lifetime-elision] section of Chapter 10 applied, and we -weren’t required to annotate the lifetime of `&str`. With the change to `args`, -the lifetime elision rules no longer apply, and we must specify the `'static` -lifetime. - #### Using `Iterator` Trait Methods Instead of Indexing Next, we’ll fix the body of `Config::new`. The standard library documentation @@ -175,5 +165,3 @@ the iterator must pass. But are the two implementations truly equivalent? The intuitive assumption might be that the more low-level loop will be faster. Let’s talk about performance. - -[lifetime-elision]: ch10-03-lifetime-syntax.html#lifetime-elision diff --git a/src/doc/book/src/ch14-02-publishing-to-crates-io.md b/src/doc/book/src/ch14-02-publishing-to-crates-io.md index 4fde74a2ac..baa8738b91 100644 --- a/src/doc/book/src/ch14-02-publishing-to-crates-io.md +++ b/src/doc/book/src/ch14-02-publishing-to-crates-io.md @@ -369,7 +369,7 @@ With a unique name, the version, your description, and a license added, the [package] name = "guessing_game" version = "0.1.0" -edition = "2018" +edition = "2021" description = "A fun game where you guess what number the computer has chosen." license = "MIT OR Apache-2.0" diff --git a/src/doc/book/src/title-page.md b/src/doc/book/src/title-page.md index 29dfdc6dd6..86f19fbb14 100644 --- a/src/doc/book/src/title-page.md +++ b/src/doc/book/src/title-page.md @@ -2,38 +2,9 @@ *by Steve Klabnik and Carol Nichols, with contributions from the Rust Community* -This version of the text assumes you’re using Rust 1.55 or later with -`edition="2018"` in *Cargo.toml* of all projects to use Rust 2018 Edition -idioms. See the [“Installation” section of Chapter 1][install] -to install or update Rust, and see the new [Appendix E][editions] for information on editions. - -The 2018 Edition of the Rust language includes a number of improvements that -make Rust more ergonomic and easier to learn. This iteration of the book -contains a number of changes to reflect those improvements: - -- Chapter 7, “Managing Growing Projects with Packages, Crates, and Modules,” - has been mostly rewritten. The module system and the way paths work in the - 2018 Edition were made more consistent. -- Chapter 10 has new sections titled “Traits as Parameters” and “Returning - Types that Implement Traits” that explain the new `impl Trait` syntax. -- Chapter 11 has a new section titled “Using `Result` in Tests” that - shows how to write tests that use the `?` operator. -- The “Advanced Lifetimes” section in Chapter 19 was removed because compiler - improvements have made the constructs in that section even rarer. -- The previous Appendix D, “Macros,” has been expanded to include procedural - macros and was moved to the “Macros” section in Chapter 19. -- Appendix A, “Keywords,” also explains the new raw identifiers feature that - enables code written in the 2015 Edition and the 2018 Edition to interoperate. -- Appendix D is now titled “Useful Development Tools” and covers recently - released tools that help you write Rust code. -- We fixed a number of small errors and imprecise wording throughout the book. - Thank you to the readers who reported them! - -Note that any code in earlier iterations of *The Rust Programming Language* -that compiled will continue to compile without `edition="2018"` in the -project’s *Cargo.toml*, even as you update the Rust compiler version you’re -using. That’s Rust’s backward compatibility guarantees at work! +This version of the text assumes you’re using Rust 1.57 (released 2021-12-02) +or later. See the [“Installation” section of Chapter 1][install] +to install or update Rust. The HTML format is available online at [https://doc.rust-lang.org/stable/book/](https://doc.rust-lang.org/stable/book/) diff --git a/src/doc/book/tools/convert-quotes.sh b/src/doc/book/tools/convert-quotes.sh index 8508e97021..bffe82359f 100755 --- a/src/doc/book/tools/convert-quotes.sh +++ b/src/doc/book/tools/convert-quotes.sh @@ -5,7 +5,7 @@ set -eu mkdir -p tmp/src rm -rf tmp/*.md -for f in src/${1:-""}*.md +for f in src/"${1:-\"\"}"*.md do cargo run --bin convert_quotes < "$f" > "tmp/$f" mv "tmp/$f" "$f" diff --git a/src/doc/book/tools/doc-to-md.sh b/src/doc/book/tools/doc-to-md.sh index 170727db9f..49b0cdfe35 100755 --- a/src/doc/book/tools/doc-to-md.sh +++ b/src/doc/book/tools/doc-to-md.sh @@ -3,7 +3,7 @@ set -eu # Get all the docx files in the tmp dir. -ls tmp/*.docx | \ +find tmp -name '*.docx' -print0 | \ # Extract just the filename so we can reuse it easily. xargs -n 1 basename -s .docx | \ while IFS= read -r filename; do diff --git a/src/doc/book/tools/megadiff.sh b/src/doc/book/tools/megadiff.sh index 9b0d943896..62ca7a0c5b 100755 --- a/src/doc/book/tools/megadiff.sh +++ b/src/doc/book/tools/megadiff.sh @@ -12,7 +12,7 @@ rm -rf tmp/book-after/css/ tmp/book-after/theme/ tmp/book-after/img/ tmp/book-af tmp/book-after/*.json tmp/book-after/print.html # Get all the html files before -ls tmp/book-before/*.html | \ +find tmp/book-before -name '*.html' -print0 | \ # Extract just the filename so we can reuse it easily. xargs -n 1 basename | \ while IFS= read -r filename; do diff --git a/src/doc/book/tools/nostarch.sh b/src/doc/book/tools/nostarch.sh index d802bf0703..d8c7994671 100755 --- a/src/doc/book/tools/nostarch.sh +++ b/src/doc/book/tools/nostarch.sh @@ -12,7 +12,7 @@ rm -rf tmp/markdown MDBOOK_OUTPUT__MARKDOWN=1 mdbook build -d tmp # Get all the Markdown files -ls tmp/markdown/${1:-""}*.md | \ +find tmp/markdown -name "${1:-\"\"}*.md" -print0 | \ # Extract just the filename so we can reuse it easily. xargs -n 1 basename | \ # Remove all links followed by ```, then diff --git a/src/doc/book/tools/update-editions.sh b/src/doc/book/tools/update-editions.sh new file mode 100755 index 0000000000..bd52bc9c81 --- /dev/null +++ b/src/doc/book/tools/update-editions.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +set -eu + +OLD_EDITION=2018 +NEW_EDITION=2021 + +find listings/** -name "Cargo.toml" -exec sed -i '' "s/edition = \"$OLD_EDITION\"/edition = \"$NEW_EDITION\"/g" '{}' \; diff --git a/src/doc/book/tools/update-rustc.sh b/src/doc/book/tools/update-rustc.sh index 53905bb466..5c9f178b1c 100755 --- a/src/doc/book/tools/update-rustc.sh +++ b/src/doc/book/tools/update-rustc.sh @@ -3,18 +3,18 @@ set -eu # Build the book before making any changes for comparison of the output. -echo 'Building book into `tmp/book-before` before updating...' +echo 'Building book into tmp/book-before before updating...' mdbook build -d tmp/book-before # Rustfmt all listings echo 'Formatting all listings...' find -s listings -name Cargo.toml -print0 | while IFS= read -r -d '' f; do - dir_to_fmt=$(dirname $f) + dir_to_fmt=$(dirname "$f") # There are a handful of listings we don't want to rustfmt and skipping # doesn't work; those will have a file in their directory that explains why. if [ ! -f "${dir_to_fmt}/rustfmt-ignore" ]; then - cd $dir_to_fmt + cd "$dir_to_fmt" cargo fmt --all && true cd - > /dev/null fi @@ -30,42 +30,42 @@ root_dir=$(pwd) echo 'Regenerating output...' # For any listings where we show the output, find -s listings -name output.txt -print0 | while IFS= read -r -d '' f; do - build_directory=$(dirname $f) + build_directory=$(dirname "$f") full_build_directory="${root_dir}/${build_directory}" full_output_path="${full_build_directory}/output.txt" tmp_build_directory="tmp/${build_directory}" - cd $tmp_build_directory + cd "$tmp_build_directory" # Save the previous compile time; we're going to keep it to minimize diff # churn - compile_time=$(sed -E -ne 's/.*Finished (dev|test) \[unoptimized \+ debuginfo] target\(s\) in ([0-9.]*).*/\2/p' ${full_output_path}) + compile_time=$(sed -E -ne 's/.*Finished (dev|test) \[unoptimized \+ debuginfo] target\(s\) in ([0-9.]*).*/\2/p' "${full_output_path}") # Save the hash from the first test binary; we're going to keep it to # minimize diff churn - test_binary_hash=$(sed -E -ne 's@.*Running [^[:space:]]+ \(target/debug/deps/[^-]*-([^\s]*)\)@\1@p' ${full_output_path} | head -n 1) + test_binary_hash=$(sed -E -ne 's@.*Running [^[:space:]]+ \(target/debug/deps/[^-]*-([^\s]*)\)@\1@p' "${full_output_path}" | head -n 1) # Act like this is the first time this listing has been built cargo clean # Run the command in the existing output file - cargo_command=$(sed -ne 's/$ \(.*\)/\1/p' ${full_output_path}) + cargo_command=$(sed -ne 's/$ \(.*\)/\1/p' "${full_output_path}") # Clear the output file of everything except the command - echo "$ ${cargo_command}" > ${full_output_path} + echo "$ ${cargo_command}" > "${full_output_path}" # Regenerate the output and append to the output file. Turn some warnings # off to reduce output noise, and use one test thread to get consistent # ordering of tests in the output when the command is `cargo test`. - RUSTFLAGS="-A unused_variables -A dead_code" RUST_TEST_THREADS=1 $cargo_command >> ${full_output_path} 2>&1 || true + RUSTFLAGS="-A unused_variables -A dead_code" RUST_TEST_THREADS=1 $cargo_command >> "${full_output_path}" 2>&1 || true # Set the project file path to the projects directory plus the crate name # instead of a path to the computer of whoever is running this - sed -i '' -E -e 's@(Compiling|Checking) ([^\)]*) v0.1.0 (.*)@\1 \2 v0.1.0 (file:///projects/\2)@' ${full_output_path} + sed -i '' -E -e 's@(Compiling|Checking) ([^\)]*) v0.1.0 (.*)@\1 \2 v0.1.0 (file:///projects/\2)@' "${full_output_path}" # Restore the previous compile time, if there is one if [ -n "${compile_time}" ]; then - sed -i '' -E -e "s/Finished (dev|test) \[unoptimized \+ debuginfo] target\(s\) in [0-9.]*/Finished \1 [unoptimized + debuginfo] target(s) in ${compile_time}/" ${full_output_path} + sed -i '' -E -e "s/Finished (dev|test) \[unoptimized \+ debuginfo] target\(s\) in [0-9.]*/Finished \1 [unoptimized + debuginfo] target(s) in ${compile_time}/" "${full_output_path}" fi # Restore the previous test binary hash, if there is one @@ -73,7 +73,7 @@ find -s listings -name output.txt -print0 | while IFS= read -r -d '' f; do replacement='s@Running ([^[:space:]]+) \(target/debug/deps/([^-]*)-([^\s]*)\)@Running \1 (target/debug/deps/\2-' replacement+="${test_binary_hash}" replacement+=')@g' - sed -i '' -E -e "${replacement}" ${full_output_path} + sed -i '' -E -e "${replacement}" "${full_output_path}" fi # Clean again @@ -83,7 +83,7 @@ find -s listings -name output.txt -print0 | while IFS= read -r -d '' f; do done # Build the book after making all the changes -echo 'Building book into `tmp/book-after` after updating...' +echo 'Building book into tmp/book-after after updating...' mdbook build -d tmp/book-after # Run the megadiff script that removes all files that are the same, leaving only files to audit diff --git a/src/doc/edition-guide/src/rust-2018/path-changes.md b/src/doc/edition-guide/src/rust-2018/path-changes.md index fc16d472ba..ca2c27ca20 100644 --- a/src/doc/edition-guide/src/rust-2018/path-changes.md +++ b/src/doc/edition-guide/src/rust-2018/path-changes.md @@ -83,7 +83,7 @@ general way to express this, though it uses it for `proc_macro` crates. Some examples of needing to explicitly import sysroot crates are: -* [`std`]: Usually this is not neccesary, because `std` is automatically +* [`std`]: Usually this is not necessary, because `std` is automatically imported unless the crate is marked with [`#![no_std]`][no_std]. * [`core`]: Usually this is not necessary, because `core` is automatically imported, unless the crate is marked with [`#![no_core]`][no_core]. For diff --git a/src/doc/nomicon/src/drop-flags.md b/src/doc/nomicon/src/drop-flags.md index 65fff15dfc..6a0236a0de 100644 --- a/src/doc/nomicon/src/drop-flags.md +++ b/src/doc/nomicon/src/drop-flags.md @@ -79,5 +79,5 @@ if condition { } ``` -The drop flags are tracked on the stack and no longer stashed in types that -implement drop. +The drop flags are tracked on the stack. +In old Rust versions, drop flags were stashed in a hidden field of types that implement `Drop`. diff --git a/src/doc/nomicon/src/unchecked-uninit.md b/src/doc/nomicon/src/unchecked-uninit.md index 7c07521329..8137233a00 100644 --- a/src/doc/nomicon/src/unchecked-uninit.md +++ b/src/doc/nomicon/src/unchecked-uninit.md @@ -135,11 +135,24 @@ to compute the address of array index `idx`. This relies on how arrays are laid out in memory. * For a struct, however, in general we do not know how it is laid out, and we also cannot use `&mut base_ptr.field` as that would be creating a -reference. Thus, it is currently not possible to create a raw pointer to a field -of a partially initialized struct, and also not possible to initialize a single -field of a partially initialized struct. (a -[solution to this problem](https://github.com/rust-lang/rust/issues/64490) is being -worked on). +reference. So, you must carefully use the [`addr_of_mut`] macro. This creates +a raw pointer to the field without creating an intermediate reference: + +```rust +use std::{ptr, mem::MaybeUninit}; + +struct Demo { + field: bool, +} + +let mut uninit = MaybeUninit::::uninit(); +// `&uninit.as_mut().field` would create a reference to an uninitialized `bool`, +// and thus be Undefined Behavior! +let f1_ptr = unsafe { ptr::addr_of_mut!((*uninit.as_mut_ptr()).field) }; +unsafe { f1_ptr.write(true); } + +let init = unsafe { uninit.assume_init() }; +``` One last remark: when reading old Rust code, you might stumble upon the deprecated `mem::uninitialized` function. That function used to be the only way @@ -155,6 +168,7 @@ it around at all, be sure to be *really* careful. [`MaybeUninit`]: ../core/mem/union.MaybeUninit.html [assume_init]: ../core/mem/union.MaybeUninit.html#method.assume_init [`ptr`]: ../core/ptr/index.html +[`addr_of_mut`]: ../core/ptr/macro.addr_of_mut.html [`write`]: ../core/ptr/fn.write.html [`copy`]: ../std/ptr/fn.copy.html [`copy_nonoverlapping`]: ../std/ptr/fn.copy_nonoverlapping.html diff --git a/src/doc/reference/.github/workflows/main.yml b/src/doc/reference/.github/workflows/main.yml index 3bcdb8a117..4456c3c9c3 100644 --- a/src/doc/reference/.github/workflows/main.yml +++ b/src/doc/reference/.github/workflows/main.yml @@ -17,7 +17,7 @@ jobs: - name: Install mdbook run: | mkdir bin - curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.5/mdbook-v0.4.5-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin + curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.14/mdbook-v0.4.14-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin echo "$(pwd)/bin" >> $GITHUB_PATH - name: Report versions run: | diff --git a/src/doc/reference/README.md b/src/doc/reference/README.md index ca6e5a67cf..65030a32c8 100644 --- a/src/doc/reference/README.md +++ b/src/doc/reference/README.md @@ -10,7 +10,7 @@ what we have for now. ## Dependencies - rustc (the Rust compiler). -- mdbook (use `cargo install mdbook` to install it). +- [mdbook](https://rust-lang.github.io/mdBook/) (use `cargo install mdbook` to install it). - rust nightly (you would be required to set your Rust version to the nightly version to make sure all tests pass) ## Build steps diff --git a/src/doc/reference/STYLE.md b/src/doc/reference/STYLE.md index 07621275c6..f51cba3d4f 100644 --- a/src/doc/reference/STYLE.md +++ b/src/doc/reference/STYLE.md @@ -41,7 +41,7 @@ See https://highlightjs.org/ for a list of supported languages. Rust examples are tested via rustdoc, and should include the appropriate annotations when tests are expected to fail: -* `edition2018` — If it is edition-specific. +* `edition2015` or `edition2018` — If it is edition-specific (see `book.toml` for the default). * `no_run` — The example should compile successfully, but should not be executed. * `should_panic` — The example should compile and run, but produce a panic. * `compile_fail` — The example is expected to fail to compile. diff --git a/src/doc/reference/book.toml b/src/doc/reference/book.toml index b2def92d5c..2bc218fe46 100644 --- a/src/doc/reference/book.toml +++ b/src/doc/reference/book.toml @@ -11,4 +11,4 @@ git-repository-url = "https://github.com/rust-lang/reference/" "/expressions/enum-variant-expr.html" = "struct-expr.html" [rust] -edition = "2018" +edition = "2021" diff --git a/src/doc/reference/src/SUMMARY.md b/src/doc/reference/src/SUMMARY.md index 783c647b43..fbbd436731 100644 --- a/src/doc/reference/src/SUMMARY.md +++ b/src/doc/reference/src/SUMMARY.md @@ -114,6 +114,8 @@ - [Linkage](linkage.md) +- [Inline assembly](inline-assembly.md) + - [Unsafety](unsafety.md) - [Unsafe functions](unsafe-functions.md) - [Unsafe blocks](unsafe-blocks.md) diff --git a/src/doc/reference/src/behavior-considered-undefined.md b/src/doc/reference/src/behavior-considered-undefined.md index 5af4a4bef7..c2e6fc0cb1 100644 --- a/src/doc/reference/src/behavior-considered-undefined.md +++ b/src/doc/reference/src/behavior-considered-undefined.md @@ -58,6 +58,8 @@ code. > **Note**: `rustc` achieves this with the unstable > `rustc_layout_scalar_valid_range_*` attributes. +* Incorrect use of inline assembly. For more details, refer to the [rules] to + follow when writing code that uses inline assembly. **Note:** Uninitialized memory is also implicitly invalid for any type that has a restricted set of valid values. In other words, the only cases in which @@ -94,3 +96,4 @@ cannot be bigger than `isize::MAX` bytes. [`NonZero*`]: ../core/num/index.html [dereference expression]: expressions/operator-expr.md#the-dereference-operator [place expression context]: expressions.md#place-expressions-and-value-expressions +[rules]: inline-assembly.md#rules-for-inline-assembly diff --git a/src/doc/reference/src/inline-assembly.md b/src/doc/reference/src/inline-assembly.md new file mode 100644 index 0000000000..9846c1561d --- /dev/null +++ b/src/doc/reference/src/inline-assembly.md @@ -0,0 +1,479 @@ +# Inline assembly + +Support for inline assembly is provided via the [`asm!`] and [`global_asm!`] macros. +It can be used to embed handwritten assembly in the assembly output generated by the compiler. + +[`asm!`]: ../core/arch/macro.asm.html +[`global_asm!`]: ../core/arch/macro.global_asm.html + +Support for inline assembly is stable on the following architectures: +- x86 and x86-64 +- ARM +- AArch64 +- RISC-V + +The compiler will emit an error if `asm!` is used on an unsupported target. + +## Example + +```rust +use std::arch::asm; + +// Multiply x by 6 using shifts and adds +let mut x: u64 = 4; +unsafe { + asm!( + "mov {tmp}, {x}", + "shl {tmp}, 1", + "shl {x}, 2", + "add {x}, {tmp}", + x = inout(reg) x, + tmp = out(reg) _, + ); +} +assert_eq!(x, 4 * 6); +``` + +## Syntax + +The following ABNF specifies the general syntax: + +```text +format_string := STRING_LITERAL / RAW_STRING_LITERAL +dir_spec := "in" / "out" / "lateout" / "inout" / "inlateout" +reg_spec := / "" +operand_expr := expr / "_" / expr "=>" expr / expr "=>" "_" +reg_operand := dir_spec "(" reg_spec ")" operand_expr +operand := reg_operand +clobber_abi := "clobber_abi(" *("," ) [","] ")" +option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nostack" / "att_syntax" / "raw" +options := "options(" option *("," option) [","] ")" +asm := "asm!(" format_string *("," format_string) *("," [ident "="] operand) *("," clobber_abi) *("," options) [","] ")" +global_asm := "global_asm!(" format_string *("," format_string) *("," [ident "="] operand) *("," options) [","] ")" +``` + + +## Scope + +Inline assembly can be used in one of two ways. + +With the `asm!` macro, the assembly code is emitted in a function scope and integrated into the compiler-generated assembly code of a function. +This assembly code must obey [strict rules](#rules-for-inline-assembly) to avoid undefined behavior. +Note that in some cases the compiler may choose to emit the assembly code as a separate function and generate a call to it. + +With the `global_asm!` macro, the assembly code is emitted in a global scope, outside a function. +This can be used to hand-write entire functions using assembly code, and generally provides much more freedom to use arbitrary registers and assembler directives. + +## Template string arguments + +The assembler template uses the same syntax as [format strings][format-syntax] (i.e. placeholders are specified by curly braces). +The corresponding arguments are accessed in order, by index, or by name. +However, implicit named arguments (introduced by [RFC #2795][rfc-2795]) are not supported. + +An `asm!` invocation may have one or more template string arguments; an `asm!` with multiple template string arguments is treated as if all the strings were concatenated with a `\n` between them. +The expected usage is for each template string argument to correspond to a line of assembly code. +All template string arguments must appear before any other arguments. + +As with format strings, named arguments must appear after positional arguments. +Explicit [register operands](#register-operands) must appear at the end of the operand list, after named arguments if any. + +Explicit register operands cannot be used by placeholders in the template string. +All other named and positional operands must appear at least once in the template string, otherwise a compiler error is generated. + +The exact assembly code syntax is target-specific and opaque to the compiler except for the way operands are substituted into the template string to form the code passed to the assembler. + +Currently, all supported targets follow the assembly code syntax used by LLVM's internal assembler which usually corresponds to that of the GNU assembler (GAS). +On x86, the `.intel_syntax noprefix` mode of GAS is used by default. +On ARM, the `.syntax unified` mode is used. +These targets impose an additional restriction on the assembly code: any assembler state (e.g. the current section which can be changed with `.section`) must be restored to its original value at the end of the asm string. +Assembly code that does not conform to the GAS syntax will result in assembler-specific behavior. + +[format-syntax]: ../std/fmt/index.html#syntax +[rfc-2795]: https://github.com/rust-lang/rfcs/pull/2795 + +## Operand type + +Several types of operands are supported: + +* `in() ` + - `` can refer to a register class or an explicit register. + The allocated register name is substituted into the asm template string. + - The allocated register will contain the value of `` at the start of the asm code. + - The allocated register must contain the same value at the end of the asm code (except if a `lateout` is allocated to the same register). +* `out() ` + - `` can refer to a register class or an explicit register. + The allocated register name is substituted into the asm template string. + - The allocated register will contain an undefined value at the start of the asm code. + - `` must be a (possibly uninitialized) place expression, to which the contents of the allocated register are written at the end of the asm code. + - An underscore (`_`) may be specified instead of an expression, which will cause the contents of the register to be discarded at the end of the asm code (effectively acting as a clobber). +* `lateout() ` + - Identical to `out` except that the register allocator can reuse a register allocated to an `in`. + - You should only write to the register after all inputs are read, otherwise you may clobber an input. +* `inout() ` + - `` can refer to a register class or an explicit register. + The allocated register name is substituted into the asm template string. + - The allocated register will contain the value of `` at the start of the asm code. + - `` must be a mutable initialized place expression, to which the contents of the allocated register are written at the end of the asm code. +* `inout() => ` + - Same as `inout` except that the initial value of the register is taken from the value of ``. + - `` must be a (possibly uninitialized) place expression, to which the contents of the allocated register are written at the end of the asm code. + - An underscore (`_`) may be specified instead of an expression for ``, which will cause the contents of the register to be discarded at the end of the asm code (effectively acting as a clobber). + - `` and `` may have different types. +* `inlateout() ` / `inlateout() => ` + - Identical to `inout` except that the register allocator can reuse a register allocated to an `in` (this can happen if the compiler knows the `in` has the same initial value as the `inlateout`). + - You should only write to the register after all inputs are read, otherwise you may clobber an input. + +Operand expressions are evaluated from left to right, just like function call arguments. +After the `asm!` has executed, outputs are written to in left to right order. +This is significant if two outputs point to the same place: that place will contain the value of the rightmost output. + +Since `global_asm!` exists outside a function, it cannot use input/output operands. + +## Register operands + +Input and output operands can be specified either as an explicit register or as a register class from which the register allocator can select a register. +Explicit registers are specified as string literals (e.g. `"eax"`) while register classes are specified as identifiers (e.g. `reg`). + +Note that explicit registers treat register aliases (e.g. `r14` vs `lr` on ARM) and smaller views of a register (e.g. `eax` vs `rax`) as equivalent to the base register. +It is a compile-time error to use the same explicit register for two input operands or two output operands. +Additionally, it is also a compile-time error to use overlapping registers (e.g. ARM VFP) in input operands or in output operands. + +Only the following types are allowed as operands for inline assembly: +- Integers (signed and unsigned) +- Floating-point numbers +- Pointers (thin only) +- Function pointers +- SIMD vectors (structs defined with `#[repr(simd)]` and which implement `Copy`). +This includes architecture-specific vector types defined in `std::arch` such as `__m128` (x86) or `int8x16_t` (ARM). + +Here is the list of currently supported register classes: + +| Architecture | Register class | Registers | LLVM constraint code | +| ------------ | -------------- | --------- | -------------------- | +| x86 | `reg` | `ax`, `bx`, `cx`, `dx`, `si`, `di`, `bp`, `r[8-15]` (x86-64 only) | `r` | +| x86 | `reg_abcd` | `ax`, `bx`, `cx`, `dx` | `Q` | +| x86-32 | `reg_byte` | `al`, `bl`, `cl`, `dl`, `ah`, `bh`, `ch`, `dh` | `q` | +| x86-64 | `reg_byte`\* | `al`, `bl`, `cl`, `dl`, `sil`, `dil`, `bpl`, `r[8-15]b` | `q` | +| x86 | `xmm_reg` | `xmm[0-7]` (x86) `xmm[0-15]` (x86-64) | `x` | +| x86 | `ymm_reg` | `ymm[0-7]` (x86) `ymm[0-15]` (x86-64) | `x` | +| x86 | `zmm_reg` | `zmm[0-7]` (x86) `zmm[0-31]` (x86-64) | `v` | +| x86 | `kreg` | `k[1-7]` | `Yk` | +| x86 | `x87_reg` | `st([0-7])` | Only clobbers | +| x86 | `mmx_reg` | `mm[0-7]` | Only clobbers | +| AArch64 | `reg` | `x[0-30]` | `r` | +| AArch64 | `vreg` | `v[0-31]` | `w` | +| AArch64 | `vreg_low16` | `v[0-15]` | `x` | +| AArch64 | `preg` | `p[0-15]`, `ffr` | Only clobbers | +| ARM (ARM/Thumb2) | `reg` | `r[0-12]`, `r14` | `r` | +| ARM (Thumb1) | `reg` | `r[0-7]` | `r` | +| ARM | `sreg` | `s[0-31]` | `t` | +| ARM | `sreg_low16` | `s[0-15]` | `x` | +| ARM | `dreg` | `d[0-31]` | `w` | +| ARM | `dreg_low16` | `d[0-15]` | `t` | +| ARM | `dreg_low8` | `d[0-8]` | `x` | +| ARM | `qreg` | `q[0-15]` | `w` | +| ARM | `qreg_low8` | `q[0-7]` | `t` | +| ARM | `qreg_low4` | `q[0-3]` | `x` | +| RISC-V | `reg` | `x1`, `x[5-7]`, `x[9-15]`, `x[16-31]` (non-RV32E) | `r` | +| RISC-V | `freg` | `f[0-31]` | `f` | +| RISC-V | `vreg` | `v[0-31]` | Only clobbers | + +> **Notes**: +> - On x86 we treat `reg_byte` differently from `reg` because the compiler can allocate `al` and `ah` separately whereas `reg` reserves the whole register. +> +> - On x86-64 the high byte registers (e.g. `ah`) are not available in the `reg_byte` register class. +> +> - Some register classes are marked as "Only clobbers" which means that they cannot be used for inputs or outputs, only clobbers of the form `out("reg") _` or `lateout("reg") _`. + +Each register class has constraints on which value types they can be used with. +This is necessary because the way a value is loaded into a register depends on its type. +For example, on big-endian systems, loading a `i32x4` and a `i8x16` into a SIMD register may result in different register contents even if the byte-wise memory representation of both values is identical. +The availability of supported types for a particular register class may depend on what target features are currently enabled. + +| Architecture | Register class | Target feature | Allowed types | +| ------------ | -------------- | -------------- | ------------- | +| x86-32 | `reg` | None | `i16`, `i32`, `f32` | +| x86-64 | `reg` | None | `i16`, `i32`, `f32`, `i64`, `f64` | +| x86 | `reg_byte` | None | `i8` | +| x86 | `xmm_reg` | `sse` | `i32`, `f32`, `i64`, `f64`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` | +| x86 | `ymm_reg` | `avx` | `i32`, `f32`, `i64`, `f64`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2`
`i8x32`, `i16x16`, `i32x8`, `i64x4`, `f32x8`, `f64x4` | +| x86 | `zmm_reg` | `avx512f` | `i32`, `f32`, `i64`, `f64`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2`
`i8x32`, `i16x16`, `i32x8`, `i64x4`, `f32x8`, `f64x4`
`i8x64`, `i16x32`, `i32x16`, `i64x8`, `f32x16`, `f64x8` | +| x86 | `kreg` | `avx512f` | `i8`, `i16` | +| x86 | `kreg` | `avx512bw` | `i32`, `i64` | +| x86 | `mmx_reg` | N/A | Only clobbers | +| x86 | `x87_reg` | N/A | Only clobbers | +| AArch64 | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | +| AArch64 | `vreg` | `fp` | `i8`, `i16`, `i32`, `f32`, `i64`, `f64`,
`i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2`, `f64x1`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` | +| AArch64 | `preg` | N/A | Only clobbers | +| ARM | `reg` | None | `i8`, `i16`, `i32`, `f32` | +| ARM | `sreg` | `vfp2` | `i32`, `f32` | +| ARM | `dreg` | `vfp2` | `i64`, `f64`, `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2` | +| ARM | `qreg` | `neon` | `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4` | +| RISC-V32 | `reg` | None | `i8`, `i16`, `i32`, `f32` | +| RISC-V64 | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | +| RISC-V | `freg` | `f` | `f32` | +| RISC-V | `freg` | `d` | `f64` | +| RISC-V | `vreg` | N/A | Only clobbers | + +> **Note**: For the purposes of the above table pointers, function pointers and `isize`/`usize` are treated as the equivalent integer type (`i16`/`i32`/`i64` depending on the target). + +If a value is of a smaller size than the register it is allocated in then the upper bits of that register will have an undefined value for inputs and will be ignored for outputs. +The only exception is the `freg` register class on RISC-V where `f32` values are NaN-boxed in a `f64` as required by the RISC-V architecture. + +When separate input and output expressions are specified for an `inout` operand, both expressions must have the same type. +The only exception is if both operands are pointers or integers, in which case they are only required to have the same size. +This restriction exists because the register allocators in LLVM and GCC sometimes cannot handle tied operands with different types. + +## Register names + +Some registers have multiple names. +These are all treated by the compiler as identical to the base register name. +Here is the list of all supported register aliases: + +| Architecture | Base register | Aliases | +| ------------ | ------------- | ------- | +| x86 | `ax` | `eax`, `rax` | +| x86 | `bx` | `ebx`, `rbx` | +| x86 | `cx` | `ecx`, `rcx` | +| x86 | `dx` | `edx`, `rdx` | +| x86 | `si` | `esi`, `rsi` | +| x86 | `di` | `edi`, `rdi` | +| x86 | `bp` | `bpl`, `ebp`, `rbp` | +| x86 | `sp` | `spl`, `esp`, `rsp` | +| x86 | `ip` | `eip`, `rip` | +| x86 | `st(0)` | `st` | +| x86 | `r[8-15]` | `r[8-15]b`, `r[8-15]w`, `r[8-15]d` | +| x86 | `xmm[0-31]` | `ymm[0-31]`, `zmm[0-31]` | +| AArch64 | `x[0-30]` | `w[0-30]` | +| AArch64 | `x29` | `fp` | +| AArch64 | `x30` | `lr` | +| AArch64 | `sp` | `wsp` | +| AArch64 | `xzr` | `wzr` | +| AArch64 | `v[0-31]` | `b[0-31]`, `h[0-31]`, `s[0-31]`, `d[0-31]`, `q[0-31]` | +| ARM | `r[0-3]` | `a[1-4]` | +| ARM | `r[4-9]` | `v[1-6]` | +| ARM | `r9` | `rfp` | +| ARM | `r10` | `sl` | +| ARM | `r11` | `fp` | +| ARM | `r12` | `ip` | +| ARM | `r13` | `sp` | +| ARM | `r14` | `lr` | +| ARM | `r15` | `pc` | +| RISC-V | `x0` | `zero` | +| RISC-V | `x1` | `ra` | +| RISC-V | `x2` | `sp` | +| RISC-V | `x3` | `gp` | +| RISC-V | `x4` | `tp` | +| RISC-V | `x[5-7]` | `t[0-2]` | +| RISC-V | `x8` | `fp`, `s0` | +| RISC-V | `x9` | `s1` | +| RISC-V | `x[10-17]` | `a[0-7]` | +| RISC-V | `x[18-27]` | `s[2-11]` | +| RISC-V | `x[28-31]` | `t[3-6]` | +| RISC-V | `f[0-7]` | `ft[0-7]` | +| RISC-V | `f[8-9]` | `fs[0-1]` | +| RISC-V | `f[10-17]` | `fa[0-7]` | +| RISC-V | `f[18-27]` | `fs[2-11]` | +| RISC-V | `f[28-31]` | `ft[8-11]` | + +Some registers cannot be used for input or output operands: + +| Architecture | Unsupported register | Reason | +| ------------ | -------------------- | ------ | +| All | `sp` | The stack pointer must be restored to its original value at the end of an asm code block. | +| All | `bp` (x86), `x29` (AArch64), `x8` (RISC-V) | The frame pointer cannot be used as an input or output. | +| ARM | `r7` or `r11` | On ARM the frame pointer can be either `r7` or `r11` depending on the target. The frame pointer cannot be used as an input or output. | +| All | `si` (x86-32), `bx` (x86-64), `r6` (ARM), `x19` (AArch64), `x9` (RISC-V) | This is used internally by LLVM as a "base pointer" for functions with complex stack frames. | +| x86 | `k0` | This is a constant zero register which can't be modified. | +| x86 | `ip` | This is the program counter, not a real register. | +| AArch64 | `xzr` | This is a constant zero register which can't be modified. | +| AArch64 | `x18` | This is an OS-reserved register on some AArch64 targets. | +| ARM | `pc` | This is the program counter, not a real register. | +| ARM | `r9` | This is an OS-reserved register on some ARM targets. | +| RISC-V | `x0` | This is a constant zero register which can't be modified. | +| RISC-V | `gp`, `tp` | These registers are reserved and cannot be used as inputs or outputs. | + +The frame pointer and base pointer registers are reserved for internal use by LLVM. While `asm!` statements cannot explicitly specify the use of reserved registers, in some cases LLVM will allocate one of these reserved registers for `reg` operands. Assembly code making use of reserved registers should be careful since `reg` operands may use the same registers. + +## Template modifiers + +The placeholders can be augmented by modifiers which are specified after the `:` in the curly braces. +These modifiers do not affect register allocation, but change the way operands are formatted when inserted into the template string. +Only one modifier is allowed per template placeholder. + +The supported modifiers are a subset of LLVM's (and GCC's) [asm template argument modifiers][llvm-argmod], but do not use the same letter codes. + +| Architecture | Register class | Modifier | Example output | LLVM modifier | +| ------------ | -------------- | -------- | -------------- | ------------- | +| x86-32 | `reg` | None | `eax` | `k` | +| x86-64 | `reg` | None | `rax` | `q` | +| x86-32 | `reg_abcd` | `l` | `al` | `b` | +| x86-64 | `reg` | `l` | `al` | `b` | +| x86 | `reg_abcd` | `h` | `ah` | `h` | +| x86 | `reg` | `x` | `ax` | `w` | +| x86 | `reg` | `e` | `eax` | `k` | +| x86-64 | `reg` | `r` | `rax` | `q` | +| x86 | `reg_byte` | None | `al` / `ah` | None | +| x86 | `xmm_reg` | None | `xmm0` | `x` | +| x86 | `ymm_reg` | None | `ymm0` | `t` | +| x86 | `zmm_reg` | None | `zmm0` | `g` | +| x86 | `*mm_reg` | `x` | `xmm0` | `x` | +| x86 | `*mm_reg` | `y` | `ymm0` | `t` | +| x86 | `*mm_reg` | `z` | `zmm0` | `g` | +| x86 | `kreg` | None | `k1` | None | +| AArch64 | `reg` | None | `x0` | `x` | +| AArch64 | `reg` | `w` | `w0` | `w` | +| AArch64 | `reg` | `x` | `x0` | `x` | +| AArch64 | `vreg` | None | `v0` | None | +| AArch64 | `vreg` | `v` | `v0` | None | +| AArch64 | `vreg` | `b` | `b0` | `b` | +| AArch64 | `vreg` | `h` | `h0` | `h` | +| AArch64 | `vreg` | `s` | `s0` | `s` | +| AArch64 | `vreg` | `d` | `d0` | `d` | +| AArch64 | `vreg` | `q` | `q0` | `q` | +| ARM | `reg` | None | `r0` | None | +| ARM | `sreg` | None | `s0` | None | +| ARM | `dreg` | None | `d0` | `P` | +| ARM | `qreg` | None | `q0` | `q` | +| ARM | `qreg` | `e` / `f` | `d0` / `d1` | `e` / `f` | +| RISC-V | `reg` | None | `x1` | None | +| RISC-V | `freg` | None | `f0` | None | + +> **Notes**: +> - on ARM `e` / `f`: this prints the low or high doubleword register name of a NEON quad (128-bit) register. +> - on x86: our behavior for `reg` with no modifiers differs from what GCC does. +> GCC will infer the modifier based on the operand value type, while we default to the full register size. +> - on x86 `xmm_reg`: the `x`, `t` and `g` LLVM modifiers are not yet implemented in LLVM (they are supported by GCC only), but this should be a simple change. + +As stated in the previous section, passing an input value smaller than the register width will result in the upper bits of the register containing undefined values. +This is not a problem if the inline asm only accesses the lower bits of the register, which can be done by using a template modifier to use a subregister name in the asm code (e.g. `ax` instead of `rax`). +Since this an easy pitfall, the compiler will suggest a template modifier to use where appropriate given the input type. +If all references to an operand already have modifiers then the warning is suppressed for that operand. + +[llvm-argmod]: http://llvm.org/docs/LangRef.html#asm-template-argument-modifiers + +## ABI clobbers + +The `clobber_abi` keyword can be used to apply a default set of clobbers to an `asm!` block. +This will automatically insert the necessary clobber constraints as needed for calling a function with a particular calling convention: if the calling convention does not fully preserve the value of a register across a call then a `lateout("reg") _` is implicitly added to the operands list. + +`clobber_abi` may be specified any number of times. It will insert a clobber for all unique registers in the union of all specified calling conventions. + +Generic register class outputs are disallowed by the compiler when `clobber_abi` is used: all outputs must specify an explicit register. +Explicit register outputs have precedence over the implicit clobbers inserted by `clobber_abi`: a clobber will only be inserted for a register if that register is not used as an output. +The following ABIs can be used with `clobber_abi`: + +| Architecture | ABI name | Clobbered registers | +| ------------ | -------- | ------------------- | +| x86-32 | `"C"`, `"system"`, `"efiapi"`, `"cdecl"`, `"stdcall"`, `"fastcall"` | `ax`, `cx`, `dx`, `xmm[0-7]`, `mm[0-7]`, `k[1-7]`, `st([0-7])` | +| x86-64 | `"C"`, `"system"` (on Windows), `"efiapi"`, `"win64"` | `ax`, `cx`, `dx`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `k[1-7]`, `st([0-7])` | +| x86-64 | `"C"`, `"system"` (on non-Windows), `"sysv64"` | `ax`, `cx`, `dx`, `si`, `di`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `k[1-7]`, `st([0-7])` | +| AArch64 | `"C"`, `"system"`, `"efiapi"` | `x[0-17]`, `x18`\*, `x30`, `v[0-31]`, `p[0-15]`, `ffr` | +| ARM | `"C"`, `"system"`, `"efiapi"`, `"aapcs"` | `r[0-3]`, `r12`, `r14`, `s[0-15]`, `d[0-7]`, `d[16-31]` | +| RISC-V | `"C"`, `"system"`, `"efiapi"` | `x1`, `x[5-7]`, `x[10-17]`, `x[28-31]`, `f[0-7]`, `f[10-17]`, `f[28-31]`, `v[0-31]` | + +> Notes: +> - On AArch64 `x18` only included in the clobber list if it is not considered as a reserved register on the target. + +The list of clobbered registers for each ABI is updated in rustc as architectures gain new registers: this ensures that `asm!` clobbers will continue to be correct when LLVM starts using these new registers in its generated code. + +## Options + +Flags are used to further influence the behavior of the inline assembly block. +Currently the following options are defined: +- `pure`: The `asm!` block has no side effects, and its outputs depend only on its direct inputs (i.e. the values themselves, not what they point to) or values read from memory (unless the `nomem` options is also set). + This allows the compiler to execute the `asm!` block fewer times than specified in the program (e.g. by hoisting it out of a loop) or even eliminate it entirely if the outputs are not used. +- `nomem`: The `asm!` blocks does not read or write to any memory. + This allows the compiler to cache the values of modified global variables in registers across the `asm!` block since it knows that they are not read or written to by the `asm!`. +- `readonly`: The `asm!` block does not write to any memory. + This allows the compiler to cache the values of unmodified global variables in registers across the `asm!` block since it knows that they are not written to by the `asm!`. +- `preserves_flags`: The `asm!` block does not modify the flags register (defined in the rules below). + This allows the compiler to avoid recomputing the condition flags after the `asm!` block. +- `noreturn`: The `asm!` block never returns, and its return type is defined as `!` (never). + Behavior is undefined if execution falls through past the end of the asm code. + A `noreturn` asm block behaves just like a function which doesn't return; notably, local variables in scope are not dropped before it is invoked. +- `nostack`: The `asm!` block does not push data to the stack, or write to the stack red-zone (if supported by the target). + If this option is *not* used then the stack pointer is guaranteed to be suitably aligned (according to the target ABI) for a function call. +- `att_syntax`: This option is only valid on x86, and causes the assembler to use the `.att_syntax prefix` mode of the GNU assembler. + Register operands are substituted in with a leading `%`. +- `raw`: This causes the template string to be parsed as a raw assembly string, with no special handling for `{` and `}`. + This is primarily useful when including raw assembly code from an external file using `include_str!`. + +The compiler performs some additional checks on options: +- The `nomem` and `readonly` options are mutually exclusive: it is a compile-time error to specify both. +- The `pure` option must be combined with either the `nomem` or `readonly` options, otherwise a compile-time error is emitted. +- It is a compile-time error to specify `pure` on an asm block with no outputs or only discarded outputs (`_`). +- It is a compile-time error to specify `noreturn` on an asm block with outputs. + +`global_asm!` only supports the `att_syntax` and `raw` options. +The remaining options are not meaningful for global-scope inline assembly + +## Rules for inline assembly + +To avoid undefined behavior, these rules must be followed when using function-scope inline assembly (`asm!`): + +- Any registers not specified as inputs will contain an undefined value on entry to the asm block. + - An "undefined value" in the context of inline assembly means that the register can (non-deterministically) have any one of the possible values allowed by the architecture. + Notably it is not the same as an LLVM `undef` which can have a different value every time you read it (since such a concept does not exist in assembly code). +- Any registers not specified as outputs must have the same value upon exiting the asm block as they had on entry, otherwise behavior is undefined. + - This only applies to registers which can be specified as an input or output. + Other registers follow target-specific rules. + - Note that a `lateout` may be allocated to the same register as an `in`, in which case this rule does not apply. + Code should not rely on this however since it depends on the results of register allocation. +- Behavior is undefined if execution unwinds out of an asm block. + - This also applies if the assembly code calls a function which then unwinds. +- The set of memory locations that assembly code is allowed to read and write are the same as those allowed for an FFI function. + - Refer to the unsafe code guidelines for the exact rules. + - If the `readonly` option is set, then only memory reads are allowed. + - If the `nomem` option is set then no reads or writes to memory are allowed. + - These rules do not apply to memory which is private to the asm code, such as stack space allocated within the asm block. +- The compiler cannot assume that the instructions in the asm are the ones that will actually end up executed. + - This effectively means that the compiler must treat the `asm!` as a black box and only take the interface specification into account, not the instructions themselves. + - Runtime code patching is allowed, via target-specific mechanisms. +- Unless the `nostack` option is set, asm code is allowed to use stack space below the stack pointer. + - On entry to the asm block the stack pointer is guaranteed to be suitably aligned (according to the target ABI) for a function call. + - You are responsible for making sure you don't overflow the stack (e.g. use stack probing to ensure you hit a guard page). + - You should adjust the stack pointer when allocating stack memory as required by the target ABI. + - The stack pointer must be restored to its original value before leaving the asm block. +- If the `noreturn` option is set then behavior is undefined if execution falls through to the end of the asm block. +- If the `pure` option is set then behavior is undefined if the `asm!` has side-effects other than its direct outputs. + Behavior is also undefined if two executions of the `asm!` code with the same inputs result in different outputs. + - When used with the `nomem` option, "inputs" are just the direct inputs of the `asm!`. + - When used with the `readonly` option, "inputs" comprise the direct inputs of the `asm!` and any memory that the `asm!` block is allowed to read. +- These flags registers must be restored upon exiting the asm block if the `preserves_flags` option is set: + - x86 + - Status flags in `EFLAGS` (CF, PF, AF, ZF, SF, OF). + - Floating-point status word (all). + - Floating-point exception flags in `MXCSR` (PE, UE, OE, ZE, DE, IE). + - ARM + - Condition flags in `CPSR` (N, Z, C, V) + - Saturation flag in `CPSR` (Q) + - Greater than or equal flags in `CPSR` (GE). + - Condition flags in `FPSCR` (N, Z, C, V) + - Saturation flag in `FPSCR` (QC) + - Floating-point exception flags in `FPSCR` (IDC, IXC, UFC, OFC, DZC, IOC). + - AArch64 + - Condition flags (`NZCV` register). + - Floating-point status (`FPSR` register). + - RISC-V + - Floating-point exception flags in `fcsr` (`fflags`). + - Vector extension state (`vtype`, `vl`, `vcsr`). +- On x86, the direction flag (DF in `EFLAGS`) is clear on entry to an asm block and must be clear on exit. + - Behavior is undefined if the direction flag is set on exiting an asm block. +- On x86, the x87 floating-point register stack must remain unchanged unless all of the `st([0-7])` registers have been marked as clobbered with `out("st(0)") _, out("st(1)") _, ...`. + - If all x87 registers are clobbered then the x87 register stack is guaranteed to be empty upon entering an `asm` block. Assembly code must ensure that the x87 register stack is also empty when exiting the asm block. +- The requirement of restoring the stack pointer and non-output registers to their original value only applies when exiting an `asm!` block. + - This means that `asm!` blocks that never return (even if not marked `noreturn`) don't need to preserve these registers. + - When returning to a different `asm!` block than you entered (e.g. for context switching), these registers must contain the value they had upon entering the `asm!` block that you are *exiting*. + - You cannot exit an `asm!` block that has not been entered. + Neither can you exit an `asm!` block that has already been exited (without first entering it again). + - You are responsible for switching any target-specific state (e.g. thread-local storage, stack bounds). + - You cannot jump from an address in one `asm!` block to an address in another, even within the same function or block, without treating their contexts as potentially different and requiring context switching. You cannot assume that any particular value in those contexts (e.g. current stack pointer or temporary values below the stack pointer) will remain unchanged between the two `asm!` blocks. + - The set of memory locations that you may access is the intersection of those allowed by the `asm!` blocks you entered and exited. +- You cannot assume that two `asm!` blocks adjacent in source code, even without any other code between them, will end up in successive addresses in the binary without any other instructions between them. +- You cannot assume that an `asm!` block will appear exactly once in the output binary. + The compiler is allowed to instantiate multiple copies of the `asm!` block, for example when the function containing it is inlined in multiple places. +- On x86, inline assembly must not end with an instruction prefix (such as `LOCK`) that would apply to instructions generated by the compiler. + - The compiler is currently unable to detect this due to the way inline assembly is compiled, but may catch and reject this in the future. + +> **Note**: As a general rule, the flags covered by `preserves_flags` are those which are *not* preserved when performing a function call. diff --git a/src/doc/reference/src/patterns.md b/src/doc/reference/src/patterns.md index 8cd8af042f..31ce30b80f 100644 --- a/src/doc/reference/src/patterns.md +++ b/src/doc/reference/src/patterns.md @@ -443,8 +443,6 @@ A half-open range pattern in the style `a..` cannot be used to match within the A pattern `a..=b` must always have a ≤ b. It is an error to have a range pattern `10..=0`, for example. -The `...` syntax is kept for backwards compatibility. - Range patterns only work on scalar types. The accepted types are: * Integer types (u8, i8, u16, i16, usize, isize, etc.). @@ -535,6 +533,8 @@ minimum to maximum value. The range of values for a `char` type are precisely th ranges containing all Unicode Scalar Values: `'\u{0000}'..='\u{D7FF}'` and `'\u{E000}'..='\u{10FFFF}'`. +> **Edition Differences**: Before the 2021 edition, closed range patterns may also be written using `...` as an alternative to `..=`, with the same meaning. + ## Reference patterns > **Syntax**\ diff --git a/src/doc/reference/src/subtyping.md b/src/doc/reference/src/subtyping.md index 3f5e35b466..15b0b206a2 100644 --- a/src/doc/reference/src/subtyping.md +++ b/src/doc/reference/src/subtyping.md @@ -29,8 +29,8 @@ let subtype: &(for<'a> fn(&'a i32) -> &'a i32) = &((|x| x) as fn(&_) -> &_); let supertype: &(fn(&'static i32) -> &'static i32) = subtype; // This works similarly for trait objects -let subtype: &(for<'a> Fn(&'a i32) -> &'a i32) = &|x| x; -let supertype: &(Fn(&'static i32) -> &'static i32) = subtype; +let subtype: &(dyn for<'a> Fn(&'a i32) -> &'a i32) = &|x| x; +let supertype: &(dyn Fn(&'static i32) -> &'static i32) = subtype; // We can also substitute one higher-ranked lifetime for another let subtype: &(for<'a, 'b> fn(&'a i32, &'b i32))= &((|x, y| {}) as fn(&_, &_)); diff --git a/src/doc/reference/src/types.md b/src/doc/reference/src/types.md index 1a3fbab820..a7ce5bc824 100644 --- a/src/doc/reference/src/types.md +++ b/src/doc/reference/src/types.md @@ -12,7 +12,7 @@ limited capabilities. The list of types is: * Primitive types: - * [Boolean] — `true` or `false` + * [Boolean] — `bool` * [Numeric] — integer and float * [Textual] — `char` and `str` * [Never] — `!` — a type with no values diff --git a/src/doc/reference/src/types/trait-object.md b/src/doc/reference/src/types/trait-object.md index acc8565631..3526b7add7 100644 --- a/src/doc/reference/src/types/trait-object.md +++ b/src/doc/reference/src/types/trait-object.md @@ -14,15 +14,14 @@ number of [auto traits]. Trait objects implement the base trait, its auto traits, and any [supertraits] of the base trait. -Trait objects are written as the optional keyword `dyn` followed by a set of -trait bounds, but with the following restrictions on the trait bounds. All -traits except the first trait must be auto traits, there may not be more than -one lifetime, and opt-out bounds (e.g. `?Sized`) are not allowed. Furthermore, +Trait objects are written as the keyword `dyn` followed by a set of trait +bounds, but with the following restrictions on the trait bounds. All traits +except the first trait must be auto traits, there may not be more than one +lifetime, and opt-out bounds (e.g. `?Sized`) are not allowed. Furthermore, paths to traits may be parenthesized. For example, given a trait `Trait`, the following are all trait objects: -* `Trait` * `dyn Trait` * `dyn Trait + Send` * `dyn Trait + Send + Sync` @@ -32,6 +31,12 @@ For example, given a trait `Trait`, the following are all trait objects: * `dyn 'static + Trait`. * `dyn (Trait)` +> **Edition Differences**: Before the 2021 edition, the `dyn` keyword may be +> omitted. +> +> Note: For clarity, it is recommended to always use the `dyn` keyword on your +> trait objects unless your codebase supports compiling with Rust 1.26 or lower. + > **Edition Differences**: In the 2015 edition, if the first bound of the > trait object is a path that starts with `::`, then the `dyn` will be treated > as a part of the path. The first path can be put in parenthesis to get @@ -41,9 +46,6 @@ For example, given a trait `Trait`, the following are all trait objects: > Beginning in the 2018 edition, `dyn` is a true keyword and is not allowed in > paths, so the parentheses are not necessary. -> Note: For clarity, it is recommended to always use the `dyn` keyword on your -> trait objects unless your codebase supports compiling with Rust 1.26 or lower. - Two trait object types alias each other if the base traits alias each other and if the sets of auto traits are the same and the lifetime bounds are the same. For example, `dyn Trait + Send + UnwindSafe` is the same as diff --git a/src/doc/rust-by-example/.github/workflows/rbe.yml b/src/doc/rust-by-example/.github/workflows/rbe.yml index 7d3b19c546..94b7cdc955 100644 --- a/src/doc/rust-by-example/.github/workflows/rbe.yml +++ b/src/doc/rust-by-example/.github/workflows/rbe.yml @@ -14,13 +14,13 @@ jobs: - name: Install Rust run: | rustup set profile minimal - rustup toolchain install stable -c rust-docs - rustup default stable + rustup toolchain install nightly -c rust-docs + rustup default nightly - name: Install mdbook run: | mkdir bin - curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.5/mdbook-v0.4.5-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin + curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.15/mdbook-v0.4.15-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin echo "$(pwd)/bin" >> ${GITHUB_PATH} - name: Report versions @@ -35,6 +35,12 @@ jobs: - name: Build HTML run: mdbook build + - name: Check for broken links + run: | + curl -sSLo linkcheck.sh \ + https://raw.githubusercontent.com/rust-lang/rust/master/src/tools/linkchecker/linkcheck.sh + sh linkcheck.sh --all rust-by-example + - name: Upload Artifact uses: actions/upload-artifact@v1 with: diff --git a/src/doc/rust-by-example/book.toml b/src/doc/rust-by-example/book.toml index 089d703286..19db456b6d 100644 --- a/src/doc/rust-by-example/book.toml +++ b/src/doc/rust-by-example/book.toml @@ -9,3 +9,9 @@ editor = "ace" [output.html.fold] enable = true + +[output.html] +git-repository-url = "https://github.com/rust-lang/rust-by-example" + +[rust] +edition = "2021" diff --git a/src/doc/rust-by-example/src/SUMMARY.md b/src/doc/rust-by-example/src/SUMMARY.md index 216bceadfe..c3875079c3 100644 --- a/src/doc/rust-by-example/src/SUMMARY.md +++ b/src/doc/rust-by-example/src/SUMMARY.md @@ -52,6 +52,7 @@ - [match](flow_control/match.md) - [Destructuring](flow_control/match/destructuring.md) - [tuples](flow_control/match/destructuring/destructure_tuple.md) + - [arrays/slices](flow_control/match/destructuring/destructure_slice.md) - [enums](flow_control/match/destructuring/destructure_enum.md) - [pointers/ref](flow_control/match/destructuring/destructure_pointers.md) - [structs](flow_control/match/destructuring/destructure_structures.md) @@ -209,6 +210,7 @@ - [Dev-dependencies](testing/dev_dependencies.md) - [Unsafe Operations](unsafe.md) + - [Inline assembly](unsafe/asm.md) - [Compatibility](compatibility.md) - [Raw identifiers](compatibility/raw_identifiers.md) diff --git a/src/doc/rust-by-example/src/attribute/cfg.md b/src/doc/rust-by-example/src/attribute/cfg.md index d0a4a10b73..e4aeb1d3d2 100644 --- a/src/doc/rust-by-example/src/attribute/cfg.md +++ b/src/doc/rust-by-example/src/attribute/cfg.md @@ -9,6 +9,8 @@ While the former enables conditional compilation, the latter conditionally evaluates to `true` or `false` literals allowing for checks at run-time. Both utilize identical argument syntax. +`cfg!`, unlike `#[cfg]`, does not remove any code and only evaluates to true or false. For example, all blocks in an if/else expression need to be valid when `cfg!` is used for the condition, regardless of what `cfg!` is evaluating. + ```rust,editable // This function only gets compiled if the target OS is linux #[cfg(target_os = "linux")] diff --git a/src/doc/rust-by-example/src/custom_types/structs.md b/src/doc/rust-by-example/src/custom_types/structs.md index f7813b4d36..e9047c5a5f 100644 --- a/src/doc/rust-by-example/src/custom_types/structs.md +++ b/src/doc/rust-by-example/src/custom_types/structs.md @@ -44,7 +44,6 @@ fn main() { // Print debug struct println!("{:?}", peter); - // Instantiate a `Point` let point: Point = Point { x: 10.3, y: 0.4 }; diff --git a/src/doc/rust-by-example/src/error/result/enter_question_mark.md b/src/doc/rust-by-example/src/error/result/enter_question_mark.md index 8101e3efd7..ca954b1ac2 100644 --- a/src/doc/rust-by-example/src/error/result/enter_question_mark.md +++ b/src/doc/rust-by-example/src/error/result/enter_question_mark.md @@ -43,7 +43,7 @@ The `?` operator is now recommended, but you may still find `try!` when looking at older code. The same `multiply` function from the previous example would look like this using `try!`: -```rust,editable +```rust,editable,edition2015 // To compile and run this example without errors, while using Cargo, change the value // of the `edition` field, in the `[package]` section of the `Cargo.toml` file, to "2015". diff --git a/src/doc/rust-by-example/src/flow_control/match/destructuring.md b/src/doc/rust-by-example/src/flow_control/match/destructuring.md index 5e82e6cf54..74df9fe6c2 100644 --- a/src/doc/rust-by-example/src/flow_control/match/destructuring.md +++ b/src/doc/rust-by-example/src/flow_control/match/destructuring.md @@ -3,6 +3,7 @@ A `match` block can destructure items in a variety of ways. * [Destructuring Tuples][tuple] +* [Destructuring Arrays and Slices][slice] * [Destructuring Enums][enum] * [Destructuring Pointers][refs] * [Destructuring Structures][struct] @@ -12,3 +13,4 @@ A `match` block can destructure items in a variety of ways. [refs]: destructuring/destructure_pointers.md [struct]: destructuring/destructure_structures.md [tuple]: destructuring/destructure_tuple.md +[slice]: destructuring/destructure_slice.md diff --git a/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_slice.md b/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_slice.md new file mode 100644 index 0000000000..e9d7ff6852 --- /dev/null +++ b/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_slice.md @@ -0,0 +1,48 @@ +# arrays/slices + +In like manner to tuples, arrays and slices can be destructured this way: + +```rust,editable +fn main() { + // Try changing the values in the array, or make it a slice! + let array = [1, -2, 6]; + + match array { + // Binds the second and the third elements to the respective variables + [0, second, third] => + println!("array[0] = 0, array[1] = {}, array[2] = {}", second, third), + + // Single values can be ignored with _ + [1, _, third] => println!( + "array[0] = 1, array[2] = {} and array[1] was ignored", + third + ), + + // You can also bind some and ignore the rest + [-1, second, ..] => println!( + "array[0] = -1, array[1] = {} and all the other ones were ignored", + second + ), + // The code below would not compile + // [-1, second] => ... + + // Or store them in another array/slice (the type depends on + // that of the value that is being matched against) + [3, second, tail @ ..] => println!( + "array[0] = 3, array[1] = {} and the other elements were {:?}", + second, tail + ), + + // Combining these patterns, we can, for example, bind the first and + // last values, and store the rest of them in a single array + [first, middle @ .., last] => println!( + "array[0] = {}, middle = {:?}, array[2] = {}", + first, middle, last + ), + } +} +``` + +### See also: + +[Arrays and Slices](../../../primitives/array.md) diff --git a/src/doc/rust-by-example/src/fn/closures/closure_examples/iter_any.md b/src/doc/rust-by-example/src/fn/closures/closure_examples/iter_any.md index 1fb64e9707..2bbf40864c 100644 --- a/src/doc/rust-by-example/src/fn/closures/closure_examples/iter_any.md +++ b/src/doc/rust-by-example/src/fn/closures/closure_examples/iter_any.md @@ -35,7 +35,7 @@ fn main() { // `iter()` for arrays yields `&i32`. println!("2 in array1: {}", array1.iter() .any(|&x| x == 2)); // `into_iter()` for arrays unusually yields `&i32`. - println!("2 in array2: {}", array2.into_iter().any(|&x| x == 2)); + println!("2 in array2: {}", array2.iter().any(|&x| x == 2)); } ``` diff --git a/src/doc/rust-by-example/src/fn/closures/closure_examples/iter_find.md b/src/doc/rust-by-example/src/fn/closures/closure_examples/iter_find.md index 9eb5072e97..1de0e84149 100644 --- a/src/doc/rust-by-example/src/fn/closures/closure_examples/iter_find.md +++ b/src/doc/rust-by-example/src/fn/closures/closure_examples/iter_find.md @@ -41,8 +41,8 @@ fn main() { // `iter()` for arrays yields `&i32` println!("Find 2 in array1: {:?}", array1.iter() .find(|&&x| x == 2)); - // `into_iter()` for arrays unusually yields `&i32` - println!("Find 2 in array2: {:?}", array2.into_iter().find(|&&x| x == 2)); + // `into_iter()` for arrays yields `i32` + println!("Find 2 in array2: {:?}", array2.into_iter().find(|&x| x == 2)); } ``` diff --git a/src/doc/rust-by-example/src/fn/closures/input_parameters.md b/src/doc/rust-by-example/src/fn/closures/input_parameters.md index be36c6d361..8f4307ff53 100644 --- a/src/doc/rust-by-example/src/fn/closures/input_parameters.md +++ b/src/doc/rust-by-example/src/fn/closures/input_parameters.md @@ -3,12 +3,13 @@ While Rust chooses how to capture variables on the fly mostly without type annotation, this ambiguity is not allowed when writing functions. When taking a closure as an input parameter, the closure's complete type must be -annotated using one of a few `traits`. In order of decreasing restriction, +annotated using one of a few `traits`, and they're determined by what the +closure does with captured value. In order of decreasing restriction, they are: -* `Fn`: the closure captures by reference (`&T`) -* `FnMut`: the closure captures by mutable reference (`&mut T`) -* `FnOnce`: the closure captures by value (`T`) +* `Fn`: the closure uses the captured value by reference (`&T`) +* `FnMut`: the closure uses the captured value by mutable reference (`&mut T`) +* `FnOnce`: the closure uses the captured value by value (`T`) On a variable-by-variable basis, the compiler will capture variables in the least restrictive manner possible. diff --git a/src/doc/rust-by-example/src/generics/assoc_items/types.md b/src/doc/rust-by-example/src/generics/assoc_items/types.md index 0358fcebca..3173704686 100644 --- a/src/doc/rust-by-example/src/generics/assoc_items/types.md +++ b/src/doc/rust-by-example/src/generics/assoc_items/types.md @@ -13,7 +13,7 @@ trait Contains { type B; // Updated syntax to refer to these new types generically. - fn contains(&self, &Self::A, &Self::B) -> bool; + fn contains(&self, _: &Self::A, _: &Self::B) -> bool; } ``` diff --git a/src/doc/rust-by-example/src/generics/bounds.md b/src/doc/rust-by-example/src/generics/bounds.md index 86e54e670c..5d7e849a8d 100644 --- a/src/doc/rust-by-example/src/generics/bounds.md +++ b/src/doc/rust-by-example/src/generics/bounds.md @@ -58,10 +58,10 @@ fn main() { let _triangle = Triangle { length: 3.0, height: 4.0 }; print_debug(&rectangle); - println!("Area: {}", area(&rectangle)); + println!("Area: {}", rectangle.area()); //print_debug(&_triangle); - //println!("Area: {}", area(&_triangle)); + //println!("Area: {}", _triangle.area()); // ^ TODO: Try uncommenting these. // | Error: Does not implement either `Debug` or `HasArea`. } diff --git a/src/doc/rust-by-example/src/hello/print.md b/src/doc/rust-by-example/src/hello/print.md index 89d2aa0de3..7575024060 100644 --- a/src/doc/rust-by-example/src/hello/print.md +++ b/src/doc/rust-by-example/src/hello/print.md @@ -74,7 +74,7 @@ Implementing the `fmt::Display` trait automatically implements the * Fix the two issues in the above code (see FIXME) so that it runs without error. - * Add a `println!` macro that prints: `Pi is roughly 3.142` by controlling + * Add a `println!` macro call that prints: `Pi is roughly 3.142` by controlling the number of decimal places shown. For the purposes of this exercise, use `let pi = 3.141592` as an estimate for pi. (Hint: you may need to check the [`std::fmt`][fmt] documentation for setting the number of diff --git a/src/doc/rust-by-example/src/macros/repeat.md b/src/doc/rust-by-example/src/macros/repeat.md index 04c3b7da66..3b8a2b6e59 100644 --- a/src/doc/rust-by-example/src/macros/repeat.md +++ b/src/doc/rust-by-example/src/macros/repeat.md @@ -21,8 +21,8 @@ macro_rules! find_min { } fn main() { - println!("{}", find_min!(1u32)); - println!("{}", find_min!(1u32 + 2, 2u32)); - println!("{}", find_min!(5u32, 2u32 * 3, 4u32)); + println!("{}", find_min!(1)); + println!("{}", find_min!(1 + 2, 2)); + println!("{}", find_min!(5, 2 * 3, 4)); } ``` diff --git a/src/doc/rust-by-example/src/meta.md b/src/doc/rust-by-example/src/meta.md index a7434521c7..367c7e121f 100644 --- a/src/doc/rust-by-example/src/meta.md +++ b/src/doc/rust-by-example/src/meta.md @@ -6,7 +6,7 @@ everyone. These topics include: - [Documentation][doc]: Generate library documentation for users via the included `rustdoc`. -- [Playpen][playpen]: Integrate the Rust Playpen(also known as the Rust Playground) in your documentation. +- [Playpen][playpen]: Integrate the Rust Playpen (also known as the Rust Playground) in your documentation. [doc]: meta/doc.md [playpen]: meta/playpen.md diff --git a/src/doc/rust-by-example/src/scope/move/partial_move.md b/src/doc/rust-by-example/src/scope/move/partial_move.md index 98c6c8dc81..21d85a8b32 100644 --- a/src/doc/rust-by-example/src/scope/move/partial_move.md +++ b/src/doc/rust-by-example/src/scope/move/partial_move.md @@ -13,12 +13,12 @@ fn main() { #[derive(Debug)] struct Person { name: String, - age: u8, + age: Box, } let person = Person { name: String::from("Alice"), - age: 20, + age: Box::new(20), }; // `name` is moved out of person, but `age` is referenced @@ -35,6 +35,13 @@ fn main() { println!("The person's age from person struct is {}", person.age); } ``` +(In this example, we store the `age` variable on the heap to +illustrate the partial move: deleting `ref` in the above code would +give an error as the ownership of `person.age` would be moved to the +variable `age`. If `Person.age` were stored on the stack, `ref` would +not be required as the definition of `age` would copy the data from +`person.age` without moving it.) + ### See also: [destructuring][destructuring] diff --git a/src/doc/rust-by-example/src/std/result/question_mark.md b/src/doc/rust-by-example/src/std/result/question_mark.md index a1f7706840..66dbd2d1e4 100644 --- a/src/doc/rust-by-example/src/std/result/question_mark.md +++ b/src/doc/rust-by-example/src/std/result/question_mark.md @@ -3,7 +3,7 @@ Chaining results using match can get pretty untidy; luckily, the `?` operator can be used to make things pretty again. `?` is used at the end of an expression returning a `Result`, and is equivalent to a match expression, where the -`Err(err)` branch expands to an early `Err(From::from(err))`, and the `Ok(ok)` +`Err(err)` branch expands to an early `return Err(From::from(err))`, and the `Ok(ok)` branch expands to an `ok` expression. ```rust,editable,ignore,mdbook-runnable diff --git a/src/doc/rust-by-example/src/std/str.md b/src/doc/rust-by-example/src/std/str.md index ba14b59db1..26d8fd1097 100644 --- a/src/doc/rust-by-example/src/std/str.md +++ b/src/doc/rust-by-example/src/std/str.md @@ -106,7 +106,7 @@ fn main() { println!("{}", quotes); // If you need "# in your string, just use more #s in the delimiter. - // There is no limit for the number of #s you can use. + // You can use up to 65535 #s. let longer_delimiter = r###"A string with "# in it. And even "##!"###; println!("{}", longer_delimiter); } diff --git a/src/doc/rust-by-example/src/unsafe/asm.md b/src/doc/rust-by-example/src/unsafe/asm.md new file mode 100644 index 0000000000..8d81a9c5f3 --- /dev/null +++ b/src/doc/rust-by-example/src/unsafe/asm.md @@ -0,0 +1,437 @@ +# Inline assembly + +Rust provides support for inline assembly via the `asm!` macro. +It can be used to embed handwritten assembly in the assembly output generated by the compiler. +Generally this should not be necessary, but might be where the required performance or timing +cannot be otherwise achieved. Accessing low level hardware primitives, e.g. in kernel code, may also demand this functionality. + +> **Note**: the examples here are given in x86/x86-64 assembly, but other architectures are also supported. + +Inline assembly is currently supported on the following architectures: +- x86 and x86-64 +- ARM +- AArch64 +- RISC-V + +## Basic usage + +Let us start with the simplest possible example: + +```rust +use std::arch::asm; + +unsafe { + asm!("nop"); +} +``` + +This will insert a NOP (no operation) instruction into the assembly generated by the compiler. +Note that all `asm!` invocations have to be inside an `unsafe` block, as they could insert +arbitrary instructions and break various invariants. The instructions to be inserted are listed +in the first argument of the `asm!` macro as a string literal. + +## Inputs and outputs + +Now inserting an instruction that does nothing is rather boring. Let us do something that +actually acts on data: + +```rust +use std::arch::asm; + +let x: u64; +unsafe { + asm!("mov {}, 5", out(reg) x); +} +assert_eq!(x, 5); +``` + +This will write the value `5` into the `u64` variable `x`. +You can see that the string literal we use to specify instructions is actually a template string. +It is governed by the same rules as Rust [format strings][format-syntax]. +The arguments that are inserted into the template however look a bit different than you may +be familiar with. First we need to specify if the variable is an input or an output of the +inline assembly. In this case it is an output. We declared this by writing `out`. +We also need to specify in what kind of register the assembly expects the variable. +In this case we put it in an arbitrary general purpose register by specifying `reg`. +The compiler will choose an appropriate register to insert into +the template and will read the variable from there after the inline assembly finishes executing. + +Let us see another example that also uses an input: + +```rust +use std::arch::asm; + +let i: u64 = 3; +let o: u64; +unsafe { + asm!( + "mov {0}, {1}", + "add {0}, 5", + out(reg) o, + in(reg) i, + ); +} +assert_eq!(o, 8); +``` + +This will add `5` to the input in variable `i` and write the result to variable `o`. +The particular way this assembly does this is first copying the value from `i` to the output, +and then adding `5` to it. + +The example shows a few things: + +First, we can see that `asm!` allows multiple template string arguments; each +one is treated as a separate line of assembly code, as if they were all joined +together with newlines between them. This makes it easy to format assembly +code. + +Second, we can see that inputs are declared by writing `in` instead of `out`. + +Third, we can see that we can specify an argument number, or name as in any format string. +For inline assembly templates this is particularly useful as arguments are often used more than once. +For more complex inline assembly using this facility is generally recommended, as it improves +readability, and allows reordering instructions without changing the argument order. + +We can further refine the above example to avoid the `mov` instruction: + +```rust +use std::arch::asm; + +let mut x: u64 = 3; +unsafe { + asm!("add {0}, 5", inout(reg) x); +} +assert_eq!(x, 8); +``` + +We can see that `inout` is used to specify an argument that is both input and output. +This is different from specifying an input and output separately in that it is guaranteed to assign both to the same register. + +It is also possible to specify different variables for the input and output parts of an `inout` operand: + +```rust +use std::arch::asm; + +let x: u64 = 3; +let y: u64; +unsafe { + asm!("add {0}, 5", inout(reg) x => y); +} +assert_eq!(y, 8); +``` + +## Late output operands + +The Rust compiler is conservative with its allocation of operands. It is assumed that an `out` +can be written at any time, and can therefore not share its location with any other argument. +However, to guarantee optimal performance it is important to use as few registers as possible, +so they won't have to be saved and reloaded around the inline assembly block. +To achieve this Rust provides a `lateout` specifier. This can be used on any output that is +written only after all inputs have been consumed. +There is also a `inlateout` variant of this specifier. + +Here is an example where `inlateout` *cannot* be used: + +```rust +use std::arch::asm; + +let mut a: u64 = 4; +let b: u64 = 4; +let c: u64 = 4; +unsafe { + asm!( + "add {0}, {1}", + "add {0}, {2}", + inout(reg) a, + in(reg) b, + in(reg) c, + ); +} +assert_eq!(a, 12); +``` + +Here the compiler is free to allocate the same register for inputs `b` and `c` since it knows they have the same value. However it must allocate a separate register for `a` since it uses `inout` and not `inlateout`. If `inlateout` was used, then `a` and `c` could be allocated to the same register, in which case the first instruction to overwrite the value of `c` and cause the assembly code to produce the wrong result. + +However the following example can use `inlateout` since the output is only modified after all input registers have been read: + +```rust +use std::arch::asm; + +let mut a: u64 = 4; +let b: u64 = 4; +unsafe { + asm!("add {0}, {1}", inlateout(reg) a, in(reg) b); +} +assert_eq!(a, 8); +``` + +As you can see, this assembly fragment will still work correctly if `a` and `b` are assigned to the same register. + +## Explicit register operands + +Some instructions require that the operands be in a specific register. +Therefore, Rust inline assembly provides some more specific constraint specifiers. +While `reg` is generally available on any architecture, explicit registers are highly architecture specific. E.g. for x86 the general purpose registers `eax`, `ebx`, `ecx`, `edx`, `ebp`, `esi`, and `edi` among others can be addressed by their name. + +```rust,no_run +use std::arch::asm; + +let cmd = 0xd1; +unsafe { + asm!("out 0x64, eax", in("eax") cmd); +} +``` + +In this example we call the `out` instruction to output the content of the `cmd` variable to port `0x64`. Since the `out` instruction only accepts `eax` (and its sub registers) as operand we had to use the `eax` constraint specifier. + +> **Note**: unlike other operand types, explicit register operands cannot be used in the template string: you can't use `{}` and should write the register name directly instead. Also, they must appear at the end of the operand list after all other operand types. + +Consider this example which uses the x86 `mul` instruction: + +```rust +use std::arch::asm; + +fn mul(a: u64, b: u64) -> u128 { + let lo: u64; + let hi: u64; + + unsafe { + asm!( + // The x86 mul instruction takes rax as an implicit input and writes + // the 128-bit result of the multiplication to rax:rdx. + "mul {}", + in(reg) a, + inlateout("rax") b => lo, + lateout("rdx") hi + ); + } + + ((hi as u128) << 64) + lo as u128 +} +``` + +This uses the `mul` instruction to multiply two 64-bit inputs with a 128-bit result. +The only explicit operand is a register, that we fill from the variable `a`. +The second operand is implicit, and must be the `rax` register, which we fill from the variable `b`. +The lower 64 bits of the result are stored in `rax` from which we fill the variable `lo`. +The higher 64 bits are stored in `rdx` from which we fill the variable `hi`. + +## Clobbered registers + +In many cases inline assembly will modify state that is not needed as an output. +Usually this is either because we have to use a scratch register in the assembly or because instructions modify state that we don't need to further examine. +This state is generally referred to as being "clobbered". +We need to tell the compiler about this since it may need to save and restore this state around the inline assembly block. + +```rust +use std::arch::asm; + +let mut ebx: u32; +let mut edx: u32; +let mut ecx: u32; +unsafe { + asm!( + "push rbx", + "cpuid", + "mov {0:e}, ebx", + "pop rbx", + // String is stored as ascii in ebx, edx, ecx in order + // Because ebx is reserved, we get a scratch register and move from + // ebx into it in the asm. The asm needs to preserve the value of + // that register though, so it is pushed and popped around the main asm + // (in 64 bit mode for 64 bit processors, 32 bit processors would use ebx) + out(reg) ebx, + out("edx") edx, + out("ecx") ecx, + // EAX 0 selects CPUID parameter and manufacturer ID + inout("eax") 0 => _, + ); +} + +// Turn the resulting values into a string +let mut s = String::with_capacity(12); +ebx.to_ne_bytes().map(|b| s.push(char::from(b))); +edx.to_ne_bytes().map(|b| s.push(char::from(b))); +ecx.to_ne_bytes().map(|b| s.push(char::from(b))); +println!("CPU Manufacturer ID: {}", s); +``` + +In the example above we use the `cpuid` instruction to read the CPU manufacturer ID. +This instruction writes to `eax` with the maximum supported `cpuid` argument and `ebx`, `esx`, and `ecx` with the CPU manufacturer ID as ASCII bytes in that order. + +Even though `eax` is never read we still need to tell the compiler that the register has been modified so that the compiler can save any values that were in these registers before the asm. This is done by declaring it as an output but with `_` instead of a variable name, which indicates that the output value is to be discarded. + +This code also works around the limitation that `ebx` is a reserved register by LLVM. That means that LLVM assumes that it has full control over the register and it must be restored to its original state before exiting the asm block, so it cannot be used as an output. To work around this we save the register via `push`, read from `ebx` inside the asm block into a temporary register allocated with `out(reg)` and then restoring `ebx` to its original state via `pop`. The `push` and `pop` use the full 64-bit `rbx` version of the register to ensure that the entire register is saved. On 32 bit targets the code would instead use `ebx` in the `push`/`pop`. + +This can also be used with a general register class (e.g. `reg`) to obtain a scratch register for use inside the asm code: + +```rust +use std::arch::asm; + +// Multiply x by 6 using shifts and adds +let mut x: u64 = 4; +unsafe { + asm!( + "mov {tmp}, {x}", + "shl {tmp}, 1", + "shl {x}, 2", + "add {x}, {tmp}", + x = inout(reg) x, + tmp = out(reg) _, + ); +} +assert_eq!(x, 4 * 6); +``` + +## Symbol operands and ABI clobbers + +By default, `asm!` assumes that any register not specified as an output will have its contents preserved by the assembly code. The [`clobber_abi`] argument to `asm!` tells the compiler to automatically insert the necessary clobber operands according to the given calling convention ABI: any register which is not fully preserved in that ABI will be treated as clobbered. Multiple `clobber_abi` arguments may be provided and all clobbers from all specified ABIs will be inserted. + +[`clobber_abi`]: ../../reference/inline-assembly.html#abi-clobbers + +```rust +use std::arch::asm; + +extern "C" fn foo(arg: i32) -> i32 { + println!("arg = {}", arg); + arg * 2 +} + +fn call_foo(arg: i32) -> i32 { + unsafe { + let result; + asm!( + "call *{}", + // Function pointer to call + in(reg) foo, + // 1st argument in rdi + in("rdi") arg, + // Return value in rax + out("rax") result, + // Mark all registers which are not preserved by the "C" calling + // convention as clobbered. + clobber_abi("C"), + ); + result + } +} +``` + +## Register template modifiers + +In some cases, fine control is needed over the way a register name is formatted when inserted into the template string. This is needed when an architecture's assembly language has several names for the same register, each typically being a "view" over a subset of the register (e.g. the low 32 bits of a 64-bit register). + +By default the compiler will always choose the name that refers to the full register size (e.g. `rax` on x86-64, `eax` on x86, etc). + +This default can be overriden by using modifiers on the template string operands, just like you would with format strings: + +```rust +use std::arch::asm; + +let mut x: u16 = 0xab; + +unsafe { + asm!("mov {0:h}, {0:l}", inout(reg_abcd) x); +} + +assert_eq!(x, 0xabab); +``` + +In this example, we use the `reg_abcd` register class to restrict the register allocator to the 4 legacy x86 registers (`ax`, `bx`, `cx`, `dx`) of which the first two bytes can be addressed independently. + +Let us assume that the register allocator has chosen to allocate `x` in the `ax` register. +The `h` modifier will emit the register name for the high byte of that register and the `l` modifier will emit the register name for the low byte. The asm code will therefore be expanded as `mov ah, al` which copies the low byte of the value into the high byte. + +If you use a smaller data type (e.g. `u16`) with an operand and forget the use template modifiers, the compiler will emit a warning and suggest the correct modifier to use. + +## Memory address operands + +Sometimes assembly instructions require operands passed via memory addresses/memory locations. +You have to manually use the memory address syntax specified by the target architecture. +For example, on x86/x86_64 using Intel assembly syntax, you should wrap inputs/outputs in `[]` to indicate they are memory operands: + +```rust +use std::arch::asm; + +fn load_fpu_control_word(control: u16) { + unsafe { + asm!("fldcw [{}]", in(reg) &control, options(nostack)); + } +} +``` + +## Labels + +Any reuse of a named label, local or otherwise, can result in an assembler or linker error or may cause other strange behavior. Reuse of a named label can happen in a variety of ways including: + +- explicitly: using a label more than once in one `asm!` block, or multiple times across blocks. +- implicitly via inlining: the compiler is allowed to instantiate multiple copies of an `asm!` block, for example when the function containing it is inlined in multiple places. +- implicitly via LTO: LTO can cause code from *other crates* to be placed in the same codegen unit, and so could bring in arbitrary labels. + +As a consequence, you should only use GNU assembler **numeric** [local labels] inside inline assembly code. Defining symbols in assembly code may lead to assembler and/or linker errors due to duplicate symbol definitions. + +Moreover, on x86 when using the default Intel syntax, due to [an LLVM bug], you shouldn't use labels exclusively made of `0` and `1` digits, e.g. `0`, `11` or `101010`, as they may end up being interpreted as binary values. Using `options(att_syntax)` will avoid any ambiguity, but that affects the syntax of the _entire_ `asm!` block. (See [Options](#options), below, for more on `options`.) + +```rust +use std::arch::asm; + +let mut a = 0; +unsafe { + asm!( + "mov {0}, 10", + "2:", + "sub {0}, 1", + "cmp {0}, 3", + "jle 2f", + "jmp 2b", + "2:", + "add {0}, 2", + out(reg) a + ); +} +assert_eq!(a, 5); +``` + +This will decrement the `{0}` register value from 10 to 3, then add 2 and store it in `a`. + +This example shows a few things: + +- First, that the same number can be used as a label multiple times in the same inline block. +- Second, that when a numeric label is used as a reference (as an instruction operand, for example), the suffixes “b” (“backward”) or ”f” (“forward”) should be added to the numeric label. It will then refer to the nearest label defined by this number in this direction. + +First that the same number can be used as a label multiple times in the same inline block. + +Second, that when a numeric label is used as a reference (as an instruction operand, for example), the suffixes b (“backward”) or f (“forward”) should be added to the numeric label. It will then refer to the nearest label defined by this number in this direction. + +[local labels]: https://sourceware.org/binutils/docs/as/Symbol-Names.html#Local-Labels +[an LLVM bug]: https://bugs.llvm.org/show_bug.cgi?id=36144 + +## Options + +By default, an inline assembly block is treated the same way as an external FFI function call with a custom calling convention: it may read/write memory, have observable side effects, etc. However, in many cases it is desirable to give the compiler more information about what the assembly code is actually doing so that it can optimize better. + +Let's take our previous example of an `add` instruction: + +```rust +use std::arch::asm; + +let mut a: u64 = 4; +let b: u64 = 4; +unsafe { + asm!( + "add {0}, {1}", + inlateout(reg) a, in(reg) b, + options(pure, nomem, nostack), + ); +} +assert_eq!(a, 8); +``` + +Options can be provided as an optional final argument to the `asm!` macro. We specified three options here: +- `pure` means that the asm code has no observable side effects and that its output depends only on its inputs. This allows the compiler optimizer to call the inline asm fewer times or even eliminate it entirely. +- `nomem` means that the asm code does not read or write to memory. By default the compiler will assume that inline assembly can read or write any memory address that is accessible to it (e.g. through a pointer passed as an operand, or a global). +- `nostack` means that the asm code does not push any data onto the stack. This allows the compiler to use optimizations such as the stack red zone on x86-64 to avoid stack pointer adjustments. + +These allow the compiler to better optimize code using `asm!`, for example by eliminating pure `asm!` blocks whose outputs are not needed. + +See the [reference](../../reference/inline-assembly.html) for the full list of available options and their effects. diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs index 51af6f5aab..29fa24784f 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs @@ -73,7 +73,7 @@ fn main() { println!("{:#?}", parse); // Analyze the program and inspect the types of definitions. queries.global_ctxt().unwrap().take().enter(|tcx| { - for (_, item) in &tcx.hir().krate().items { + for item in tcx.hir().items() { match item.kind { rustc_hir::ItemKind::Static(_, _, _) | rustc_hir::ItemKind::Fn(_, _, _) => { let name = item.ident; diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs index ee9a20c059..d1b42658e1 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-getting-diagnostics.rs @@ -81,7 +81,7 @@ fn main() { compiler.enter(|queries| { queries.global_ctxt().unwrap().take().enter(|tcx| { // Run the analysis phase on the local crate to trigger the type error. - tcx.analysis(rustc_hir::def_id::LOCAL_CRATE); + let _ = tcx.analysis(()); }); }); }); diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs index 2c75334980..cbf48c9ceb 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs @@ -64,9 +64,9 @@ fn main() { // Analyze the crate and inspect the types under the cursor. queries.global_ctxt().unwrap().take().enter(|tcx| { // Every compilation contains a single crate. - let hir_krate = tcx.hir().krate(); + let hir_krate = tcx.hir(); // Iterate over the top-level items in the crate, looking for the main function. - for (_, item) in &hir_krate.items { + for item in hir_krate.items() { // Use pattern-matching to find a specific node inside the main function. if let rustc_hir::ItemKind::Fn(_, _, body_id) = item.kind { let expr = &tcx.hir().body(body_id).value; diff --git a/src/doc/rustc-dev-guide/src/appendix/humorust.md b/src/doc/rustc-dev-guide/src/appendix/humorust.md index a7ba617699..c502527d5b 100644 --- a/src/doc/rustc-dev-guide/src/appendix/humorust.md +++ b/src/doc/rustc-dev-guide/src/appendix/humorust.md @@ -11,3 +11,4 @@ enlightening? - [`break rust;`](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=0ab2bd6a9d722e0f05a95e2a5dcf89cc) - [The Nomicon Intro](https://doc.rust-lang.org/stable/nomicon/) - [`rustc-ty` renaming punfest](https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/rustc-ty.20naming.20bikeshed.20.2F.20punfest.20%28was.3A.20design.20meeting.202.2E.2E.2E/near/189906455) +- [try using their name "ferris" instead](https://github.com/rust-lang/rust/pull/91476) diff --git a/src/doc/rustc-dev-guide/src/backend/libs-and-metadata.md b/src/doc/rustc-dev-guide/src/backend/libs-and-metadata.md index d2cf8b6929..5e005c965e 100644 --- a/src/doc/rustc-dev-guide/src/backend/libs-and-metadata.md +++ b/src/doc/rustc-dev-guide/src/backend/libs-and-metadata.md @@ -107,12 +107,11 @@ The hash includes a variety of elements: Disambiguator](#crate-disambiguator), and all CLI options marked with `[TRACKED]`). -See [`finalize_and_compute_crate_hash`] for where the hash is actually -computed. +See [`compute_hir_hash`] for where the hash is actually computed. [SVH]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_data_structures/svh/struct.Svh.html [incremental compilation]: ../queries/incremental-compilation.md -[`finalize_and_compute_crate_hash`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/collector/struct.NodeCollector.html#method.finalize_and_compute_crate_hash +[`compute_hir_hash`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast_lowering/struct.LoweringContext.html#method.compute_hir_hash ### Stable Crate Id diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping.md b/src/doc/rustc-dev-guide/src/building/bootstrapping.md index fc1ad6c000..460776e51a 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping.md @@ -56,7 +56,7 @@ because one must first build the new compiler with an older compiler and then use that to build the new compiler with itself. For development, you usually only want the `stage1` compiler, which you can build with `./x.py build library/std`. -See [Building the Compiler](/building/how-to-build-and-run.html#building-the-compiler). +See [Building the Compiler](./how-to-build-and-run.html#building-the-compiler). ### Stage 3 diff --git a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md index 981bb6e50e..4fe1da6d0a 100644 --- a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md +++ b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md @@ -11,6 +11,12 @@ see [the next page](./prerequisites.md). ## Get the source code +The main repository is [`rust-lang/rust`][repo]. This contains the compiler, +the standard library (including `core`, `alloc`, `test`, `proc_macro`, etc), +and a bunch of tools (e.g. `rustdoc`, the bootstrapping infrastructure, etc). + +[repo]: https://github.com/rust-lang/rust + The very first step to work on `rustc` is to clone the repository: ```bash @@ -18,36 +24,50 @@ git clone https://github.com/rust-lang/rust.git cd rust ``` +There are also submodules for things like LLVM, `clippy`, `miri`, etc. The +build tool will automatically clone and sync these for you. But if you want to, +you can do the following: + +```sh +# first time +git submodule update --init --recursive + +# subsequent times (to pull new commits) +git submodule update +``` + ## Create a `config.toml` -To start, run `./x.py setup`. This will create a `config.toml` with reasonable defaults. +To start, run `./x.py setup`. This will do some initialization and create a +`config.toml` for you with reasonable defaults. These defaults are specified +indirectly via the `profile` setting, which points to one of the TOML files in +`src/bootstrap/defaults.` -You may also want to change some of the following settings (and possibly others, such as +Alternatively, you can write `config.toml` by hand. See `config.toml.example` +for all the available settings and explanations of them. The following settings +are of particular interest, and `config.toml.example` has full explanations. + +You may want to change some of the following settings (and possibly others, such as `llvm.ccache`): ```toml [llvm] # Whether to use Rust CI built LLVM instead of locally building it. -download-ci-llvm = true - -# Indicates whether the LLVM assertions are enabled or not -assertions = true +download-ci-llvm = true # Download a pre-built LLVM? +assertions = true # LLVM assertions on? +ccache = "/path/to/ccache" # Use ccache when building LLVM? [rust] -# Whether or not to leave debug! and trace! calls in the rust binary. -# Overrides the `debug-assertions` option, if defined. -# -# Defaults to rust.debug-assertions value -# -# If you see a message from `tracing` saying -# `max_level_info` is enabled and means logging won't be shown, -# set this value to `true`. -debug-logging = true - -# Whether to always use incremental compilation when building rustc -incremental = true +debug-logging = true # Leave debug! and trace! calls in rustc? +incremental = true # Build rustc with incremental compilation? ``` +If you set `download-ci-llvm = true`, in some circumstances, such as when +updating the version of LLVM used by `rustc`, you may want to temporarily +disable this feature. See the ["Updating LLVM" section] for more. + +["Updating LLVM" section]: https://rustc-dev-guide.rust-lang.org/backend/updating-llvm.html?highlight=download-ci-llvm#feature-updates + If you have already built `rustc` and you change settings related to LLVM, then you may have to execute `rm -rf build` for subsequent configuration changes to take effect. Note that `./x.py clean` will not cause a rebuild of LLVM. @@ -212,6 +232,11 @@ host: x86_64-unknown-linux-gnu release: 1.48.0-dev LLVM version: 11.0 ``` + +The rustup toolchain points to the specified toolchain compiled in your `build` directory, +so the rustup toolchain will be updated whenever `x.py build` or `x.py test` are run for +that toolchain/stage. + ## Other `x.py` commands Here are a few other useful `x.py` commands. We'll cover some of them in detail diff --git a/src/doc/rustc-dev-guide/src/building/prerequisites.md b/src/doc/rustc-dev-guide/src/building/prerequisites.md index be5d96ad9b..cfe4c77383 100644 --- a/src/doc/rustc-dev-guide/src/building/prerequisites.md +++ b/src/doc/rustc-dev-guide/src/building/prerequisites.md @@ -19,7 +19,7 @@ If building LLVM from source (the default), you'll need additional tools: Otherwise, you'll need LLVM installed and `llvm-config` in your path. See [this section for more info][sysllvm]. -[sysllvm]: ./suggested.md#skipping-llvm-build +[sysllvm]: ./new-target.md#using-pre-built-llvm ### Windows @@ -43,17 +43,40 @@ see [the `rust-lang/rust` README](https://github.com/rust-lang/rust#building-on- ## Hardware -These are not so much requirements as _recommendations_: +You will need an internet connection to build. The bootstrapping process +involves updating git submodules and downloading a beta compiler. It doesn't +need to be super fast, but that can help. -* ~15GB of free disk space (~25GB or more if doing incremental builds). -* \>= 8GB RAM -* \>= 2 cores -* Internet access +There are no strict hardware requirements, but building the compiler is +computationally expensive, so a beefier machine will help, and I wouldn't +recommend trying to build on a Raspberry Pi! We recommend the following. +* 30GB+ of free disk space. Otherwise, you will have to keep + clearing incremental caches. More space is better, the compiler is a bit of a + hog; it's a problem we are aware of. +* 8GB+ RAM +* 2+ cores. Having more cores really helps. 10 or 20 or more is not too many! Beefier machines will lead to much faster builds. If your machine is not very powerful, a common strategy is to only use `./x.py check` on your local machine and let the CI build test your changes when you push to a PR branch. +Building the compiler takes more than half an hour on my moderately powerful +laptop. The first time you build the compiler, LLVM will also be built unless +you use CI-built LLVM ([see here][config]). + +Like `cargo`, the build system will use as many cores as possible. Sometimes +this can cause you to run low on memory. You can use `-j` to adjust the number +concurrent jobs. If a full build takes more than ~45 minutes to an hour, you +are probably spending most of the time swapping memory in and out; try using +`-j1`. + +If you don't have too much free disk space, you may want to turn off +incremental compilation ([see here][config]). This will make compilation take +longer (especially after a rebase), but will save a ton of space from the +incremental caches. + +[config]: ./how-to-build-and-run.md#create-a-configtoml + ## `rustc` and toolchain installation Follow the installation given in the [Rust book][install] to install a working diff --git a/src/doc/rustc-dev-guide/src/constants.md b/src/doc/rustc-dev-guide/src/constants.md index 137351c22f..30c0da736f 100644 --- a/src/doc/rustc-dev-guide/src/constants.md +++ b/src/doc/rustc-dev-guide/src/constants.md @@ -39,7 +39,7 @@ why the array length in `foo() -> [u8; N + 1]` can use `N`. Without any manual adjustments, this causes us to include parameters even if the constant doesn't use them in any way. This can cause -[some interesting errors](pcg-unused-substs) and breaks some already stable code. +[some interesting errors][pcg-unused-substs] and breaks some already stable code. To deal with this, we intend to look at the generic parameters explicitly mentioned by the constants and then search the predicates of its parents to figure out which diff --git a/src/doc/rustc-dev-guide/src/contributing.md b/src/doc/rustc-dev-guide/src/contributing.md index 6be8802c7c..8f6d1d6d8a 100644 --- a/src/doc/rustc-dev-guide/src/contributing.md +++ b/src/doc/rustc-dev-guide/src/contributing.md @@ -70,9 +70,11 @@ when contributing to Rust under [the git section](./git.md). [about-pull-requests]: https://help.github.com/articles/about-pull-requests/ [development-models]: https://help.github.com/articles/about-collaborative-development-models/ +### r? + All pull requests are reviewed by another person. We have a bot, [@rust-highfive][rust-highfive], that will automatically assign a random person -to review your request. +to review your request based on which files you changed. If you want to request that a specific person reviews your pull request, you can add an `r?` to the pull request description. For example, @@ -84,6 +86,17 @@ make a documentation change, add to the end of the pull request description, and [@rust-highfive][rust-highfive] will assign [@steveklabnik][steveklabnik] instead of a random person. This is entirely optional. +You can also assign a random reviewer from a specific team by writing `r? rust-lang/groupname`. +So if you were making a diagnostics change, then you could get a reviewer from the diagnostics +team by adding: + + r? rust-lang/diagnostics + +For a full list of possible `groupname` check the `groups` section at the +[rust highfive config file](https://github.com/rust-lang/highfive/blob/master/highfive/configs/rust-lang/rust.json). + +### CI + In addition to being reviewed by a human, pull requests are automatically tested thanks to continuous integration (CI). Basically, every time you open and update a pull request, CI builds the compiler and tests it against the @@ -100,6 +113,8 @@ computational resources each time you push a change. It is also perfectly fine productivity. In particular, we don't recommend running the full `./x.py test` suite locally, since it takes a very long time to execute. +### r+ + After someone has reviewed your pull request, they will leave an annotation on the pull request with an `r+`. It will look something like this: @@ -382,9 +397,9 @@ in the same way as other pull requests. [`src/doc`]: https://github.com/rust-lang/rust/tree/master/src/doc [`lib.rs`]: https://github.com/rust-lang/rust/blob/master/library/std/src/lib.rs#L1 -To find documentation-related issues, sort by the [T-doc label][tdoc]. +To find documentation-related issues, sort by the [A-docs label][adocs]. -[tdoc]: https://github.com/rust-lang/rust/issues?q=is%3Aopen%20is%3Aissue%20label%3AT-doc +[adocs]: https://github.com/rust-lang/rust/issues?q=is%3Aopen%20is%3Aissue%20label%3AA-docs You can find documentation style guidelines in [RFC 1574][rfc1574]. diff --git a/src/doc/rustc-dev-guide/src/getting-started.md b/src/doc/rustc-dev-guide/src/getting-started.md index f8273d631f..40e68cf0ee 100644 --- a/src/doc/rustc-dev-guide/src/getting-started.md +++ b/src/doc/rustc-dev-guide/src/getting-started.md @@ -44,59 +44,24 @@ just create noise, so we ask that you be mindful of the fact that the ## Cloning and Building -The main repository is [`rust-lang/rust`][repo]. This contains the compiler, -the standard library (including `core`, `alloc`, `test`, `proc_macro`, etc), -and a bunch of tools (e.g. `rustdoc`, the bootstrapping infrastructure, etc). - -[repo]: https://github.com/rust-lang/rust - -There are also a bunch of submodules for things like LLVM, `clippy`, `miri`, -etc. You don't need to clone these immediately, but the build tool will -automatically clone and sync them (more on this later). - -[**Take a look at the "Suggested Workflows" chapter for some helpful -advice.**][suggested] - -[suggested]: ./building/suggested.md - ### System Requirements -[**See this chapter for detailed software requirements.**](./building/prerequisites.md) -Most notably, you will need Python 2 or 3 to run `x.py`. +Internet access is required. -There are no hard hardware requirements, but building the compiler is -computationally expensive, so a beefier machine will help, and I wouldn't -recommend trying to build on a Raspberry Pi :P +The most notable software requirement is that you will need Python 2 or 3, but +there are various others. -- Recommended >=30GB of free disk space; otherwise, you will have to keep - clearing incremental caches. More space is better, the compiler is a bit of a - hog; it's a problem we are aware of. -- Recommended >=8GB RAM. -- Recommended >=2 cores; having more cores really helps. -- You will need an internet connection to build; the bootstrapping process - involves updating git submodules and downloading a beta compiler. It doesn't - need to be super fast, but that can help. +The following hardware is recommended. +* 30GB+ of free disk space. +* 8GB+ RAM +* 2+ cores -Building the compiler takes more than half an hour on my moderately powerful -laptop. The first time you build the compiler, LLVM will also be built unless -you use CI-built LLVM ([see below][configsec]). +More powerful machines will lead to much faster builds. There are various +strategies to work around lesser hardware in the following chapters. -[configsec]: #configuring-the-compiler +See [this chapter][prereqs] for more details about software and hardware prerequisites. -Like `cargo`, the build system will use as many cores as possible. Sometimes -this can cause you to run low on memory. You can use `-j` to adjust the number -concurrent jobs. If a full build takes more than ~45 minutes to an hour, -you are probably spending most of the time swapping memory in and out; -try using `-j1`. - -On a slow machine, the build times for rustc are very painful. Consider using -`./x.py check` instead of a full build and letting the automated tests run -when you push to GitHub. - -If you don't have too much free disk space, you may want to turn off -incremental compilation ([see below][configsec]). This will make -compilation take longer (especially after a rebase), -but will save a ton of space from the incremental caches. +[prereqs]: ./building/prerequisites.md ### Cloning @@ -104,89 +69,32 @@ You can just do a normal git clone: ```sh git clone https://github.com/rust-lang/rust.git +cd rust ``` -You don't need to clone the submodules at this time. But if you want to, you -can do the following: +### `x.py` Intro -```sh -# first time -git submodule update --init --recursive +`rustc` is a [bootstrapping] compiler, which makes it more complex than a +typical Rust program. As a result, you cannot use Cargo to build it. Instead +you must use the special tool `x.py`. It is used for the things Cargo is +normally used for: building, testing, creating releases, formatting, etc. -# subsequent times (to pull new commits) -git submodule update -``` +[bootstrapping]: ./building/bootstrapping.md ### Configuring the Compiler -The compiler has a configuration file which contains a ton of settings. We will -provide some recommendations here that should work for most, but [check out -this chapter for more info][config]. - -[config]: ./building/how-to-build-and-run.md#create-a-configtoml - In the top level of the repo: ```sh $ ./x.py setup ``` -This will walk you through an interactive setup for `x.py` that looks like this: +This will do some initialization and walk you through an interactive setup to +create `config.toml`, the primary configuration file. -``` -$ ./x.py setup -Welcome to the Rust project! What do you want to do with x.py? -a) Contribute to the standard library -b) Contribute to the compiler -c) Contribute to the compiler, and also modify LLVM or codegen -d) Install Rust from source -Please choose one (a/b/c/d): a -`x.py` will now use the configuration at /home/joshua/rustc2/src/bootstrap/defaults/config.toml.library -To get started, try one of the following commands: -- `x.py check` -- `x.py build` -- `x.py test library/std` -- `x.py doc` -For more suggestions, see https://rustc-dev-guide.rust-lang.org/building/suggested.html -``` +See [this chapter][config] for more info about configuration. -Note that by default, `./x.py setup` will use CI-built LLVM if available for your -platform so that you don't need to build LLVM in addition to building the -compiler. In some circumstances, such as when updating the version of LLVM used -by `rustc`, you may want to temporarily disable this feature. See the ["Updating -LLVM" section] for more. - -If you want to download LLVM from CI without running `./x.py setup`, you can set -the `download-ci-llvm` option to `true` in your `config.toml`: - -```toml -[llvm] -download-ci-llvm = true -``` - -["Updating LLVM" section]: https://rustc-dev-guide.rust-lang.org/backend/updating-llvm.html?highlight=download-ci-llvm#feature-updates - -### `x.py` Intro - -`rustc` is a _bootstrapping_ compiler, which means that it is written in Rust -and thus needs to be compiled by itself. So where do you -get the original compiler from? We use the current beta compiler -to build a new compiler. Then, we use that compiler to build itself. Thus, -`rustc` has a 2-stage build. You can read more about bootstrapping -[here][boot], but you don't need to know much more to contribute. - -[boot]: ./building/bootstrapping.md - -We have a special tool `x.py` that drives this process. It is used for -building the compiler, the standard libraries, and `rustdoc`. It is also used -for driving CI and building the final release artifacts. - -Unfortunately, a proper 2-stage build takes a long time depending on your -hardware, but it is the only correct way to build everything (e.g. it's what -the CI and release processes use). **However, in most cases, you can get by -without a full 2-stage build**. In the following section, we give instructions -for how to do "the correct thing", but then we also give various tips to speed -things up. +[config]: ./building/how-to-build-and-run.md#create-a-configtoml ### Building and Testing `rustc` @@ -387,7 +295,6 @@ incredibly helpful: [wd]: ./contributing.md#writing-documentation [wg]: https://rust-lang.github.io/compiler-team/working-groups/ - ## Contributor Procedures There are some official procedures to know about. This is a tour of the @@ -396,11 +303,12 @@ highlights, but there are a lot more details, which we will link to below. ### Code Review When you open a PR on the `rust-lang/rust` repo, a bot called `@rust-highfive` will -automatically assign a reviewer to the PR. The reviewer is the person that will -approve the PR to be tested and merged. If you want a specific reviewer (e.g. a -team member you've been working with), you can specifically request them by -writing `r? @user` (e.g. `r? @eddyb`) in either the original post or a followup -comment (you can see [this comment][r?] for example). +automatically assign a reviewer to the PR based on which files you changed. +The reviewer is the person that will approve the PR to be tested and merged. +If you want a specific reviewer (e.g. a team member you've been working with), +you can specifically request them by writing `r? @user` (e.g. `r? @jyn514`) in +either the original post or a followup comment +(you can see [this comment][r?] for example). Please note that the reviewers are humans, who for the most part work on `rustc` in their free time. This means that they can take some time to respond and review diff --git a/src/doc/rustc-dev-guide/src/hir.md b/src/doc/rustc-dev-guide/src/hir.md index 51e18973b8..8316f7ce34 100644 --- a/src/doc/rustc-dev-guide/src/hir.md +++ b/src/doc/rustc-dev-guide/src/hir.md @@ -96,21 +96,16 @@ with a HIR node. [HIR map]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html [number of methods]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#methods -For example, if you have a [`DefId`], and you would like to convert it -to a [`NodeId`], you can use -[`tcx.hir().as_local_node_id(def_id)`][as_local_node_id]. This returns -an `Option` – this will be `None` if the def-id refers to -something outside of the current crate (since then it has no HIR -node), but otherwise returns `Some(n)` where `n` is the node-id of the -definition. +For example, if you have a [`LocalDefId`], and you would like to convert it +to a [`HirId`], you can use [`tcx.hir().local_def_id_to_hir_id(def_id)`][local_def_id_to_hir_id]. +You need a `LocalDefId`, rather than a `DefId`, since only local items have HIR nodes. -[`NodeId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/node_id/struct.NodeId.html -[as_local_node_id]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.as_local_node_id +[local_def_id_to_hir_id]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/hir/map/struct.Map.html#method.local_def_id_to_hir_id Similarly, you can use [`tcx.hir().find(n)`][find] to lookup the node for a -[`NodeId`]. This returns a `Option>`, where [`Node`] is an enum -defined in the map; by matching on this you can find out what sort of -node the node-id referred to and also get a pointer to the data +[`HirId`]. This returns a `Option>`, where [`Node`] is an enum +defined in the map. By matching on this, you can find out what sort of +node the `HirId` referred to and also get a pointer to the data itself. Often, you know what sort of node `n` is – e.g. if you know that `n` must be some HIR expression, you can do [`tcx.hir().expect_expr(n)`][expect_expr], which will extract and return the diff --git a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md index 4a0f53bfa1..cb3be57ac0 100644 --- a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md +++ b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md @@ -221,17 +221,15 @@ substitution combinations), `mapgen`'s `finalize()` method queries the and `CodeRegion`s; and calls LLVM codegen APIs to generate properly-configured variables in LLVM IR, according to very specific details of the [_LLVM Coverage Mapping Format_][coverage-mapping-format] -(Version 4).[^llvm-and-covmap-versions] +(Version 6).[^llvm-and-covmap-versions] -[^llvm-and-covmap-versions]: The Rust compiler (as of -January 2021) supports _LLVM Coverage Mapping Format_ Version 4 (the most -up-to-date version of the format, at the time of this writing) for improved -compatibility with other LLVM-based compilers (like _Clang_), and to take -advantage of some format optimizations. Version 4 was introduced in _LLVM 11_, -which is currently the default LLVM version for Rust. Note that the Rust -compiler optionally supports some earlier LLVM versions, prior to _LLVM 11_. If -`rustc` is configured to use an incompatible version of LLVM, compiling with `-Z -instrument-coverage` will generate an error message. +[^llvm-and-covmap-versions]: The Rust compiler (as of +December 2021) supports _LLVM Coverage Mapping Format_ Version 5 or 6. Version 5 +was introduced in _LLVM 12_, which is (as of this writing) the minimum LLVM +version supported by the current version of Rust. Version 6 was introduced in +_LLVM 13_, which is currently the default LLVM version for Rust. The Rust +compiler will automatically use the most up-to-date coverage mapping format +version that is compatible with the compiler's built-in version of LLVM. ```rust pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) { diff --git a/src/doc/rustc-dev-guide/src/mir/optimizations.md b/src/doc/rustc-dev-guide/src/mir/optimizations.md index 9ecf4e0d30..add22c6fcf 100644 --- a/src/doc/rustc-dev-guide/src/mir/optimizations.md +++ b/src/doc/rustc-dev-guide/src/mir/optimizations.md @@ -85,7 +85,7 @@ The array is an array of `&dyn MirPass` trait objects. Typically, a pass is implemented in its own module of the [`rustc_mir_transform`][trans] crate. [rop]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/fn.run_optimization_passes.html -[`MirPass`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/trait.MirPass.html +[`MirPass`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/trait.MirPass.html [trans]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/index.html Some examples of passes are: @@ -95,7 +95,7 @@ Some examples of passes are: You can see the ["Implementors" section of the `MirPass` rustdocs][impl] for more examples. -[impl]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_transform/trait.MirPass.html#implementors +[impl]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/trait.MirPass.html#implementors [constprop]: https://en.wikipedia.org/wiki/Constant_folding#Constant_propagation ## MIR optimization levels diff --git a/src/doc/rustc-dev-guide/src/profiling.md b/src/doc/rustc-dev-guide/src/profiling.md index fd7014224d..ae76d977fd 100644 --- a/src/doc/rustc-dev-guide/src/profiling.md +++ b/src/doc/rustc-dev-guide/src/profiling.md @@ -12,10 +12,10 @@ Depending on what you're trying to measure, there are several different approach - If you want a medium-to-high level overview of where `rustc` is spending its time: - The `-Z self-profile` flag and [measureme](https://github.com/rust-lang/measureme) tools offer a query-based approach to profiling. - See [their docs](https://github.com/rust-lang/measureme/blob/master/summarize/Readme.md) for more information. + See [their docs](https://github.com/rust-lang/measureme/blob/master/summarize/README.md) for more information. - If you want function level performance data or even just more details than the above approaches: - - Consider using a native code profiler such as [perf](profiling/with_perf.html) + - Consider using a native code profiler such as [perf](profiling/with_perf.md) - or [tracy](https://github.com/nagisa/rust_tracy_client) for a nanosecond-precision, full-featured graphical interface. @@ -26,7 +26,7 @@ Depending on what you're trying to measure, there are several different approach - If you want to profile memory usage, you can use various tools depending on what operating system you are using. - - For Windows, read our [WPA guide](profiling/wpa_profiling.html). + - For Windows, read our [WPA guide](profiling/wpa_profiling.md). ## Optimizing rustc's bootstrap times with `cargo-llvm-lines` diff --git a/src/doc/rustc-dev-guide/src/rustdoc-internals.md b/src/doc/rustc-dev-guide/src/rustdoc-internals.md index 0d7459b1d3..ccf0fcc5fe 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc-internals.md +++ b/src/doc/rustc-dev-guide/src/rustdoc-internals.md @@ -73,8 +73,8 @@ Here is the list of passes as of October 2021: - `check-bare-urls` detects links that are not linkified, e.g., in Markdown such as `Go to https://example.com/.` It suggests wrapping the link with angle brackets: - `Go to .` to linkify it. This is the code behind the - `rustdoc::bare_urls` lint. + `Go to .` to linkify it. This is the code behind the `rustdoc::bare_urls` lint. - `check-code-block-syntax` validates syntax inside Rust code blocks (```rust) diff --git a/src/doc/rustc-dev-guide/src/rustdoc.md b/src/doc/rustc-dev-guide/src/rustdoc.md index 2123d2b748..66cb496dcb 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc.md +++ b/src/doc/rustc-dev-guide/src/rustdoc.md @@ -36,30 +36,141 @@ does is call the `main()` that's in this crate's `lib.rs`, though.) ## Cheat sheet +* Run `./x.py setup tools` before getting started. This will configure `x.py` + with nice settings for developing rustdoc and other tools, including + downloading a copy of rustc rather than building it. * Use `./x.py build` to make a usable rustdoc you can run on other projects. * Add `library/test` to be able to use `rustdoc --test`. - * If you've used `rustup toolchain link local /path/to/build/$TARGET/stage1` - previously, then after the previous build command, `cargo +local doc` will - Just Work. + * Run `rustup toolchain link stage2 build/$TARGET/stage2` to add a + custom toolchain called `stage2` to your rustup environment. After + running that, `cargo +stage2 doc` in any directory will build with + your locally-compiled rustdoc. * Use `./x.py doc library/std` to use this rustdoc to generate the standard library docs. - * The completed docs will be available in `build/$TARGET/doc/std`, though the - bundle is meant to be used as though you would copy out the `doc` folder to - a web server, since that's where the CSS/JS and landing page are. + * The completed docs will be available in `build/$TARGET/doc/std`. + * If you want to copy those docs to a webserver, copy all of + `build/$TARGET/doc`, since that's where the CSS, JS, fonts, and landing + page are. * Use `./x.py test src/test/rustdoc*` to run the tests using a stage1 rustdoc. * See [Rustdoc internals] for more information about tests. -* Most of the HTML printing code is in `html/format.rs` and `html/render.rs`. + +## Code structure + +* All paths in this section are relative to `src/librustdoc` in the rust-lang/rust repository. +* Most of the HTML printing code is in `html/format.rs` and `html/render/mod.rs`. It's in a bunch of `fmt::Display` implementations and supplementary functions. * The types that got `Display` impls above are defined in `clean/mod.rs`, right next to the custom `Clean` trait used to process them out of the rustc HIR. -* The bits specific to using rustdoc as a test harness are in `test.rs`. +* The bits specific to using rustdoc as a test harness are in + `doctest.rs`. * The Markdown renderer is loaded up in `html/markdown.rs`, including functions for extracting doctests from a given block of Markdown. -* The tests on rustdoc *output* are located in `src/test/rustdoc`, where +* The tests on the structure of rustdoc HTML output are located in `src/test/rustdoc`, where they're handled by the test runner of rustbuild and the supplementary script `src/etc/htmldocck.py`. -* Tests on search index generation are located in `src/test/rustdoc-js`, as a + +## Tests + +* All paths in this section are relative to `src/test` in the rust-lang/rust repository. +* Tests on search index generation are located in `rustdoc-js`, as a series of JavaScript files that encode queries on the standard library search index and expected results. +* Tests on the "UI" of rustdoc (the terminal output it produces when run) are in + `rustdoc-ui` +* Tests on the "GUI" of rustdoc (the HTML, JS, and CSS as rendered in a browser) + are in `rustdoc-gui`. These use a [NodeJS tool called + browser-UI-test](https://github.com/GuillaumeGomez/browser-UI-test/) that uses + puppeteer to run tests in a headless browser and check rendering and + interactivity. + +## Constraints + +We try to make rustdoc work reasonably well with JavaScript disabled, and when +browsing local files. We support +[these browsers](https://rust-lang.github.io/rfcs/1985-tiered-browser-support.html#supported-browsers). + +Supporting local files (`file:///` URLs) brings some surprising restrictions. +Certain browser features that require secure origins, like `localStorage` and +Service Workers, don't work reliably. We can still use such features but we +should make sure pages are still usable without them. + +## Multiple runs, same output directory + +Rustdoc can be run multiple times for varying inputs, with its output set to the +same directory. That's how cargo produces documentation for dependencies of the +current crate. It can also be done manually if a user wants a big +documentation bundle with all of the docs they care about. + +HTML is generated independently for each crate, but there is some cross-crate +information that we update as we add crates to the output directory: + + - `crates.js` holds a list of all crates in the output directory. + - `search-index.js` holds a list of all searchable items. + - For each trait, there is a file under `implementors/.../trait.TraitName.js` + containing a list of implementors of that trait. The implementors may be in + different crates than the trait, and the JS file is updated as we discover + new ones. + +## Use cases + +There are a few major use cases for rustdoc that you should keep in mind when +working on it: + +### Standard library docs + +These are published at as part of the Rust release +process. Stable releases are also uploaded to specific versioned URLs like +. Beta and nightly docs are published to + and . +The docs are uploaded with the [promote-release +tool](https://github.com/rust-lang/promote-release) and served from S3 with +CloudFront. + +The standard library docs contain five crates: alloc, core, proc_macro, std, and +test. + +### docs.rs + +When crates are published to crates.io, docs.rs automatically builds +and publishes their documentation, for instance at +. It always builds with the current nightly +rustdoc, so any changes you land in rustdoc are "insta-stable" in that they will +have an immediate public effect on docs.rs. Old documentation is not rebuilt, so +you will see some variation in UI when browsing old releases in docs.rs. Crate +authors can request rebuilds, which will be run with the latest rustdoc. + +Docs.rs performs some transformations on rustdoc's output in order to save +storage and display a navigation bar at the top. In particular, certain static +files (like main.js and rustdoc.css may be shared across multiple invocations +of the same version of rustdoc. Others, like crates.js and sidebar-items.js, are +different for different invocations. Still others, like fonts, will never +change. These categories are distinguished using the `SharedResource` enum in +`src/librustdoc/html/render/write_shared.rs` + +Documentation on docs.rs is always generated for a single crate at a time, so +the search and sidebar functionality don't include dependencies of the current +crate. + +### Locally generated docs + +Crate authors can run `cargo doc --open` in crates they have checked +out locally to see the docs. This is useful to check that the docs they +are writing are useful and display correctly. It can also be useful for +people to view documentation on crates they aren't authors of, but want to +use. In both cases, people may use `--document-private-items` Cargo flag to +see private methods, fields, and so on, which are normally not displayed. + +By default `cargo doc` will generate documentation for a crate and all of its +dependencies. That can result in a very large documentation bundle, with a large +(and slow) search corpus. The Cargo flag `--no-deps` inhibits that behavior and +generates docs for just the crate. + +### Self-hosted project docs + +Some projects like to host their own documentation. For example: +. This is easy to do by locally generating docs, and +simply copying them to a web server. Rustdoc's HTML output can be extensively +customized by flags. Users can add a theme, set the default theme, and inject +arbitrary HTML. See `rustdoc --help` for details. diff --git a/src/doc/rustc-dev-guide/src/tests/adding.md b/src/doc/rustc-dev-guide/src/tests/adding.md index 34bd6f20ee..d7ad2871df 100644 --- a/src/doc/rustc-dev-guide/src/tests/adding.md +++ b/src/doc/rustc-dev-guide/src/tests/adding.md @@ -169,6 +169,11 @@ source. source is compiled, and this compilation is required to succeed. The `.fixed` file can also be generated automatically with the `--bless` option, described in [this section][bless]. +* `rustfix-only-machine-applicable` is equivalent to `run-rustfix` except it + will only apply [`MachineApplicable`](../diagnostics.md#suggestions) + suggestions. `run-rustfix` will apply *all* suggestions. This should be used + if there is a mixture of different suggestion levels, and some of the + non-machine-applicable ones do not apply cleanly. * `min-gdb-version` specifies the minimum gdb version required for this test; see also `ignore-gdb-version` * `min-lldb-version` specifies the minimum lldb version required for @@ -214,9 +219,62 @@ source. * `error-pattern` checks the diagnostics just like the `ERROR` annotation without specifying error line. This is useful when the error doesn't give any span. +* `incremental` runs the test with the `-C incremental` flag and an empty + incremental directory. This should be avoided when possible; you should use + an *incremental mode* test instead. Incremental mode tests support running + the compiler multiple times and verifying that it can load the generated + incremental cache. This flag is for specialized circumstances, like checking + the interaction of codegen unit partitioning with generating an incremental + cache. +* `aux-build` is used to compile additional crates to link. Just pass it the + name of the source file. The source file should be in a directory called + `auxiliary` beside the test file. The aux crate will be built as a dylib if + possible (unless on a platform that does not support them, or + `no-prefer-dynamic` is specified in the aux file). The `-L` flag is used to + find the extern crates. +* `aux-crate` is very similar to `aux-build`; however, it uses the `--extern` + flag to link to the extern crate. That allows you to specify the additional + syntax of the `--extern` flag, such as renaming a dependency. For example, + `// aux-crate:foo=bar.rs` will compile `auxiliary/bar.rs` and make it + available under then name `foo` within the test. This is similar to how + Cargo does dependency renaming. +* `no-prefer-dynamic` will force an auxiliary crate to be built as an rlib + instead of a dylib. When specified in a test, it will remove the use of `-C + prefer-dynamic`. This can be useful in a variety of circumstances. For + example, it can prevent a proc-macro from being built with the wrong crate + type. Or if your test is specifically targeting behavior of other crate + types, it can be used to prevent building with the wrong crate type. +* `force-host` will force the test to build for the host platform instead of + the target. This is useful primarily for auxiliary proc-macros, which need + to be loaded by the host compiler. +* `pretty-mode` specifies the mode pretty-print tests should run in. + The default is `normal` if not specified. +* `pretty-compare-only` causes a pretty test to only compare the + pretty-printed output. It will not try to compile the expanded output to + typecheck it. This is needed for a pretty-mode that does not expand to valid + Rust, or for other situations where the expanded output cannot be compiled. +* `pretty-expanded` allows a pretty test to also run with + `-Zunpretty=expanded` as a final step. It will also try to compile the + resulting output (without codegen). This is needed because not all code can + be compiled after being expanded. Pretty tests should specify this if they + can. An example where this cannot be used is if the test includes + `println!`. That macro expands to reference private internal functions of + the standard library that cannot be called directly without the + `fmt_internals` feature gate. + + More history about this may be found in [#23616]. +* `pp-exact` is used to ensure a pretty-print test results in specific output. + If specified without a value, then it means the pretty-print output should + match the original source. If specified with a value, as in `// + pp-exact:foo.pp`, it will ensure that the pretty-printed output matches the + contents of the given file. Otherwise, if `pp-exact` is not specified, then + the pretty-printed output will be pretty-printed one more time, and the + output of the two pretty-printing rounds will be compared to ensure that the + pretty-printed output converges to a steady state. [`header.rs`]: https://github.com/rust-lang/rust/tree/master/src/tools/compiletest/src/header.rs [bless]: ./running.md#editing-and-updating-the-reference-files +[#23616]: https://github.com/rust-lang/rust/issues/23616#issuecomment-484999901 diff --git a/src/doc/rustc-dev-guide/src/tests/intro.md b/src/doc/rustc-dev-guide/src/tests/intro.md index 25c1d059c1..d92f042e4e 100644 --- a/src/doc/rustc-dev-guide/src/tests/intro.md +++ b/src/doc/rustc-dev-guide/src/tests/intro.md @@ -50,9 +50,6 @@ details. ultimate in flexibility but quite annoying to write. - `rustdoc` – tests for rustdoc, making sure that the generated files contain the expected documentation. -- `rustfix` – tests for applying [diagnostic - suggestions](../diagnostics.md#suggestions) with the - [`rustfix`](https://github.com/rust-lang/rustfix/) crate - `*-fulldeps` – same as above, but indicates that the test depends on things other than `std` (and hence those things must be built) diff --git a/src/doc/rustc-dev-guide/src/tests/running.md b/src/doc/rustc-dev-guide/src/tests/running.md index 2e1ce0a910..c91a27bf2d 100644 --- a/src/doc/rustc-dev-guide/src/tests/running.md +++ b/src/doc/rustc-dev-guide/src/tests/running.md @@ -200,8 +200,10 @@ however compare-modes must be manually run individually via the `--compare-mode` ## Running tests manually -Sometimes it's easier and faster to just run the test by hand. Most tests are -just `rs` files, so you can do something like +Sometimes it's easier and faster to just run the test by hand. +Most tests are just `rs` files, so after +[creating a rustup toolchain](/building/how-to-build-and-run.html#creating-a-rustup-toolchain), +you can do something like: ```bash rustc +stage1 src/test/ui/issue-1234.rs diff --git a/src/doc/rustc-dev-guide/src/walkthrough.md b/src/doc/rustc-dev-guide/src/walkthrough.md index 5841afe4f5..8f5dc525ec 100644 --- a/src/doc/rustc-dev-guide/src/walkthrough.md +++ b/src/doc/rustc-dev-guide/src/walkthrough.md @@ -184,7 +184,7 @@ When you open a PR on the [rust-lang/rust], a bot will assign your PR to a review. If there is a particular rust team member you are working with, you can request that reviewer by leaving a comment on the thread with `r? @reviewer-github-id` (e.g. `r? @eddyb`). If you don't know who to request, -don't request anyone; the bot will assign someone automatically. +don't request anyone; the bot will assign someone automatically based on which files you changed. The reviewer may request changes before they approve your PR. Feel free to ask questions or discuss things you don't understand or disagree with. However, diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 0201b88417..ec03d4b82b 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -160,6 +160,9 @@ to save information after compiling a crate to be reused when recompiling the crate, improving re-compile times. This takes a path to a directory where incremental files will be stored. +Note that this option currently does not take effect unless +`RUSTC_FORCE_INCREMENTAL=1` in the environment. + ## inline-threshold This option lets you set the default threshold for inlining a function. It diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 4da3491c58..f4f659ffa2 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -267,6 +267,7 @@ target | std | host | notes `riscv32gc-unknown-linux-gnu` | | | RISC-V Linux (kernel 5.4, glibc 2.33) `riscv32gc-unknown-linux-musl` | | | RISC-V Linux (kernel 5.4, musl + RISCV32 support patches) `riscv32imc-esp-espidf` | ✓ | | RISC-V ESP-IDF +`riscv64gc-unknown-freebsd` | | | RISC-V FreeBSD `riscv64gc-unknown-linux-musl` | | | RISC-V Linux (kernel 4.20, musl 1.2.0) `s390x-unknown-linux-musl` | | | S390x Linux (kernel 2.6.32, MUSL) `sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index d694862266..9de2e733de 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -57,13 +57,13 @@ release: 1.17.0 LLVM version: 3.9 ``` -## `-o`/`--output`: output path +## `-o`/`--out-dir`: output directory path Using this flag looks like this: ```bash $ rustdoc src/lib.rs -o target/doc -$ rustdoc src/lib.rs --output target/doc +$ rustdoc src/lib.rs --out-dir target/doc ``` By default, `rustdoc`'s output appears in a directory named `doc` in diff --git a/src/doc/rustdoc/src/documentation-tests.md b/src/doc/rustdoc/src/documentation-tests.md index 6be53fb4cf..aea55d4f4b 100644 --- a/src/doc/rustdoc/src/documentation-tests.md +++ b/src/doc/rustdoc/src/documentation-tests.md @@ -359,9 +359,8 @@ are added. # fn foo() {} ``` -`edition2018` tells `rustdoc` that the code sample should be compiled using -the 2018 edition of Rust. Similarly, you can specify `edition2015` to compile -the code with the 2015 edition. +`edition2015`, `edition2018` and `edition2021` tell `rustdoc` +that the code sample should be compiled using the respective edition of Rust. ```rust /// Only runs on the 2018 edition. diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 0210402154..56ca7c0392 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -396,7 +396,7 @@ Note that the third item is the crate root, which in this case is undocumented. ### `-w`/`--output-format`: output format `--output-format json` emits documentation in the experimental -[JSON format](https://github.com/rust-lang/rfcs/pull/2963). `--output-format html` has no effect, +[JSON format](https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc_json_types/). `--output-format html` has no effect, and is also accepted on stable toolchains. It can also be used with `--show-coverage`. Take a look at its diff --git a/src/doc/unstable-book/src/compiler-flags/instrument-coverage.md b/src/doc/unstable-book/src/compiler-flags/instrument-coverage.md index f7c2a26f01..39eb407269 100644 --- a/src/doc/unstable-book/src/compiler-flags/instrument-coverage.md +++ b/src/doc/unstable-book/src/compiler-flags/instrument-coverage.md @@ -20,14 +20,14 @@ This document describes how to enable and use the LLVM instrumentation-based cov When `-Z instrument-coverage` is enabled, the Rust compiler enhances rust-based libraries and binaries by: - Automatically injecting calls to an LLVM intrinsic ([`llvm.instrprof.increment`]), at functions and branches in compiled code, to increment counters when conditional sections of code are executed. -- Embedding additional information in the data section of each library and binary (using the [LLVM Code Coverage Mapping Format] _Version 4_, supported _only_ in LLVM 11 and up), to define the code regions (start and end positions in the source code) being counted. +- Embedding additional information in the data section of each library and binary (using the [LLVM Code Coverage Mapping Format] _Version 5_, if compiling with LLVM 12, or _Version 6_, if compiling with LLVM 13 or higher), to define the code regions (start and end positions in the source code) being counted. When running a coverage-instrumented program, the counter values are written to a `profraw` file at program termination. LLVM bundles tools that read the counter results, combine those results with the coverage map (embedded in the program binary), and generate coverage reports in multiple formats. [`llvm.instrprof.increment`]: https://llvm.org/docs/LangRef.html#llvm-instrprof-increment-intrinsic [llvm code coverage mapping format]: https://llvm.org/docs/CoverageMappingFormat.html -> **Note**: `-Z instrument-coverage` also automatically enables `-Z symbol-mangling-version=v0` (tracking issue [#60705]). The `v0` symbol mangler is strongly recommended, but be aware that this demangler is also experimental. The `v0` demangler can be overridden by explicitly adding `-Z symbol-mangling-version=legacy`. +> **Note**: `-Z instrument-coverage` also automatically enables `-C symbol-mangling-version=v0` (tracking issue [#60705]). The `v0` symbol mangler is strongly recommended, but be aware that this demangler is also experimental. The `v0` demangler can be overridden by explicitly adding `-Z unstable-options -C symbol-mangling-version=legacy`. [#60705]: https://github.com/rust-lang/rust/issues/60705 @@ -123,7 +123,7 @@ If `LLVM_PROFILE_FILE` contains a path to a non-existent directory, the missing ## Installing LLVM coverage tools -LLVM's supplies two tools—`llvm-profdata` and `llvm-cov`—that process coverage data and generate reports. There are several ways to find and/or install these tools, but note that the coverage mapping data generated by the Rust compiler requires LLVM version 11 or higher. (`llvm-cov --version` typically shows the tool's LLVM version number.): +LLVM's supplies two tools—`llvm-profdata` and `llvm-cov`—that process coverage data and generate reports. There are several ways to find and/or install these tools, but note that the coverage mapping data generated by the Rust compiler requires LLVM version 12 or higher. (`llvm-cov --version` typically shows the tool's LLVM version number.): - The LLVM tools may be installed (or installable) directly to your OS (such as via `apt-get`, for Linux). - If you are building the Rust compiler from source, you can optionally use the bundled LLVM tools, built from source. Those tool binaries can typically be found in your build platform directory at something like: `rust/build/x86_64-unknown-linux-gnu/llvm/bin/llvm-*`. diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md index b3dbc9a995..d630f4ecb7 100644 --- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -199,8 +199,9 @@ LLVM CFI can be enabled with -Zsanitizer=cfi and requires LTO (i.e., -Clto). ## Example ```text -#![feature(asm, naked_functions)] +#![feature(naked_functions)] +use std::arch::asm; use std::mem; fn add_one(x: i32) -> i32 { diff --git a/src/doc/unstable-book/src/language-features/asm-const.md b/src/doc/unstable-book/src/language-features/asm-const.md new file mode 100644 index 0000000000..1063c23b6d --- /dev/null +++ b/src/doc/unstable-book/src/language-features/asm-const.md @@ -0,0 +1,11 @@ +# `asm_const` + +The tracking issue for this feature is: [#72016] + +[#72016]: https://github.com/rust-lang/rust/issues/72016 + +------------------------ + +This feature adds a `const ` operand type to `asm!` and `global_asm!`. +- `` must be an integer constant expression. +- The value of the expression is formatted as a string and substituted directly into the asm template string. diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md new file mode 100644 index 0000000000..ec97eaa8b2 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md @@ -0,0 +1,117 @@ +# `asm_experimental_arch` + +The tracking issue for this feature is: [#72016] + +[#72016]: https://github.com/rust-lang/rust/issues/72016 + +------------------------ + +This feature tracks `asm!` and `global_asm!` support for the following architectures: +- NVPTX +- PowerPC +- Hexagon +- MIPS32r2 and MIPS64r2 +- wasm32 +- BPF +- SPIR-V +- AVR + +## Register classes + +| Architecture | Register class | Registers | LLVM constraint code | +| ------------ | -------------- | ---------------------------------- | -------------------- | +| MIPS | `reg` | `$[2-25]` | `r` | +| MIPS | `freg` | `$f[0-31]` | `f` | +| NVPTX | `reg16` | None\* | `h` | +| NVPTX | `reg32` | None\* | `r` | +| NVPTX | `reg64` | None\* | `l` | +| Hexagon | `reg` | `r[0-28]` | `r` | +| PowerPC | `reg` | `r[0-31]` | `r` | +| PowerPC | `reg_nonzero` | `r[1-31]` | `b` | +| PowerPC | `freg` | `f[0-31]` | `f` | +| PowerPC | `cr` | `cr[0-7]`, `cr` | Only clobbers | +| PowerPC | `xer` | `xer` | Only clobbers | +| wasm32 | `local` | None\* | `r` | +| BPF | `reg` | `r[0-10]` | `r` | +| BPF | `wreg` | `w[0-10]` | `w` | +| AVR | `reg` | `r[2-25]`, `XH`, `XL`, `ZH`, `ZL` | `r` | +| AVR | `reg_upper` | `r[16-25]`, `XH`, `XL`, `ZH`, `ZL` | `d` | +| AVR | `reg_pair` | `r3r2` .. `r25r24`, `X`, `Z` | `r` | +| AVR | `reg_iw` | `r25r24`, `X`, `Z` | `w` | +| AVR | `reg_ptr` | `X`, `Z` | `e` | + +> **Notes**: +> - NVPTX doesn't have a fixed register set, so named registers are not supported. +> +> - WebAssembly doesn't have registers, so named registers are not supported. + +# Register class supported types + +| Architecture | Register class | Target feature | Allowed types | +| ------------ | ------------------------------- | -------------- | --------------------------------------- | +| MIPS32 | `reg` | None | `i8`, `i16`, `i32`, `f32` | +| MIPS32 | `freg` | None | `f32`, `f64` | +| MIPS64 | `reg` | None | `i8`, `i16`, `i32`, `i64`, `f32`, `f64` | +| MIPS64 | `freg` | None | `f32`, `f64` | +| NVPTX | `reg16` | None | `i8`, `i16` | +| NVPTX | `reg32` | None | `i8`, `i16`, `i32`, `f32` | +| NVPTX | `reg64` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | +| Hexagon | `reg` | None | `i8`, `i16`, `i32`, `f32` | +| PowerPC | `reg` | None | `i8`, `i16`, `i32` | +| PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32` | +| PowerPC | `freg` | None | `f32`, `f64` | +| PowerPC | `cr` | N/A | Only clobbers | +| PowerPC | `xer` | N/A | Only clobbers | +| wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` | +| BPF | `reg` | None | `i8` `i16` `i32` `i64` | +| BPF | `wreg` | `alu32` | `i8` `i16` `i32` | +| AVR | `reg`, `reg_upper` | None | `i8` | +| AVR | `reg_pair`, `reg_iw`, `reg_ptr` | None | `i16` | + +## Register aliases + +| Architecture | Base register | Aliases | +| ------------ | ------------- | --------- | +| Hexagon | `r29` | `sp` | +| Hexagon | `r30` | `fr` | +| Hexagon | `r31` | `lr` | +| BPF | `r[0-10]` | `w[0-10]` | +| AVR | `XH` | `r27` | +| AVR | `XL` | `r26` | +| AVR | `ZH` | `r31` | +| AVR | `ZL` | `r30` | + +## Unsupported registers + +| Architecture | Unsupported register | Reason | +| ------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| All | `sp` | The stack pointer must be restored to its original value at the end of an asm code block. | +| All | `fr` (Hexagon), `$fp` (MIPS), `Y` (AVR) | The frame pointer cannot be used as an input or output. | +| All | `r19` (Hexagon) | This is used internally by LLVM as a "base pointer" for functions with complex stack frames. | +| MIPS | `$0` or `$zero` | This is a constant zero register which can't be modified. | +| MIPS | `$1` or `$at` | Reserved for assembler. | +| MIPS | `$26`/`$k0`, `$27`/`$k1` | OS-reserved registers. | +| MIPS | `$28`/`$gp` | Global pointer cannot be used as inputs or outputs. | +| MIPS | `$ra` | Return address cannot be used as inputs or outputs. | +| Hexagon | `lr` | This is the link register which cannot be used as an input or output. | +| AVR | `r0`, `r1`, `r1r0` | Due to an issue in LLVM, the `r0` and `r1` registers cannot be used as inputs or outputs. If modified, they must be restored to their original values before the end of the block. | + +## Template modifiers + +| Architecture | Register class | Modifier | Example output | LLVM modifier | +| ------------ | -------------- | -------- | -------------- | ------------- | +| MIPS | `reg` | None | `$2` | None | +| MIPS | `freg` | None | `$f0` | None | +| NVPTX | `reg16` | None | `rs0` | None | +| NVPTX | `reg32` | None | `r0` | None | +| NVPTX | `reg64` | None | `rd0` | None | +| Hexagon | `reg` | None | `r0` | None | +| PowerPC | `reg` | None | `0` | None | +| PowerPC | `reg_nonzero` | None | `3` | `b` | +| PowerPC | `freg` | None | `0` | None | + +# Flags covered by `preserves_flags` + +These flags registers must be restored upon exiting the asm block if the `preserves_flags` option is set: +- AVR + - The status register `SREG`. diff --git a/src/doc/unstable-book/src/language-features/asm-sym.md b/src/doc/unstable-book/src/language-features/asm-sym.md new file mode 100644 index 0000000000..7544e20807 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/asm-sym.md @@ -0,0 +1,13 @@ +# `asm_sym` + +The tracking issue for this feature is: [#72016] + +[#72016]: https://github.com/rust-lang/rust/issues/72016 + +------------------------ + +This feature adds a `sym ` operand type to `asm!` and `global_asm!`. +- `` must refer to a `fn` or `static`. +- A mangled symbol name referring to the item is substituted into the asm template string. +- The substituted string does not include any modifiers (e.g. GOT, PLT, relocations, etc). +- `` is allowed to point to a `#[thread_local]` static, in which case the asm code can combine the symbol with relocations (e.g. `@plt`, `@TPOFF`) to read from thread-local data. diff --git a/src/doc/unstable-book/src/language-features/asm-unwind.md b/src/doc/unstable-book/src/language-features/asm-unwind.md new file mode 100644 index 0000000000..414193fe80 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/asm-unwind.md @@ -0,0 +1,9 @@ +# `asm_unwind` + +The tracking issue for this feature is: [#72016] + +[#72016]: https://github.com/rust-lang/rust/issues/72016 + +------------------------ + +This feature adds a `may_unwind` option to `asm!` which allows an `asm` block to unwind stack and be part of the stack unwinding process. This option is only supported by the LLVM backend right now. diff --git a/src/doc/unstable-book/src/library-features/asm.md b/src/doc/unstable-book/src/library-features/asm.md deleted file mode 100644 index fac55b9788..0000000000 --- a/src/doc/unstable-book/src/library-features/asm.md +++ /dev/null @@ -1,896 +0,0 @@ -# `asm` - -The tracking issue for this feature is: [#72016] - -[#72016]: https://github.com/rust-lang/rust/issues/72016 - ------------------------- - -For extremely low-level manipulations and performance reasons, one -might wish to control the CPU directly. Rust supports using inline -assembly to do this via the `asm!` macro. - -# Guide-level explanation -[guide-level-explanation]: #guide-level-explanation - -Rust provides support for inline assembly via the `asm!` macro. -It can be used to embed handwritten assembly in the assembly output generated by the compiler. -Generally this should not be necessary, but might be where the required performance or timing -cannot be otherwise achieved. Accessing low level hardware primitives, e.g. in kernel code, may also demand this functionality. - -> **Note**: the examples here are given in x86/x86-64 assembly, but other architectures are also supported. - -Inline assembly is currently supported on the following architectures: -- x86 and x86-64 -- ARM -- AArch64 -- RISC-V -- NVPTX -- PowerPC -- Hexagon -- MIPS32r2 and MIPS64r2 -- wasm32 -- BPF -- SPIR-V - -## Basic usage - -Let us start with the simplest possible example: - -```rust,allow_fail -#![feature(asm)] -unsafe { - asm!("nop"); -} -``` - -This will insert a NOP (no operation) instruction into the assembly generated by the compiler. -Note that all `asm!` invocations have to be inside an `unsafe` block, as they could insert -arbitrary instructions and break various invariants. The instructions to be inserted are listed -in the first argument of the `asm!` macro as a string literal. - -## Inputs and outputs - -Now inserting an instruction that does nothing is rather boring. Let us do something that -actually acts on data: - -```rust,allow_fail -#![feature(asm)] -let x: u64; -unsafe { - asm!("mov {}, 5", out(reg) x); -} -assert_eq!(x, 5); -``` - -This will write the value `5` into the `u64` variable `x`. -You can see that the string literal we use to specify instructions is actually a template string. -It is governed by the same rules as Rust [format strings][format-syntax]. -The arguments that are inserted into the template however look a bit different than you may -be familiar with. First we need to specify if the variable is an input or an output of the -inline assembly. In this case it is an output. We declared this by writing `out`. -We also need to specify in what kind of register the assembly expects the variable. -In this case we put it in an arbitrary general purpose register by specifying `reg`. -The compiler will choose an appropriate register to insert into -the template and will read the variable from there after the inline assembly finishes executing. - -Let us see another example that also uses an input: - -```rust,allow_fail -#![feature(asm)] -let i: u64 = 3; -let o: u64; -unsafe { - asm!( - "mov {0}, {1}", - "add {0}, {number}", - out(reg) o, - in(reg) i, - number = const 5, - ); -} -assert_eq!(o, 8); -``` - -This will add `5` to the input in variable `i` and write the result to variable `o`. -The particular way this assembly does this is first copying the value from `i` to the output, -and then adding `5` to it. - -The example shows a few things: - -First, we can see that `asm!` allows multiple template string arguments; each -one is treated as a separate line of assembly code, as if they were all joined -together with newlines between them. This makes it easy to format assembly -code. - -Second, we can see that inputs are declared by writing `in` instead of `out`. - -Third, one of our operands has a type we haven't seen yet, `const`. -This tells the compiler to expand this argument to a value directly inside the assembly template. -This is only possible for constants and literals. - -Fourth, we can see that we can specify an argument number, or name as in any format string. -For inline assembly templates this is particularly useful as arguments are often used more than once. -For more complex inline assembly using this facility is generally recommended, as it improves -readability, and allows reordering instructions without changing the argument order. - -We can further refine the above example to avoid the `mov` instruction: - -```rust,allow_fail -#![feature(asm)] -let mut x: u64 = 3; -unsafe { - asm!("add {0}, {number}", inout(reg) x, number = const 5); -} -assert_eq!(x, 8); -``` - -We can see that `inout` is used to specify an argument that is both input and output. -This is different from specifying an input and output separately in that it is guaranteed to assign both to the same register. - -It is also possible to specify different variables for the input and output parts of an `inout` operand: - -```rust,allow_fail -#![feature(asm)] -let x: u64 = 3; -let y: u64; -unsafe { - asm!("add {0}, {number}", inout(reg) x => y, number = const 5); -} -assert_eq!(y, 8); -``` - -## Late output operands - -The Rust compiler is conservative with its allocation of operands. It is assumed that an `out` -can be written at any time, and can therefore not share its location with any other argument. -However, to guarantee optimal performance it is important to use as few registers as possible, -so they won't have to be saved and reloaded around the inline assembly block. -To achieve this Rust provides a `lateout` specifier. This can be used on any output that is -written only after all inputs have been consumed. -There is also a `inlateout` variant of this specifier. - -Here is an example where `inlateout` *cannot* be used: - -```rust,allow_fail -#![feature(asm)] -let mut a: u64 = 4; -let b: u64 = 4; -let c: u64 = 4; -unsafe { - asm!( - "add {0}, {1}", - "add {0}, {2}", - inout(reg) a, - in(reg) b, - in(reg) c, - ); -} -assert_eq!(a, 12); -``` - -Here the compiler is free to allocate the same register for inputs `b` and `c` since it knows they have the same value. However it must allocate a separate register for `a` since it uses `inout` and not `inlateout`. If `inlateout` was used, then `a` and `c` could be allocated to the same register, in which case the first instruction to overwrite the value of `c` and cause the assembly code to produce the wrong result. - -However the following example can use `inlateout` since the output is only modified after all input registers have been read: - -```rust,allow_fail -#![feature(asm)] -let mut a: u64 = 4; -let b: u64 = 4; -unsafe { - asm!("add {0}, {1}", inlateout(reg) a, in(reg) b); -} -assert_eq!(a, 8); -``` - -As you can see, this assembly fragment will still work correctly if `a` and `b` are assigned to the same register. - -## Explicit register operands - -Some instructions require that the operands be in a specific register. -Therefore, Rust inline assembly provides some more specific constraint specifiers. -While `reg` is generally available on any architecture, explicit registers are highly architecture specific. E.g. for x86 the general purpose registers `eax`, `ebx`, `ecx`, `edx`, `ebp`, `esi`, and `edi` among others can be addressed by their name. - -```rust,allow_fail,no_run -#![feature(asm)] -let cmd = 0xd1; -unsafe { - asm!("out 0x64, eax", in("eax") cmd); -} -``` - -In this example we call the `out` instruction to output the content of the `cmd` variable to port `0x64`. Since the `out` instruction only accepts `eax` (and its sub registers) as operand we had to use the `eax` constraint specifier. - -> **Note**: unlike other operand types, explicit register operands cannot be used in the template string: you can't use `{}` and should write the register name directly instead. Also, they must appear at the end of the operand list after all other operand types. - -Consider this example which uses the x86 `mul` instruction: - -```rust,allow_fail -#![feature(asm)] -fn mul(a: u64, b: u64) -> u128 { - let lo: u64; - let hi: u64; - - unsafe { - asm!( - // The x86 mul instruction takes rax as an implicit input and writes - // the 128-bit result of the multiplication to rax:rdx. - "mul {}", - in(reg) a, - inlateout("rax") b => lo, - lateout("rdx") hi - ); - } - - ((hi as u128) << 64) + lo as u128 -} -``` - -This uses the `mul` instruction to multiply two 64-bit inputs with a 128-bit result. -The only explicit operand is a register, that we fill from the variable `a`. -The second operand is implicit, and must be the `rax` register, which we fill from the variable `b`. -The lower 64 bits of the result are stored in `rax` from which we fill the variable `lo`. -The higher 64 bits are stored in `rdx` from which we fill the variable `hi`. - -## Clobbered registers - -In many cases inline assembly will modify state that is not needed as an output. -Usually this is either because we have to use a scratch register in the assembly or because instructions modify state that we don't need to further examine. -This state is generally referred to as being "clobbered". -We need to tell the compiler about this since it may need to save and restore this state around the inline assembly block. - -```rust,allow_fail -#![feature(asm)] -let ebx: u32; -let ecx: u32; - -unsafe { - asm!( - "cpuid", - // EAX 4 selects the "Deterministic Cache Parameters" CPUID leaf - inout("eax") 4 => _, - // ECX 0 selects the L0 cache information. - inout("ecx") 0 => ecx, - lateout("ebx") ebx, - lateout("edx") _, - ); -} - -println!( - "L0 Cache: {}", - ((ebx >> 22) + 1) * (((ebx >> 12) & 0x3ff) + 1) * ((ebx & 0xfff) + 1) * (ecx + 1) -); -``` - -In the example above we use the `cpuid` instruction to get the L1 cache size. -This instruction writes to `eax`, `ebx`, `ecx`, and `edx`, but for the cache size we only care about the contents of `ebx` and `ecx`. - -However we still need to tell the compiler that `eax` and `edx` have been modified so that it can save any values that were in these registers before the asm. This is done by declaring these as outputs but with `_` instead of a variable name, which indicates that the output value is to be discarded. - -This can also be used with a general register class (e.g. `reg`) to obtain a scratch register for use inside the asm code: - -```rust,allow_fail -#![feature(asm)] -// Multiply x by 6 using shifts and adds -let mut x: u64 = 4; -unsafe { - asm!( - "mov {tmp}, {x}", - "shl {tmp}, 1", - "shl {x}, 2", - "add {x}, {tmp}", - x = inout(reg) x, - tmp = out(reg) _, - ); -} -assert_eq!(x, 4 * 6); -``` - -## Symbol operands and ABI clobbers - -A special operand type, `sym`, allows you to use the symbol name of a `fn` or `static` in inline assembly code. -This allows you to call a function or access a global variable without needing to keep its address in a register. - -```rust,allow_fail -#![feature(asm)] -extern "C" fn foo(arg: i32) -> i32 { - println!("arg = {}", arg); - arg * 2 -} - -fn call_foo(arg: i32) -> i32 { - unsafe { - let result; - asm!( - "call {}", - sym foo, - // 1st argument in rdi - in("rdi") arg, - // Return value in rax - out("rax") result, - // Mark all registers which are not preserved by the "C" calling - // convention as clobbered. - clobber_abi("C"), - ); - result - } -} -``` - -Note that the `fn` or `static` item does not need to be public or `#[no_mangle]`: the compiler will automatically insert the appropriate mangled symbol name into the assembly code. - -By default, `asm!` assumes that any register not specified as an output will have its contents preserved by the assembly code. The [`clobber_abi`](#abi-clobbers) argument to `asm!` tells the compiler to automatically insert the necessary clobber operands according to the given calling convention ABI: any register which is not fully preserved in that ABI will be treated as clobbered. Multiple `clobber_abi` arguments may be provided and all clobbers from all specified ABIs will be inserted. - -## Register template modifiers - -In some cases, fine control is needed over the way a register name is formatted when inserted into the template string. This is needed when an architecture's assembly language has several names for the same register, each typically being a "view" over a subset of the register (e.g. the low 32 bits of a 64-bit register). - -By default the compiler will always choose the name that refers to the full register size (e.g. `rax` on x86-64, `eax` on x86, etc). - -This default can be overriden by using modifiers on the template string operands, just like you would with format strings: - -```rust,allow_fail -#![feature(asm)] -let mut x: u16 = 0xab; - -unsafe { - asm!("mov {0:h}, {0:l}", inout(reg_abcd) x); -} - -assert_eq!(x, 0xabab); -``` - -In this example, we use the `reg_abcd` register class to restrict the register allocator to the 4 legacy x86 register (`ax`, `bx`, `cx`, `dx`) of which the first two bytes can be addressed independently. - -Let us assume that the register allocator has chosen to allocate `x` in the `ax` register. -The `h` modifier will emit the register name for the high byte of that register and the `l` modifier will emit the register name for the low byte. The asm code will therefore be expanded as `mov ah, al` which copies the low byte of the value into the high byte. - -If you use a smaller data type (e.g. `u16`) with an operand and forget the use template modifiers, the compiler will emit a warning and suggest the correct modifier to use. - -## Memory address operands - -Sometimes assembly instructions require operands passed via memory addresses/memory locations. -You have to manually use the memory address syntax specified by the target architecture. -For example, on x86/x86_64 using intel assembly syntax, you should wrap inputs/outputs in `[]` to indicate they are memory operands: - -```rust,allow_fail -#![feature(asm, llvm_asm)] -# fn load_fpu_control_word(control: u16) { -unsafe { - asm!("fldcw [{}]", in(reg) &control, options(nostack)); - - // Previously this would have been written with the deprecated `llvm_asm!` like this - llvm_asm!("fldcw $0" :: "m" (control) :: "volatile"); -} -# } -``` - -## Labels - -Any reuse of a named label, local or otherwise, can result in a assembler or linker error or may cause other strange behavior. Reuse of a named label can happen in a variety of ways including: - -- explicitly: using a label more than once in one `asm!` block, or multiple times across blocks -- implicitly via inlining: the compiler is allowed to instantiate multiple copies of an `asm!` block, for example when the function containing it is inlined in multiple places. -- implicitly via LTO: LTO can cause code from *other crates* to be placed in the same codegen unit, and so could bring in arbitrary labels - -As a consequence, you should only use GNU assembler **numeric** [local labels] inside inline assembly code. Defining symbols in assembly code may lead to assembler and/or linker errors due to duplicate symbol definitions. - -Moreover, on x86 when using the default intel syntax, due to [an llvm bug], you shouldn't use labels exclusively made of `0` and `1` digits, e.g. `0`, `11` or `101010`, as they may end up being interpreted as binary values. Using `options(att_syntax)` will avoid any ambiguity, but that affects the syntax of the _entire_ `asm!` block. - -```rust,allow_fail -#![feature(asm)] - -let mut a = 0; -unsafe { - asm!( - "mov {0}, 10", - "2:", - "sub {0}, 1", - "cmp {0}, 3", - "jle 2f", - "jmp 2b", - "2:", - "add {0}, 2", - out(reg) a - ); -} -assert_eq!(a, 5); -``` - -This will decrement the `{0}` register value from 10 to 3, then add 2 and store it in `a`. - -This example shows a few things: - -First that the same number can be used as a label multiple times in the same inline block. - -Second, that when a numeric label is used as a reference (as an instruction operand, for example), the suffixes b (“backward”) or f (“forward”) should be added to the numeric label. It will then refer to the nearest label defined by this number in this direction. - -[local labels]: https://sourceware.org/binutils/docs/as/Symbol-Names.html#Local-Labels -[an llvm bug]: https://bugs.llvm.org/show_bug.cgi?id=36144 - -## Options - -By default, an inline assembly block is treated the same way as an external FFI function call with a custom calling convention: it may read/write memory, have observable side effects, etc. However, in many cases it is desirable to give the compiler more information about what the assembly code is actually doing so that it can optimize better. - -Let's take our previous example of an `add` instruction: - -```rust,allow_fail -#![feature(asm)] -let mut a: u64 = 4; -let b: u64 = 4; -unsafe { - asm!( - "add {0}, {1}", - inlateout(reg) a, in(reg) b, - options(pure, nomem, nostack), - ); -} -assert_eq!(a, 8); -``` - -Options can be provided as an optional final argument to the `asm!` macro. We specified three options here: -- `pure` means that the asm code has no observable side effects and that its output depends only on its inputs. This allows the compiler optimizer to call the inline asm fewer times or even eliminate it entirely. -- `nomem` means that the asm code does not read or write to memory. By default the compiler will assume that inline assembly can read or write any memory address that is accessible to it (e.g. through a pointer passed as an operand, or a global). -- `nostack` means that the asm code does not push any data onto the stack. This allows the compiler to use optimizations such as the stack red zone on x86-64 to avoid stack pointer adjustments. - -These allow the compiler to better optimize code using `asm!`, for example by eliminating pure `asm!` blocks whose outputs are not needed. - -See the reference for the full list of available options and their effects. - -# Reference-level explanation -[reference-level-explanation]: #reference-level-explanation - -Inline assembler is implemented as an unsafe macro `asm!()`. -The first argument to this macro is a template string literal used to build the final assembly. -The following arguments specify input and output operands. -When required, options are specified as the final argument. - -The following ABNF specifies the general syntax: - -```text -dir_spec := "in" / "out" / "lateout" / "inout" / "inlateout" -reg_spec := / "" -operand_expr := expr / "_" / expr "=>" expr / expr "=>" "_" -reg_operand := dir_spec "(" reg_spec ")" operand_expr -operand := reg_operand / "const" const_expr / "sym" path -clobber_abi := "clobber_abi(" *["," ] [","] ")" -option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nostack" / "att_syntax" / "raw" -options := "options(" option *["," option] [","] ")" -asm := "asm!(" format_string *("," format_string) *("," [ident "="] operand) *("," clobber_abi) *("," options) [","] ")" -``` - -Inline assembly is currently supported on the following architectures: -- x86 and x86-64 -- ARM -- AArch64 -- RISC-V -- NVPTX -- PowerPC -- Hexagon -- MIPS32r2 and MIPS64r2 -- wasm32 -- BPF -- SPIR-V - -Support for more targets may be added in the future. The compiler will emit an error if `asm!` is used on an unsupported target. - -[format-syntax]: https://doc.rust-lang.org/std/fmt/#syntax - -## Template string arguments - -The assembler template uses the same syntax as [format strings][format-syntax] (i.e. placeholders are specified by curly braces). The corresponding arguments are accessed in order, by index, or by name. However, implicit named arguments (introduced by [RFC #2795][rfc-2795]) are not supported. - -An `asm!` invocation may have one or more template string arguments; an `asm!` with multiple template string arguments is treated as if all the strings were concatenated with a `\n` between them. The expected usage is for each template string argument to correspond to a line of assembly code. All template string arguments must appear before any other arguments. - -As with format strings, named arguments must appear after positional arguments. Explicit register operands must appear at the end of the operand list, after named arguments if any. - -Explicit register operands cannot be used by placeholders in the template string. All other named and positional operands must appear at least once in the template string, otherwise a compiler error is generated. - -The exact assembly code syntax is target-specific and opaque to the compiler except for the way operands are substituted into the template string to form the code passed to the assembler. - -The 5 targets specified in this RFC (x86, ARM, AArch64, RISC-V, Hexagon) all use the assembly code syntax of the GNU assembler (GAS). On x86, the `.intel_syntax noprefix` mode of GAS is used by default. On ARM, the `.syntax unified` mode is used. These targets impose an additional restriction on the assembly code: any assembler state (e.g. the current section which can be changed with `.section`) must be restored to its original value at the end of the asm string. Assembly code that does not conform to the GAS syntax will result in assembler-specific behavior. - -[rfc-2795]: https://github.com/rust-lang/rfcs/pull/2795 - -## Operand type - -Several types of operands are supported: - -* `in() ` - - `` can refer to a register class or an explicit register. The allocated register name is substituted into the asm template string. - - The allocated register will contain the value of `` at the start of the asm code. - - The allocated register must contain the same value at the end of the asm code (except if a `lateout` is allocated to the same register). -* `out() ` - - `` can refer to a register class or an explicit register. The allocated register name is substituted into the asm template string. - - The allocated register will contain an undefined value at the start of the asm code. - - `` must be a (possibly uninitialized) place expression, to which the contents of the allocated register is written to at the end of the asm code. - - An underscore (`_`) may be specified instead of an expression, which will cause the contents of the register to be discarded at the end of the asm code (effectively acting as a clobber). -* `lateout() ` - - Identical to `out` except that the register allocator can reuse a register allocated to an `in`. - - You should only write to the register after all inputs are read, otherwise you may clobber an input. -* `inout() ` - - `` can refer to a register class or an explicit register. The allocated register name is substituted into the asm template string. - - The allocated register will contain the value of `` at the start of the asm code. - - `` must be a mutable initialized place expression, to which the contents of the allocated register is written to at the end of the asm code. -* `inout() => ` - - Same as `inout` except that the initial value of the register is taken from the value of ``. - - `` must be a (possibly uninitialized) place expression, to which the contents of the allocated register is written to at the end of the asm code. - - An underscore (`_`) may be specified instead of an expression for ``, which will cause the contents of the register to be discarded at the end of the asm code (effectively acting as a clobber). - - `` and `` may have different types. -* `inlateout() ` / `inlateout() => ` - - Identical to `inout` except that the register allocator can reuse a register allocated to an `in` (this can happen if the compiler knows the `in` has the same initial value as the `inlateout`). - - You should only write to the register after all inputs are read, otherwise you may clobber an input. -* `const ` - - `` must be an integer constant expression. - - The value of the expression is formatted as a string and substituted directly into the asm template string. -* `sym ` - - `` must refer to a `fn` or `static`. - - A mangled symbol name referring to the item is substituted into the asm template string. - - The substituted string does not include any modifiers (e.g. GOT, PLT, relocations, etc). - - `` is allowed to point to a `#[thread_local]` static, in which case the asm code can combine the symbol with relocations (e.g. `@plt`, `@TPOFF`) to read from thread-local data. - -Operand expressions are evaluated from left to right, just like function call arguments. After the `asm!` has executed, outputs are written to in left to right order. This is significant if two outputs point to the same place: that place will contain the value of the rightmost output. - -## Register operands - -Input and output operands can be specified either as an explicit register or as a register class from which the register allocator can select a register. Explicit registers are specified as string literals (e.g. `"eax"`) while register classes are specified as identifiers (e.g. `reg`). Using string literals for register names enables support for architectures that use special characters in register names, such as MIPS (`$0`, `$1`, etc). - -Note that explicit registers treat register aliases (e.g. `r14` vs `lr` on ARM) and smaller views of a register (e.g. `eax` vs `rax`) as equivalent to the base register. It is a compile-time error to use the same explicit register for two input operands or two output operands. Additionally, it is also a compile-time error to use overlapping registers (e.g. ARM VFP) in input operands or in output operands. - -Only the following types are allowed as operands for inline assembly: -- Integers (signed and unsigned) -- Floating-point numbers -- Pointers (thin only) -- Function pointers -- SIMD vectors (structs defined with `#[repr(simd)]` and which implement `Copy`). This includes architecture-specific vector types defined in `std::arch` such as `__m128` (x86) or `int8x16_t` (ARM). - -Here is the list of currently supported register classes: - -| Architecture | Register class | Registers | LLVM constraint code | -| ------------ | -------------- | --------- | -------------------- | -| x86 | `reg` | `ax`, `bx`, `cx`, `dx`, `si`, `di`, `bp`, `r[8-15]` (x86-64 only) | `r` | -| x86 | `reg_abcd` | `ax`, `bx`, `cx`, `dx` | `Q` | -| x86-32 | `reg_byte` | `al`, `bl`, `cl`, `dl`, `ah`, `bh`, `ch`, `dh` | `q` | -| x86-64 | `reg_byte`\* | `al`, `bl`, `cl`, `dl`, `sil`, `dil`, `bpl`, `r[8-15]b` | `q` | -| x86 | `xmm_reg` | `xmm[0-7]` (x86) `xmm[0-15]` (x86-64) | `x` | -| x86 | `ymm_reg` | `ymm[0-7]` (x86) `ymm[0-15]` (x86-64) | `x` | -| x86 | `zmm_reg` | `zmm[0-7]` (x86) `zmm[0-31]` (x86-64) | `v` | -| x86 | `kreg` | `k[1-7]` | `Yk` | -| x86 | `x87_reg` | `st([0-7])` | Only clobbers | -| x86 | `mmx_reg` | `mm[0-7]` | Only clobbers | -| AArch64 | `reg` | `x[0-30]` | `r` | -| AArch64 | `vreg` | `v[0-31]` | `w` | -| AArch64 | `vreg_low16` | `v[0-15]` | `x` | -| AArch64 | `preg` | `p[0-15]`, `ffr` | Only clobbers | -| ARM (ARM) | `reg` | `r[0-12]`, `r14` | `r` | -| ARM (Thumb2) | `reg` | `r[0-12]`, `r14` | `r` | -| ARM (Thumb1) | `reg` | `r[0-7]` | `r` | -| ARM (ARM) | `reg_thumb` | `r[0-r12]`, `r14` | `l` | -| ARM (Thumb2) | `reg_thumb` | `r[0-7]` | `l` | -| ARM (Thumb1) | `reg_thumb` | `r[0-7]` | `l` | -| ARM | `sreg` | `s[0-31]` | `t` | -| ARM | `sreg_low16` | `s[0-15]` | `x` | -| ARM | `dreg` | `d[0-31]` | `w` | -| ARM | `dreg_low16` | `d[0-15]` | `t` | -| ARM | `dreg_low8` | `d[0-8]` | `x` | -| ARM | `qreg` | `q[0-15]` | `w` | -| ARM | `qreg_low8` | `q[0-7]` | `t` | -| ARM | `qreg_low4` | `q[0-3]` | `x` | -| MIPS | `reg` | `$[2-25]` | `r` | -| MIPS | `freg` | `$f[0-31]` | `f` | -| NVPTX | `reg16` | None\* | `h` | -| NVPTX | `reg32` | None\* | `r` | -| NVPTX | `reg64` | None\* | `l` | -| RISC-V | `reg` | `x1`, `x[5-7]`, `x[9-15]`, `x[16-31]` (non-RV32E) | `r` | -| RISC-V | `freg` | `f[0-31]` | `f` | -| RISC-V | `vreg` | `v[0-31]` | Only clobbers | -| Hexagon | `reg` | `r[0-28]` | `r` | -| PowerPC | `reg` | `r[0-31]` | `r` | -| PowerPC | `reg_nonzero` | | `r[1-31]` | `b` | -| PowerPC | `freg` | `f[0-31]` | `f` | -| PowerPC | `cr` | `cr[0-7]`, `cr` | Only clobbers | -| PowerPC | `xer` | `xer` | Only clobbers | -| wasm32 | `local` | None\* | `r` | -| BPF | `reg` | `r[0-10]` | `r` | -| BPF | `wreg` | `w[0-10]` | `w` | - -> **Note**: On x86 we treat `reg_byte` differently from `reg` because the compiler can allocate `al` and `ah` separately whereas `reg` reserves the whole register. -> -> Note #2: On x86-64 the high byte registers (e.g. `ah`) are not available in the `reg_byte` register class. -> -> Note #3: NVPTX doesn't have a fixed register set, so named registers are not supported. -> -> Note #4: WebAssembly doesn't have registers, so named registers are not supported. -> -> Note #5: Some register classes are marked as "Only clobbers" which means that they cannot be used for inputs or outputs, only clobbers of the form `out("reg") _` or `lateout("reg") _`. - -Additional register classes may be added in the future based on demand (e.g. MMX, x87, etc). - -Each register class has constraints on which value types they can be used with. This is necessary because the way a value is loaded into a register depends on its type. For example, on big-endian systems, loading a `i32x4` and a `i8x16` into a SIMD register may result in different register contents even if the byte-wise memory representation of both values is identical. The availability of supported types for a particular register class may depend on what target features are currently enabled. - -| Architecture | Register class | Target feature | Allowed types | -| ------------ | -------------- | -------------- | ------------- | -| x86-32 | `reg` | None | `i16`, `i32`, `f32` | -| x86-64 | `reg` | None | `i16`, `i32`, `f32`, `i64`, `f64` | -| x86 | `reg_byte` | None | `i8` | -| x86 | `xmm_reg` | `sse` | `i32`, `f32`, `i64`, `f64`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` | -| x86 | `ymm_reg` | `avx` | `i32`, `f32`, `i64`, `f64`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2`
`i8x32`, `i16x16`, `i32x8`, `i64x4`, `f32x8`, `f64x4` | -| x86 | `zmm_reg` | `avx512f` | `i32`, `f32`, `i64`, `f64`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2`
`i8x32`, `i16x16`, `i32x8`, `i64x4`, `f32x8`, `f64x4`
`i8x64`, `i16x32`, `i32x16`, `i64x8`, `f32x16`, `f64x8` | -| x86 | `kreg` | `avx512f` | `i8`, `i16` | -| x86 | `kreg` | `avx512bw` | `i32`, `i64` | -| x86 | `mmx_reg` | N/A | Only clobbers | -| x86 | `x87_reg` | N/A | Only clobbers | -| AArch64 | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | -| AArch64 | `vreg` | `fp` | `i8`, `i16`, `i32`, `f32`, `i64`, `f64`,
`i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2`, `f64x1`,
`i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` | -| AArch64 | `preg` | N/A | Only clobbers | -| ARM | `reg` | None | `i8`, `i16`, `i32`, `f32` | -| ARM | `sreg` | `vfp2` | `i32`, `f32` | -| ARM | `dreg` | `vfp2` | `i64`, `f64`, `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2` | -| ARM | `qreg` | `neon` | `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4` | -| MIPS32 | `reg` | None | `i8`, `i16`, `i32`, `f32` | -| MIPS32 | `freg` | None | `f32`, `f64` | -| MIPS64 | `reg` | None | `i8`, `i16`, `i32`, `i64`, `f32`, `f64` | -| MIPS64 | `freg` | None | `f32`, `f64` | -| NVPTX | `reg16` | None | `i8`, `i16` | -| NVPTX | `reg32` | None | `i8`, `i16`, `i32`, `f32` | -| NVPTX | `reg64` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | -| RISC-V32 | `reg` | None | `i8`, `i16`, `i32`, `f32` | -| RISC-V64 | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | -| RISC-V | `freg` | `f` | `f32` | -| RISC-V | `freg` | `d` | `f64` | -| RISC-V | `vreg` | N/A | Only clobbers | -| Hexagon | `reg` | None | `i8`, `i16`, `i32`, `f32` | -| PowerPC | `reg` | None | `i8`, `i16`, `i32` | -| PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32` | -| PowerPC | `freg` | None | `f32`, `f64` | -| PowerPC | `cr` | N/A | Only clobbers | -| PowerPC | `xer` | N/A | Only clobbers | -| wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` | -| BPF | `reg` | None | `i8` `i16` `i32` `i64` | -| BPF | `wreg` | `alu32` | `i8` `i16` `i32` | - -> **Note**: For the purposes of the above table pointers, function pointers and `isize`/`usize` are treated as the equivalent integer type (`i16`/`i32`/`i64` depending on the target). - -If a value is of a smaller size than the register it is allocated in then the upper bits of that register will have an undefined value for inputs and will be ignored for outputs. The only exception is the `freg` register class on RISC-V where `f32` values are NaN-boxed in a `f64` as required by the RISC-V architecture. - -When separate input and output expressions are specified for an `inout` operand, both expressions must have the same type. The only exception is if both operands are pointers or integers, in which case they are only required to have the same size. This restriction exists because the register allocators in LLVM and GCC sometimes cannot handle tied operands with different types. - -## Register names - -Some registers have multiple names. These are all treated by the compiler as identical to the base register name. Here is the list of all supported register aliases: - -| Architecture | Base register | Aliases | -| ------------ | ------------- | ------- | -| x86 | `ax` | `eax`, `rax` | -| x86 | `bx` | `ebx`, `rbx` | -| x86 | `cx` | `ecx`, `rcx` | -| x86 | `dx` | `edx`, `rdx` | -| x86 | `si` | `esi`, `rsi` | -| x86 | `di` | `edi`, `rdi` | -| x86 | `bp` | `bpl`, `ebp`, `rbp` | -| x86 | `sp` | `spl`, `esp`, `rsp` | -| x86 | `ip` | `eip`, `rip` | -| x86 | `st(0)` | `st` | -| x86 | `r[8-15]` | `r[8-15]b`, `r[8-15]w`, `r[8-15]d` | -| x86 | `xmm[0-31]` | `ymm[0-31]`, `zmm[0-31]` | -| AArch64 | `x[0-30]` | `w[0-30]` | -| AArch64 | `x29` | `fp` | -| AArch64 | `x30` | `lr` | -| AArch64 | `sp` | `wsp` | -| AArch64 | `xzr` | `wzr` | -| AArch64 | `v[0-31]` | `b[0-31]`, `h[0-31]`, `s[0-31]`, `d[0-31]`, `q[0-31]` | -| ARM | `r[0-3]` | `a[1-4]` | -| ARM | `r[4-9]` | `v[1-6]` | -| ARM | `r9` | `rfp` | -| ARM | `r10` | `sl` | -| ARM | `r11` | `fp` | -| ARM | `r12` | `ip` | -| ARM | `r13` | `sp` | -| ARM | `r14` | `lr` | -| ARM | `r15` | `pc` | -| RISC-V | `x0` | `zero` | -| RISC-V | `x1` | `ra` | -| RISC-V | `x2` | `sp` | -| RISC-V | `x3` | `gp` | -| RISC-V | `x4` | `tp` | -| RISC-V | `x[5-7]` | `t[0-2]` | -| RISC-V | `x8` | `fp`, `s0` | -| RISC-V | `x9` | `s1` | -| RISC-V | `x[10-17]` | `a[0-7]` | -| RISC-V | `x[18-27]` | `s[2-11]` | -| RISC-V | `x[28-31]` | `t[3-6]` | -| RISC-V | `f[0-7]` | `ft[0-7]` | -| RISC-V | `f[8-9]` | `fs[0-1]` | -| RISC-V | `f[10-17]` | `fa[0-7]` | -| RISC-V | `f[18-27]` | `fs[2-11]` | -| RISC-V | `f[28-31]` | `ft[8-11]` | -| Hexagon | `r29` | `sp` | -| Hexagon | `r30` | `fr` | -| Hexagon | `r31` | `lr` | -| BPF | `r[0-10]` | `w[0-10]` | - -Some registers cannot be used for input or output operands: - -| Architecture | Unsupported register | Reason | -| ------------ | -------------------- | ------ | -| All | `sp` | The stack pointer must be restored to its original value at the end of an asm code block. | -| All | `bp` (x86), `x29` (AArch64), `x8` (RISC-V), `fr` (Hexagon), `$fp` (MIPS) | The frame pointer cannot be used as an input or output. | -| ARM | `r7` or `r11` | On ARM the frame pointer can be either `r7` or `r11` depending on the target. The frame pointer cannot be used as an input or output. | -| All | `si` (x86-32), `bx` (x86-64), `r6` (ARM), `x19` (AArch64), `r19` (Hexagon), `x9` (RISC-V) | This is used internally by LLVM as a "base pointer" for functions with complex stack frames. | -| x86 | `k0` | This is a constant zero register which can't be modified. | -| x86 | `ip` | This is the program counter, not a real register. | -| x86 | `mm[0-7]` | MMX registers are not currently supported (but may be in the future). | -| x86 | `st([0-7])` | x87 registers are not currently supported (but may be in the future). | -| AArch64 | `xzr` | This is a constant zero register which can't be modified. | -| ARM | `pc` | This is the program counter, not a real register. | -| ARM | `r9` | This is a reserved register on some ARM targets. | -| MIPS | `$0` or `$zero` | This is a constant zero register which can't be modified. | -| MIPS | `$1` or `$at` | Reserved for assembler. | -| MIPS | `$26`/`$k0`, `$27`/`$k1` | OS-reserved registers. | -| MIPS | `$28`/`$gp` | Global pointer cannot be used as inputs or outputs. | -| MIPS | `$ra` | Return address cannot be used as inputs or outputs. | -| RISC-V | `x0` | This is a constant zero register which can't be modified. | -| RISC-V | `gp`, `tp` | These registers are reserved and cannot be used as inputs or outputs. | -| Hexagon | `lr` | This is the link register which cannot be used as an input or output. | - -In some cases LLVM will allocate a "reserved register" for `reg` operands even though this register cannot be explicitly specified. Assembly code making use of reserved registers should be careful since `reg` operands may alias with those registers. Reserved registers are the frame pointer and base pointer -- The frame pointer and LLVM base pointer on all architectures. -- `r9` on ARM. -- `x18` on AArch64. - -## Template modifiers - -The placeholders can be augmented by modifiers which are specified after the `:` in the curly braces. These modifiers do not affect register allocation, but change the way operands are formatted when inserted into the template string. Only one modifier is allowed per template placeholder. - -The supported modifiers are a subset of LLVM's (and GCC's) [asm template argument modifiers][llvm-argmod], but do not use the same letter codes. - -| Architecture | Register class | Modifier | Example output | LLVM modifier | -| ------------ | -------------- | -------- | -------------- | ------------- | -| x86-32 | `reg` | None | `eax` | `k` | -| x86-64 | `reg` | None | `rax` | `q` | -| x86-32 | `reg_abcd` | `l` | `al` | `b` | -| x86-64 | `reg` | `l` | `al` | `b` | -| x86 | `reg_abcd` | `h` | `ah` | `h` | -| x86 | `reg` | `x` | `ax` | `w` | -| x86 | `reg` | `e` | `eax` | `k` | -| x86-64 | `reg` | `r` | `rax` | `q` | -| x86 | `reg_byte` | None | `al` / `ah` | None | -| x86 | `xmm_reg` | None | `xmm0` | `x` | -| x86 | `ymm_reg` | None | `ymm0` | `t` | -| x86 | `zmm_reg` | None | `zmm0` | `g` | -| x86 | `*mm_reg` | `x` | `xmm0` | `x` | -| x86 | `*mm_reg` | `y` | `ymm0` | `t` | -| x86 | `*mm_reg` | `z` | `zmm0` | `g` | -| x86 | `kreg` | None | `k1` | None | -| AArch64 | `reg` | None | `x0` | `x` | -| AArch64 | `reg` | `w` | `w0` | `w` | -| AArch64 | `reg` | `x` | `x0` | `x` | -| AArch64 | `vreg` | None | `v0` | None | -| AArch64 | `vreg` | `v` | `v0` | None | -| AArch64 | `vreg` | `b` | `b0` | `b` | -| AArch64 | `vreg` | `h` | `h0` | `h` | -| AArch64 | `vreg` | `s` | `s0` | `s` | -| AArch64 | `vreg` | `d` | `d0` | `d` | -| AArch64 | `vreg` | `q` | `q0` | `q` | -| ARM | `reg` | None | `r0` | None | -| ARM | `sreg` | None | `s0` | None | -| ARM | `dreg` | None | `d0` | `P` | -| ARM | `qreg` | None | `q0` | `q` | -| ARM | `qreg` | `e` / `f` | `d0` / `d1` | `e` / `f` | -| MIPS | `reg` | None | `$2` | None | -| MIPS | `freg` | None | `$f0` | None | -| NVPTX | `reg16` | None | `rs0` | None | -| NVPTX | `reg32` | None | `r0` | None | -| NVPTX | `reg64` | None | `rd0` | None | -| RISC-V | `reg` | None | `x1` | None | -| RISC-V | `freg` | None | `f0` | None | -| Hexagon | `reg` | None | `r0` | None | -| PowerPC | `reg` | None | `0` | None | -| PowerPC | `reg_nonzero` | None | `3` | `b` | -| PowerPC | `freg` | None | `0` | None | - -> Notes: -> - on ARM `e` / `f`: this prints the low or high doubleword register name of a NEON quad (128-bit) register. -> - on x86: our behavior for `reg` with no modifiers differs from what GCC does. GCC will infer the modifier based on the operand value type, while we default to the full register size. -> - on x86 `xmm_reg`: the `x`, `t` and `g` LLVM modifiers are not yet implemented in LLVM (they are supported by GCC only), but this should be a simple change. - -As stated in the previous section, passing an input value smaller than the register width will result in the upper bits of the register containing undefined values. This is not a problem if the inline asm only accesses the lower bits of the register, which can be done by using a template modifier to use a subregister name in the asm code (e.g. `ax` instead of `rax`). Since this an easy pitfall, the compiler will suggest a template modifier to use where appropriate given the input type. If all references to an operand already have modifiers then the warning is suppressed for that operand. - -[llvm-argmod]: http://llvm.org/docs/LangRef.html#asm-template-argument-modifiers - -## ABI clobbers - -The `clobber_abi` keyword can be used to apply a default set of clobbers to an `asm` block. This will automatically insert the necessary clobber constraints as needed for calling a function with a particular calling convention: if the calling convention does not fully preserve the value of a register across a call then a `lateout("reg") _` is implicitly added to the operands list. - -`clobber_abi` may be specified any number of times. It will insert a clobber for all unique registers in the union of all specified calling conventions. - -Generic register class outputs are disallowed by the compiler when `clobber_abi` is used: all outputs must specify an explicit register. Explicit register outputs have precedence over the implicit clobbers inserted by `clobber_abi`: a clobber will only be inserted for a register if that register is not used as an output. -The following ABIs can be used with `clobber_abi`: - -| Architecture | ABI name | Clobbered registers | -| ------------ | -------- | ------------------- | -| x86-32 | `"C"`, `"system"`, `"efiapi"`, `"cdecl"`, `"stdcall"`, `"fastcall"` | `ax`, `cx`, `dx`, `xmm[0-7]`, `mm[0-7]`, `k[1-7]`, `st([0-7])` | -| x86-64 | `"C"`, `"system"` (on Windows), `"efiapi"`, `"win64"` | `ax`, `cx`, `dx`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `k[1-7]`, `st([0-7])` | -| x86-64 | `"C"`, `"system"` (on non-Windows), `"sysv64"` | `ax`, `cx`, `dx`, `si`, `di`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `k[1-7]`, `st([0-7])` | -| AArch64 | `"C"`, `"system"`, `"efiapi"` | `x[0-17]`, `x30`, `v[0-31]`, `p[0-15]`, `ffr` | -| ARM | `"C"`, `"system"`, `"efiapi"`, `"aapcs"` | `r[0-3]`, `r12`, `r14`, `s[0-15]`, `d[0-7]`, `d[16-31]` | -| RISC-V | `"C"`, `"system"`, `"efiapi"` | `x1`, `x[5-7]`, `x[10-17]`, `x[28-31]`, `f[0-7]`, `f[10-17]`, `f[28-31]`, `v[0-31]` | - -The list of clobbered registers for each ABI is updated in rustc as architectures gain new registers: this ensures that `asm` clobbers will continue to be correct when LLVM starts using these new registers in its generated code. - -## Options - -Flags are used to further influence the behavior of the inline assembly block. -Currently the following options are defined: -- `pure`: The `asm` block has no side effects, and its outputs depend only on its direct inputs (i.e. the values themselves, not what they point to) or values read from memory (unless the `nomem` options is also set). This allows the compiler to execute the `asm` block fewer times than specified in the program (e.g. by hoisting it out of a loop) or even eliminate it entirely if the outputs are not used. -- `nomem`: The `asm` blocks does not read or write to any memory. This allows the compiler to cache the values of modified global variables in registers across the `asm` block since it knows that they are not read or written to by the `asm`. -- `readonly`: The `asm` block does not write to any memory. This allows the compiler to cache the values of unmodified global variables in registers across the `asm` block since it knows that they are not written to by the `asm`. -- `preserves_flags`: The `asm` block does not modify the flags register (defined in the rules below). This allows the compiler to avoid recomputing the condition flags after the `asm` block. -- `noreturn`: The `asm` block never returns, and its return type is defined as `!` (never). Behavior is undefined if execution falls through past the end of the asm code. A `noreturn` asm block behaves just like a function which doesn't return; notably, local variables in scope are not dropped before it is invoked. -- `nostack`: The `asm` block does not push data to the stack, or write to the stack red-zone (if supported by the target). If this option is *not* used then the stack pointer is guaranteed to be suitably aligned (according to the target ABI) for a function call. -- `att_syntax`: This option is only valid on x86, and causes the assembler to use the `.att_syntax prefix` mode of the GNU assembler. Register operands are substituted in with a leading `%`. -- `raw`: This causes the template string to be parsed as a raw assembly string, with no special handling for `{` and `}`. This is primarily useful when including raw assembly code from an external file using `include_str!`. - -The compiler performs some additional checks on options: -- The `nomem` and `readonly` options are mutually exclusive: it is a compile-time error to specify both. -- The `pure` option must be combined with either the `nomem` or `readonly` options, otherwise a compile-time error is emitted. -- It is a compile-time error to specify `pure` on an asm block with no outputs or only discarded outputs (`_`). -- It is a compile-time error to specify `noreturn` on an asm block with outputs. - -## Rules for inline assembly - -- Any registers not specified as inputs will contain an undefined value on entry to the asm block. - - An "undefined value" in the context of inline assembly means that the register can (non-deterministically) have any one of the possible values allowed by the architecture. Notably it is not the same as an LLVM `undef` which can have a different value every time you read it (since such a concept does not exist in assembly code). -- Any registers not specified as outputs must have the same value upon exiting the asm block as they had on entry, otherwise behavior is undefined. - - This only applies to registers which can be specified as an input or output. Other registers follow target-specific rules. - - Note that a `lateout` may be allocated to the same register as an `in`, in which case this rule does not apply. Code should not rely on this however since it depends on the results of register allocation. -- Behavior is undefined if execution unwinds out of an asm block. - - This also applies if the assembly code calls a function which then unwinds. -- The set of memory locations that assembly code is allowed to read and write are the same as those allowed for an FFI function. - - Refer to the unsafe code guidelines for the exact rules. - - If the `readonly` option is set, then only memory reads are allowed. - - If the `nomem` option is set then no reads or writes to memory are allowed. - - These rules do not apply to memory which is private to the asm code, such as stack space allocated within the asm block. -- The compiler cannot assume that the instructions in the asm are the ones that will actually end up executed. - - This effectively means that the compiler must treat the `asm!` as a black box and only take the interface specification into account, not the instructions themselves. - - Runtime code patching is allowed, via target-specific mechanisms (outside the scope of this RFC). -- Unless the `nostack` option is set, asm code is allowed to use stack space below the stack pointer. - - On entry to the asm block the stack pointer is guaranteed to be suitably aligned (according to the target ABI) for a function call. - - You are responsible for making sure you don't overflow the stack (e.g. use stack probing to ensure you hit a guard page). - - You should adjust the stack pointer when allocating stack memory as required by the target ABI. - - The stack pointer must be restored to its original value before leaving the asm block. -- If the `noreturn` option is set then behavior is undefined if execution falls through to the end of the asm block. -- If the `pure` option is set then behavior is undefined if the `asm` has side-effects other than its direct outputs. Behavior is also undefined if two executions of the `asm` code with the same inputs result in different outputs. - - When used with the `nomem` option, "inputs" are just the direct inputs of the `asm!`. - - When used with the `readonly` option, "inputs" comprise the direct inputs of the `asm!` and any memory that the `asm!` block is allowed to read. -- These flags registers must be restored upon exiting the asm block if the `preserves_flags` option is set: - - x86 - - Status flags in `EFLAGS` (CF, PF, AF, ZF, SF, OF). - - Floating-point status word (all). - - Floating-point exception flags in `MXCSR` (PE, UE, OE, ZE, DE, IE). - - ARM - - Condition flags in `CPSR` (N, Z, C, V) - - Saturation flag in `CPSR` (Q) - - Greater than or equal flags in `CPSR` (GE). - - Condition flags in `FPSCR` (N, Z, C, V) - - Saturation flag in `FPSCR` (QC) - - Floating-point exception flags in `FPSCR` (IDC, IXC, UFC, OFC, DZC, IOC). - - AArch64 - - Condition flags (`NZCV` register). - - Floating-point status (`FPSR` register). - - RISC-V - - Floating-point exception flags in `fcsr` (`fflags`). - - Vector extension state (`vtype`, `vl`, `vcsr`). -- On x86, the direction flag (DF in `EFLAGS`) is clear on entry to an asm block and must be clear on exit. - - Behavior is undefined if the direction flag is set on exiting an asm block. -- The requirement of restoring the stack pointer and non-output registers to their original value only applies when exiting an `asm!` block. - - This means that `asm!` blocks that never return (even if not marked `noreturn`) don't need to preserve these registers. - - When returning to a different `asm!` block than you entered (e.g. for context switching), these registers must contain the value they had upon entering the `asm!` block that you are *exiting*. - - You cannot exit an `asm!` block that has not been entered. Neither can you exit an `asm!` block that has already been exited. - - You are responsible for switching any target-specific state (e.g. thread-local storage, stack bounds). - - The set of memory locations that you may access is the intersection of those allowed by the `asm!` blocks you entered and exited. -- You cannot assume that an `asm!` block will appear exactly once in the output binary. The compiler is allowed to instantiate multiple copies of the `asm!` block, for example when the function containing it is inlined in multiple places. -- On x86, inline assembly must not end with an instruction prefix (such as `LOCK`) that would apply to instructions generated by the compiler. - - The compiler is currently unable to detect this due to the way inline assembly is compiled, but may catch and reject this in the future. - -> **Note**: As a general rule, the flags covered by `preserves_flags` are those which are *not* preserved when performing a function call. diff --git a/src/doc/unstable-book/src/library-features/global-asm.md b/src/doc/unstable-book/src/library-features/global-asm.md deleted file mode 100644 index 3f8e165841..0000000000 --- a/src/doc/unstable-book/src/library-features/global-asm.md +++ /dev/null @@ -1,113 +0,0 @@ -# `global_asm` - -The tracking issue for this feature is: [#35119] - -[#35119]: https://github.com/rust-lang/rust/issues/35119 - ------------------------- - -The `global_asm!` macro allows the programmer to write arbitrary -assembly outside the scope of a function body, passing it through -`rustc` and `llvm` to the assembler. That is to say, `global_asm!` is -equivalent to assembling the asm with an external assembler and then -linking the resulting object file with the current crate. - -`global_asm!` fills a role not currently satisfied by either `asm!` -or `#[naked]` functions. The programmer has _all_ features of the -assembler at their disposal. The linker will expect to resolve any -symbols defined in the inline assembly, modulo any symbols marked as -external. It also means syntax for directives and assembly follow the -conventions of the assembler in your toolchain. - -A simple usage looks like this: - -```rust,ignore (requires-external-file) -#![feature(global_asm)] -# // you also need relevant target_arch cfgs -global_asm!(include_str!("something_neato.s")); -``` - -And a more complicated usage looks like this: - -```rust,no_run -#![feature(global_asm)] -# #[cfg(any(target_arch="x86", target_arch="x86_64"))] -# mod x86 { - -pub mod sally { - global_asm!( - ".global foo", - "foo:", - "jmp baz", - ); - - #[no_mangle] - pub unsafe extern "C" fn baz() {} -} - -// the symbols `foo` and `bar` are global, no matter where -// `global_asm!` was used. -extern "C" { - fn foo(); - fn bar(); -} - -pub mod harry { - global_asm!( - ".global bar", - "bar:", - "jmp quux", - ); - - #[no_mangle] - pub unsafe extern "C" fn quux() {} -} -# } -``` - -You may use `global_asm!` multiple times, anywhere in your crate, in -whatever way suits you. However, you should not rely on assembler state -(e.g. assembler macros) defined in one `global_asm!` to be available in -another one. It is implementation-defined whether the multiple usages -are concatenated into one or assembled separately. - -`global_asm!` also supports `const` operands like `asm!`, which allows -constants defined in Rust to be used in assembly code: - -```rust,no_run -#![feature(global_asm, asm_const)] -# #[cfg(any(target_arch="x86", target_arch="x86_64"))] -# mod x86 { -const C: i32 = 1234; -global_asm!( - ".global bar", - "bar: .word {c}", - c = const C, -); -# } -``` - -The syntax for passing operands is the same as `asm!` except that only -`const` operands are allowed. Refer to the [asm](asm.md) documentation -for more details. - -On x86, the assembly code will use intel syntax by default. You can -override this by adding `options(att_syntax)` at the end of the macro -arguments list: - -```rust,no_run -#![feature(global_asm, asm_const)] -# #[cfg(any(target_arch="x86", target_arch="x86_64"))] -# mod x86 { -global_asm!("movl ${}, %ecx", const 5, options(att_syntax)); -// is equivalent to -global_asm!("mov ecx, {}", const 5); -# } -``` - ------------------------- - -If you don't need quite as much power and flexibility as -`global_asm!` provides, and you don't mind restricting your inline -assembly to `fn` bodies only, you might try the -[asm](asm.md) feature instead. diff --git a/src/doc/unstable-book/src/library-features/llvm-asm.md b/src/doc/unstable-book/src/library-features/llvm-asm.md index 07fc16261d..094124998b 100644 --- a/src/doc/unstable-book/src/library-features/llvm-asm.md +++ b/src/doc/unstable-book/src/library-features/llvm-asm.md @@ -188,6 +188,3 @@ documentation as well][llvm-docs] for more information about clobbers, constraints, etc. [llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions - -If you need more power and don't mind losing some of the niceties of -`llvm_asm!`, check out [global_asm](global-asm.md). diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py index 8647db5a45..48a341ffe0 100644 --- a/src/etc/htmldocck.py +++ b/src/etc/htmldocck.py @@ -90,10 +90,20 @@ There are a number of supported commands: highlights for example. If you want to simply check for the presence of a given node or attribute, use an empty string (`""`) as a `PATTERN`. -* `@count PATH XPATH COUNT' checks for the occurrence of the given XPath +* `@count PATH XPATH COUNT` checks for the occurrence of the given XPath in the specified file. The number of occurrences must match the given count. +* `@snapshot NAME PATH XPATH` creates a snapshot test named NAME. + A snapshot test captures a subtree of the DOM, at the location + determined by the XPath, and compares it to a pre-recorded value + in a file. The file's name is the test's name with the `.rs` extension + replaced with `.NAME.html`, where NAME is the snapshot's name. + + htmldocck supports the `--bless` option to accept the current subtree + as expected, saving it to the file determined by the snapshot's name. + compiletest's `--bless` flag is forwarded to htmldocck. + * `@has-dir PATH` checks for the existence of the given directory. All conditions can be negated with `!`. `@!has foo/type.NoSuch.html` @@ -137,6 +147,10 @@ except NameError: channel = os.environ["DOC_RUST_LANG_ORG_CHANNEL"] +# Initialized in main +rust_test_path = None +bless = None + class CustomHTMLParser(HTMLParser): """simplified HTML parser. @@ -387,6 +401,32 @@ def get_tree_count(tree, path): return len(tree.findall(path)) +def check_snapshot(snapshot_name, tree): + assert rust_test_path.endswith('.rs') + snapshot_path = '{}.{}.{}'.format(rust_test_path[:-3], snapshot_name, 'html') + try: + with open(snapshot_path, 'r') as snapshot_file: + expected_str = snapshot_file.read() + except FileNotFoundError: + if bless: + expected_str = None + else: + raise FailedCheck('No saved snapshot value') + + actual_str = ET.tostring(tree).decode('utf-8') + + if expected_str != actual_str: + if bless: + with open(snapshot_path, 'w') as snapshot_file: + snapshot_file.write(actual_str) + else: + print('--- expected ---\n') + print(expected_str) + print('\n\n--- actual ---\n') + print(actual_str) + print() + raise FailedCheck('Actual snapshot value is different than expected') + def stderr(*args): if sys.version_info.major < 3: file = codecs.getwriter('utf-8')(sys.stderr) @@ -448,6 +488,28 @@ def check_command(c, cache): ret = expected == found else: raise InvalidCheck('Invalid number of @{} arguments'.format(c.cmd)) + + elif c.cmd == 'snapshot': # snapshot test + if len(c.args) == 3: # @snapshot + [snapshot_name, html_path, pattern] = c.args + tree = cache.get_tree(html_path) + xpath = normalize_xpath(pattern) + subtrees = tree.findall(xpath) + if len(subtrees) == 1: + [subtree] = subtrees + try: + check_snapshot(snapshot_name, subtree) + ret = True + except FailedCheck as err: + cerr = str(err) + ret = False + elif len(subtrees) == 0: + raise FailedCheck('XPATH did not match') + else: + raise FailedCheck('Expected 1 match, but found {}'.format(len(subtrees))) + else: + raise InvalidCheck('Invalid number of @{} arguments'.format(c.cmd)) + elif c.cmd == 'has-dir': # has-dir test if len(c.args) == 1: # @has-dir = has-dir test try: @@ -458,11 +520,13 @@ def check_command(c, cache): ret = False else: raise InvalidCheck('Invalid number of @{} arguments'.format(c.cmd)) + elif c.cmd == 'valid-html': raise InvalidCheck('Unimplemented @valid-html') elif c.cmd == 'valid-links': raise InvalidCheck('Unimplemented @valid-links') + else: raise InvalidCheck('Unrecognized @{}'.format(c.cmd)) @@ -483,11 +547,19 @@ def check(target, commands): if __name__ == '__main__': - if len(sys.argv) != 3: - stderr('Usage: {}