New upstream version 1.59.0+dfsg1

This commit is contained in:
Ximin Luo 2022-03-29 13:22:26 +01:00
parent 3c0e092ef8
commit a2a8927aec
4709 changed files with 200302 additions and 67573 deletions

302
Cargo.lock generated
View File

@ -9,7 +9,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd" checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd"
dependencies = [ dependencies = [
"compiler_builtins", "compiler_builtins",
"gimli", "gimli 0.25.0",
"rustc-std-workspace-alloc", "rustc-std-workspace-alloc",
"rustc-std-workspace-core", "rustc-std-workspace-core",
] ]
@ -87,9 +87,9 @@ dependencies = [
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.34" version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf8dcb5b4bbaa28653b647d8c77bd4ed40183b48882e130c1f1ffb73de069fd7" checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203"
[[package]] [[package]]
name = "array_tool" name = "array_tool"
@ -175,9 +175,7 @@ dependencies = [
"filetime", "filetime",
"getopts", "getopts",
"ignore", "ignore",
"lazy_static",
"libc", "libc",
"merge",
"num_cpus", "num_cpus",
"once_cell", "once_cell",
"opener", "opener",
@ -276,7 +274,7 @@ dependencies = [
[[package]] [[package]]
name = "cargo" name = "cargo"
version = "0.59.0" version = "0.60.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"atty", "atty",
@ -370,7 +368,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"directories", "directories",
"rustc-workspace-hack", "rustc-workspace-hack",
"rustc_version 0.3.3", "rustc_version",
"serde", "serde",
"serde_json", "serde_json",
"vergen", "vergen",
@ -419,7 +417,7 @@ dependencies = [
[[package]] [[package]]
name = "cargo-util" name = "cargo-util"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"core-foundation", "core-foundation",
@ -492,9 +490,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "chalk-derive" name = "chalk-derive"
version = "0.55.0" version = "0.75.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3983193cacd81f0f924acb666b7fe5e1a0d81db9f113fa69203eda7ea8ce8b6c" checksum = "d54e3b5f9e3425e6b119ff07568d8d006bfa5a8d6f78a9cbc3530b1e962e316c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -504,9 +502,9 @@ dependencies = [
[[package]] [[package]]
name = "chalk-engine" name = "chalk-engine"
version = "0.55.0" version = "0.75.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05a171ce5abbf0fbd06f221ab80ab182c7ef78603d23b858bc44e7ce8a86a396" checksum = "bdc891073396b167163db77123b0a3c00088edc00466cecc5531f33e3e989523"
dependencies = [ dependencies = [
"chalk-derive", "chalk-derive",
"chalk-ir", "chalk-ir",
@ -517,9 +515,9 @@ dependencies = [
[[package]] [[package]]
name = "chalk-ir" name = "chalk-ir"
version = "0.55.0" version = "0.75.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a522f53af971e7678f472d687e053120157b3ae26e2ebd5ecbc0f5ab124f2cb6" checksum = "2b79e5a1d04b79311e90c69356a2c62027853906a7e33b3e070b93c055fc3e8a"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"chalk-derive", "chalk-derive",
@ -528,14 +526,14 @@ dependencies = [
[[package]] [[package]]
name = "chalk-solve" name = "chalk-solve"
version = "0.55.0" version = "0.75.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdf79fb77a567e456a170f7ec84ea6584163d4ba3f13660cd182013d34ca667c" checksum = "a5d2a1db6605aba70a58820bd80ac422b218913a510f1a40beef9efc5371ea1d"
dependencies = [ dependencies = [
"chalk-derive", "chalk-derive",
"chalk-ir", "chalk-ir",
"ena", "ena",
"itertools 0.9.0", "itertools 0.10.1",
"petgraph", "petgraph",
"rustc-hash", "rustc-hash",
"tracing", "tracing",
@ -558,11 +556,11 @@ dependencies = [
[[package]] [[package]]
name = "clap" name = "clap"
version = "2.33.3" version = "2.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
dependencies = [ dependencies = [
"ansi_term 0.11.0", "ansi_term 0.12.1",
"atty", "atty",
"bitflags", "bitflags",
"strsim", "strsim",
@ -574,7 +572,7 @@ dependencies = [
[[package]] [[package]]
name = "clippy" name = "clippy"
version = "0.1.58" version = "0.1.59"
dependencies = [ dependencies = [
"cargo_metadata 0.14.0", "cargo_metadata 0.14.0",
"clippy_lints", "clippy_lints",
@ -584,6 +582,7 @@ dependencies = [
"filetime", "filetime",
"if_chain", "if_chain",
"itertools 0.10.1", "itertools 0.10.1",
"parking_lot",
"quote", "quote",
"regex", "regex",
"rustc-workspace-hack", "rustc-workspace-hack",
@ -600,6 +599,7 @@ name = "clippy_dev"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"bytecount", "bytecount",
"cargo_metadata 0.14.0",
"clap", "clap",
"indoc", "indoc",
"itertools 0.10.1", "itertools 0.10.1",
@ -611,13 +611,13 @@ dependencies = [
[[package]] [[package]]
name = "clippy_lints" name = "clippy_lints"
version = "0.1.58" version = "0.1.59"
dependencies = [ dependencies = [
"cargo_metadata 0.14.0", "cargo_metadata 0.14.0",
"clippy_utils", "clippy_utils",
"if_chain", "if_chain",
"itertools 0.10.1", "itertools 0.10.1",
"pulldown-cmark 0.8.0", "pulldown-cmark",
"quine-mc_cluskey", "quine-mc_cluskey",
"regex-syntax", "regex-syntax",
"rustc-semver", "rustc-semver",
@ -632,7 +632,7 @@ dependencies = [
[[package]] [[package]]
name = "clippy_utils" name = "clippy_utils"
version = "0.1.58" version = "0.1.59"
dependencies = [ dependencies = [
"if_chain", "if_chain",
"rustc-semver", "rustc-semver",
@ -678,9 +678,9 @@ dependencies = [
[[package]] [[package]]
name = "compiler_builtins" name = "compiler_builtins"
version = "0.1.53" version = "0.1.67"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2467ff455350a4df7d02f1ed1449d0279605a763de5d586dcf6aa7d732508bcb" checksum = "a68c69e9451f1df4b215c9588c621670c12286b53e60fb5ec4b59aaa1138d18e"
dependencies = [ dependencies = [
"cc", "cc",
"rustc-std-workspace-core", "rustc-std-workspace-core",
@ -766,7 +766,7 @@ checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634"
[[package]] [[package]]
name = "crates-io" name = "crates-io"
version = "0.33.0" version = "0.33.1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"curl", "curl",
@ -1158,6 +1158,12 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
[[package]]
name = "fallible-iterator"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
[[package]] [[package]]
name = "filetime" name = "filetime"
version = "0.2.14" version = "0.2.14"
@ -1446,6 +1452,17 @@ dependencies = [
"rustc-std-workspace-core", "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]] [[package]]
name = "git2" name = "git2"
version = "0.13.23" version = "0.13.23"
@ -1713,9 +1730,12 @@ dependencies = [
[[package]] [[package]]
name = "instant" name = "instant"
version = "0.1.6" version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b141fdc7836c525d4d594027d318c84161ca17aaf8113ab1f81ab93ae897485" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if 1.0.0",
]
[[package]] [[package]]
name = "itertools" name = "itertools"
@ -1900,9 +1920,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.106" version = "0.2.108"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a60553f9a9e039a333b4e9b20573b9e9b9c0bb3a11e201ccc48ef4283456d673" checksum = "8521a1b57e76b1ec69af7599e75e38e7b7fad6610f037db8c79b127201b5d119"
dependencies = [ dependencies = [
"rustc-std-workspace-core", "rustc-std-workspace-core",
] ]
@ -1921,6 +1941,16 @@ dependencies = [
"pkg-config", "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]] [[package]]
name = "libm" name = "libm"
version = "0.1.4" version = "0.1.4"
@ -1939,9 +1969,9 @@ dependencies = [
[[package]] [[package]]
name = "libssh2-sys" name = "libssh2-sys"
version = "0.2.19" version = "0.2.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca46220853ba1c512fc82826d0834d87b06bcd3c2a42241b7de72f3d2fe17056" checksum = "b094a36eb4b8b8c8a7b4b8ae43b2944502be3e59cd87687595cf6b0a71b3f4ca"
dependencies = [ dependencies = [
"cc", "cc",
"libc", "libc",
@ -1992,9 +2022,9 @@ version = "0.1.0"
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.1" version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28247cc5a5be2f05fbcd76dd0cf2c7d3b5400cb978a28042abcd4fa0b3f8261c" checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109"
dependencies = [ dependencies = [
"scopeguard", "scopeguard",
] ]
@ -2092,9 +2122,9 @@ dependencies = [
[[package]] [[package]]
name = "matchers" name = "matchers"
version = "0.0.1" version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
dependencies = [ dependencies = [
"regex-automata", "regex-automata",
] ]
@ -2124,9 +2154,9 @@ dependencies = [
[[package]] [[package]]
name = "mdbook" name = "mdbook"
version = "0.4.12" version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0651782b4cc514c3f98c0acf9b5af1101a735bbe1ac6852bb1a90cb91bdf0ed4" checksum = "241f10687eb3b4e0634b3b4e423f97c5f1efbd69dc9522e24a8b94583eeec3c6"
dependencies = [ dependencies = [
"ammonia", "ammonia",
"anyhow", "anyhow",
@ -2138,8 +2168,8 @@ dependencies = [
"lazy_static", "lazy_static",
"log", "log",
"memchr", "memchr",
"open", "opener",
"pulldown-cmark 0.7.2", "pulldown-cmark",
"regex", "regex",
"serde", "serde",
"serde_derive", "serde_derive",
@ -2147,6 +2177,7 @@ dependencies = [
"shlex", "shlex",
"tempfile", "tempfile",
"toml", "toml",
"topological-sort",
] ]
[[package]] [[package]]
@ -2205,28 +2236,6 @@ dependencies = [
"autocfg", "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]] [[package]]
name = "minifier" name = "minifier"
version = "0.0.41" version = "0.0.41"
@ -2284,7 +2293,7 @@ dependencies = [
"measureme 9.1.2", "measureme 9.1.2",
"rand 0.8.4", "rand 0.8.4",
"rustc-workspace-hack", "rustc-workspace-hack",
"rustc_version 0.4.0", "rustc_version",
"shell-escape", "shell-escape",
"smallvec", "smallvec",
] ]
@ -2347,6 +2356,18 @@ dependencies = [
"rustc-std-workspace-core", "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]] [[package]]
name = "odht" name = "odht"
version = "0.3.1" version = "0.3.1"
@ -2374,15 +2395,6 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "open"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c283bf0114efea9e42f1a60edea9859e8c47528eae09d01df4b29c1e489cc48"
dependencies = [
"winapi",
]
[[package]] [[package]]
name = "opener" name = "opener"
version = "0.5.0" version = "0.5.0"
@ -2511,9 +2523,9 @@ dependencies = [
[[package]] [[package]]
name = "parking_lot" name = "parking_lot"
version = "0.11.1" version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
dependencies = [ dependencies = [
"instant", "instant",
"lock_api", "lock_api",
@ -2522,9 +2534,9 @@ dependencies = [
[[package]] [[package]]
name = "parking_lot_core" name = "parking_lot_core"
version = "0.8.3" version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"instant", "instant",
@ -2796,9 +2808,9 @@ dependencies = [
[[package]] [[package]]
name = "pulldown-cmark" name = "pulldown-cmark"
version = "0.7.2" version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca36dea94d187597e104a5c8e4b07576a8a45aa5db48a65e12940d3eb7461f55" checksum = "34f197a544b0c9ab3ae46c359a7ec9cbbb5c7bf97054266fecb7ead794a181d6"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"getopts", "getopts",
@ -2806,17 +2818,6 @@ dependencies = [
"unicase", "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]] [[package]]
name = "punycode" name = "punycode"
version = "0.4.1" version = "0.4.1"
@ -3085,15 +3086,15 @@ dependencies = [
"anyhow", "anyhow",
"cargo", "cargo",
"cargo-util", "cargo-util",
"cargo_metadata 0.12.0", "cargo_metadata 0.14.0",
"clippy_lints", "clippy_lints",
"crossbeam-channel", "crossbeam-channel",
"difference", "difference",
"env_logger 0.7.1", "env_logger 0.9.0",
"futures 0.3.12", "futures 0.3.12",
"heck", "heck",
"home", "home",
"itertools 0.9.0", "itertools 0.10.1",
"jsonrpc-core", "jsonrpc-core",
"lazy_static", "lazy_static",
"log", "log",
@ -3102,7 +3103,7 @@ dependencies = [
"num_cpus", "num_cpus",
"ordslice", "ordslice",
"racer", "racer",
"rand 0.7.3", "rand 0.8.4",
"rayon", "rayon",
"regex", "regex",
"rls-analysis", "rls-analysis",
@ -3692,6 +3693,7 @@ dependencies = [
"rustc_expand", "rustc_expand",
"rustc_feature", "rustc_feature",
"rustc_lexer", "rustc_lexer",
"rustc_lint_defs",
"rustc_parse", "rustc_parse",
"rustc_parse_format", "rustc_parse_format",
"rustc_session", "rustc_session",
@ -3708,6 +3710,7 @@ dependencies = [
"bitflags", "bitflags",
"cstr", "cstr",
"libc", "libc",
"libloading",
"measureme 10.0.0", "measureme 10.0.0",
"rustc-demangle", "rustc-demangle",
"rustc_arena", "rustc_arena",
@ -3728,7 +3731,6 @@ dependencies = [
"rustc_span", "rustc_span",
"rustc_target", "rustc_target",
"smallvec", "smallvec",
"snap",
"tracing", "tracing",
] ]
@ -3741,10 +3743,11 @@ dependencies = [
"itertools 0.9.0", "itertools 0.9.0",
"jobserver", "jobserver",
"libc", "libc",
"object", "object 0.26.2",
"pathdiff", "pathdiff",
"regex", "regex",
"rustc_apfloat", "rustc_apfloat",
"rustc_arena",
"rustc_ast", "rustc_ast",
"rustc_attr", "rustc_attr",
"rustc_data_structures", "rustc_data_structures",
@ -3763,7 +3766,9 @@ dependencies = [
"rustc_symbol_mangling", "rustc_symbol_mangling",
"rustc_target", "rustc_target",
"smallvec", "smallvec",
"snap",
"tempfile", "tempfile",
"thorin-dwp",
"tracing", "tracing",
] ]
@ -3823,7 +3828,6 @@ dependencies = [
name = "rustc_driver" name = "rustc_driver"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"atty",
"libc", "libc",
"rustc_ast", "rustc_ast",
"rustc_ast_pretty", "rustc_ast_pretty",
@ -3837,6 +3841,7 @@ dependencies = [
"rustc_hir_pretty", "rustc_hir_pretty",
"rustc_interface", "rustc_interface",
"rustc_lint", "rustc_lint",
"rustc_log",
"rustc_metadata", "rustc_metadata",
"rustc_middle", "rustc_middle",
"rustc_parse", "rustc_parse",
@ -3848,8 +3853,6 @@ dependencies = [
"rustc_target", "rustc_target",
"rustc_typeck", "rustc_typeck",
"tracing", "tracing",
"tracing-subscriber",
"tracing-tree",
"winapi", "winapi",
] ]
@ -3967,6 +3970,7 @@ dependencies = [
"arrayvec", "arrayvec",
"rustc_macros", "rustc_macros",
"rustc_serialize", "rustc_serialize",
"smallvec",
] ]
[[package]] [[package]]
@ -3992,6 +3996,7 @@ name = "rustc_interface"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"libc", "libc",
"libloading",
"rustc-rayon", "rustc-rayon",
"rustc-rayon-core", "rustc-rayon-core",
"rustc_ast", "rustc_ast",
@ -4090,6 +4095,17 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "rustc_log"
version = "0.0.0"
dependencies = [
"atty",
"rustc_span",
"tracing",
"tracing-subscriber",
"tracing-tree",
]
[[package]] [[package]]
name = "rustc_macros" name = "rustc_macros"
version = "0.1.0" version = "0.1.0"
@ -4104,7 +4120,7 @@ dependencies = [
name = "rustc_metadata" name = "rustc_metadata"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"libc", "libloading",
"odht", "odht",
"rustc_ast", "rustc_ast",
"rustc_attr", "rustc_attr",
@ -4124,7 +4140,6 @@ dependencies = [
"smallvec", "smallvec",
"snap", "snap",
"tracing", "tracing",
"winapi",
] ]
[[package]] [[package]]
@ -4297,6 +4312,7 @@ dependencies = [
name = "rustc_plugin_impl" name = "rustc_plugin_impl"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"libloading",
"rustc_ast", "rustc_ast",
"rustc_errors", "rustc_errors",
"rustc_hir", "rustc_hir",
@ -4590,15 +4606,6 @@ dependencies = [
"tracing", "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]] [[package]]
name = "rustc_version" name = "rustc_version"
version = "0.4.0" version = "0.4.0"
@ -4616,7 +4623,7 @@ dependencies = [
"expect-test", "expect-test",
"itertools 0.9.0", "itertools 0.9.0",
"minifier", "minifier",
"pulldown-cmark 0.8.0", "pulldown-cmark",
"rayon", "rayon",
"regex", "regex",
"rustdoc-json-types", "rustdoc-json-types",
@ -5006,7 +5013,7 @@ dependencies = [
"hermit-abi", "hermit-abi",
"libc", "libc",
"miniz_oxide", "miniz_oxide",
"object", "object 0.26.2",
"panic_abort", "panic_abort",
"panic_unwind", "panic_unwind",
"profiler_builtins", "profiler_builtins",
@ -5070,9 +5077,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]] [[package]]
name = "structopt" name = "structopt"
version = "0.3.16" version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de5472fb24d7e80ae84a7801b7978f95a19ec32cb1876faea59ab711eb901976" checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c"
dependencies = [ dependencies = [
"clap", "clap",
"lazy_static", "lazy_static",
@ -5081,9 +5088,9 @@ dependencies = [
[[package]] [[package]]
name = "structopt-derive" name = "structopt-derive"
version = "0.4.9" version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0eb37335aeeebe51be42e2dc07f031163fbabfa6ac67d7ea68b5c2f68d5f99" checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0"
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro-error", "proc-macro-error",
@ -5123,9 +5130,9 @@ dependencies = [
[[package]] [[package]]
name = "synstructure" name = "synstructure"
version = "0.12.4" version = "0.12.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -5262,24 +5269,36 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.20" version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dfdd070ccd8ccb78f4ad66bf1982dc37f620ef696c6b5028fe2ed83dd3d0d08" checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.20" version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793" checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "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]] [[package]]
name = "thread_local" name = "thread_local"
version = "1.0.1" version = "1.0.1"
@ -5393,6 +5412,12 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "topological-sort"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa7c7f42dea4b1b99439786f5633aeb9c14c1b53f75e282803c2ec2ad545873c"
[[package]] [[package]]
name = "tower-service" name = "tower-service"
version = "0.3.1" version = "0.3.1"
@ -5401,9 +5426,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
[[package]] [[package]]
name = "tracing" name = "tracing"
version = "0.1.28" version = "0.1.29"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84f96e095c0c82419687c20ddf5cb3eadb61f4e1405923c9dc8e53a1adacbda8" checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"pin-project-lite", "pin-project-lite",
@ -5413,9 +5438,9 @@ dependencies = [
[[package]] [[package]]
name = "tracing-attributes" name = "tracing-attributes"
version = "0.1.17" version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4f915eb6abf914599c200260efced9203504c4c37380af10cdf3b7d36970650" checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -5442,49 +5467,34 @@ dependencies = [
"tracing-core", "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]] [[package]]
name = "tracing-subscriber" name = "tracing-subscriber"
version = "0.2.16" version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ab8966ac3ca27126141f7999361cc97dd6fb4b71da04c02044fa9045d98bb96" checksum = "245da694cc7fc4729f3f418b304cb57789f1bed2a78c575407ab8a23f53cb4d3"
dependencies = [ dependencies = [
"ansi_term 0.12.1", "ansi_term 0.12.1",
"chrono",
"lazy_static", "lazy_static",
"matchers", "matchers",
"parking_lot", "parking_lot",
"regex", "regex",
"serde",
"serde_json",
"sharded-slab", "sharded-slab",
"smallvec", "smallvec",
"thread_local", "thread_local",
"tracing", "tracing",
"tracing-core", "tracing-core",
"tracing-log", "tracing-log",
"tracing-serde",
] ]
[[package]] [[package]]
name = "tracing-tree" name = "tracing-tree"
version = "0.1.9" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1712b40907f8d9bc2bc66763ab61dec914b7123d7149e59feb0d4e2a95fc4967" checksum = "3ce989c9962c7f61fe084dd4a230eec784649dfc2392467c790007c3a6e134e7"
dependencies = [ dependencies = [
"ansi_term 0.12.1", "ansi_term 0.12.1",
"atty", "atty",
"termcolor", "tracing-core",
"tracing",
"tracing-log", "tracing-log",
"tracing-subscriber", "tracing-subscriber",
] ]

View File

@ -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<char> 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) 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 wrong error message displayed when some imports are missing][91254]
* [Fix rustfmt not formatting generated files from stdin][92912] * [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 [91254]: https://github.com/rust-lang/rust/pull/91254
[92912]: https://github.com/rust-lang/rust/pull/92912 [92912]: https://github.com/rust-lang/rust/pull/92912
[clippy/8075]: https://github.com/rust-lang/rust-clippy/pull/8075 [clippy/8075]: https://github.com/rust-lang/rust-clippy/pull/8075
@ -58,7 +239,6 @@ Stabilized APIs
- [`Option::unwrap_unchecked`] - [`Option::unwrap_unchecked`]
- [`Result::unwrap_unchecked`] - [`Result::unwrap_unchecked`]
- [`Result::unwrap_err_unchecked`] - [`Result::unwrap_err_unchecked`]
- [`NonZero{unsigned}::is_power_of_two`]
- [`File::options`] - [`File::options`]
These APIs are now usable in const contexts: These APIs are now usable in const contexts:
@ -71,10 +251,6 @@ These APIs are now usable in const contexts:
- [`Duration::checked_mul`] - [`Duration::checked_mul`]
- [`Duration::saturating_mul`] - [`Duration::saturating_mul`]
- [`Duration::checked_div`] - [`Duration::checked_div`]
- [`MaybeUninit::as_ptr`]
- [`MaybeUninit::as_mut_ptr`]
- [`MaybeUninit::assume_init`]
- [`MaybeUninit::assume_init_ref`]
Cargo Cargo
----- -----
@ -115,19 +291,14 @@ and related tools.
[87467]: https://github.com/rust-lang/rust/pull/87467/ [87467]: https://github.com/rust-lang/rust/pull/87467/
[87704]: https://github.com/rust-lang/rust/pull/87704/ [87704]: https://github.com/rust-lang/rust/pull/87704/
[88041]: https://github.com/rust-lang/rust/pull/88041/ [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/ [88447]: https://github.com/rust-lang/rust/pull/88447/
[88601]: https://github.com/rust-lang/rust/pull/88601/ [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/ [89062]: https://github.com/rust-lang/rust/pull/89062/
[89174]: https://github.com/rust-lang/rust/pull/89174/ [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/ [89551]: https://github.com/rust-lang/rust/pull/89551/
[89558]: https://github.com/rust-lang/rust/pull/89558/ [89558]: https://github.com/rust-lang/rust/pull/89558/
[89580]: https://github.com/rust-lang/rust/pull/89580/ [89580]: https://github.com/rust-lang/rust/pull/89580/
[89652]: https://github.com/rust-lang/rust/pull/89652/ [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/ [90041]: https://github.com/rust-lang/rust/pull/90041/
[90058]: https://github.com/rust-lang/rust/pull/90058/ [90058]: https://github.com/rust-lang/rust/pull/90058/
[90104]: https://github.com/rust-lang/rust/pull/90104/ [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/ [90733]: https://github.com/rust-lang/rust/pull/90733/
[90833]: https://github.com/rust-lang/rust/pull/90833/ [90833]: https://github.com/rust-lang/rust/pull/90833/
[90846]: https://github.com/rust-lang/rust/pull/90846/ [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/ [91026]: https://github.com/rust-lang/rust/pull/91026/
[91207]: https://github.com/rust-lang/rust/pull/91207/ [91207]: https://github.com/rust-lang/rust/pull/91207/
[91255]: https://github.com/rust-lang/rust/pull/91255/ [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/10082]: https://github.com/rust-lang/cargo/pull/10082/
[cargo/10107]: https://github.com/rust-lang/cargo/pull/10107/ [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 [`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 [`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_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 [`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 [`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::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) 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] - [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] - [Accept curly-brace macros in expressions, like `m!{ .. }.method()` and `m!{ .. }?`.][88690]
- [Allow panicking in constant evaluation.][89508] - [Allow panicking in constant evaluation.][89508]
- [Ignore derived `Clone` and `Debug` implementations during dead code analysis.][85200]
Compiler Compiler
-------- --------
@ -254,6 +398,9 @@ Cargo
Compatibility notes 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 Internal changes
---------------- ----------------
These changes provide no direct user facing benefits, but represent significant 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] - [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/ [86191]: https://github.com/rust-lang/rust/pull/86191/
[87220]: https://github.com/rust-lang/rust/pull/87220/ [87220]: https://github.com/rust-lang/rust/pull/87220/
[87260]: https://github.com/rust-lang/rust/pull/87260/ [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/ [88321]: https://github.com/rust-lang/rust/pull/88321/
[88529]: https://github.com/rust-lang/rust/pull/88529/ [88529]: https://github.com/rust-lang/rust/pull/88529/
[88690]: https://github.com/rust-lang/rust/pull/88690/ [88690]: https://github.com/rust-lang/rust/pull/88690/
@ -421,8 +568,6 @@ and related tools.
as well as rustdoc. as well as rustdoc.
[`std::os::unix::fs::chroot`]: https://doc.rust-lang.org/stable/std/os/unix/fs/fn.chroot.html [`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 [`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 [`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 [`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#86183]: https://github.com/rust-lang/rust/pull/86183
[rust#87385]: https://github.com/rust-lang/rust/pull/87385 [rust#87385]: https://github.com/rust-lang/rust/pull/87385
[rust#88100]: https://github.com/rust-lang/rust/pull/88100 [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#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#88069]: https://github.com/rust-lang/rust/pull/88069
[rust#87472]: https://github.com/rust-lang/rust/pull/87472 [rust#87472]: https://github.com/rust-lang/rust/pull/87472
[rust#87699]: https://github.com/rust-lang/rust/pull/87699 [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#87580]: https://github.com/rust-lang/rust/pull/87580
[rust#83342]: https://github.com/rust-lang/rust/pull/83342 [rust#83342]: https://github.com/rust-lang/rust/pull/83342
[rust#83093]: https://github.com/rust-lang/rust/pull/83093 [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#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#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#81363]: https://github.com/rust-lang/rust/pull/81363
[rust#84111]: https://github.com/rust-lang/rust/pull/84111 [rust#84111]: https://github.com/rust-lang/rust/pull/84111
[rust#85769]: https://github.com/rust-lang/rust/pull/85769#issuecomment-854363720 [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#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#81825]: https://github.com/rust-lang/rust/pull/81825#issuecomment-808406918
[rust#88019]: https://github.com/rust-lang/rust/pull/88019 [rust#88019]: https://github.com/rust-lang/rust/pull/88019
[rust#87666]: https://github.com/rust-lang/rust/pull/87666 [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 [86294]: https://github.com/rust-lang/rust/pull/86294
[86858]: https://github.com/rust-lang/rust/pull/86858 [86858]: https://github.com/rust-lang/rust/pull/86858
[86761]: https://github.com/rust-lang/rust/pull/86761 [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 [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 [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 [83918]: https://github.com/rust-lang/rust/pull/83918
[79965]: https://github.com/rust-lang/rust/pull/79965 [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/9663]: https://github.com/rust-lang/cargo/pull/9663
[cargo/9675]: https://github.com/rust-lang/cargo/pull/9675 [cargo/9675]: https://github.com/rust-lang/cargo/pull/9675
[cargo/9550]: https://github.com/rust-lang/cargo/pull/9550 [cargo/9550]: https://github.com/rust-lang/cargo/pull/9550
[cargo/9680]: https://github.com/rust-lang/cargo/pull/9680 [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 [`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 [`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 [`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_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::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 [`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 [`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 [`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 [`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 [85574]: https://github.com/rust-lang/rust/issues/85574
[86831]: https://github.com/rust-lang/rust/issues/86831 [86831]: https://github.com/rust-lang/rust/issues/86831
[86063]: https://github.com/rust-lang/rust/issues/86063 [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 [79608]: https://github.com/rust-lang/rust/pull/79608
[84988]: https://github.com/rust-lang/rust/pull/84988 [84988]: https://github.com/rust-lang/rust/pull/84988
[84701]: https://github.com/rust-lang/rust/pull/84701 [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_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_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 [`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::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_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 [`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 [80053]: https://github.com/rust-lang/rust/pull/80053
[79502]: https://github.com/rust-lang/rust/pull/79502 [79502]: https://github.com/rust-lang/rust/pull/79502
[75180]: https://github.com/rust-lang/rust/pull/75180 [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 [81521]: https://github.com/rust-lang/rust/pull/81521
[80968]: https://github.com/rust-lang/rust/pull/80968 [80968]: https://github.com/rust-lang/rust/pull/80968
[80959]: https://github.com/rust-lang/rust/pull/80959 [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`]: 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`]: 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 [`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_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 [`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 [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/ [74869]: https://github.com/rust-lang/rust/pull/74869/
[73858]: https://github.com/rust-lang/rust/pull/73858/ [73858]: https://github.com/rust-lang/rust/pull/73858/
[75716]: https://github.com/rust-lang/rust/pull/75716/ [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/ [75560]: https://github.com/rust-lang/rust/pull/75560/
[75568]: https://github.com/rust-lang/rust/pull/75568/ [75568]: https://github.com/rust-lang/rust/pull/75568/
[75366]: https://github.com/rust-lang/rust/pull/75366/ [75366]: https://github.com/rust-lang/rust/pull/75366/
@ -1826,7 +1934,6 @@ Internal Only
[73583]: https://github.com/rust-lang/rust/pull/73583/ [73583]: https://github.com/rust-lang/rust/pull/73583/
[73084]: https://github.com/rust-lang/rust/pull/73084/ [73084]: https://github.com/rust-lang/rust/pull/73084/
[73197]: https://github.com/rust-lang/rust/pull/73197/ [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/8456]: https://github.com/rust-lang/cargo/pull/8456/
[cargo/8478]: https://github.com/rust-lang/cargo/pull/8478/ [cargo/8478]: https://github.com/rust-lang/cargo/pull/8478/
[cargo/8485]: https://github.com/rust-lang/cargo/pull/8485/ [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 [`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_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 [`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 [`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 [`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 [`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 - [Visibility modifiers (e.g. `pub`) are now syntactically allowed on trait items and
enum variants.][66183] These are still rejected semantically, but enum variants.][66183] These are still rejected semantically, but
can be seen and parsed by procedural macros and conditional compilation. can be seen and parsed by procedural macros and conditional compilation.
- [You can now define a Rust `extern "C"` function with `Box<T>` 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<T>` in Rust signatures for functions defined in C.
[box-memory-layout]: https://doc.rust-lang.org/std/boxed/index.html#memory-layout
Compiler Compiler
-------- --------
@ -2679,6 +2790,7 @@ Compatibility Notes
[54733]: https://github.com/rust-lang/rust/pull/54733/ [54733]: https://github.com/rust-lang/rust/pull/54733/
[61351]: https://github.com/rust-lang/rust/pull/61351/ [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/ [67255]: https://github.com/rust-lang/rust/pull/67255/
[66661]: https://github.com/rust-lang/rust/pull/66661/ [66661]: https://github.com/rust-lang/rust/pull/66661/
[66771]: https://github.com/rust-lang/rust/pull/66771/ [66771]: https://github.com/rust-lang/rust/pull/66771/
@ -2815,7 +2927,6 @@ Compatibility Notes
[63803]: https://github.com/rust-lang/rust/pull/63803/ [63803]: https://github.com/rust-lang/rust/pull/63803/
[cargo/7450]: https://github.com/rust-lang/cargo/pull/7450/ [cargo/7450]: https://github.com/rust-lang/cargo/pull/7450/
[cargo/7507]: https://github.com/rust-lang/cargo/pull/7507/ [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/ [cargo/7333]: https://github.com/rust-lang/cargo/pull/7333/
[(rfc 2008)]: https://rust-lang.github.io/rfcs/2008-non-exhaustive.html [(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 [`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/ [63786]: https://github.com/rust-lang/rust/pull/63786/
[63827]: https://github.com/rust-lang/rust/pull/63827/ [63827]: https://github.com/rust-lang/rust/pull/63827/
[63834]: https://github.com/rust-lang/rust/pull/63834/ [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/ [64010]: https://github.com/rust-lang/rust/pull/64010/
[64028]: https://github.com/rust-lang/rust/pull/64028/ [64028]: https://github.com/rust-lang/rust/pull/64028/
[64334]: https://github.com/rust-lang/rust/pull/64334/ [64334]: https://github.com/rust-lang/rust/pull/64334/
@ -3183,7 +3287,6 @@ Compatibility Notes
[`Cell<slice>::as_slice_of_cells`]: https://doc.rust-lang.org/std/cell/struct.Cell.html#method.as_slice_of_cells [`Cell<slice>::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 [`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 [`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 [`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 [`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 [`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 - [Libtest no longer creates a new thread for each test when
`--test-threads=1`. It also runs the tests in deterministic order][56243] `--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 [56243]: https://github.com/rust-lang/rust/pull/56243
[56303]: https://github.com/rust-lang/rust/pull/56303/ [56303]: https://github.com/rust-lang/rust/pull/56303/
[56351]: https://github.com/rust-lang/rust/pull/56351/ [56351]: https://github.com/rust-lang/rust/pull/56351/
@ -4082,7 +4184,6 @@ Cargo
[52813]: https://github.com/rust-lang/rust/pull/52813/ [52813]: https://github.com/rust-lang/rust/pull/52813/
[53218]: https://github.com/rust-lang/rust/pull/53218/ [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/ [54057]: https://github.com/rust-lang/rust/pull/54057/
[54240]: https://github.com/rust-lang/rust/pull/54240/ [54240]: https://github.com/rust-lang/rust/pull/54240/
[54430]: https://github.com/rust-lang/rust/pull/54430/ [54430]: https://github.com/rust-lang/rust/pull/54430/
@ -4204,7 +4305,6 @@ Misc
[53044]: https://github.com/rust-lang/rust/pull/53044/ [53044]: https://github.com/rust-lang/rust/pull/53044/
[53165]: https://github.com/rust-lang/rust/pull/53165/ [53165]: https://github.com/rust-lang/rust/pull/53165/
[53611]: https://github.com/rust-lang/rust/pull/53611/ [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/ [53236]: https://github.com/rust-lang/rust/pull/53236/
[53272]: https://github.com/rust-lang/rust/pull/53272/ [53272]: https://github.com/rust-lang/rust/pull/53272/
[53370]: https://github.com/rust-lang/rust/pull/53370/ [53370]: https://github.com/rust-lang/rust/pull/53370/
@ -4212,7 +4312,6 @@ Misc
[53774]: https://github.com/rust-lang/rust/pull/53774/ [53774]: https://github.com/rust-lang/rust/pull/53774/
[53822]: https://github.com/rust-lang/rust/pull/53822/ [53822]: https://github.com/rust-lang/rust/pull/53822/
[54057]: https://github.com/rust-lang/rust/pull/54057/ [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/ [54404]: https://github.com/rust-lang/rust/pull/54404/
[cargo/5877]: https://github.com/rust-lang/cargo/pull/5877/ [cargo/5877]: https://github.com/rust-lang/cargo/pull/5877/
[cargo/5878]: https://github.com/rust-lang/cargo/pull/5878/ [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/ [52330]: https://github.com/rust-lang/rust/pull/52330/
[52354]: https://github.com/rust-lang/rust/pull/52354/ [52354]: https://github.com/rust-lang/rust/pull/52354/
[52402]: https://github.com/rust-lang/rust/pull/52402/ [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/ [52197]: https://github.com/rust-lang/rust/pull/52197/
[51807]: https://github.com/rust-lang/rust/pull/51807/ [51807]: https://github.com/rust-lang/rust/pull/51807/
[51899]: https://github.com/rust-lang/rust/pull/51899/ [51899]: https://github.com/rust-lang/rust/pull/51899/
[51912]: https://github.com/rust-lang/rust/pull/51912/ [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/ [51619]: https://github.com/rust-lang/rust/pull/51619/
[51656]: https://github.com/rust-lang/rust/pull/51656/ [51656]: https://github.com/rust-lang/rust/pull/51656/
[51178]: https://github.com/rust-lang/rust/pull/51178/ [51178]: https://github.com/rust-lang/rust/pull/51178/
@ -4465,7 +4562,6 @@ Compatibility Notes
[50855]: https://github.com/rust-lang/rust/pull/50855/ [50855]: https://github.com/rust-lang/rust/pull/50855/
[51050]: https://github.com/rust-lang/rust/pull/51050/ [51050]: https://github.com/rust-lang/rust/pull/51050/
[51196]: https://github.com/rust-lang/rust/pull/51196/ [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/ [51241]: https://github.com/rust-lang/rust/pull/51241/
[51276]: https://github.com/rust-lang/rust/pull/51276/ [51276]: https://github.com/rust-lang/rust/pull/51276/
[51298]: https://github.com/rust-lang/rust/pull/51298/ [51298]: https://github.com/rust-lang/rust/pull/51298/
@ -4646,15 +4742,12 @@ Compatibility Notes
[49664]: https://github.com/rust-lang/rust/pull/49664/ [49664]: https://github.com/rust-lang/rust/pull/49664/
[49699]: https://github.com/rust-lang/rust/pull/49699/ [49699]: https://github.com/rust-lang/rust/pull/49699/
[49707]: https://github.com/rust-lang/rust/pull/49707/ [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/ [49896]: https://github.com/rust-lang/rust/pull/49896/
[49968]: https://github.com/rust-lang/rust/pull/49968/ [49968]: https://github.com/rust-lang/rust/pull/49968/
[50163]: https://github.com/rust-lang/rust/pull/50163 [50163]: https://github.com/rust-lang/rust/pull/50163
[50177]: https://github.com/rust-lang/rust/pull/50177/ [50177]: https://github.com/rust-lang/rust/pull/50177/
[50378]: https://github.com/rust-lang/rust/pull/50378/ [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/ [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/5335]: https://github.com/rust-lang/cargo/pull/5335/
[cargo/5359]: https://github.com/rust-lang/cargo/pull/5359/ [cargo/5359]: https://github.com/rust-lang/cargo/pull/5359/
[cargo/5360]: https://github.com/rust-lang/cargo/pull/5360/ [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 [47813]: https://github.com/rust-lang/rust/pull/47813
[48056]: https://github.com/rust-lang/rust/pull/48056 [48056]: https://github.com/rust-lang/rust/pull/48056
[48125]: https://github.com/rust-lang/rust/pull/48125 [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 [48235]: https://github.com/rust-lang/rust/pull/48235
[48274]: https://github.com/rust-lang/rust/pull/48274 [48274]: https://github.com/rust-lang/rust/pull/48274
[48281]: https://github.com/rust-lang/rust/pull/48281 [48281]: https://github.com/rust-lang/rust/pull/48281
@ -4873,10 +4965,7 @@ Compatibility Notes
[48978]: https://github.com/rust-lang/rust/pull/48978 [48978]: https://github.com/rust-lang/rust/pull/48978
[49101]: https://github.com/rust-lang/rust/pull/49101 [49101]: https://github.com/rust-lang/rust/pull/49101
[49109]: https://github.com/rust-lang/rust/pull/49109 [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 [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 [49255]: https://github.com/rust-lang/rust/pull/49255
[49299]: https://github.com/rust-lang/rust/pull/49299 [49299]: https://github.com/rust-lang/rust/pull/49299
[49305]: https://github.com/rust-lang/rust/pull/49305 [49305]: https://github.com/rust-lang/rust/pull/49305
@ -5123,7 +5212,6 @@ Compatibility Notes
[44884]: https://github.com/rust-lang/rust/pull/44884 [44884]: https://github.com/rust-lang/rust/pull/44884
[45198]: https://github.com/rust-lang/rust/pull/45198 [45198]: https://github.com/rust-lang/rust/pull/45198
[45506]: https://github.com/rust-lang/rust/pull/45506 [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 [45990]: https://github.com/rust-lang/rust/pull/45990
[46012]: https://github.com/rust-lang/rust/pull/46012 [46012]: https://github.com/rust-lang/rust/pull/46012
[46077]: https://github.com/rust-lang/rust/pull/46077 [46077]: https://github.com/rust-lang/rust/pull/46077
@ -5135,7 +5223,6 @@ Compatibility Notes
[46671]: https://github.com/rust-lang/rust/pull/46671 [46671]: https://github.com/rust-lang/rust/pull/46671
[46713]: https://github.com/rust-lang/rust/pull/46713 [46713]: https://github.com/rust-lang/rust/pull/46713
[46735]: https://github.com/rust-lang/rust/pull/46735 [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 [46760]: https://github.com/rust-lang/rust/pull/46760
[46798]: https://github.com/rust-lang/rust/pull/46798 [46798]: https://github.com/rust-lang/rust/pull/46798
[46828]: https://github.com/rust-lang/rust/pull/46828 [46828]: https://github.com/rust-lang/rust/pull/46828
@ -5306,7 +5393,6 @@ Compatibility Notes
[42526]: https://github.com/rust-lang/rust/pull/42526 [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 [43716]: https://github.com/rust-lang/rust/pull/43716
[43949]: https://github.com/rust-lang/rust/pull/43949 [43949]: https://github.com/rust-lang/rust/pull/43949
[44015]: https://github.com/rust-lang/rust/pull/44015 [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 - [Added `--no-fail-fast` flag to cargo to run all benchmarks regardless of
failure.][cargo/4248] failure.][cargo/4248]
- [Changed the convention around which file is the crate root.][cargo/4259] - [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 Compatibility Notes
------------------- -------------------
@ -5580,7 +5664,6 @@ Compatibility Notes
[cargo/4229]: https://github.com/rust-lang/cargo/pull/4229 [cargo/4229]: https://github.com/rust-lang/cargo/pull/4229
[cargo/4248]: https://github.com/rust-lang/cargo/pull/4248 [cargo/4248]: https://github.com/rust-lang/cargo/pull/4248
[cargo/4259]: https://github.com/rust-lang/cargo/pull/4259 [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 [`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::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 [`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] - [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] - [Rust now uses the official cross compiler for NetBSD][40612]
- [rustdoc now accepts `#` at the start of files][40828] - [rustdoc now accepts `#` at the start of files][40828]
- [Fixed jemalloc support for musl][41168] - [Fixed jemalloc support for musl][41168]
@ -5908,7 +5990,6 @@ Compatibility Notes
[38165]: https://github.com/rust-lang/rust/pull/38165 [38165]: https://github.com/rust-lang/rust/pull/38165
[39799]: https://github.com/rust-lang/rust/pull/39799 [39799]: https://github.com/rust-lang/rust/pull/39799
[39891]: https://github.com/rust-lang/rust/pull/39891 [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 [40043]: https://github.com/rust-lang/rust/pull/40043
[40241]: https://github.com/rust-lang/rust/pull/40241 [40241]: https://github.com/rust-lang/rust/pull/40241
[40338]: https://github.com/rust-lang/rust/pull/40338 [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/3691]: https://github.com/rust-lang/cargo/pull/3691
[cargo/3699]: https://github.com/rust-lang/cargo/pull/3699 [cargo/3699]: https://github.com/rust-lang/cargo/pull/3699
[cargo/3731]: https://github.com/rust-lang/cargo/pull/3731 [cargo/3731]: https://github.com/rust-lang/cargo/pull/3731
[mdbook]: https://crates.io/crates/mdbook
[ubook]: https://doc.rust-lang.org/unstable-book/ [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 * [Ctrl-Z returns from `Stdin.read()` when reading from the console on
Windows][38274] Windows][38274]
* [std: Fix partial writes in `LineWriter`][38062] * [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] * [Use more specific panic message for `&str` slicing errors][38066]
* [`TcpListener::set_only_v6` is deprecated][38304]. This * [`TcpListener::set_only_v6` is deprecated][38304]. This
functionality cannot be achieved in std currently. functionality cannot be achieved in std currently.
@ -6341,7 +6421,7 @@ Compatibility Notes
[38006]: https://github.com/rust-lang/rust/pull/38006 [38006]: https://github.com/rust-lang/rust/pull/38006
[38051]: https://github.com/rust-lang/rust/pull/38051 [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/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 [38066]: https://github.com/rust-lang/rust/pull/38066
[38069]: https://github.com/rust-lang/rust/pull/38069 [38069]: https://github.com/rust-lang/rust/pull/38069
[38131]: https://github.com/rust-lang/rust/pull/38131 [38131]: https://github.com/rust-lang/rust/pull/38131
@ -6349,7 +6429,6 @@ Compatibility Notes
[38274]: https://github.com/rust-lang/rust/pull/38274 [38274]: https://github.com/rust-lang/rust/pull/38274
[38304]: https://github.com/rust-lang/rust/pull/38304 [38304]: https://github.com/rust-lang/rust/pull/38304
[38313]: https://github.com/rust-lang/rust/pull/38313 [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 [38327]: https://github.com/rust-lang/rust/pull/38327
[38401]: https://github.com/rust-lang/rust/pull/38401 [38401]: https://github.com/rust-lang/rust/pull/38401
[38413]: https://github.com/rust-lang/rust/pull/38413 [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/3546]: https://github.com/rust-lang/cargo/pull/3546
[cargo/3557]: https://github.com/rust-lang/cargo/pull/3557 [cargo/3557]: https://github.com/rust-lang/cargo/pull/3557
[cargo/3604]: https://github.com/rust-lang/cargo/pull/3604 [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) Version 1.15.1 (2017-02-09)
@ -6614,7 +6692,6 @@ Compatibility Notes
[38192]: https://github.com/rust-lang/rust/pull/38192 [38192]: https://github.com/rust-lang/rust/pull/38192
[38279]: https://github.com/rust-lang/rust/pull/38279 [38279]: https://github.com/rust-lang/rust/pull/38279
[38835]: https://github.com/rust-lang/rust/pull/38835 [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 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 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 [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 [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 [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
[36595]: https://github.com/rust-lang/rust/pull/36595
[36692]: https://github.com/rust-lang/rust/pull/36692 [36692]: https://github.com/rust-lang/rust/pull/36692
[36767]: https://github.com/rust-lang/rust/pull/36767 [36767]: https://github.com/rust-lang/rust/pull/36767
[36794]: https://github.com/rust-lang/rust/pull/36794 [36794]: https://github.com/rust-lang/rust/pull/36794
@ -7031,7 +7107,6 @@ Compatibility Notes
[34623]: https://github.com/rust-lang/rust/pull/34623 [34623]: https://github.com/rust-lang/rust/pull/34623
[34923]: https://github.com/rust-lang/rust/pull/34923 [34923]: https://github.com/rust-lang/rust/pull/34923
[34942]: https://github.com/rust-lang/rust/pull/34942 [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 [35021]: https://github.com/rust-lang/rust/pull/35021
[35048]: https://github.com/rust-lang/rust/pull/35048 [35048]: https://github.com/rust-lang/rust/pull/35048
[35074]: https://github.com/rust-lang/rust/pull/35074 [35074]: https://github.com/rust-lang/rust/pull/35074
@ -7088,7 +7163,6 @@ Compatibility Notes
[36586]: https://github.com/rust-lang/rust/pull/36586 [36586]: https://github.com/rust-lang/rust/pull/36586
[36592]: https://github.com/rust-lang/rust/pull/36592 [36592]: https://github.com/rust-lang/rust/pull/36592
[36631]: https://github.com/rust-lang/rust/pull/36631 [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 [36721]: https://github.com/rust-lang/rust/pull/36721
[36727]: https://github.com/rust-lang/rust/pull/36727 [36727]: https://github.com/rust-lang/rust/pull/36727
[36730]: https://github.com/rust-lang/rust/pull/36730 [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/3205]: https://github.com/rust-lang/cargo/pull/3205
[cargo/3241]: https://github.com/rust-lang/cargo/pull/3241 [cargo/3241]: https://github.com/rust-lang/cargo/pull/3241
[cargo/3242]: https://github.com/rust-lang/cargo/pull/3242 [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 [`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 [`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 [`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]. targets can be specified together. [RFC 1361].
* [The environment variables `CARGO_TARGET_ROOT`, `RUSTC`, and * [The environment variables `CARGO_TARGET_ROOT`, `RUSTC`, and
`RUSTDOC` take precedence over the `build.target-dir`, `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 * [The child process tree is killed on Windows when Cargo is
killed][1.8ck]. killed][1.8ck].
* [The `build.target` configuration value sets the target platform, * [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.8ck]: https://github.com/rust-lang/cargo/pull/2370
[1.8ct]: https://github.com/rust-lang/cargo/pull/2335 [1.8ct]: https://github.com/rust-lang/cargo/pull/2335
[1.8cu]: https://github.com/rust-lang/rust/pull/31390 [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.8cv]: https://github.com/rust-lang/rust/pull/30998
[1.8h]: https://github.com/rust-lang/rust/pull/31460 [1.8h]: https://github.com/rust-lang/rust/pull/31460
[1.8l]: https://github.com/rust-lang/rust/pull/31668 [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 * The compiler gained many new extended error descriptions, which can
be accessed with the `--explain` flag. be accessed with the `--explain` flag.
* The `dropck` pass, which checks that destructors can't access * 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 soundness holes, and as such will cause some previously-compiling
code to no longer build. code to no longer build.
* `rustc` now uses [LLVM to write archive files where possible][ar]. * `rustc` now uses [LLVM to write archive files where possible][ar].
Eventually this will eliminate the compiler's dependency on the ar Eventually this will eliminate the compiler's dependency on the ar
utility. 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). supported FreeBSD on x86_64).
* The [`unused_mut`][lum], [`unconditional_recursion`][lur], * The [`unused_mut`][lum], [`unconditional_recursion`][lur],
[`improper_ctypes`][lic], and [`negate_unsigned`][lnu] lints are [`improper_ctypes`][lic], and [`negate_unsigned`][lnu] lints are
@ -9056,7 +9129,7 @@ Misc
[ar]: https://github.com/rust-lang/rust/pull/26926 [ar]: https://github.com/rust-lang/rust/pull/26926
[b14]: https://static.rust-lang.org/dist/rust-beta-x86_64-pc-windows-msvc.msi [b14]: https://static.rust-lang.org/dist/rust-beta-x86_64-pc-windows-msvc.msi
[dms]: https://github.com/rust-lang/rust/pull/26241 [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 [dropckrfc]: https://github.com/rust-lang/rfcs/blob/master/text/0769-sound-generic-drop.md
[ds]: https://github.com/rust-lang/rust/pull/26818 [ds]: https://github.com/rust-lang/rust/pull/26818
[dst1]: http://doc.rust-lang.org/nightly/std/mem/fn.size_of_val.html [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 [dst3]: https://github.com/rust-lang/rust/pull/27351
[e]: https://github.com/rust-lang/rust/pull/24793 [e]: https://github.com/rust-lang/rust/pull/24793
[f]: https://github.com/rust-lang/rust/pull/26588 [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 [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 [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 [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 [iegm]: http://doc.rust-lang.org/nightly/std/io/struct.Error.html#method.get_mut
@ -9337,7 +9409,7 @@ Misc
to rustc. to rustc.
* [Android executables are always position independent][pie]. * [Android executables are always position independent][pie].
* [The `drop_with_repr_extern` lint warns about mixing `repr(C)` * [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 [`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 [`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 [`BinaryHeap`]: https://doc.rust-lang.org/nightly/std/collections/struct.BinaryHeap.html
[ll]: https://github.com/rust-lang/rust/pull/26022 [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 [`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) Version 1.0.0 (2015-05-15)
======================== ========================
@ -9420,7 +9492,7 @@ Language
property: generic code cannot behave differently for different type property: generic code cannot behave differently for different type
arguments except in minor ways. arguments except in minor ways.
* The `unsafe_destructor` feature is now deprecated in favor of the * 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. code.
Libraries Libraries
@ -9428,7 +9500,7 @@ Libraries
* The `thread_local` module [has been renamed to `std::thread`][th]. * The `thread_local` module [has been renamed to `std::thread`][th].
* The methods of `IteratorExt` [have been moved to the `Iterator` * 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 * Several traits that implement Rust's conventions for type
conversions, `AsMut`, `AsRef`, `From`, and `Into` have been conversions, `AsMut`, `AsRef`, `From`, and `Into` have been
[centralized in the `std::convert` module][con]. [centralized in the `std::convert` module][con].
@ -9447,7 +9519,7 @@ Libraries
* [In method resolution, object methods are resolved before inherent * [In method resolution, object methods are resolved before inherent
methods][meth]. methods][meth].
* [`String::from_str` has been deprecated in favor of the `From` impl, * [`String::from_str` has been deprecated in favor of the `From` impl,
`String::from`][sf]. `String::from`][24517].
* [`io::Error` implements `Sync`][ios]. * [`io::Error` implements `Sync`][ios].
* [The `words` method on `&str` has been replaced with * [The `words` method on `&str` has been replaced with
`split_whitespace`][sw], to avoid answering the tricky question, 'what is `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 [con]: https://github.com/rust-lang/rust/pull/23875
[cr]: https://github.com/rust-lang/rust/pull/23419 [cr]: https://github.com/rust-lang/rust/pull/23419
[fe]: https://github.com/rust-lang/rust/pull/23879 [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 [inv]: https://github.com/rust-lang/rust/pull/23938
[ios]: https://github.com/rust-lang/rust/pull/24133 [ios]: https://github.com/rust-lang/rust/pull/24133
[lex]: https://github.com/rust-lang/rfcs/blob/master/text/0879-small-base-lexing.md [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 [meth]: https://github.com/rust-lang/rust/pull/24056
[pat]: https://github.com/rust-lang/rfcs/blob/master/text/0528-string-patterns.md [pat]: https://github.com/rust-lang/rfcs/blob/master/text/0528-string-patterns.md
[po]: https://github.com/rust-lang/rust/pull/24270 [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 [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 [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 [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 [conversion]: https://github.com/rust-lang/rfcs/pull/529
[num-traits]: https://github.com/rust-lang/rust/pull/23549 [num-traits]: https://github.com/rust-lang/rust/pull/23549
[index-value]: https://github.com/rust-lang/rust/pull/23601 [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 [ci-compare]: https://gist.github.com/brson/a30a77836fbec057cbee
[fn-inherit]: https://github.com/rust-lang/rust/pull/23282 [fn-inherit]: https://github.com/rust-lang/rust/pull/23282
[fn-blanket]: https://github.com/rust-lang/rust/pull/23895 [fn-blanket]: https://github.com/rust-lang/rust/pull/23895

View File

@ -1,25 +1,32 @@
// Configure jemalloc as the `global_allocator` when configured. This is // A note about jemalloc: rustc uses jemalloc when built for CI and
// so that we use the sized deallocation apis jemalloc provides // distribution. The obvious way to do this is with the `#[global_allocator]`
// (namely `sdallocx`). // 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 // Instead, we use a lower-level mechanism. rustc is linked with jemalloc in a
// ensure that we use a consistent allocator across the rustc <-> llvm boundary // way such that jemalloc's implementation of `malloc`, `free`, etc., override
#[cfg(feature = "jemalloc")] // the libc allocator's implementation. This means that Rust's `System`
#[global_allocator] // allocator, which calls `libc::malloc()` et al., is actually calling into
static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; // 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")] #[cfg(feature = "tikv-jemalloc-sys")]
use tikv_jemalloc_sys as jemalloc_sys; use tikv_jemalloc_sys as jemalloc_sys;
fn main() { fn main() {
// Pull in jemalloc when enabled. // See the comment at the top of this file for an explanation of this.
//
// 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).
#[cfg(feature = "tikv-jemalloc-sys")] #[cfg(feature = "tikv-jemalloc-sys")]
{ {
use std::os::raw::{c_int, c_void}; use std::os::raw::{c_int, c_void};

View File

@ -33,7 +33,6 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![no_std] #![no_std]
#![forbid(unsafe_code)] #![forbid(unsafe_code)]
#![feature(iter_zip)]
#![feature(nll)] #![feature(nll)]
#[macro_use] #[macro_use]

View File

@ -332,10 +332,7 @@ pub type GenericBounds = Vec<GenericBound>;
pub enum ParamKindOrd { pub enum ParamKindOrd {
Lifetime, Lifetime,
Type, Type,
// `unordered` is only `true` if `sess.unordered_const_ty_params()` Const,
// returns true. Specifically, if it's only `min_const_generics`, it will still require
// ordering consts after types.
Const { unordered: bool },
// `Infer` is not actually constructed directly from the AST, but is implicitly constructed // `Infer` is not actually constructed directly from the AST, but is implicitly constructed
// during HIR lowering, and `ParamKindOrd` will implicitly order inferred variables last. // during HIR lowering, and `ParamKindOrd` will implicitly order inferred variables last.
Infer, Infer,
@ -346,11 +343,7 @@ impl Ord for ParamKindOrd {
use ParamKindOrd::*; use ParamKindOrd::*;
let to_int = |v| match v { let to_int = |v| match v {
Lifetime => 0, Lifetime => 0,
Infer | Type | Const { unordered: true } => 1, Infer | Type | Const => 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,
}; };
to_int(*self).cmp(&to_int(*other)) to_int(*self).cmp(&to_int(*other))
@ -517,6 +510,10 @@ pub struct Crate {
pub attrs: Vec<Attribute>, pub attrs: Vec<Attribute>,
pub items: Vec<P<Item>>, pub items: Vec<P<Item>>,
pub span: Span, 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. /// Possible values inside of compile-time attribute lists.
@ -1979,7 +1976,7 @@ pub enum InlineAsmRegOrRegClass {
bitflags::bitflags! { bitflags::bitflags! {
#[derive(Encodable, Decodable, HashStable_Generic)] #[derive(Encodable, Decodable, HashStable_Generic)]
pub struct InlineAsmOptions: u8 { pub struct InlineAsmOptions: u16 {
const PURE = 1 << 0; const PURE = 1 << 0;
const NOMEM = 1 << 1; const NOMEM = 1 << 1;
const READONLY = 1 << 2; const READONLY = 1 << 2;
@ -1988,6 +1985,7 @@ bitflags::bitflags! {
const NOSTACK = 1 << 5; const NOSTACK = 1 << 5;
const ATT_SYNTAX = 1 << 6; const ATT_SYNTAX = 1 << 6;
const RAW = 1 << 7; const RAW = 1 << 7;
const MAY_UNWIND = 1 << 8;
} }
} }

View File

@ -1,7 +1,7 @@
use super::ptr::P; use super::ptr::P;
use super::token::Nonterminal; use super::token::Nonterminal;
use super::tokenstream::LazyTokenStream; 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::{AssocItem, Expr, ForeignItem, Item, Local, MacCallStmt};
use super::{AttrItem, AttrKind, Block, Pat, Path, Ty, Visibility}; use super::{AttrItem, AttrKind, Block, Pat, Path, Ty, Visibility};
use super::{AttrVec, Attribute, Stmt, StmtKind}; 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 // These ast nodes only support inert attributes, so they don't
// store tokens (since nothing can observe them) // store tokens (since nothing can observe them)
derive_has_attrs_no_tokens! { 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 // These AST nodes don't support attributes, but can

View File

@ -136,15 +136,15 @@ impl Attribute {
pub fn value_str(&self) -> Option<Symbol> { pub fn value_str(&self) -> Option<Symbol> {
match self.kind { 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, AttrKind::DocComment(..) => None,
} }
} }
pub fn meta_item_list(&self) -> Option<Vec<NestedMetaItem>> { pub fn meta_item_list(&self) -> Option<Vec<NestedMetaItem>> {
match self.kind { match self.kind {
AttrKind::Normal(ref item, _) => match item.meta(self.span) { AttrKind::Normal(ref item, _) => match item.meta_kind() {
Some(MetaItem { kind: MetaItemKind::List(list), .. }) => Some(list), Some(MetaItemKind::List(list)) => Some(list),
_ => None, _ => None,
}, },
AttrKind::DocComment(..) => None, AttrKind::DocComment(..) => None,
@ -228,6 +228,10 @@ impl AttrItem {
span, span,
}) })
} }
pub fn meta_kind(&self) -> Option<MetaItemKind> {
Some(MetaItemKind::from_mac_args(&self.args)?)
}
} }
impl Attribute { impl Attribute {
@ -242,7 +246,7 @@ impl Attribute {
match self.kind { match self.kind {
AttrKind::DocComment(.., data) => Some(data), AttrKind::DocComment(.., data) => Some(data),
AttrKind::Normal(ref item, _) if item.path == sym::doc => { 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, _ => None,
} }
@ -270,6 +274,13 @@ impl Attribute {
} }
} }
pub fn meta_kind(&self) -> Option<MetaItemKind> {
match self.kind {
AttrKind::Normal(ref item, _) => item.meta_kind(),
AttrKind::DocComment(..) => None,
}
}
pub fn tokens(&self) -> AttrAnnotatedTokenStream { pub fn tokens(&self) -> AttrAnnotatedTokenStream {
match self.kind { match self.kind {
AttrKind::Normal(_, ref tokens) => tokens AttrKind::Normal(_, ref tokens) => tokens
@ -436,6 +447,16 @@ impl MetaItem {
} }
impl MetaItemKind { impl MetaItemKind {
pub fn value_str(&self) -> Option<Symbol> {
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 { pub fn mac_args(&self, span: Span) -> MacArgs {
match self { match self {
MetaItemKind::Word => MacArgs::Empty, MetaItemKind::Word => MacArgs::Empty,

View File

@ -11,7 +11,6 @@
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(crate_visibility_modifier)] #![feature(crate_visibility_modifier)]
#![feature(if_let_guard)] #![feature(if_let_guard)]
#![feature(iter_zip)]
#![feature(label_break_value)] #![feature(label_break_value)]
#![feature(nll)] #![feature(nll)]
#![feature(min_specialization)] #![feature(min_specialization)]

View File

@ -1,5 +1,5 @@
//! A `MutVisitor` represents an AST modification; it accepts an AST piece and //! 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. //! that walks over an AST and modifies it.
//! //!
//! Note: using a `MutVisitor` (other than the `MacroExpander` `MutVisitor`) on //! 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::map_in_place::MapInPlace;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_data_structures::thin_vec::ThinVec;
use rustc_span::source_map::Spanned; use rustc_span::source_map::Spanned;
use rustc_span::symbol::Ident; use rustc_span::symbol::Ident;
use rustc_span::Span; use rustc_span::Span;
use smallvec::{smallvec, Array, SmallVec}; use smallvec::{smallvec, Array, SmallVec};
use std::ops::DerefMut; use std::ops::DerefMut;
use std::{panic, process, ptr}; use std::{panic, ptr};
pub trait ExpectOne<A: Array> { pub trait ExpectOne<A: Array> {
fn expect_one(self, err: &'static str) -> A::Item; 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 /// 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_` /// 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`. // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
pub fn visit_clobber<T, F>(t: &mut T, f: F) pub fn visit_clobber<T: DummyAstNode>(t: &mut T, f: impl FnOnce(T) -> T) {
where
F: FnOnce(T) -> T,
{
unsafe { unsafe {
// Safe because `t` is used in a read-only fashion by `read()` before // Safe because `t` is used in a read-only fashion by `read()` before
// being overwritten by `write()`. // being overwritten by `write()`.
let old_t = ptr::read(t); let old_t = ptr::read(t);
let new_t = panic::catch_unwind(panic::AssertUnwindSafe(|| f(old_t))) let new_t =
.unwrap_or_else(|_| process::abort()); 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); ptr::write(t, new_t);
} }
} }
@ -1105,36 +1108,12 @@ pub fn noop_visit_fn_header<T: MutVisitor>(header: &mut FnHeader, vis: &mut T) {
visit_unsafety(unsafety, vis); 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<T: MutVisitor>(krate: &mut Crate, vis: &mut T) { pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) {
visit_clobber(krate, |Crate { attrs, items, span }| { let Crate { attrs, items, span, id, is_placeholder: _ } = krate;
let item_vis = vis.visit_id(id);
Visibility { kind: VisibilityKind::Public, span: span.shrink_to_lo(), tokens: None }; visit_attrs(attrs, vis);
let item = P(Item { items.flat_map_in_place(|item| vis.flat_map_item(item));
ident: Ident::empty(), vis.visit_span(span);
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");
}
});
} }
// Mutates one item into possibly many items. // Mutates one item into possibly many items.
@ -1475,3 +1454,109 @@ pub fn noop_visit_vis<T: MutVisitor>(visibility: &mut Visibility, vis: &mut T) {
} }
vis.visit_span(&mut visibility.span); 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<T> DummyAstNode for Option<T> {
fn dummy() -> Self {
Default::default()
}
}
impl<T: DummyAstNode + 'static> DummyAstNode for P<T> {
fn dummy() -> Self {
P(DummyAstNode::dummy())
}
}
impl<T> DummyAstNode for ThinVec<T> {
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(),
}
}
}

View File

@ -35,12 +35,12 @@ impl LitKind {
LitKind::Bool(symbol == kw::True) LitKind::Bool(symbol == kw::True)
} }
token::Byte => { token::Byte => {
return unescape_byte(&symbol.as_str()) return unescape_byte(symbol.as_str())
.map(LitKind::Byte) .map(LitKind::Byte)
.map_err(|_| LitError::LexerError); .map_err(|_| LitError::LexerError);
} }
token::Char => { token::Char => {
return unescape_char(&symbol.as_str()) return unescape_char(symbol.as_str())
.map(LitKind::Char) .map(LitKind::Char)
.map_err(|_| LitError::LexerError); .map_err(|_| LitError::LexerError);
} }
@ -57,7 +57,7 @@ impl LitKind {
// string in the token. // string in the token.
let s = symbol.as_str(); let s = symbol.as_str();
let symbol = let symbol =
if s.contains(&['\\', '\r'][..]) { if s.contains(&['\\', '\r']) {
let mut buf = String::with_capacity(s.len()); let mut buf = String::with_capacity(s.len());
let mut error = Ok(()); let mut error = Ok(());
unescape_literal(&s, Mode::Str, &mut |_, unescaped_char| { unescape_literal(&s, Mode::Str, &mut |_, unescaped_char| {

View File

@ -211,6 +211,9 @@ pub trait Visitor<'ast>: Sized {
fn visit_pat_field(&mut self, fp: &'ast PatField) { fn visit_pat_field(&mut self, fp: &'ast PatField) {
walk_pat_field(self, fp) walk_pat_field(self, fp)
} }
fn visit_crate(&mut self, krate: &'ast Crate) {
walk_crate(self, krate)
}
} }
#[macro_export] #[macro_export]

View File

@ -49,11 +49,27 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
.struct_span_err(sp, "the `att_syntax` option is only supported on x86") .struct_span_err(sp, "the `att_syntax` option is only supported on x86")
.emit(); .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(); let mut clobber_abis = FxHashMap::default();
if let Some(asm_arch) = asm_arch { if let Some(asm_arch) = asm_arch {
for (abi_name, abi_span) in &asm.clobber_abis { 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) => { Ok(abi) => {
// If the abi was already in the list, emit an error // If the abi was already in the list, emit an error
match clobber_abis.get(&abi) { match clobber_abis.get(&abi) {

View File

@ -2,7 +2,6 @@ use crate::{ImplTraitContext, ImplTraitPosition, LoweringContext};
use rustc_ast::{AttrVec, Block, BlockCheckMode, Expr, Local, LocalKind, Stmt, StmtKind}; use rustc_ast::{AttrVec, Block, BlockCheckMode, Expr, Local, LocalKind, Stmt, StmtKind};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_session::parse::feature_err; use rustc_session::parse::feature_err;
use rustc_span::symbol::Ident;
use rustc_span::{sym, DesugaringKind}; use rustc_span::{sym, DesugaringKind};
use smallvec::SmallVec; use smallvec::SmallVec;
@ -39,8 +38,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let hir_id = self.lower_node_id(s.id); let hir_id = self.lower_node_id(s.id);
match &local.kind { match &local.kind {
LocalKind::InitElse(init, els) => { LocalKind::InitElse(init, els) => {
let (s, e) = self.lower_let_else(hir_id, local, init, els, tail); let e = self.lower_let_else(hir_id, local, init, els, tail);
stmts.push(s);
expr = Some(e); expr = Some(e);
// remaining statements are in let-else expression // remaining statements are in let-else expression
break; break;
@ -125,36 +123,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
init: &Expr, init: &Expr,
els: &Block, els: &Block,
tail: &[Stmt], tail: &[Stmt],
) -> (hir::Stmt<'hir>, &'hir hir::Expr<'hir>) { ) -> &'hir hir::Expr<'hir> {
let ty = local let ty = local
.ty .ty
.as_ref() .as_ref()
.map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Binding))); .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Binding)));
let span = self.lower_span(local.span); let span = self.lower_span(local.span);
let span = self.mark_span_with_reason(DesugaringKind::LetElse, span, None); let span = self.mark_span_with_reason(DesugaringKind::LetElse, span, None);
let init = Some(self.lower_expr(init)); let init = 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 local_hir_id = self.lower_node_id(local.id); let local_hir_id = self.lower_node_id(local.id);
self.lower_attrs(local_hir_id, &local.attrs); self.lower_attrs(local_hir_id, &local.attrs);
// first statement which basically exists for the type annotation let let_expr = {
let stmt = { let lex = self.arena.alloc(hir::Let {
let local = self.arena.alloc(hir::Local {
hir_id: local_hir_id, hir_id: local_hir_id,
pat: self.lower_pat(&local.pat),
ty, ty,
pat,
init, init,
span, span,
source: hir::LocalSource::Normal,
}); });
let kind = hir::StmtKind::Local(local); self.arena.alloc(self.expr(span, hir::ExprKind::Let(lex), AttrVec::new()))
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()))
}; };
let then_expr = { let then_expr = {
let (stmts, expr) = self.lower_stmts(tail); let (stmts, expr) = self.lower_stmts(tail);
@ -165,9 +152,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let block = self.lower_block(els, false); let block = self.lower_block(els, false);
self.arena.alloc(self.expr_block(block, AttrVec::new())) 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); self.alias_attrs(else_expr.hir_id, local_hir_id);
let if_expr = self.arena.alloc(hir::Expr { let if_expr = self.arena.alloc(hir::Expr {
hir_id: self.next_id(), hir_id: stmt_hir_id,
span, span,
kind: hir::ExprKind::If(let_expr, then_expr, Some(else_expr)), kind: hir::ExprKind::If(let_expr, then_expr, Some(else_expr)),
}); });
@ -180,6 +168,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
) )
.emit(); .emit();
} }
(stmt, if_expr) if_expr
} }
} }

View File

@ -9,7 +9,6 @@ use rustc_errors::struct_span_err;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::Res; use rustc_hir::def::Res;
use rustc_hir::definitions::DefPathData; use rustc_hir::definitions::DefPathData;
use rustc_session::parse::feature_err;
use rustc_span::hygiene::ExpnId; use rustc_span::hygiene::ExpnId;
use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned}; use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::symbol::{sym, Ident, Symbol};
@ -35,7 +34,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
} }
ExprKind::Repeat(ref expr, ref count) => { ExprKind::Repeat(ref expr, ref count) => {
let expr = self.lower_expr(expr); 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) hir::ExprKind::Repeat(expr, count)
} }
ExprKind::Tup(ref elts) => hir::ExprKind::Tup(self.lower_exprs(elts)), 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); let ohs = self.lower_expr(ohs);
hir::ExprKind::AddrOf(k, m, ohs) hir::ExprKind::AddrOf(k, m, ohs)
} }
ExprKind::Let(ref pat, ref scrutinee, span) => hir::ExprKind::Let( ExprKind::Let(ref pat, ref scrutinee, span) => {
self.lower_pat(pat), hir::ExprKind::Let(self.arena.alloc(hir::Let {
self.lower_expr(scrutinee), hir_id: self.next_id(),
self.lower_span(span), 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) => { ExprKind::If(ref cond, ref then, ref else_opt) => {
self.lower_expr_if(cond, then, else_opt.as_deref()) self.lower_expr_if(cond, then, else_opt.as_deref())
} }
@ -130,7 +133,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::AsyncGeneratorKind::Block, hir::AsyncGeneratorKind::Block,
|this| this.with_new_scopes(|this| this.lower_block_expr(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( ExprKind::Closure(
capture_clause, capture_clause,
asyncness, asyncness,
@ -479,8 +490,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
expr: &'hir hir::Expr<'hir>, expr: &'hir hir::Expr<'hir>,
overall_span: Span, overall_span: Span,
) -> &'hir hir::Expr<'hir> { ) -> &'hir hir::Expr<'hir> {
let constructor = let constructor = self.arena.alloc(self.expr_lang_item_path(
self.arena.alloc(self.expr_lang_item_path(method_span, lang_item, ThinVec::new())); method_span,
lang_item,
ThinVec::new(),
None,
));
self.expr_call(overall_span, constructor, std::slice::from_ref(expr)) self.expr_call(overall_span, constructor, std::slice::from_ref(expr))
} }
@ -584,8 +599,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
// `future::from_generator`: // `future::from_generator`:
let unstable_span = let unstable_span =
self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone()); self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
let gen_future = let gen_future = self.expr_lang_item_path(
self.expr_lang_item_path(unstable_span, hir::LangItem::FromGenerator, ThinVec::new()); unstable_span,
hir::LangItem::FromGenerator,
ThinVec::new(),
None,
);
// `future::from_generator(generator)`: // `future::from_generator(generator)`:
hir::ExprKind::Call(self.arena.alloc(gen_future), arena_vec![self; generator]) hir::ExprKind::Call(self.arena.alloc(gen_future), arena_vec![self; generator])
@ -593,7 +612,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
/// Desugar `<expr>.await` into: /// Desugar `<expr>.await` into:
/// ```rust /// ```rust
/// match <expr> { /// match ::std::future::IntoFuture::into_future(<expr>) {
/// mut pinned => loop { /// mut pinned => loop {
/// match unsafe { ::std::future::Future::poll( /// match unsafe { ::std::future::Future::poll(
/// <::std::pin::Pin>::new_unchecked(&mut pinned), /// <::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> { 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 { match self.generator_kind {
Some(hir::GeneratorKind::Async(_)) => {} Some(hir::GeneratorKind::Async(_)) => {}
Some(hir::GeneratorKind::Gen) | None => { Some(hir::GeneratorKind::Gen) | None => {
@ -623,13 +643,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
err.emit(); 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( let gen_future_span = self.mark_span_with_reason(
DesugaringKind::Await, DesugaringKind::Await,
await_span, await_span,
self.allow_gen_future.clone(), 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_ident = Ident::with_dummy_span(sym::pinned);
let (pinned_pat, pinned_pat_hid) = let (pinned_pat, pinned_pat_hid) =
@ -656,16 +677,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
span, span,
hir::LangItem::PinNewUnchecked, hir::LangItem::PinNewUnchecked,
arena_vec![self; ref_mut_pinned], arena_vec![self; ref_mut_pinned],
Some(expr_hir_id),
); );
let get_context = self.expr_call_lang_item_fn_mut( let get_context = self.expr_call_lang_item_fn_mut(
gen_future_span, gen_future_span,
hir::LangItem::GetContext, hir::LangItem::GetContext,
arena_vec![self; task_context], arena_vec![self; task_context],
Some(expr_hir_id),
); );
let call = self.expr_call_lang_item_fn( let call = self.expr_call_lang_item_fn(
span, span,
hir::LangItem::FuturePoll, hir::LangItem::FuturePoll,
arena_vec![self; new_unchecked, get_context], arena_vec![self; new_unchecked, get_context],
Some(expr_hir_id),
); );
self.arena.alloc(self.expr_unsafe(call)) 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_pat, x_pat_hid) = self.pat_ident(span, x_ident);
let x_expr = self.expr_ident(span, x_ident, x_pat_hid); let x_expr = self.expr_ident(span, x_ident, x_pat_hid);
let ready_field = self.single_pat_field(span, x_pat); 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 break_x = self.with_loop_scope(loop_node_id, move |this| {
let expr_break = let expr_break =
hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr)); 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) self.arm(ready_pat, break_x)
}; };
// `::std::task::Poll::Pending => {}` // `::std::task::Poll::Pending => {}`
let pending_arm = { 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); let empty_block = self.expr_block_empty(span);
self.arm(pending_pat, empty_block) self.arm(pending_pat, empty_block)
}; };
@ -709,7 +743,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let unit = self.expr_unit(span); let unit = self.expr_unit(span);
let yield_expr = self.expr( let yield_expr = self.expr(
span, 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(), ThinVec::new(),
); );
let yield_expr = self.arena.alloc(yield_expr); let yield_expr = self.arena.alloc(yield_expr);
@ -746,10 +780,27 @@ impl<'hir> LoweringContext<'_, 'hir> {
// mut pinned => loop { ... } // mut pinned => loop { ... }
let pinned_arm = self.arm(pinned_pat, loop_expr); let pinned_arm = self.arm(pinned_pat, loop_expr);
// match <expr> { // `match ::std::future::IntoFuture::into_future(<expr>) { ... }`
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 <into_future_expr> {
// mut pinned => loop { .. } // 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( fn lower_expr_closure(
@ -914,24 +965,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_span(eq_sign_span), 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![]; 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> { fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind<'hir> {
let e1 = self.lower_expr_mut(e1); let e1 = self.lower_expr_mut(e1);
let e2 = self.lower_expr_mut(e2); 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 = let fn_expr =
self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new())); self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new()));
hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2]) hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2])
@ -1178,7 +1212,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
); );
hir::ExprKind::Struct( 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, fields,
None, None,
) )
@ -1373,6 +1407,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
head_span, head_span,
hir::LangItem::IteratorNext, hir::LangItem::IteratorNext,
arena_vec![self; ref_mut_iter], arena_vec![self; ref_mut_iter],
None,
); );
let arms = arena_vec![self; none_arm, some_arm]; let arms = arena_vec![self; none_arm, some_arm];
@ -1401,6 +1436,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
head_span, head_span,
hir::LangItem::IntoIterIntoIter, hir::LangItem::IntoIterIntoIter,
arena_vec![self; head], arena_vec![self; head],
None,
) )
}; };
@ -1456,6 +1492,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
unstable_span, unstable_span,
hir::LangItem::TryTraitBranch, hir::LangItem::TryTraitBranch,
arena_vec![self; sub_expr], arena_vec![self; sub_expr],
None,
) )
}; };
@ -1612,8 +1649,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
span: Span, span: Span,
lang_item: hir::LangItem, lang_item: hir::LangItem,
args: &'hir [hir::Expr<'hir>], args: &'hir [hir::Expr<'hir>],
hir_id: Option<hir::HirId>,
) -> hir::Expr<'hir> { ) -> 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) self.expr_call_mut(span, path, args)
} }
@ -1622,8 +1661,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
span: Span, span: Span,
lang_item: hir::LangItem, lang_item: hir::LangItem,
args: &'hir [hir::Expr<'hir>], args: &'hir [hir::Expr<'hir>],
hir_id: Option<hir::HirId>,
) -> &'hir hir::Expr<'hir> { ) -> &'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( fn expr_lang_item_path(
@ -1631,10 +1671,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
span: Span, span: Span,
lang_item: hir::LangItem, lang_item: hir::LangItem,
attrs: AttrVec, attrs: AttrVec,
hir_id: Option<hir::HirId>,
) -> hir::Expr<'hir> { ) -> hir::Expr<'hir> {
self.expr( self.expr(
span, 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, attrs,
) )
} }

View File

@ -247,12 +247,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
AnonymousLifetimeMode::PassThrough, AnonymousLifetimeMode::PassThrough,
|this, idty| { |this, idty| {
let ret_id = asyncness.opt_return_id(); let ret_id = asyncness.opt_return_id();
this.lower_fn_decl( this.lower_fn_decl(&decl, Some((fn_def_id, idty)), true, ret_id)
&decl,
Some((fn_def_id.to_def_id(), idty)),
true,
ret_id,
)
}, },
); );
let sig = hir::FnSig { let sig = hir::FnSig {
@ -1264,7 +1259,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|this, idty| { |this, idty| {
this.lower_fn_decl( this.lower_fn_decl(
&sig.decl, &sig.decl,
Some((fn_def_id.to_def_id(), idty)), Some((fn_def_id, idty)),
impl_trait_return_allow, impl_trait_return_allow,
is_async, is_async,
) )
@ -1283,7 +1278,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
} }
pub(super) fn lower_abi(&mut self, abi: StrLit) -> abi::Abi { 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); self.error_on_invalid_abi(abi);
abi::Abi::Rust abi::Abi::Rust
}) })

View File

@ -32,7 +32,6 @@
#![feature(crate_visibility_modifier)] #![feature(crate_visibility_modifier)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(iter_zip)]
#![feature(never_type)] #![feature(never_type)]
#![recursion_limit = "256"] #![recursion_limit = "256"]
@ -47,20 +46,19 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::sorted_map::SortedMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::Lrc; 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 as hir;
use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res};
use rustc_hir::def_id::{DefId, DefPathHash, LocalDefId, CRATE_DEF_ID}; use rustc_hir::def_id::{DefId, DefPathHash, LocalDefId, CRATE_DEF_ID};
use rustc_hir::definitions::{DefKey, DefPathData, Definitions}; use rustc_hir::definitions::{DefKey, DefPathData, Definitions};
use rustc_hir::intravisit; 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_index::vec::{Idx, IndexVec};
use rustc_query_system::ich::StableHashingContext; use rustc_query_system::ich::StableHashingContext;
use rustc_session::lint::builtin::BARE_TRAIT_OBJECTS; use rustc_session::lint::LintBuffer;
use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; use rustc_session::parse::feature_err;
use rustc_session::utils::{FlattenNonterminals, NtToTokenstream}; use rustc_session::utils::{FlattenNonterminals, NtToTokenstream};
use rustc_session::Session; use rustc_session::Session;
use rustc_span::edition::Edition;
use rustc_span::hygiene::ExpnId; use rustc_span::hygiene::ExpnId;
use rustc_span::source_map::{respan, DesugaringKind}; use rustc_span::source_map::{respan, DesugaringKind};
use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::symbol::{kw, sym, Ident, Symbol};
@ -70,10 +68,9 @@ use smallvec::SmallVec;
use tracing::{debug, trace}; use tracing::{debug, trace};
macro_rules! arena_vec { macro_rules! arena_vec {
($this:expr; $($x:expr),*) => ({ ($this:expr; $($x:expr),*) => (
let a = [$($x),*]; $this.arena.alloc_from_iter([$($x),*])
$this.arena.alloc_from_iter(std::array::IntoIter::new(a)) );
});
} }
mod asm; mod asm;
@ -162,6 +159,7 @@ struct LoweringContext<'a, 'hir: 'a> {
allow_try_trait: Option<Lrc<[Symbol]>>, allow_try_trait: Option<Lrc<[Symbol]>>,
allow_gen_future: Option<Lrc<[Symbol]>>, allow_gen_future: Option<Lrc<[Symbol]>>,
allow_into_future: Option<Lrc<[Symbol]>>,
} }
pub trait ResolverAstLowering { pub trait ResolverAstLowering {
@ -228,7 +226,7 @@ enum ImplTraitContext<'b, 'a> {
ReturnPositionOpaqueTy { ReturnPositionOpaqueTy {
/// `DefId` for the parent function, used to look up necessary /// `DefId` for the parent function, used to look up necessary
/// information later. /// information later.
fn_def_id: DefId, fn_def_id: LocalDefId,
/// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn, /// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn,
origin: hir::OpaqueTyOrigin, origin: hir::OpaqueTyOrigin,
}, },
@ -320,6 +318,7 @@ pub fn lower_crate<'a, 'hir>(
in_scope_lifetimes: Vec::new(), in_scope_lifetimes: Vec::new(),
allow_try_trait: Some([sym::try_trait_v2][..].into()), allow_try_trait: Some([sym::try_trait_v2][..].into()),
allow_gen_future: Some([sym::gen_future][..].into()), allow_gen_future: Some([sym::gen_future][..].into()),
allow_into_future: Some([sym::into_future][..].into()),
} }
.lower_crate(krate) .lower_crate(krate)
} }
@ -645,31 +644,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
/// parameter while `f` is running (and restored afterwards). /// parameter while `f` is running (and restored afterwards).
fn collect_in_band_defs<T>( fn collect_in_band_defs<T>(
&mut self, &mut self,
parent_def_id: LocalDefId, f: impl FnOnce(&mut Self) -> T,
anonymous_lifetime_mode: AnonymousLifetimeMode, ) -> (Vec<(Span, ParamName)>, T) {
f: impl FnOnce(&mut Self) -> (Vec<hir::GenericParam<'hir>>, T), let was_collecting = std::mem::replace(&mut self.is_collecting_in_band_lifetimes, true);
) -> (Vec<hir::GenericParam<'hir>>, T) { let len = self.lifetimes_to_define.len();
assert!(!self.is_collecting_in_band_lifetimes);
assert!(self.lifetimes_to_define.is_empty());
let old_anonymous_lifetime_mode = self.anonymous_lifetime_mode;
self.anonymous_lifetime_mode = anonymous_lifetime_mode; let res = f(self);
self.is_collecting_in_band_lifetimes = true;
let (in_band_ty_params, res) = f(self); let lifetimes_to_define = self.lifetimes_to_define.split_off(len);
self.is_collecting_in_band_lifetimes = was_collecting;
self.is_collecting_in_band_lifetimes = false; (lifetimes_to_define, res)
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)
} }
/// Converts a lifetime into a new generic parameter. /// Converts a lifetime into a new generic parameter.
@ -784,27 +768,39 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
anonymous_lifetime_mode: AnonymousLifetimeMode, anonymous_lifetime_mode: AnonymousLifetimeMode,
f: impl FnOnce(&mut Self, &mut Vec<hir::GenericParam<'hir>>) -> T, f: impl FnOnce(&mut Self, &mut Vec<hir::GenericParam<'hir>>) -> T,
) -> (hir::Generics<'hir>, T) { ) -> (hir::Generics<'hir>, T) {
let (in_band_defs, (mut lowered_generics, res)) = let (lifetimes_to_define, (mut lowered_generics, impl_trait_defs, res)) = self
self.with_in_scope_lifetime_defs(&generics.params, |this| { .collect_in_band_defs(|this| {
this.collect_in_band_defs(parent_def_id, anonymous_lifetime_mode, |this| { this.with_anonymous_lifetime_mode(anonymous_lifetime_mode, |this| {
let mut params = Vec::new(); this.with_in_scope_lifetime_defs(&generics.params, |this| {
// Note: it is necessary to lower generics *before* calling `f`. let mut impl_trait_defs = Vec::new();
// When lowering `async fn`, there's a final step when lowering // Note: it is necessary to lower generics *before* calling `f`.
// the return type that assumes that all in-scope lifetimes have // When lowering `async fn`, there's a final step when lowering
// already been added to either `in_scope_lifetimes` or // the return type that assumes that all in-scope lifetimes have
// `lifetimes_to_define`. If we swapped the order of these two, // already been added to either `in_scope_lifetimes` or
// in-band-lifetimes introduced by generics or where-clauses // `lifetimes_to_define`. If we swapped the order of these two,
// wouldn't have been added yet. // in-band-lifetimes introduced by generics or where-clauses
let generics = this.lower_generics_mut( // wouldn't have been added yet.
generics, let generics = this.lower_generics_mut(
ImplTraitContext::Universal(&mut params, this.current_hir_id_owner), generics,
); ImplTraitContext::Universal(
let res = f(this, &mut params); &mut impl_trait_defs,
(params, (generics, res)) 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); let lowered_generics = lowered_generics.into_generics(self.arena);
(lowered_generics, res) (lowered_generics, res)
@ -1116,7 +1112,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
return GenericArg::Infer(hir::InferArg { return GenericArg::Infer(hir::InferArg {
hir_id: self.lower_node_id(ty.id), hir_id: self.lower_node_id(ty.id),
span: self.lower_span(ty.span), span: self.lower_span(ty.span),
kind: InferKind::Type,
}); });
} }
// We parse const arguments as path types as we cannot distinguish them during // 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> { ) -> hir::Ty<'hir> {
let id = self.lower_node_id(t.id); let id = self.lower_node_id(t.id);
let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx); let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx);
let ty = self.ty_path(id, t.span, qpath); 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
} }
fn ty(&mut self, span: Span, kind: hir::TyKind<'hir>) -> hir::Ty<'hir> { 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) => { 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::Typeof(ref expr) => hir::TyKind::Typeof(self.lower_anon_const(expr)),
TyKind::TraitObject(ref bounds, kind) => { 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)); lifetime_bound.unwrap_or_else(|| this.elided_dyn_bound(t.span));
(bounds, lifetime_bound) (bounds, lifetime_bound)
}); });
if kind != TraitObjectSyntax::Dyn {
self.maybe_lint_bare_trait(t.span, t.id, false);
}
hir::TyKind::TraitObject(bounds, lifetime_bound, kind) hir::TyKind::TraitObject(bounds, lifetime_bound, kind)
} }
TyKind::ImplTrait(def_node_id, ref bounds) => { TyKind::ImplTrait(def_node_id, ref bounds) => {
@ -1379,7 +1367,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_opaque_impl_trait( fn lower_opaque_impl_trait(
&mut self, &mut self,
span: Span, span: Span,
fn_def_id: Option<DefId>, fn_def_id: Option<LocalDefId>,
origin: hir::OpaqueTyOrigin, origin: hir::OpaqueTyOrigin,
opaque_ty_node_id: NodeId, opaque_ty_node_id: NodeId,
capturable_lifetimes: Option<&FxHashSet<hir::LifetimeName>>, capturable_lifetimes: Option<&FxHashSet<hir::LifetimeName>>,
@ -1451,7 +1439,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
span: lctx.lower_span(span), span: lctx.lower_span(span),
}, },
bounds: hir_bounds, bounds: hir_bounds,
impl_trait_fn: fn_def_id,
origin, origin,
}; };
@ -1521,7 +1508,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_fn_decl( fn lower_fn_decl(
&mut self, &mut self,
decl: &FnDecl, decl: &FnDecl,
mut in_band_ty_params: Option<(DefId, &mut Vec<hir::GenericParam<'hir>>)>, mut in_band_ty_params: Option<(LocalDefId, &mut Vec<hir::GenericParam<'hir>>)>,
impl_trait_return_allow: bool, impl_trait_return_allow: bool,
make_ret_async: Option<NodeId>, make_ret_async: Option<NodeId>,
) -> &'hir hir::FnDecl<'hir> { ) -> &'hir hir::FnDecl<'hir> {
@ -1579,7 +1566,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
Some((def_id, _)) if impl_trait_return_allow => { Some((def_id, _)) if impl_trait_return_allow => {
ImplTraitContext::ReturnPositionOpaqueTy { ImplTraitContext::ReturnPositionOpaqueTy {
fn_def_id: def_id, fn_def_id: def_id,
origin: hir::OpaqueTyOrigin::FnReturn, origin: hir::OpaqueTyOrigin::FnReturn(def_id),
} }
} }
_ => ImplTraitContext::disallowed(), _ => ImplTraitContext::disallowed(),
@ -1634,7 +1621,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_async_fn_ret_ty( fn lower_async_fn_ret_ty(
&mut self, &mut self,
output: &FnRetTy, output: &FnRetTy,
fn_def_id: DefId, fn_def_id: LocalDefId,
opaque_ty_node_id: NodeId, opaque_ty_node_id: NodeId,
) -> hir::FnRetTy<'hir> { ) -> hir::FnRetTy<'hir> {
debug!( debug!(
@ -1688,18 +1675,29 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// this is because the elided lifetimes from the return type // this is because the elided lifetimes from the return type
// should be figured out using the ordinary elision rules, and // should be figured out using the ordinary elision rules, and
// this desugaring achieves that. // 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| { self.with_hir_id_owner(opaque_ty_node_id, |this| {
// We have to be careful to get elision right here. The // We have to be careful to get elision right here. The
// idea is that we create a lifetime parameter for each // 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 // Then, we will create `fn foo(..) -> Foo<'_, '_>`, and
// hence the elision takes place at the fn site. // hence the elision takes place at the fn site.
let future_bound = this let (lifetimes_to_define, future_bound) =
.with_anonymous_lifetime_mode(AnonymousLifetimeMode::CreateParameter, |this| { this.with_anonymous_lifetime_mode(AnonymousLifetimeMode::CreateParameter, |this| {
this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span) 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: future_bound={:#?}", future_bound);
debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", lifetimes_to_define);
// Calculate all the lifetimes that should be captured lifetime_params.extend(
// by the opaque type. This should include all in-scope // Output lifetime like `'_`:
// lifetime parameters, including those defined in-band. lifetimes_to_define
// .into_iter()
// Note: this must be done after lowering the output type, .map(|(span, name)| (span, name, hir::LifetimeName::Implicit(false))),
// 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);
debug!("lower_async_fn_ret_ty: lifetime_params={:#?}", lifetime_params); debug!("lower_async_fn_ret_ty: lifetime_params={:#?}", lifetime_params);
let generic_params = let generic_params =
this.arena.alloc_from_iter(lifetime_params.iter().map(|(span, hir_name)| { 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.lifetime_to_generic_param(span, hir_name, opaque_ty_def_id)
})); }));
let opaque_ty_item = hir::OpaqueTy { let opaque_ty_item = hir::OpaqueTy {
@ -1746,8 +1736,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
span: this.lower_span(span), span: this.lower_span(span),
}, },
bounds: arena_vec![this; future_bound], bounds: arena_vec![this; future_bound],
impl_trait_fn: Some(fn_def_id), origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
origin: hir::OpaqueTyOrigin::AsyncFn,
}; };
trace!("exist ty from async fn def id: {:#?}", opaque_ty_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 // For the "output" lifetime parameters, we just want to
// generate `'_`. // generate `'_`.
let mut generic_args = Vec::with_capacity(lifetime_params.len()); let generic_args =
generic_args.extend(lifetime_params[..input_lifetimes_count].iter().map( self.arena.alloc_from_iter(lifetime_params.into_iter().map(|(span, _, name)| {
|&(span, hir_name)| {
// Input lifetime like `'a` or `'1`:
GenericArg::Lifetime(hir::Lifetime { GenericArg::Lifetime(hir::Lifetime {
hir_id: self.next_id(), hir_id: self.next_id(),
span: self.lower_span(span), 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 // Create the `Foo<...>` reference itself. Note that the `type
// Foo = impl Trait` is, internally, created as a child of the // 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( fn lower_async_fn_output_type_to_future_bound(
&mut self, &mut self,
output: &FnRetTy, output: &FnRetTy,
fn_def_id: DefId, fn_def_id: LocalDefId,
span: Span, span: Span,
) -> hir::GenericBound<'hir> { ) -> hir::GenericBound<'hir> {
// Compute the `T` in `Future<Output = T>` from the return type. // Compute the `T` in `Future<Output = T>` from the return type.
@ -1815,7 +1793,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// generates. // generates.
let context = ImplTraitContext::ReturnPositionOpaqueTy { let context = ImplTraitContext::ReturnPositionOpaqueTy {
fn_def_id, fn_def_id,
origin: hir::OpaqueTyOrigin::FnReturn, origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
}; };
self.lower_ty(ty, context) self.lower_ty(ty, context)
} }
@ -1927,7 +1905,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}); });
let param_name = match lt.name { let param_name = match lt.name {
hir::LifetimeName::Param(param_name) => param_name, hir::LifetimeName::Param(param_name) => param_name,
hir::LifetimeName::Implicit hir::LifetimeName::Implicit(_)
| hir::LifetimeName::Underscore | hir::LifetimeName::Underscore
| hir::LifetimeName::Static => hir::ParamName::Plain(lt.name.ident()), | hir::LifetimeName::Static => hir::ParamName::Plain(lt.name.ident()),
hir::LifetimeName::ImplicitObjectLifetimeDefault => { hir::LifetimeName::ImplicitObjectLifetimeDefault => {
@ -2062,6 +2040,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.expr_block(block, AttrVec::new()) 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 { fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst {
self.with_new_scopes(|this| hir::AnonConst { self.with_new_scopes(|this| hir::AnonConst {
hir_id: this.lower_node_id(c.id), 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> { 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); 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> { 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); 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> { fn pat_some(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
let field = self.single_pat_field(span, pat); 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> { 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( fn single_pat_field(
@ -2176,8 +2174,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
span: Span, span: Span,
lang_item: hir::LangItem, lang_item: hir::LangItem,
fields: &'hir [hir::PatField<'hir>], fields: &'hir [hir::PatField<'hir>],
hir_id: Option<hir::HirId>,
) -> &'hir hir::Pat<'hir> { ) -> &'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)) 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::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, &'s mut self,
span: Span, span: Span,
count: usize, count: usize,
param_mode: ParamMode,
) -> impl Iterator<Item = hir::Lifetime> + Captures<'a> + Captures<'s> + Captures<'hir> { ) -> impl Iterator<Item = hir::Lifetime> + 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 { match self.anonymous_lifetime_mode {
AnonymousLifetimeMode::CreateParameter => { AnonymousLifetimeMode::CreateParameter => {
// We should have emitted E0726 when processing this path above // 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 // lifetime. Instead, we simply create an implicit lifetime, which will be checked
// later, at which point a suitable error will be emitted. // later, at which point a suitable error will be emitted.
AnonymousLifetimeMode::PassThrough | AnonymousLifetimeMode::ReportError => { 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 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::Lifetime {
hir_id: self.next_id(), hir_id: self.next_id(),
span: self.lower_span(span), span: self.lower_span(span),
name: hir::LifetimeName::Implicit, name: hir::LifetimeName::Implicit(missing),
}
}
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();
}
} }
} }
} }
@ -2451,17 +2418,12 @@ impl<'hir> GenericArgsCtor<'hir> {
} }
} }
#[tracing::instrument(level = "debug")]
fn lifetimes_from_impl_trait_bounds( fn lifetimes_from_impl_trait_bounds(
opaque_ty_id: NodeId, opaque_ty_id: NodeId,
bounds: hir::GenericBounds<'_>, bounds: hir::GenericBounds<'_>,
lifetimes_to_include: Option<&FxHashSet<hir::LifetimeName>>, lifetimes_to_include: Option<&FxHashSet<hir::LifetimeName>>,
) -> Vec<(hir::LifetimeName, Span)> { ) -> 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 // 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. // 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>`. // 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) { fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
let name = match lifetime.name { let name = match lifetime.name {
hir::LifetimeName::Implicit | hir::LifetimeName::Underscore => { hir::LifetimeName::Implicit(_) | hir::LifetimeName::Underscore => {
if self.collect_elided_lifetimes { if self.collect_elided_lifetimes {
// Use `'_` for both implicit and underscore lifetimes in // Use `'_` for both implicit and underscore lifetimes in
// `type Foo<'_> = impl SomeTrait<'_>;`. // `type Foo<'_> = impl SomeTrait<'_>;`.

View File

@ -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)); 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); 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) => { PatKind::TupleStruct(ref qself, ref path, ref pats) => {
let qpath = self.lower_qpath( let qpath = self.lower_qpath(
pattern.id, pattern.id,
@ -81,8 +83,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
PatKind::Range(ref e1, ref e2, Spanned { node: ref end, .. }) => { PatKind::Range(ref e1, ref e2, Spanned { node: ref end, .. }) => {
break hir::PatKind::Range( break hir::PatKind::Range(
e1.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(e)), e2.as_deref().map(|e| self.lower_expr_within_pat(e, true)),
self.lower_range_end(end, e2.is_some()), 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, 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)
}
} }

View File

@ -7,8 +7,6 @@ use rustc_hir as hir;
use rustc_hir::def::{DefKind, PartialRes, Res}; use rustc_hir::def::{DefKind, PartialRes, Res};
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::GenericArg; 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::symbol::Ident;
use rustc_span::{BytePos, Span, DUMMY_SP}; 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) { if let Ok(snippet) = self.sess.source_map().span_to_snippet(data.span) {
// Do not suggest going from `Trait()` to `Trait<>` // Do not suggest going from `Trait()` to `Trait<>`
if !data.inputs.is_empty() { if !data.inputs.is_empty() {
if let Some(split) = snippet.find('(') { // Suggest replacing `(` and `)` with `<` and `>`
let trait_name = &snippet[0..split]; // The snippet may be missing the closing `)`, skip that case
let args = &snippet[split + 1..snippet.len() - 1]; if snippet.ends_with(')') {
err.span_suggestion( if let Some(split) = snippet.find('(') {
data.span, let trait_name = &snippet[0..split];
"use angle brackets instead", let args = &snippet[split + 1..snippet.len() - 1];
format!("{}<{}>", trait_name, args), err.span_suggestion(
Applicability::MaybeIncorrect, 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 = let has_lifetimes =
generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_))); 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. // Note: these spans are used for diagnostics when they can't be inferred.
// See rustc_resolve::late::lifetimes::LifetimeContext::add_missing_lifetime_specifiers_label // See rustc_resolve::late::lifetimes::LifetimeContext::add_missing_lifetime_specifiers_label
let elided_lifetime_span = if generic_args.span.is_empty() { let elided_lifetime_span = if generic_args.span.is_empty() {
// If there are no brackets, use the identifier span. // 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() { } else if generic_args.is_empty() {
// If there are brackets, but not generic arguments, then use the opening bracket // If there are brackets, but not generic arguments, then use the opening bracket
generic_args.span.with_hi(generic_args.span.lo() + BytePos(1)) 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.span.with_lo(generic_args.span.lo() + BytePos(1)).shrink_to_lo()
}; };
generic_args.args = self 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) .map(GenericArg::Lifetime)
.chain(generic_args.args.into_iter()) .chain(generic_args.args.into_iter())
.collect(); .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<u32> // note lack of '_
// async fn foo(_: std::cell::Ref<u32>) { ... }
if let (ParamMode::Explicit, AnonymousLifetimeMode::CreateParameter) =
(param_mode, self.anonymous_lifetime_mode)
{
let anon_lt_suggestion = vec!["'_"; expected_lifetimes].join(", "); let anon_lt_suggestion = vec!["'_"; expected_lifetimes].join(", ");
let no_non_lt_args = generic_args.args.len() == expected_lifetimes; let no_non_lt_args = generic_args.args.len() == expected_lifetimes;
let no_bindings = generic_args.bindings.is_empty(); 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. // 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 { } else {
// Otherwise we'll insert a `'_, ` right after the opening bracket. // Otherwise we'll insert a `'_, ` right after the opening bracket.
let span = generic_args (false, format!("{}, ", anon_lt_suggestion))
.span
.with_lo(generic_args.span.lo() + BytePos(1))
.shrink_to_lo();
(false, span, format!("{}, ", anon_lt_suggestion))
}; };
match self.anonymous_lifetime_mode { let insertion_sp = elided_lifetime_span.shrink_to_hi();
// In create-parameter mode we error here because we don't want to support let mut err = struct_span_err!(
// deprecated impl elision in new features like impl elision and `async fn`, self.sess,
// both of which work using the `CreateParameter` mode: path_span,
// E0726,
// impl Foo for std::cell::Ref<u32> // note lack of '_ "implicit elided lifetime not allowed here"
// async fn foo(_: std::cell::Ref<u32>) { ... } );
AnonymousLifetimeMode::CreateParameter => { rustc_errors::add_elided_lifetime_in_path_suggestion(
let mut err = struct_span_err!( &self.sess.source_map(),
self.sess, &mut err,
path_span, expected_lifetimes,
E0726, path_span,
"implicit elided lifetime not allowed here" incl_angl_brckt,
); insertion_sp,
rustc_errors::add_elided_lifetime_in_path_suggestion( suggestion,
&self.sess.source_map(), );
&mut err, err.note("assuming a `'static` lifetime...");
expected_lifetimes, err.emit();
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,
),
);
}
}
} }
} }

View File

@ -23,7 +23,7 @@ use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Span; use rustc_span::Span;
use rustc_target::spec::abi; use rustc_target::spec::abi;
use std::mem; use std::mem;
use std::ops::DerefMut; use std::ops::{Deref, DerefMut};
const MORE_EXTERN: &str = const MORE_EXTERN: &str =
"for more information, visit https://doc.rust-lang.org/std/keyword.extern.html"; "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]) { fn check_late_bound_lifetime_defs(&self, params: &[GenericParam]) {
// Check only lifetime parameters are present and that the lifetime // Check only lifetime parameters are present and that the lifetime
// parameters that are present have no bounds. // parameters that are present have no bounds.
@ -580,8 +552,7 @@ impl<'a> AstValidator<'a> {
/// An item in `extern { ... }` cannot use non-ascii identifier. /// An item in `extern { ... }` cannot use non-ascii identifier.
fn check_foreign_item_ascii_only(&self, ident: Ident) { fn check_foreign_item_ascii_only(&self, ident: Ident) {
let symbol_str = ident.as_str(); if !ident.as_str().is_ascii() {
if !symbol_str.is_ascii() {
let n = 83942; let n = 83942;
self.err_handler() self.err_handler()
.struct_span_err( .struct_span_err(
@ -894,7 +865,6 @@ impl<'a> AstValidator<'a> {
/// Checks that generic parameters are in the correct order, /// Checks that generic parameters are in the correct order,
/// which is lifetimes, then types and then consts. (`<'a, T, const N: usize>`) /// which is lifetimes, then types and then consts. (`<'a, T, const N: usize>`)
fn validate_generic_param_order( fn validate_generic_param_order(
sess: &Session,
handler: &rustc_errors::Handler, handler: &rustc_errors::Handler,
generics: &[GenericParam], generics: &[GenericParam],
span: Span, span: Span,
@ -911,8 +881,7 @@ fn validate_generic_param_order(
GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident.to_string()), GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident.to_string()),
GenericParamKind::Const { ref ty, kw_span: _, default: _ } => { GenericParamKind::Const { ref ty, kw_span: _, default: _ } => {
let ty = pprust::ty_to_string(ty); let ty = pprust::ty_to_string(ty);
let unordered = sess.features_untracked().unordered_const_ty_params(); (ParamKindOrd::Const, format!("const {}: {}", ident, ty))
(ParamKindOrd::Const { unordered }, format!("const {}: {}", ident, ty))
} }
}; };
param_idents.push((kind, ord_kind, bounds, idx, ident)); param_idents.push((kind, ord_kind, bounds, idx, ident));
@ -968,14 +937,7 @@ fn validate_generic_param_order(
); );
err.span_suggestion( err.span_suggestion(
span, span,
&format!( "reorder the parameters: lifetimes, then consts and types",
"reorder the parameters: lifetimes, {}",
if sess.features_untracked().unordered_const_ty_params() {
"then consts and types"
} else {
"then types, then consts"
}
),
ordered_params.clone(), ordered_params.clone(),
Applicability::MachineApplicable, Applicability::MachineApplicable,
); );
@ -1342,8 +1304,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
} }
fn visit_generics(&mut self, generics: &'a Generics) { 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; let mut prev_param_default = None;
for param in &generics.params { for param in &generics.params {
match param.kind { match param.kind {
@ -1358,12 +1318,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
span, span,
"generic parameters with a default must be trailing", "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(); err.emit();
break; break;
} }
@ -1371,12 +1325,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
} }
} }
validate_generic_param_order( validate_generic_param_order(self.err_handler(), &generics.params, generics.span);
self.session,
self.err_handler(),
&generics.params,
generics.span,
);
for predicate in &generics.where_clause.predicates { for predicate in &generics.where_clause.predicates {
if let WherePredicate::EqPredicate(ref predicate) = *predicate { if let WherePredicate::EqPredicate(ref predicate) = *predicate {
@ -1449,25 +1398,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
visit::walk_param_bound(self, bound) 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) { fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef, m: &'a TraitBoundModifier) {
self.check_late_bound_lifetime_defs(&t.bound_generic_params); self.check_late_bound_lifetime_defs(&t.bound_generic_params);
visit::walk_poly_trait_ref(self, t, m); 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<Bar = RhsTy>`.
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 &param.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( err.note(
"see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information", "see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information",
); );

View File

@ -61,7 +61,7 @@ impl<'a> PostExpansionVisitor<'a> {
fn check_abi(&self, abi: ast::StrLit) { fn check_abi(&self, abi: ast::StrLit) {
let ast::StrLit { symbol_unescaped, span, .. } = abi; let ast::StrLit { symbol_unescaped, span, .. } = abi;
match &*symbol_unescaped.as_str() { match symbol_unescaped.as_str() {
// Stable // Stable
"Rust" | "C" | "cdecl" | "stdcall" | "fastcall" | "aapcs" | "win64" | "sysv64" "Rust" | "C" | "cdecl" | "stdcall" | "fastcall" | "aapcs" | "win64" | "sysv64"
| "system" => {} | "system" => {}
@ -347,7 +347,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
if let Some(modifiers) = nested_meta.value_str() { if let Some(modifiers) = nested_meta.value_str() {
for modifier in modifiers.as_str().split(',') { 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)*) => { macro_rules! gate_modifier { ($($name:literal => $feature:ident)*) => {
$(if modifier == $name { $(if modifier == $name {
let msg = concat!("`#[link(modifiers=\"", $name, "\")]` is unstable"); let msg = concat!("`#[link(modifiers=\"", $name, "\")]` is unstable");
@ -383,7 +383,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
} }
ast::ItemKind::Fn(..) => { ast::ItemKind::Fn(..) => {
if self.sess.contains_name(&i.attrs[..], sym::start) { if self.sess.contains_name(&i.attrs, sym::start) {
gate_feature_post!( gate_feature_post!(
&self, &self,
start, start,
@ -396,7 +396,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
} }
ast::ItemKind::Struct(..) => { 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) { for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
if item.has_name(sym::simd) { if item.has_name(sym::simd) {
gate_feature_post!( 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!(half_open_range_patterns, "half-open range patterns are unstable");
gate_all!(inline_const, "inline-const is experimental"); gate_all!(inline_const, "inline-const is experimental");
gate_all!(inline_const_pat, "inline-const in pattern position 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, // All uses of `gate_all!` below this point were added in #65742,
// and subsequently disabled (with the non-early gating readded). // and subsequently disabled (with the non-early gating readded).

View File

@ -6,6 +6,7 @@
#![feature(iter_is_partitioned)] #![feature(iter_is_partitioned)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(let_else)]
#![recursion_limit = "256"] #![recursion_limit = "256"]
pub mod ast_validation; pub mod ast_validation;

View File

@ -35,4 +35,14 @@ impl Printer {
self.word(w); self.word(w);
self.nbsp() self.nbsp()
} }
// Synthesizes a comment that was not textually present in the original
// source file.
pub fn synth_comment(&mut self, text: impl Into<Cow<'static, str>>) {
self.word("/*");
self.space();
self.word(text);
self.space();
self.word("*/")
}
} }

View File

@ -73,5 +73,14 @@ pub fn attribute_to_string(attr: &ast::Attribute) -> String {
} }
pub fn to_string(f: impl FnOnce(&mut State<'_>)) -> 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);
}
})
} }

File diff suppressed because it is too large Load Diff

View File

@ -236,7 +236,7 @@ where
// These unwraps are safe because `get` ensures the meta item // These unwraps are safe because `get` ensures the meta item
// is a name/value pair string literal. // is a name/value pair string literal.
issue_num = match &*issue.unwrap().as_str() { issue_num = match issue.unwrap().as_str() {
"none" => None, "none" => None,
issue => { issue => {
let emit_diag = |msg: &str| { let emit_diag = |msg: &str| {
@ -301,7 +301,7 @@ where
match (feature, reason, issue) { match (feature, reason, issue) {
(Some(feature), reason, Some(_)) => { (Some(feature), reason, Some(_)) => {
if !rustc_lexer::is_ident(&feature.as_str()) { if !rustc_lexer::is_ident(feature.as_str()) {
handle_errors( handle_errors(
&sess.parse_sess, &sess.parse_sess,
attr.span, attr.span,
@ -519,8 +519,10 @@ pub fn eval_condition(
[NestedMetaItem::Literal(Lit { kind: LitKind::Str(sym, ..), span, .. })] => { [NestedMetaItem::Literal(Lit { kind: LitKind::Str(sym, ..), span, .. })] => {
(sym, span) (sym, span)
} }
[NestedMetaItem::Literal(Lit { span, .. }) [
| NestedMetaItem::MetaItem(MetaItem { span, .. })] => { NestedMetaItem::Literal(Lit { span, .. })
| NestedMetaItem::MetaItem(MetaItem { span, .. }),
] => {
sess.span_diagnostic sess.span_diagnostic
.struct_span_err(*span, "expected a version literal") .struct_span_err(*span, "expected a version literal")
.emit(); .emit();
@ -533,7 +535,7 @@ pub fn eval_condition(
return false; 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, Some(ver) => ver,
None => { None => {
sess.span_diagnostic sess.span_diagnostic

View File

@ -84,7 +84,7 @@ pub enum LocalsStateAtExit {
} }
impl LocalsStateAtExit { impl LocalsStateAtExit {
fn build( fn build<'tcx>(
locals_are_invalidated_at_exit: bool, locals_are_invalidated_at_exit: bool,
body: &Body<'tcx>, body: &Body<'tcx>,
move_data: &MoveData<'tcx>, move_data: &MoveData<'tcx>,

View File

@ -5,7 +5,7 @@ use rustc_middle::ty::RegionVid;
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces}; use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces};
use rustc_mir_dataflow::ResultsVisitable; 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 rustc_mir_dataflow::{Analysis, Direction, Results};
use std::fmt; use std::fmt;
use std::iter; use std::iter;
@ -434,9 +434,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
&self, &self,
_trans: &mut impl GenKill<Self::Idx>, _trans: &mut impl GenKill<Self::Idx>,
_block: mir::BasicBlock, _block: mir::BasicBlock,
_func: &mir::Operand<'tcx>, _return_places: CallReturnPlaces<'_, 'tcx>,
_args: &[mir::Operand<'tcx>],
_dest_place: mir::Place<'tcx>,
) { ) {
} }
} }

View File

@ -17,7 +17,7 @@ pub fn categorize(context: PlaceContext) -> Option<DefUse> {
PlaceContext::MutatingUse(MutatingUseContext::Store) | PlaceContext::MutatingUse(MutatingUseContext::Store) |
// This is potentially both a def and a use... // 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 // We let Call define the result in both the success and
// unwind cases. This is not really correct, however it // unwind cases. This is not really correct, however it
@ -26,6 +26,7 @@ pub fn categorize(context: PlaceContext) -> Option<DefUse> {
// the def in call only to the input from the success // the def in call only to the input from the success
// path and not the unwind path. -nmatsakis // path and not the unwind path. -nmatsakis
PlaceContext::MutatingUse(MutatingUseContext::Call) | PlaceContext::MutatingUse(MutatingUseContext::Call) |
PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) |
PlaceContext::MutatingUse(MutatingUseContext::Yield) | PlaceContext::MutatingUse(MutatingUseContext::Yield) |
// Storage live and storage dead aren't proper defines, but we can ignore // Storage live and storage dead aren't proper defines, but we can ignore

View File

@ -31,7 +31,7 @@ enum UniverseInfoInner<'tcx> {
Other, Other,
} }
impl UniverseInfo<'tcx> { impl<'tcx> UniverseInfo<'tcx> {
crate fn other() -> UniverseInfo<'tcx> { crate fn other() -> UniverseInfo<'tcx> {
UniverseInfo(UniverseInfoInner::Other) UniverseInfo(UniverseInfoInner::Other)
} }
@ -191,7 +191,7 @@ struct PredicateQuery<'tcx> {
base_universe: ty::UniverseIndex, 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> { fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
let mut err = tcx.sess.struct_span_err(span, "higher-ranked lifetime error"); 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)); err.note(&format!("could not prove {}", self.canonical_query.value.value.predicate));
@ -231,7 +231,7 @@ struct NormalizeQuery<'tcx, T> {
base_universe: ty::UniverseIndex, base_universe: ty::UniverseIndex,
} }
impl<T> TypeOpInfo<'tcx> for NormalizeQuery<'tcx, T> impl<'tcx, T> TypeOpInfo<'tcx> for NormalizeQuery<'tcx, T>
where where
T: Copy + fmt::Display + TypeFoldable<'tcx> + 'tcx, T: Copy + fmt::Display + TypeFoldable<'tcx> + 'tcx,
{ {
@ -291,7 +291,7 @@ struct AscribeUserTypeQuery<'tcx> {
base_universe: ty::UniverseIndex, 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> { 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, // 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. // 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, error_region,
cause.clone(), cause.clone(),
placeholder_region, placeholder_region,
vec![],
), ),
), ),
(Some(error_region), _) => NiceRegionError::new( (Some(error_region), _) => NiceRegionError::new(

View File

@ -15,16 +15,18 @@ use rustc_span::symbol::sym;
use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP}; use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP};
use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::infer::InferCtxtExt;
use crate::borrow_set::TwoPhaseActivation;
use crate::borrowck_errors; use crate::borrowck_errors;
use crate::diagnostics::find_all_local_uses;
use crate::{ use crate::{
borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf, borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind, InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind,
}; };
use super::{ use super::{
explain_borrow::BorrowExplanation, FnSelfUseKind, IncludingDowncast, RegionName, explain_borrow::{BorrowExplanation, LaterUseKind},
RegionNameSource, UseSpans, FnSelfUseKind, IncludingDowncast, RegionName, RegionNameSource, UseSpans,
}; };
#[derive(Debug)] #[derive(Debug)]
@ -414,7 +416,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
tcx, tcx,
generics, generics,
&mut err, &mut err,
&param.name.as_str(), param.name.as_str(),
"Copy", "Copy",
None, None,
); );
@ -768,9 +770,92 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
Some((issued_span, span)), Some((issued_span, span)),
); );
self.suggest_using_local_if_applicable(
&mut err,
location,
(place, span),
gen_borrow_kind,
issued_borrow,
explanation,
);
err 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( fn suggest_split_at_mut_if_applicable(
&self, &self,
err: &mut DiagnosticBuilder<'_>, err: &mut DiagnosticBuilder<'_>,
@ -977,9 +1062,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
Some(ref name), Some(ref name),
BorrowExplanation::MustBeValidFor { BorrowExplanation::MustBeValidFor {
category: category:
category category @ (ConstraintCategory::Return(_)
@
(ConstraintCategory::Return(_)
| ConstraintCategory::CallArgument | ConstraintCategory::CallArgument
| ConstraintCategory::OpaqueType), | ConstraintCategory::OpaqueType),
from_closure: false, from_closure: false,
@ -1515,8 +1598,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
location: Location, location: Location,
mpi: MovePathIndex, mpi: MovePathIndex,
) -> (Vec<MoveSite>, Vec<Location>) { ) -> (Vec<MoveSite>, Vec<Location>) {
fn predecessor_locations( fn predecessor_locations<'a>(
body: &'a mir::Body<'tcx>, body: &'a mir::Body<'_>,
location: Location, location: Location,
) -> impl Iterator<Item = Location> + 'a { ) -> impl Iterator<Item = Location> + 'a {
if location.statement_index == 0 { if location.statement_index == 0 {

View File

@ -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<Location> {
let mut visitor = AllLocalUsesVisitor { for_local: local, uses: BTreeSet::default() };
visitor.visit_body(body);
visitor.uses
}
struct AllLocalUsesVisitor {
for_local: Local,
uses: BTreeSet<Location>,
}
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);
}
}
}

View File

@ -19,6 +19,7 @@ use rustc_target::abi::VariantIdx;
use super::borrow_set::BorrowData; use super::borrow_set::BorrowData;
use super::MirBorrowckCtxt; use super::MirBorrowckCtxt;
mod find_all_local_uses;
mod find_use; mod find_use;
mod outlives_suggestion; mod outlives_suggestion;
mod region_name; mod region_name;
@ -205,7 +206,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
{ {
let local_info = &self.body.local_decls[local].local_info; let local_info = &self.body.local_decls[local].local_info;
if let Some(box LocalInfo::StaticRef { def_id, .. }) = *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 { } else {
unreachable!(); unreachable!();
} }
@ -317,7 +318,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let decl = &self.body.local_decls[local]; let decl = &self.body.local_decls[local];
match self.local_names[local] { match self.local_names[local] {
Some(name) if !decl.from_compiler_desugaring() => { Some(name) if !decl.from_compiler_desugaring() => {
buf.push_str(&name.as_str()); buf.push_str(name.as_str());
Ok(()) Ok(())
} }
_ => Err(()), _ => Err(()),
@ -408,7 +409,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// Add a note that a type does not implement `Copy` /// Add a note that a type does not implement `Copy`
pub(super) fn note_type_does_not_implement_copy( pub(super) fn note_type_does_not_implement_copy(
&self, &self,
err: &mut DiagnosticBuilder<'a>, err: &mut DiagnosticBuilder<'_>,
place_desc: &str, place_desc: &str,
ty: Ty<'tcx>, ty: Ty<'tcx>,
span: Option<Span>, span: Option<Span>,
@ -732,21 +733,19 @@ pub(super) enum BorrowedContentSource<'tcx> {
OverloadedIndex(Ty<'tcx>), OverloadedIndex(Ty<'tcx>),
} }
impl BorrowedContentSource<'tcx> { impl<'tcx> BorrowedContentSource<'tcx> {
pub(super) fn describe_for_unnamed_place(&self, tcx: TyCtxt<'_>) -> String { pub(super) fn describe_for_unnamed_place(&self, tcx: TyCtxt<'_>) -> String {
match *self { match *self {
BorrowedContentSource::DerefRawPointer => "a raw pointer".to_string(), BorrowedContentSource::DerefRawPointer => "a raw pointer".to_string(),
BorrowedContentSource::DerefSharedRef => "a shared reference".to_string(), BorrowedContentSource::DerefSharedRef => "a shared reference".to_string(),
BorrowedContentSource::DerefMutableRef => "a mutable reference".to_string(), BorrowedContentSource::DerefMutableRef => "a mutable reference".to_string(),
BorrowedContentSource::OverloadedDeref(ty) => match ty.kind() { BorrowedContentSource::OverloadedDeref(ty) => ty
ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Rc, def.did) => { .ty_adt_def()
"an `Rc`".to_string() .and_then(|adt| match tcx.get_diagnostic_name(adt.did)? {
} name @ (sym::Rc | sym::Arc) => Some(format!("an `{}`", name)),
ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Arc, def.did) => { _ => None,
"an `Arc`".to_string() })
} .unwrap_or_else(|| format!("dereference of `{}`", ty)),
_ => format!("dereference of `{}`", ty),
},
BorrowedContentSource::OverloadedIndex(ty) => format!("index of `{}`", ty), BorrowedContentSource::OverloadedIndex(ty) => format!("index of `{}`", ty),
} }
} }
@ -770,15 +769,13 @@ impl BorrowedContentSource<'tcx> {
BorrowedContentSource::DerefMutableRef => { BorrowedContentSource::DerefMutableRef => {
bug!("describe_for_immutable_place: DerefMutableRef isn't immutable") bug!("describe_for_immutable_place: DerefMutableRef isn't immutable")
} }
BorrowedContentSource::OverloadedDeref(ty) => match ty.kind() { BorrowedContentSource::OverloadedDeref(ty) => ty
ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Rc, def.did) => { .ty_adt_def()
"an `Rc`".to_string() .and_then(|adt| match tcx.get_diagnostic_name(adt.did)? {
} name @ (sym::Rc | sym::Arc) => Some(format!("an `{}`", name)),
ty::Adt(def, _) if tcx.is_diagnostic_item(sym::Arc, def.did) => { _ => None,
"an `Arc`".to_string() })
} .unwrap_or_else(|| format!("dereference of `{}`", ty)),
_ => format!("a dereference of `{}`", ty),
},
BorrowedContentSource::OverloadedIndex(ty) => format!("an index of `{}`", ty), BorrowedContentSource::OverloadedIndex(ty) => format!("an index of `{}`", ty),
} }
} }
@ -960,8 +957,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
_ => None, _ => None,
}); });
let is_option_or_result = parent_self_ty.map_or(false, |def_id| { let is_option_or_result = parent_self_ty.map_or(false, |def_id| {
tcx.is_diagnostic_item(sym::Option, def_id) matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
|| tcx.is_diagnostic_item(sym::Result, def_id)
}); });
FnSelfUseKind::Normal { self_arg, implicit_into_iter, is_option_or_result } FnSelfUseKind::Normal { self_arg, implicit_into_iter, is_option_or_result }
}); });

View File

@ -165,10 +165,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
PlaceRef { PlaceRef {
local: _, local: _,
projection: projection:
[.., ProjectionElem::Index(_) [
| ProjectionElem::ConstantIndex { .. } ..,
| ProjectionElem::Subslice { .. } ProjectionElem::Index(_)
| ProjectionElem::Downcast(..)], | ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Subslice { .. }
| ProjectionElem::Downcast(..),
],
} => bug!("Unexpected immutable place."), } => bug!("Unexpected immutable place."),
} }
@ -217,19 +220,24 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
PlaceRef { PlaceRef {
local, local,
projection: 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)); 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, self.infcx.tcx,
Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty, Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty,
field, field,
) { ) {
err.span_suggestion( err.span_suggestion_verbose(
span, span,
"consider changing this to be mutable", "consider changing this to be mutable",
message, " mut ".into(),
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );
} }
@ -739,7 +747,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
HirId, ImplItem, ImplItemKind, Item, ItemKind, HirId, ImplItem, ImplItemKind, Item, ItemKind,
}; };
fn maybe_body_id_of_fn(hir_map: &Map<'tcx>, id: HirId) -> Option<BodyId> { fn maybe_body_id_of_fn(hir_map: &Map<'_>, id: HirId) -> Option<BodyId> {
match hir_map.find(id) { match hir_map.find(id) {
Some(Node::Item(Item { kind: ItemKind::Fn(_, _, body_id), .. })) Some(Node::Item(Item { kind: ItemKind::Fn(_, _, body_id), .. }))
| Some(Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(_, body_id), .. })) => { | Some(Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(_, body_id), .. })) => {
@ -763,11 +771,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
kind: kind:
Call( Call(
_, _,
[Expr { [
kind: MethodCall(path_segment, ..), Expr {
hir_id, kind: MethodCall(path_segment, ..),
.. hir_id,
}, ..], ..
},
..,
],
), ),
.. ..
}, },
@ -1048,18 +1059,18 @@ fn is_closure_or_generator(ty: Ty<'_>) -> bool {
ty.is_closure() || ty.is_generator() ty.is_closure() || ty.is_generator()
} }
/// Adds a suggestion to a struct definition given a field access to a local. /// 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 suggestion. /// This function expects the local to be a reference to a struct in order to produce a span.
/// ///
/// ```text /// ```text
/// LL | s: &'a String /// LL | s: &'a String
/// | ---------- use `&'a mut String` here to make mutable /// | ^^^ returns a span taking up the space here
/// ``` /// ```
fn annotate_struct_field( fn get_mut_span_in_struct_field<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
field: &mir::Field, field: &mir::Field,
) -> Option<(Span, String)> { ) -> Option<Span> {
// Expect our local to be a reference to a struct of some kind. // Expect our local to be a reference to a struct of some kind.
if let ty::Ref(_, ty, _) = ty.kind() { if let ty::Ref(_, ty, _) = ty.kind() {
if let ty::Adt(def, _) = 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, // 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. // we can expect a field that is an immutable reference to a type.
if let hir::Node::Field(field) = node { if let hir::Node::Field(field) = node {
if let hir::TyKind::Rptr( if let hir::TyKind::Rptr(lifetime, hir::MutTy { mutbl: hir::Mutability::Not, ty }) =
lifetime, field.ty.kind
hir::MutTy { mutbl: hir::Mutability::Not, ref ty },
) = field.ty.kind
{ {
// Get the snippets in two parts - the named lifetime (if there is one) and return Some(lifetime.span.between(ty.span));
// 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,),
));
} }
} }
} }

View File

@ -6,7 +6,7 @@ use rustc_infer::infer::{
error_reporting::unexpected_hidden_region_diagnostic, NllRegionVariableOrigin, error_reporting::unexpected_hidden_region_diagnostic, NllRegionVariableOrigin,
}; };
use rustc_middle::mir::{ConstraintCategory, ReturnConstraint}; 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_middle::ty::{self, RegionVid, Ty};
use rustc_span::symbol::{kw, sym}; use rustc_span::symbol::{kw, sym};
use rustc_span::{BytePos, Span}; use rustc_span::{BytePos, Span};
@ -334,13 +334,43 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
match variance_info { match variance_info {
ty::VarianceDiagInfo::None => {} ty::VarianceDiagInfo::None => {}
ty::VarianceDiagInfo::Mut { kind, ty } => { ty::VarianceDiagInfo::Invariant { ty, param_index } => {
let kind_name = match kind { let (desc, note) = match ty.kind() {
ty::VarianceDiagMutKind::Ref => "reference", ty::RawPtr(ty_mut) => {
ty::VarianceDiagMutKind::RawPtr => "pointer", 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!("requirement occurs because of {desc}",));
diag.note(&format!("mutable {kind_name}s are invariant over their type parameter")); diag.note(&note);
diag.help("see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance"); diag.help("see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance");
} }
} }

View File

@ -584,7 +584,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
Some(RegionNameHighlight::MatchedAdtAndSegment(lifetime_span)) 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 // In this case, the user left off the lifetime; so
// they wrote something like: // they wrote something like:
// //
@ -769,20 +769,24 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
let opaque_ty = hir.item(id); let opaque_ty = hir.item(id);
if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { if let hir::ItemKind::OpaqueTy(hir::OpaqueTy {
bounds: bounds:
[hir::GenericBound::LangItemTrait( [
hir::LangItem::Future, hir::GenericBound::LangItemTrait(
_, hir::LangItem::Future,
_, _,
hir::GenericArgs { _,
bindings: hir::GenericArgs {
[hir::TypeBinding { bindings:
ident: Ident { name: sym::Output, .. }, [
kind: hir::TypeBindingKind::Equality { ty }, hir::TypeBinding {
.. ident: Ident { name: sym::Output, .. },
}], kind: hir::TypeBindingKind::Equality { ty },
.. ..
}, },
)], ],
..
},
),
],
.. ..
}) = opaque_ty.kind }) = opaque_ty.kind
{ {

View File

@ -199,6 +199,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
options: _, options: _,
line_spans: _, line_spans: _,
destination: _, destination: _,
cleanup: _,
} => { } => {
for op in operands { for op in operands {
match *op { match *op {

View File

@ -3,9 +3,6 @@
#![feature(bool_to_option)] #![feature(bool_to_option)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(crate_visibility_modifier)] #![feature(crate_visibility_modifier)]
#![cfg_attr(bootstrap, feature(format_args_capture))]
#![feature(in_band_lifetimes)]
#![feature(iter_zip)]
#![feature(let_else)] #![feature(let_else)]
#![feature(min_specialization)] #![feature(min_specialization)]
#![feature(stmt_expr_attributes)] #![feature(stmt_expr_attributes)]
@ -792,6 +789,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
options: _, options: _,
line_spans: _, line_spans: _,
destination: _, destination: _,
cleanup: _,
} => { } => {
for op in operands { for op in operands {
match *op { match *op {
@ -1396,10 +1394,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
Rvalue::NullaryOp(_op, _ty) => { Rvalue::NullaryOp(_op, _ty) => {
// nullary ops take no dynamic input; no borrowck effect. // 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) => { Rvalue::Aggregate(ref aggregate_kind, ref operands) => {

View File

@ -53,7 +53,7 @@ rustc_index::newtype_index! {
} }
} }
impl Default for MemberConstraintSet<'tcx, ty::RegionVid> { impl Default for MemberConstraintSet<'_, ty::RegionVid> {
fn default() -> Self { fn default() -> Self {
Self { Self {
first_constraints: Default::default(), first_constraints: Default::default(),
@ -97,7 +97,7 @@ impl<'tcx> MemberConstraintSet<'tcx, ty::RegionVid> {
} }
} }
impl<R1> MemberConstraintSet<'tcx, R1> impl<'tcx, R1> MemberConstraintSet<'tcx, R1>
where where
R1: Copy + Hash + Eq, R1: Copy + Hash + Eq,
{ {
@ -140,7 +140,7 @@ where
} }
} }
impl<R> MemberConstraintSet<'tcx, R> impl<R> MemberConstraintSet<'_, R>
where where
R: Copy + Hash + Eq, R: Copy + Hash + Eq,
{ {

View File

@ -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 /// 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 /// be `self` in the current MIR, because that is the only time we directly access the fields
/// of a closure type. /// of a closure type.
pub(crate) fn is_upvar_field_projection( pub(crate) fn is_upvar_field_projection<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
upvars: &[Upvar<'tcx>], upvars: &[Upvar<'tcx>],
place_ref: PlaceRef<'tcx>, place_ref: PlaceRef<'tcx>,

View File

@ -173,7 +173,7 @@ fn check_opaque_type_parameter_valid(
// fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>. // fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
// //
// which would error here on all of the `'static` args. // which would error here on all of the `'static` args.
OpaqueTyOrigin::FnReturn | OpaqueTyOrigin::AsyncFn => return true, OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return true,
// Check these // Check these
OpaqueTyOrigin::TyAlias => {} OpaqueTyOrigin::TyAlias => {}
} }

View File

@ -1,5 +1,7 @@
use rustc_data_structures::fx::FxIndexSet; 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::Idx;
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
use rustc_middle::mir::{BasicBlock, Body, Location}; use rustc_middle::mir::{BasicBlock, Body, Location};
@ -110,11 +112,11 @@ crate enum RegionElement {
PlaceholderRegion(ty::PlaceholderRegion), PlaceholderRegion(ty::PlaceholderRegion),
} }
/// When we initially compute liveness, we use a bit matrix storing /// When we initially compute liveness, we use an interval matrix storing
/// points for each region-vid. /// liveness ranges for each region-vid.
crate struct LivenessValues<N: Idx> { crate struct LivenessValues<N: Idx> {
elements: Rc<RegionValueElements>, elements: Rc<RegionValueElements>,
points: SparseBitMatrix<N, PointIndex>, points: SparseIntervalMatrix<N, PointIndex>,
} }
impl<N: Idx> LivenessValues<N> { impl<N: Idx> LivenessValues<N> {
@ -122,7 +124,7 @@ impl<N: Idx> LivenessValues<N> {
/// Each of the regions in num_region_variables will be initialized with an /// Each of the regions in num_region_variables will be initialized with an
/// empty set of points and no causal information. /// empty set of points and no causal information.
crate fn new(elements: Rc<RegionValueElements>) -> Self { crate fn new(elements: Rc<RegionValueElements>) -> 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. /// Iterate through each region that has a value in this set.
@ -140,7 +142,7 @@ impl<N: Idx> LivenessValues<N> {
/// Adds all the elements in the given bit array into the given /// Adds all the elements in the given bit array into the given
/// region. Returns whether any of them are newly added. /// region. Returns whether any of them are newly added.
crate fn add_elements(&mut self, row: N, locations: &HybridBitSet<PointIndex>) -> bool { crate fn add_elements(&mut self, row: N, locations: &IntervalSet<PointIndex>) -> bool {
debug!("LivenessValues::add_elements(row={:?}, locations={:?})", row, locations); debug!("LivenessValues::add_elements(row={:?}, locations={:?})", row, locations);
self.points.union_row(row, locations) self.points.union_row(row, locations)
} }
@ -153,7 +155,7 @@ impl<N: Idx> LivenessValues<N> {
/// Returns `true` if the region `r` contains the given element. /// Returns `true` if the region `r` contains the given element.
crate fn contains(&self, row: N, location: Location) -> bool { crate fn contains(&self, row: N, location: Location) -> bool {
let index = self.elements.point_from_location(location); 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` /// Returns an iterator of all the elements contained by the region `r`
@ -221,7 +223,7 @@ impl PlaceholderIndices {
crate struct RegionValues<N: Idx> { crate struct RegionValues<N: Idx> {
elements: Rc<RegionValueElements>, elements: Rc<RegionValueElements>,
placeholder_indices: Rc<PlaceholderIndices>, placeholder_indices: Rc<PlaceholderIndices>,
points: SparseBitMatrix<N, PointIndex>, points: SparseIntervalMatrix<N, PointIndex>,
free_regions: SparseBitMatrix<N, RegionVid>, free_regions: SparseBitMatrix<N, RegionVid>,
/// Placeholders represent bound regions -- so something like `'a` /// Placeholders represent bound regions -- so something like `'a`
@ -241,7 +243,7 @@ impl<N: Idx> RegionValues<N> {
let num_placeholders = placeholder_indices.len(); let num_placeholders = placeholder_indices.len();
Self { Self {
elements: elements.clone(), elements: elements.clone(),
points: SparseBitMatrix::new(elements.num_points), points: SparseIntervalMatrix::new(elements.num_points),
placeholder_indices: placeholder_indices.clone(), placeholder_indices: placeholder_indices.clone(),
free_regions: SparseBitMatrix::new(num_universal_regions), free_regions: SparseBitMatrix::new(num_universal_regions),
placeholders: SparseBitMatrix::new(num_placeholders), placeholders: SparseBitMatrix::new(num_placeholders),

View File

@ -1,7 +1,7 @@
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin}; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
use rustc_middle::mir::visit::{MutVisitor, TyContext}; 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::subst::SubstsRef;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
@ -62,22 +62,6 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NllVisitor<'a, 'tcx> {
debug!(?ty); debug!(?ty);
} }
fn process_projection_elem(
&mut self,
elem: PlaceElem<'tcx>,
_: Location,
) -> Option<PlaceElem<'tcx>> {
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")] #[instrument(skip(self), level = "debug")]
fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, location: Location) { fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, location: Location) {
*substs = self.renumber_regions(*substs); *substs = self.renumber_regions(*substs);

View File

@ -6,6 +6,7 @@ use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound};
use rustc_infer::infer::{self, InferCtxt, SubregionOrigin}; use rustc_infer::infer::{self, InferCtxt, SubregionOrigin};
use rustc_middle::mir::ConstraintCategory; use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::TypeFoldable;
use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{self, TyCtxt};
use rustc_span::DUMMY_SP; use rustc_span::DUMMY_SP;
@ -95,11 +96,23 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
self.add_outlives(r1_vid, r2_vid); self.add_outlives(r1_vid, r2_vid);
} }
GenericArgKind::Type(t1) => { GenericArgKind::Type(mut t1) => {
// we don't actually use this for anything, but // we don't actually use this for anything, but
// the `TypeOutlives` code needs an origin. // the `TypeOutlives` code needs an origin.
let origin = infer::RelateParamBound(DUMMY_SP, t1, None); 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( TypeOutlives::new(
&mut *self, &mut *self,
tcx, tcx,

View File

@ -58,7 +58,7 @@ crate struct CreateResult<'tcx> {
crate normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>, crate normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>,
} }
crate fn create( crate fn create<'tcx>(
infcx: &InferCtxt<'_, 'tcx>, infcx: &InferCtxt<'_, 'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
implicit_region_bound: Option<ty::Region<'tcx>>, implicit_region_bound: Option<ty::Region<'tcx>>,
@ -81,7 +81,7 @@ crate fn create(
.create() .create()
} }
impl UniversalRegionRelations<'tcx> { impl UniversalRegionRelations<'_> {
/// Records in the `outlives_relation` (and /// Records in the `outlives_relation` (and
/// `inverse_outlives_relation`) that `fr_a: fr_b`. Invoked by the /// `inverse_outlives_relation`) that `fr_a: fr_b`. Invoked by the
/// builder below. /// builder below.
@ -110,7 +110,7 @@ impl UniversalRegionRelations<'tcx> {
/// outlives `fr` and (b) is not local. /// outlives `fr` and (b) is not local.
/// ///
/// (*) If there are multiple competing choices, we return all of them. /// (*) 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); debug!("non_local_upper_bound(fr={:?})", fr);
let res = self.non_local_bounds(&self.inverse_outlives, fr); let res = self.non_local_bounds(&self.inverse_outlives, fr);
assert!(!res.is_empty(), "can't find an upper bound!?"); assert!(!res.is_empty(), "can't find an upper bound!?");
@ -232,7 +232,7 @@ struct UniversalRegionRelationsBuilder<'this, 'tcx> {
region_bound_pairs: RegionBoundPairs<'tcx>, region_bound_pairs: RegionBoundPairs<'tcx>,
} }
impl UniversalRegionRelationsBuilder<'cx, 'tcx> { impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
crate fn create(mut self) -> CreateResult<'tcx> { crate fn create(mut self) -> CreateResult<'tcx> {
let unnormalized_input_output_tys = self let unnormalized_input_output_tys = self
.universal_regions .universal_regions

View File

@ -117,9 +117,29 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
} }
assert!(body.yield_ty().is_some() == universal_regions.yield_ty.is_some()); debug!(
if let Some(mir_yield_ty) = body.yield_ty() { "equate_inputs_and_outputs: body.yield_ty {:?}, universal_regions.yield_ty {:?}",
let ur_yield_ty = universal_regions.yield_ty.unwrap(); 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; 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); self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty, yield_span);
} }

View File

@ -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) { fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) {
if self.locals_with_use_data[local] { if self.locals_with_use_data[local] {
match def_use::categorize(context) { match def_use::categorize(context) {

View File

@ -74,7 +74,7 @@ pub(super) fn generate<'mir, 'tcx>(
// to compute whether a variable `X` is live if that variable contains // 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 // 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). // 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>, tcx: TyCtxt<'tcx>,
free_regions: &FxHashSet<RegionVid>, free_regions: &FxHashSet<RegionVid>,
body: &Body<'tcx>, body: &Body<'tcx>,
@ -104,7 +104,7 @@ fn compute_live_locals(
/// regions. For these regions, we do not need to compute /// regions. For these regions, we do not need to compute
/// liveness, since the outlives constraints will ensure that they /// liveness, since the outlives constraints will ensure that they
/// are live over the whole fn body anyhow. /// 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, num_region_vars: usize,
universal_regions: &UniversalRegions<'tcx>, universal_regions: &UniversalRegions<'tcx>,
constraint_set: &OutlivesConstraintSet<'tcx>, constraint_set: &OutlivesConstraintSet<'tcx>,

View File

@ -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) { fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) {
match def_use::categorize(context) { match def_use::categorize(context) {
Some(DefUse::Def) => self.insert_def(local, location), 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); self.super_place(place, context, location);
match context { match context {
PlaceContext::NonMutatingUse(_) => { 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>, typeck: &mut TypeChecker<'_, 'tcx>,
body: &Body<'tcx>, body: &Body<'tcx>,
location_table: &LocationTable, location_table: &LocationTable,
@ -123,7 +123,7 @@ pub(super) fn populate_access_facts(
// For every potentially drop()-touched region `region` in `local`'s type // For every potentially drop()-touched region `region` in `local`'s type
// (`kind`), emit a Polonius `use_of_var_derefs_origin(local, origin)` fact. // (`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>, typeck: &mut TypeChecker<'_, 'tcx>,
local: Local, local: Local,
kind: &GenericArg<'tcx>, kind: &GenericArg<'tcx>,

View File

@ -1,5 +1,6 @@
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_index::bit_set::HybridBitSet; use rustc_index::bit_set::HybridBitSet;
use rustc_index::interval::IntervalSet;
use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_infer::infer::canonical::QueryRegionConstraints;
use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location}; use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
use rustc_middle::ty::{Ty, TypeFoldable}; 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 /// DROP-LIVE set are to the liveness sets for regions found in the
/// `dropck_outlives` result of the variable's type (in particular, /// `dropck_outlives` result of the variable's type (in particular,
/// this respects `#[may_dangle]` annotations). /// this respects `#[may_dangle]` annotations).
pub(super) fn trace( pub(super) fn trace<'mir, 'tcx>(
typeck: &mut TypeChecker<'_, 'tcx>, typeck: &mut TypeChecker<'_, 'tcx>,
body: &Body<'tcx>, body: &Body<'tcx>,
elements: &Rc<RegionValueElements>, elements: &Rc<RegionValueElements>,
@ -105,12 +106,12 @@ struct LivenessResults<'me, 'typeck, 'flow, 'tcx> {
/// Points where the current variable is "use live" -- meaning /// Points where the current variable is "use live" -- meaning
/// that there is a future "full use" that may use its value. /// that there is a future "full use" that may use its value.
use_live_at: HybridBitSet<PointIndex>, use_live_at: IntervalSet<PointIndex>,
/// Points where the current variable is "drop live" -- meaning /// Points where the current variable is "drop live" -- meaning
/// that there is no future "full use" that may use its value, but /// that there is no future "full use" that may use its value, but
/// there is a future drop. /// there is a future drop.
drop_live_at: HybridBitSet<PointIndex>, drop_live_at: IntervalSet<PointIndex>,
/// Locations where drops may occur. /// Locations where drops may occur.
drop_locations: Vec<Location>, drop_locations: Vec<Location>,
@ -119,14 +120,14 @@ struct LivenessResults<'me, 'typeck, 'flow, 'tcx> {
stack: Vec<PointIndex>, stack: Vec<PointIndex>,
} }
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 { fn new(cx: LivenessContext<'me, 'typeck, 'flow, 'tcx>) -> Self {
let num_points = cx.elements.num_points(); let num_points = cx.elements.num_points();
LivenessResults { LivenessResults {
cx, cx,
defs: HybridBitSet::new_empty(num_points), defs: HybridBitSet::new_empty(num_points),
use_live_at: HybridBitSet::new_empty(num_points), use_live_at: IntervalSet::new(num_points),
drop_live_at: HybridBitSet::new_empty(num_points), drop_live_at: IntervalSet::new(num_points),
drop_locations: vec![], drop_locations: vec![],
stack: vec![], stack: vec![],
} }
@ -165,7 +166,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
drop_used: Vec<(Local, Location)>, drop_used: Vec<(Local, Location)>,
live_locals: FxHashSet<Local>, live_locals: FxHashSet<Local>,
) { ) {
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 { for (local, location) in drop_used {
if !live_locals.contains(&local) { 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 /// 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 /// cursor position. Callers should call one of the `seek` methods immediately before to point
/// the cursor to the desired location. /// the cursor to the desired location.
@ -456,7 +457,7 @@ impl LivenessContext<'_, '_, '_, 'tcx> {
fn add_use_live_facts_for( fn add_use_live_facts_for(
&mut self, &mut self,
value: impl TypeFoldable<'tcx>, value: impl TypeFoldable<'tcx>,
live_at: &HybridBitSet<PointIndex>, live_at: &IntervalSet<PointIndex>,
) { ) {
debug!("add_use_live_facts_for(value={:?})", value); debug!("add_use_live_facts_for(value={:?})", value);
@ -473,7 +474,7 @@ impl LivenessContext<'_, '_, '_, 'tcx> {
dropped_local: Local, dropped_local: Local,
dropped_ty: Ty<'tcx>, dropped_ty: Ty<'tcx>,
drop_locations: &[Location], drop_locations: &[Location],
live_at: &HybridBitSet<PointIndex>, live_at: &IntervalSet<PointIndex>,
) { ) {
debug!( debug!(
"add_drop_live_constraint(\ "add_drop_live_constraint(\
@ -521,7 +522,7 @@ impl LivenessContext<'_, '_, '_, 'tcx> {
elements: &RegionValueElements, elements: &RegionValueElements,
typeck: &mut TypeChecker<'_, 'tcx>, typeck: &mut TypeChecker<'_, 'tcx>,
value: impl TypeFoldable<'tcx>, value: impl TypeFoldable<'tcx>,
live_at: &HybridBitSet<PointIndex>, live_at: &IntervalSet<PointIndex>,
) { ) {
debug!("make_all_regions_live(value={:?})", value); debug!("make_all_regions_live(value={:?})", value);
debug!( debug!(

View File

@ -31,7 +31,7 @@ use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts}; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts};
use rustc_middle::ty::{ use rustc_middle::ty::{
self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, OpaqueTypeKey, RegionVid, 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::def_id::CRATE_DEF_ID;
use rustc_span::{Span, DUMMY_SP}; use rustc_span::{Span, DUMMY_SP};
@ -945,7 +945,7 @@ crate struct MirTypeckRegionConstraints<'tcx> {
crate type_tests: Vec<TypeTest<'tcx>>, crate type_tests: Vec<TypeTest<'tcx>>,
} }
impl MirTypeckRegionConstraints<'tcx> { impl<'tcx> MirTypeckRegionConstraints<'tcx> {
fn placeholder_region( fn placeholder_region(
&mut self, &mut self,
infcx: &InferCtxt<'_, 'tcx>, infcx: &InferCtxt<'_, 'tcx>,
@ -1828,10 +1828,16 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
self.assert_iscleanup(body, block_data, unwind, true); self.assert_iscleanup(body, block_data, unwind, true);
} }
} }
TerminatorKind::InlineAsm { destination, .. } => { TerminatorKind::InlineAsm { destination, cleanup, .. } => {
if let Some(target) = destination { if let Some(target) = destination {
self.assert_iscleanup(body, block_data, target, is_cleanup); 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(); let tcx = self.tcx();
match *ak { 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 variant = &def.variants[variant_index];
let adj_field_index = active_field_index.unwrap_or(field_index); let adj_field_index = active_field_index.unwrap_or(field_index);
if let Some(field) = variant.fields.get(adj_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 { let (def_id, instantiated_predicates) = match aggregate_kind {
AggregateKind::Adt(def, _, substs, _, _) => { AggregateKind::Adt(adt_did, _, substs, _, _) => {
(def.did, tcx.predicates_of(def.did).instantiate(tcx, substs)) (*adt_did, tcx.predicates_of(*adt_did).instantiate(tcx, substs))
} }
// For closures, we have some **extra requirements** we // For closures, we have some **extra requirements** we

View File

@ -51,7 +51,7 @@ struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
universe_info: UniverseInfo<'tcx>, universe_info: UniverseInfo<'tcx>,
} }
impl NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { impl<'me, 'bccx, 'tcx> NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
fn new( fn new(
type_checker: &'me mut TypeChecker<'bccx, 'tcx>, type_checker: &'me mut TypeChecker<'bccx, 'tcx>,
locations: Locations, 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> { fn param_env(&self) -> ty::ParamEnv<'tcx> {
self.type_checker.param_env self.type_checker.param_env
} }

View File

@ -15,6 +15,7 @@ rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" } rustc_errors = { path = "../rustc_errors" }
rustc_feature = { path = "../rustc_feature" } rustc_feature = { path = "../rustc_feature" }
rustc_lexer = { path = "../rustc_lexer" } rustc_lexer = { path = "../rustc_lexer" }
rustc_lint_defs = { path = "../rustc_lint_defs" }
rustc_parse = { path = "../rustc_parse" } rustc_parse = { path = "../rustc_parse" }
rustc_target = { path = "../rustc_target" } rustc_target = { path = "../rustc_target" }
rustc_session = { path = "../rustc_session" } rustc_session = { path = "../rustc_session" }

View File

@ -8,13 +8,14 @@ use rustc_expand::base::{self, *};
use rustc_parse::parser::Parser; use rustc_parse::parser::Parser;
use rustc_parse_format as parse; use rustc_parse_format as parse;
use rustc_session::lint; use rustc_session::lint;
use rustc_session::parse::ParseSess;
use rustc_span::symbol::Ident; use rustc_span::symbol::Ident;
use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::{InnerSpan, Span}; use rustc_span::{InnerSpan, Span};
use rustc_target::asm::InlineAsmArch; use rustc_target::asm::InlineAsmArch;
use smallvec::smallvec; use smallvec::smallvec;
struct AsmArgs { pub struct AsmArgs {
templates: Vec<P<ast::Expr>>, templates: Vec<P<ast::Expr>>,
operands: Vec<(ast::InlineAsmOperand, Span)>, operands: Vec<(ast::InlineAsmOperand, Span)>,
named_args: FxHashMap<Symbol, usize>, named_args: FxHashMap<Symbol, usize>,
@ -31,30 +32,30 @@ fn parse_args<'a>(
is_global_asm: bool, is_global_asm: bool,
) -> Result<AsmArgs, DiagnosticBuilder<'a>> { ) -> Result<AsmArgs, DiagnosticBuilder<'a>> {
let mut p = ecx.new_parser_from_tts(tts); 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<AsmArgs, DiagnosticBuilder<'a>> {
let diag = &sess.span_diagnostic;
if p.token == token::Eof { 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!) // 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) { if !is_global_asm && p.look_ahead(1, |t| *t == token::Colon || *t == token::ModSep) {
let mut err = 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("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"); 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); return Err(err);
} }
@ -74,7 +75,7 @@ fn parse_args<'a>(
if !p.eat(&token::Comma) { if !p.eat(&token::Comma) {
if allow_templates { if allow_templates {
// After a template string, we always expect *only* a comma... // 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 `,`"); err.span_label(p.token.span, "expected `,`");
p.maybe_annotate_with_ascription(&mut err, false); p.maybe_annotate_with_ascription(&mut err, false);
return Err(err); return Err(err);
@ -89,14 +90,14 @@ fn parse_args<'a>(
// Parse clobber_abi // Parse clobber_abi
if p.eat_keyword(sym::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; allow_templates = false;
continue; continue;
} }
// Parse options // Parse options
if p.eat_keyword(sym::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; allow_templates = false;
continue; continue;
} }
@ -116,25 +117,25 @@ fn parse_args<'a>(
let mut explicit_reg = false; let mut explicit_reg = false;
let op = if !is_global_asm && p.eat_keyword(kw::In) { 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) { 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); return Err(err);
} }
let expr = p.parse_expr()?; let expr = p.parse_expr()?;
ast::InlineAsmOperand::In { reg, expr } ast::InlineAsmOperand::In { reg, expr }
} else if !is_global_asm && p.eat_keyword(sym::out) { } 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()?) }; let expr = if p.eat_keyword(kw::Underscore) { None } else { Some(p.parse_expr()?) };
ast::InlineAsmOperand::Out { reg, expr, late: false } ast::InlineAsmOperand::Out { reg, expr, late: false }
} else if !is_global_asm && p.eat_keyword(sym::lateout) { } 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()?) }; let expr = if p.eat_keyword(kw::Underscore) { None } else { Some(p.parse_expr()?) };
ast::InlineAsmOperand::Out { reg, expr, late: true } ast::InlineAsmOperand::Out { reg, expr, late: true }
} else if !is_global_asm && p.eat_keyword(sym::inout) { } 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) { 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); return Err(err);
} }
let expr = p.parse_expr()?; let expr = p.parse_expr()?;
@ -146,9 +147,9 @@ fn parse_args<'a>(
ast::InlineAsmOperand::InOut { reg, expr, late: false } ast::InlineAsmOperand::InOut { reg, expr, late: false }
} }
} else if !is_global_asm && p.eat_keyword(sym::inlateout) { } 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) { 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); return Err(err);
} }
let expr = p.parse_expr()?; let expr = p.parse_expr()?;
@ -167,7 +168,7 @@ fn parse_args<'a>(
match expr.kind { match expr.kind {
ast::ExprKind::Path(..) => {} ast::ExprKind::Path(..) => {}
_ => { _ => {
let err = ecx let err = diag
.struct_span_err(expr.span, "argument to `sym` must be a path expression"); .struct_span_err(expr.span, "argument to `sym` must be a path expression");
return Err(err); return Err(err);
} }
@ -186,7 +187,7 @@ fn parse_args<'a>(
} else { } else {
"expected operand, clobber_abi, options, or additional template string" "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); err.span_label(template.span, errstr);
return Err(err); 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 // clobber_abi/options. We do this at the end once we have the full span
// of the argument available. // of the argument available.
if !args.options_spans.is_empty() { 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_labels(args.options_spans.clone(), "previous options")
.span_label(span, "argument") .span_label(span, "argument")
.emit(); .emit();
} else if let Some((_, abi_span)) = args.clobber_abis.last() { } 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(*abi_span, "clobber_abi")
.span_label(span, "argument") .span_label(span, "argument")
.emit(); .emit();
} }
if explicit_reg { if explicit_reg {
if name.is_some() { 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); args.reg_args.insert(slot);
} else if let Some(name) = name { } else if let Some(name) = name {
if let Some(&prev) = args.named_args.get(&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(args.operands[prev].1, "previously here")
.span_label(span, "duplicate argument") .span_label(span, "duplicate argument")
.emit(); .emit();
continue; continue;
} }
if !args.reg_args.is_empty() { if !args.reg_args.is_empty() {
let mut err = ecx.struct_span_err( let mut err = diag.struct_span_err(
span, span,
"named arguments cannot follow explicit register arguments", "named arguments cannot follow explicit register arguments",
); );
@ -243,7 +244,7 @@ fn parse_args<'a>(
args.named_args.insert(name, slot); args.named_args.insert(name, slot);
} else { } else {
if !args.named_args.is_empty() || !args.reg_args.is_empty() { 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, span,
"positional arguments cannot follow named arguments \ "positional arguments cannot follow named arguments \
or explicit register arguments", or explicit register arguments",
@ -264,21 +265,21 @@ fn parse_args<'a>(
&& args.options.contains(ast::InlineAsmOptions::READONLY) && args.options.contains(ast::InlineAsmOptions::READONLY)
{ {
let spans = args.options_spans.clone(); 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(); .emit();
} }
if args.options.contains(ast::InlineAsmOptions::PURE) if args.options.contains(ast::InlineAsmOptions::PURE)
&& args.options.contains(ast::InlineAsmOptions::NORETURN) && args.options.contains(ast::InlineAsmOptions::NORETURN)
{ {
let spans = args.options_spans.clone(); 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(); .emit();
} }
if args.options.contains(ast::InlineAsmOptions::PURE) if args.options.contains(ast::InlineAsmOptions::PURE)
&& !args.options.intersects(ast::InlineAsmOptions::NOMEM | ast::InlineAsmOptions::READONLY) && !args.options.intersects(ast::InlineAsmOptions::NOMEM | ast::InlineAsmOptions::READONLY)
{ {
let spans = args.options_spans.clone(); let spans = args.options_spans.clone();
ecx.struct_span_err( diag.struct_span_err(
spans, spans,
"the `pure` option must be combined with either `nomem` or `readonly`", "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 { if args.options.contains(ast::InlineAsmOptions::PURE) && !have_real_output {
ecx.struct_span_err( diag.struct_span_err(
args.options_spans.clone(), args.options_spans.clone(),
"asm with the `pure` option must have at least one output", "asm with the `pure` option must have at least one output",
) )
.emit(); .emit();
} }
if args.options.contains(ast::InlineAsmOptions::NORETURN) && !outputs_sp.is_empty() { 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"); .struct_span_err(outputs_sp, "asm outputs are not allowed with the `noreturn` option");
// Bail out now since this is likely to confuse MIR // 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 args.clobber_abis.len() > 0 {
if is_global_asm { if is_global_asm {
let err = ecx.struct_span_err( let err = diag.struct_span_err(
args.clobber_abis.iter().map(|(_, span)| *span).collect::<Vec<Span>>(), args.clobber_abis.iter().map(|(_, span)| *span).collect::<Vec<Span>>(),
"`clobber_abi` cannot be used with `global_asm!`", "`clobber_abi` cannot be used with `global_asm!`",
); );
@ -334,7 +335,7 @@ fn parse_args<'a>(
return Err(err); return Err(err);
} }
if !regclass_outputs.is_empty() { if !regclass_outputs.is_empty() {
ecx.struct_span_err( diag.struct_span_err(
regclass_outputs.clone(), regclass_outputs.clone(),
"asm with `clobber_abi` must specify explicit registers for outputs", "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); try_set_option(p, args, sym::att_syntax, ast::InlineAsmOptions::ATT_SYNTAX);
} else if p.eat_keyword(kw::Raw) { } else if p.eat_keyword(kw::Raw) {
try_set_option(p, args, kw::Raw, ast::InlineAsmOptions::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 { } else {
return p.unexpected(); return p.unexpected();
} }
@ -570,7 +573,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
template_snippet.as_ref().map(|s| Symbol::intern(s)), template_snippet.as_ref().map(|s| Symbol::intern(s)),
template_sp, template_sp,
)); ));
let template_str = &template_str.as_str(); let template_str = template_str.as_str();
if let Some(InlineAsmArch::X86 | InlineAsmArch::X86_64) = ecx.sess.asm_arch { if let Some(InlineAsmArch::X86 | InlineAsmArch::X86_64) = ecx.sess.asm_arch {
let find_span = |needle: &str| -> Span { let find_span = |needle: &str| -> Span {
@ -710,7 +713,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
Some(&idx) => Some(idx), Some(&idx) => Some(idx),
None => { None => {
let msg = format!("there is no argument named `{}`", name); let msg = format!("there is no argument named `{}`", name);
ecx.struct_span_err(span, &msg[..]).emit(); ecx.struct_span_err(span, &msg).emit();
None None
} }
}, },
@ -806,7 +809,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
}) })
} }
pub fn expand_asm<'cx>( pub(super) fn expand_asm<'cx>(
ecx: &'cx mut ExtCtxt<'_>, ecx: &'cx mut ExtCtxt<'_>,
sp: Span, sp: Span,
tts: TokenStream, 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<'_>, ecx: &'cx mut ExtCtxt<'_>,
sp: Span, sp: Span,
tts: TokenStream, tts: TokenStream,

View File

@ -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::ptr::P;
use rustc_ast::token; use rustc_ast::token;
use rustc_ast::tokenstream::{DelimSpan, TokenStream}; use rustc_ast::tokenstream::{DelimSpan, TokenStream};

View File

@ -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 as ast;
use rustc_ast::mut_visit::MutVisitor; use rustc_ast::mut_visit::MutVisitor;
@ -11,7 +11,7 @@ use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_expand::config::StripUnconfigured; use rustc_expand::config::StripUnconfigured;
use rustc_expand::configure; use rustc_expand::configure;
use rustc_feature::Features; use rustc_feature::Features;
use rustc_parse::parser::ForceCollect; use rustc_parse::parser::{ForceCollect, Parser};
use rustc_session::utils::FlattenNonterminals; use rustc_session::utils::FlattenNonterminals;
use rustc_session::Session; use rustc_session::Session;
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
@ -25,6 +25,7 @@ crate fn expand(
annotatable: Annotatable, annotatable: Annotatable,
) -> Vec<Annotatable> { ) -> Vec<Annotatable> {
check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval); 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)] 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::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::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::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(&param), Annotatable::Param(param) => finder.visit_param(&param),
Annotatable::FieldDef(field) => finder.visit_field_def(&field), Annotatable::FieldDef(field) => finder.visit_field_def(&field),
Annotatable::Variant(variant) => finder.visit_variant(&variant), Annotatable::Variant(variant) => finder.visit_variant(&variant),
Annotatable::Crate(krate) => finder.visit_crate(krate),
}; };
finder.has_cfg_or_cfg_attr 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 // the location of `#[cfg]` and `#[cfg_attr]` in the token stream. The tokenization
// process is lossless, so this process is invisible to proc-macros. // process is lossless, so this process is invisible to proc-macros.
// FIXME - get rid of this clone let parse_annotatable_with: fn(&mut Parser<'_>) -> _ = match annotatable {
let nt = annotatable.clone().into_nonterminal(); 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( let mut orig_tokens = rustc_parse::nt_to_tokenstream(
&nt, &nt,
@ -173,25 +205,7 @@ impl CfgEval<'_, '_> {
let mut parser = let mut parser =
rustc_parse::stream_to_parser(&self.cfg.sess.parse_sess, orig_tokens, None); rustc_parse::stream_to_parser(&self.cfg.sess.parse_sess, orig_tokens, None);
parser.capture_cfg = true; parser.capture_cfg = true;
annotatable = match annotatable { annotatable = parse_annotatable_with(&mut parser);
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!(),
};
// Now that we have our re-parsed `AttrAnnotatedTokenStream`, recursively configuring // Now that we have our re-parsed `AttrAnnotatedTokenStream`, recursively configuring
// our attribute target will correctly the tokens as well. // our attribute target will correctly the tokens as well.

View File

@ -21,7 +21,7 @@ pub fn expand_concat(
match e.kind { match e.kind {
ast::ExprKind::Lit(ref lit) => match lit.kind { ast::ExprKind::Lit(ref lit) => match lit.kind {
ast::LitKind::Str(ref s, _) | ast::LitKind::Float(ref s, _) => { 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) => { ast::LitKind::Char(c) => {
accumulator.push(c); accumulator.push(c);

View File

@ -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<rustc_ast::Expr>, 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<rustc_span::Span>,
expr: &P<rustc_ast::Expr>,
) -> Option<u8> {
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<dyn base::MacResult + 'static> {
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))))
}

View File

@ -29,7 +29,7 @@ pub fn expand_concat_idents<'cx>(
} else { } else {
if let TokenTree::Token(token) = e { if let TokenTree::Token(token) = e {
if let Some((ident, _)) = token.ident() { if let Some((ident, _)) = token.ident() {
res_str.push_str(&ident.name.as_str()); res_str.push_str(ident.name.as_str());
continue; continue;
} }
} }

View File

@ -121,7 +121,7 @@ fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool {
fn report_unexpected_literal(sess: &Session, lit: &ast::Lit) { fn report_unexpected_literal(sess: &Session, lit: &ast::Lit) {
let help_msg = match lit.token.kind { 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) format!("try using `#[derive({})]`", lit.token.symbol)
} }
_ => "for example, write `#[derive(Debug)]` for `Debug`".to_string(), _ => "for example, write `#[derive(Debug)]` for `Debug`".to_string(),

View File

@ -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); 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 // Create the generic parameters
params.extend(generics.params.iter().map(|param| match &param.kind { params.extend(generics.params.iter().map(|param| match &param.kind {
@ -589,12 +592,12 @@ impl<'a> TraitDef<'a> {
param.bounds.iter().cloned() param.bounds.iter().cloned()
).collect(); ).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, .. } => { GenericParamKind::Const { ty, kw_span, .. } => {
let const_nodefault_kind = GenericParamKind::Const { let const_nodefault_kind = GenericParamKind::Const {
ty: ty.clone(), ty: ty.clone(),
kw_span: *kw_span, kw_span: kw_span.with_ctxt(ctxt),
// We can't have default values inside impl block // We can't have default values inside impl block
default: None, default: None,
@ -607,28 +610,27 @@ impl<'a> TraitDef<'a> {
// and similarly for where clauses // and similarly for where clauses
where_clause.predicates.extend(generics.where_clause.predicates.iter().map(|clause| { where_clause.predicates.extend(generics.where_clause.predicates.iter().map(|clause| {
match *clause { match clause {
ast::WherePredicate::BoundPredicate(ref wb) => { ast::WherePredicate::BoundPredicate(wb) => {
let span = wb.span.with_ctxt(ctxt);
ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
span: self.span, span,
bound_generic_params: wb.bound_generic_params.clone(), ..wb.clone()
bounded_ty: wb.bounded_ty.clone(),
bounds: wb.bounds.to_vec(),
}) })
} }
ast::WherePredicate::RegionPredicate(ref rb) => { ast::WherePredicate::RegionPredicate(wr) => {
let span = wr.span.with_ctxt(ctxt);
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
span: self.span, span,
lifetime: rb.lifetime, ..wr.clone()
bounds: rb.bounds.to_vec(),
}) })
} }
ast::WherePredicate::EqPredicate(ref we) => { ast::WherePredicate::EqPredicate(we) => {
let span = we.span.with_ctxt(ctxt);
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { ast::WherePredicate::EqPredicate(ast::WhereEqPredicate {
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
span: self.span, span,
lhs_ty: we.lhs_ty.clone(), ..we.clone()
rhs_ty: we.rhs_ty.clone(),
}) })
} }
} }
@ -691,13 +693,13 @@ impl<'a> TraitDef<'a> {
.iter() .iter()
.map(|param| match param.kind { .map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => { GenericParamKind::Lifetime { .. } => {
GenericArg::Lifetime(cx.lifetime(self.span, param.ident)) GenericArg::Lifetime(cx.lifetime(param.ident.span.with_ctxt(ctxt), param.ident))
} }
GenericParamKind::Type { .. } => { 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 { .. } => { 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(); .collect();
@ -764,8 +766,8 @@ impl<'a> TraitDef<'a> {
self, self,
struct_def, struct_def,
type_ident, type_ident,
&self_args[..], &self_args,
&nonself_args[..], &nonself_args,
) )
} else { } else {
method_def.expand_struct_method_body( method_def.expand_struct_method_body(
@ -773,8 +775,8 @@ impl<'a> TraitDef<'a> {
self, self,
struct_def, struct_def,
type_ident, type_ident,
&self_args[..], &self_args,
&nonself_args[..], &nonself_args,
use_temporaries, use_temporaries,
) )
}; };
@ -813,8 +815,8 @@ impl<'a> TraitDef<'a> {
self, self,
enum_def, enum_def,
type_ident, type_ident,
&self_args[..], &self_args,
&nonself_args[..], &nonself_args,
) )
} else { } else {
method_def.expand_enum_method_body( method_def.expand_enum_method_body(
@ -823,7 +825,7 @@ impl<'a> TraitDef<'a> {
enum_def, enum_def,
type_ident, type_ident,
self_args, self_args,
&nonself_args[..], &nonself_args,
) )
}; };
@ -845,16 +847,17 @@ impl<'a> MethodDef<'a> {
nonself_args: &[P<Expr>], nonself_args: &[P<Expr>],
fields: &SubstructureFields<'_>, fields: &SubstructureFields<'_>,
) -> P<Expr> { ) -> P<Expr> {
let span = trait_.span;
let substructure = Substructure { let substructure = Substructure {
type_ident, type_ident,
method_ident: Ident::new(self.name, trait_.span), method_ident: Ident::new(self.name, span),
self_args, self_args,
nonself_args, nonself_args,
fields, fields,
}; };
let mut f = self.combine_substructure.borrow_mut(); let mut f = self.combine_substructure.borrow_mut();
let f: &mut CombineSubstructureFunc<'_> = &mut *f; let f: &mut CombineSubstructureFunc<'_> = &mut *f;
f(cx, trait_.span, &substructure) f(cx, span, &substructure)
} }
fn get_ret_ty( fn get_ret_ty(
@ -882,9 +885,10 @@ impl<'a> MethodDef<'a> {
let mut nonself_args = Vec::new(); let mut nonself_args = Vec::new();
let mut arg_tys = Vec::new(); let mut arg_tys = Vec::new();
let mut nonstatic = false; let mut nonstatic = false;
let span = trait_.span;
let ast_explicit_self = self.explicit_self.as_ref().map(|self_ptr| { 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); self_args.push(self_expr);
nonstatic = true; nonstatic = true;
@ -893,11 +897,11 @@ impl<'a> MethodDef<'a> {
}); });
for (ty, name) in self.args.iter() { for (ty, name) in self.args.iter() {
let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics); let ast_ty = ty.to_ty(cx, span, type_ident, generics);
let ident = Ident::new(*name, trait_.span); let ident = Ident::new(*name, span);
arg_tys.push((ident, ast_ty)); 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 { match *ty {
// for static methods, just treat any Self // for static methods, just treat any Self
@ -906,7 +910,7 @@ impl<'a> MethodDef<'a> {
self_args.push(arg_expr); self_args.push(arg_expr);
} }
Ptr(ref ty, _) if matches!(**ty, Self_) && nonstatic => { 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); nonself_args.push(arg_expr);
@ -927,33 +931,33 @@ impl<'a> MethodDef<'a> {
arg_types: Vec<(Ident, P<ast::Ty>)>, arg_types: Vec<(Ident, P<ast::Ty>)>,
body: P<Expr>, body: P<Expr>,
) -> P<ast::AssocItem> { ) -> P<ast::AssocItem> {
let span = trait_.span;
// Create the generics that aren't for `Self`. // 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 args = {
let self_args = explicit_self.map(|explicit_self| { 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) ast::Param::from_self(ast::AttrVec::default(), explicit_self, ident)
}); });
let nonself_args = let nonself_args = arg_types.into_iter().map(|(name, ty)| cx.param(span, name, ty));
arg_types.into_iter().map(|(name, ty)| cx.param(trait_.span, name, ty));
self_args.into_iter().chain(nonself_args).collect() self_args.into_iter().chain(nonself_args).collect()
}; };
let ret_type = self.get_ret_ty(cx, trait_, generics, type_ident); 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 fn_decl = cx.fn_decl(args, ast::FnRetTy::Ty(ret_type));
let body_block = cx.block_expr(body); 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 { let sig = ast::FnSig {
header: ast::FnHeader { unsafety, ext: ast::Extern::None, ..ast::FnHeader::default() }, header: ast::FnHeader { unsafety, ext: ast::Extern::None, ..ast::FnHeader::default() },
decl: fn_decl, decl: fn_decl,
span: trait_.span, span,
}; };
let defaultness = ast::Defaultness::Final; let defaultness = ast::Defaultness::Final;
@ -961,7 +965,7 @@ impl<'a> MethodDef<'a> {
P(ast::AssocItem { P(ast::AssocItem {
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
attrs: self.attributes.clone(), attrs: self.attributes.clone(),
span: trait_.span, span,
vis: ast::Visibility { vis: ast::Visibility {
span: trait_lo_sp, span: trait_lo_sp,
kind: ast::VisibilityKind::Inherited, kind: ast::VisibilityKind::Inherited,
@ -1024,11 +1028,11 @@ impl<'a> MethodDef<'a> {
nonself_args: &[P<Expr>], nonself_args: &[P<Expr>],
use_temporaries: bool, use_temporaries: bool,
) -> P<Expr> { ) -> P<Expr> {
let mut raw_fields = Vec::new(); // Vec<[fields of self], let mut raw_fields = Vec::new(); // Vec<[fields of self], [fields of next Self arg], [etc]>
// [fields of next Self arg], [etc]> let span = trait_.span;
let mut patterns = Vec::new(); let mut patterns = Vec::new();
for i in 0..self_args.len() { 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( let (pat, ident_expr) = trait_.create_struct_pattern(
cx, cx,
struct_path, struct_path,
@ -1048,7 +1052,7 @@ impl<'a> MethodDef<'a> {
let mut other_fields: Vec<vec::IntoIter<_>> = raw_fields.collect(); let mut other_fields: Vec<vec::IntoIter<_>> = raw_fields.collect();
first_field first_field
.map(|(span, opt_id, field, attrs)| FieldInfo { .map(|(span, opt_id, field, attrs)| FieldInfo {
span, span: span.with_ctxt(trait_.span.ctxt()),
name: opt_id, name: opt_id,
self_: field, self_: field,
other: other_fields other: other_fields
@ -1062,7 +1066,7 @@ impl<'a> MethodDef<'a> {
}) })
.collect() .collect()
} else { } 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 // 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 // structs. This is actually right-to-left, but it shouldn't
// matter. // matter.
for (arg_expr, pat) in iter::zip(self_args, patterns) { for (arg_expr, pat) in iter::zip(self_args, patterns) {
body = cx.expr_match( body = cx.expr_match(span, arg_expr.clone(), vec![cx.arm(span, pat.clone(), body)])
trait_.span,
arg_expr.clone(),
vec![cx.arm(trait_.span, pat.clone(), body)],
)
} }
body body
@ -1193,7 +1193,7 @@ impl<'a> MethodDef<'a> {
mut self_args: Vec<P<Expr>>, mut self_args: Vec<P<Expr>>,
nonself_args: &[P<Expr>], nonself_args: &[P<Expr>],
) -> P<Expr> { ) -> P<Expr> {
let sp = trait_.span; let span = trait_.span;
let variants = &enum_def.variants; let variants = &enum_def.variants;
let self_arg_names = iter::once("__self".to_string()) let self_arg_names = iter::once("__self".to_string())
@ -1208,7 +1208,7 @@ impl<'a> MethodDef<'a> {
let self_arg_idents = self_arg_names let self_arg_idents = self_arg_names
.iter() .iter()
.map(|name| Ident::from_str_and_span(name, sp)) .map(|name| Ident::from_str_and_span(name, span))
.collect::<Vec<Ident>>(); .collect::<Vec<Ident>>();
// The `vi_idents` will be bound, solely in the catch-all, to // 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 let vi_idents = self_arg_names
.iter() .iter()
.map(|name| { .map(|name| {
let vi_suffix = format!("{}_vi", &name[..]); let vi_suffix = format!("{}_vi", name);
Ident::from_str_and_span(&vi_suffix, trait_.span) Ident::from_str_and_span(&vi_suffix, span)
}) })
.collect::<Vec<Ident>>(); .collect::<Vec<Ident>>();
@ -1226,7 +1226,7 @@ impl<'a> MethodDef<'a> {
// delegated expression that handles the catch-all case, // delegated expression that handles the catch-all case,
// using `__variants_tuple` to drive logic if necessary. // using `__variants_tuple` to drive logic if necessary.
let catch_all_substructure = 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()); let first_fieldless = variants.iter().find(|v| v.data.fields().is_empty());
@ -1248,7 +1248,7 @@ impl<'a> MethodDef<'a> {
self_arg_name, self_arg_name,
ast::Mutability::Not, 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 // A single arm has form (&VariantK, &VariantK, ...) => BodyK
@ -1261,13 +1261,13 @@ impl<'a> MethodDef<'a> {
idents idents
}; };
for self_arg_name in &self_arg_names[1..] { 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); subpats.push(p);
self_pats_idents.push(idents); self_pats_idents.push(idents);
} }
// Here is the pat = `(&VariantK, &VariantK, ...)` // 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, // For the BodyK, we need to delegate to our caller,
// passing it an EnumMatching to indicate which case // passing it an EnumMatching to indicate which case
@ -1284,7 +1284,7 @@ impl<'a> MethodDef<'a> {
.into_iter() .into_iter()
.enumerate() .enumerate()
// For each arg field of self, pull out its getter expr ... // 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 // ... but FieldInfo also wants getter expr
// for matching other arguments of Self type; // for matching other arguments of Self type;
// so walk across the *other* self_pats_idents // so walk across the *other* self_pats_idents
@ -1307,7 +1307,7 @@ impl<'a> MethodDef<'a> {
.collect::<Vec<P<Expr>>>(); .collect::<Vec<P<Expr>>>();
FieldInfo { FieldInfo {
span: sp, span,
name: opt_ident, name: opt_ident,
self_: self_getter_expr, self_: self_getter_expr,
other: others, other: others,
@ -1330,7 +1330,7 @@ impl<'a> MethodDef<'a> {
&substructure, &substructure,
); );
cx.arm(sp, single_pat, arm_expr) cx.arm(span, single_pat, arm_expr)
}) })
.collect(); .collect();
@ -1353,12 +1353,12 @@ impl<'a> MethodDef<'a> {
// Since we know that all the arguments will match if we reach // Since we know that all the arguments will match if we reach
// the match expression we add the unreachable intrinsics as the // the match expression we add the unreachable intrinsics as the
// result of the catch all which should help llvm in optimizing it // 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, _ => None,
}; };
if let Some(arm) = default { 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 // 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 // We also build an expression which checks whether all discriminants are equal
// discriminant_test = __self0_vi == __self1_vi && __self0_vi == __self2_vi && ... // 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; let mut first_ident = None;
for (&ident, self_arg) in iter::zip(&vi_idents, &self_args) { 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 = let variant_value =
deriving::call_intrinsic(cx, sp, sym::discriminant_value, vec![self_addr]); deriving::call_intrinsic(cx, span, sym::discriminant_value, vec![self_addr]);
let let_stmt = cx.stmt_let(sp, false, ident, variant_value); let let_stmt = cx.stmt_let(span, false, ident, variant_value);
index_let_stmts.push(let_stmt); index_let_stmts.push(let_stmt);
match first_ident { match first_ident {
Some(first) => { Some(first) => {
let first_expr = cx.expr_ident(sp, first); let first_expr = cx.expr_ident(span, first);
let id = cx.expr_ident(sp, ident); let id = cx.expr_ident(span, ident);
let test = cx.expr_binary(sp, BinOpKind::Eq, first_expr, id); let test = cx.expr_binary(span, BinOpKind::Eq, first_expr, id);
discriminant_test = discriminant_test =
cx.expr_binary(sp, BinOpKind::And, discriminant_test, test) cx.expr_binary(span, BinOpKind::And, discriminant_test, test)
} }
None => { None => {
first_ident = Some(ident); first_ident = Some(ident);
@ -1430,8 +1430,8 @@ impl<'a> MethodDef<'a> {
// them when they are fed as r-values into a tuple // them when they are fed as r-values into a tuple
// expression; here add a layer of borrowing, turning // expression; here add a layer of borrowing, turning
// `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`. // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`.
self_args.map_in_place(|self_arg| cx.expr_addr_of(sp, self_arg)); self_args.map_in_place(|self_arg| cx.expr_addr_of(span, self_arg));
let match_arg = cx.expr(sp, ast::ExprKind::Tup(self_args)); let match_arg = cx.expr(span, ast::ExprKind::Tup(self_args));
// Lastly we create an expression which branches on all discriminants being equal // Lastly we create an expression which branches on all discriminants being equal
// if discriminant_test { // if discriminant_test {
@ -1445,10 +1445,10 @@ impl<'a> MethodDef<'a> {
// else { // else {
// <delegated expression referring to __self0_vi, et al.> // <delegated expression referring to __self0_vi, et al.>
// } // }
let all_match = cx.expr_match(sp, match_arg, match_arms); let all_match = cx.expr_match(span, match_arg, match_arms);
let arm_expr = cx.expr_if(sp, discriminant_test, all_match, Some(arm_expr)); let arm_expr = cx.expr_if(span, discriminant_test, all_match, Some(arm_expr));
index_let_stmts.push(cx.stmt_expr(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() { } else if variants.is_empty() {
// As an additional wrinkle, For a zero-variant enum A, // As an additional wrinkle, For a zero-variant enum A,
// currently the compiler // currently the compiler
@ -1499,16 +1499,16 @@ impl<'a> MethodDef<'a> {
// derive Debug on such a type could here generate code // derive Debug on such a type could here generate code
// that needs the feature gate enabled.) // that needs the feature gate enabled.)
deriving::call_unreachable(cx, sp) deriving::call_unreachable(cx, span)
} else { } else {
// Final wrinkle: the self_args are expressions that deref // Final wrinkle: the self_args are expressions that deref
// down to desired places, but we cannot actually deref // down to desired places, but we cannot actually deref
// them when they are fed as r-values into a tuple // them when they are fed as r-values into a tuple
// expression; here add a layer of borrowing, turning // expression; here add a layer of borrowing, turning
// `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`. // `(*self, *__arg_0, ...)` into `(&*self, &*__arg_0, ...)`.
self_args.map_in_place(|self_arg| cx.expr_addr_of(sp, self_arg)); self_args.map_in_place(|self_arg| cx.expr_addr_of(span, self_arg));
let match_arg = cx.expr(sp, ast::ExprKind::Tup(self_args)); let match_arg = cx.expr(span, ast::ExprKind::Tup(self_args));
cx.expr_match(sp, match_arg, match_arms) 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(..)); let is_tuple = matches!(struct_def, ast::VariantData::Tuple(..));
match (just_spans.is_empty(), named_idents.is_empty()) { match (just_spans.is_empty(), named_idents.is_empty()) {
(false, false) => cx.span_bug( (false, false) => {
self.span, cx.span_bug(self.span, "a struct with named and unnamed fields in generic `derive`")
"a struct with named and unnamed \ }
fields in generic `derive`",
),
// named fields // named fields
(_, false) => Named(named_idents), (_, false) => Named(named_idents),
// unnamed fields // unnamed fields

View File

@ -211,14 +211,6 @@ fn mk_ty_param(
cx.typaram(span, Ident::new(name, span), attrs.to_owned(), bounds, None) cx.typaram(span, Ident::new(name, span), attrs.to_owned(), bounds, None)
} }
fn mk_generics(params: Vec<ast::GenericParam>, span: Span) -> Generics {
Generics {
params,
where_clause: ast::WhereClause { has_where_token: false, predicates: Vec::new(), span },
span,
}
}
/// Bounds on type parameters. /// Bounds on type parameters.
#[derive(Clone)] #[derive(Clone)]
pub struct Bounds { pub struct Bounds {
@ -236,7 +228,7 @@ impl Bounds {
self_ty: Ident, self_ty: Ident,
self_generics: &Generics, self_generics: &Generics,
) -> Generics { ) -> Generics {
let generic_params = self let params = self
.bounds .bounds
.iter() .iter()
.map(|t| { .map(|t| {
@ -245,7 +237,11 @@ impl Bounds {
}) })
.collect(); .collect();
mk_generics(generic_params, span) Generics {
params,
where_clause: ast::WhereClause { has_where_token: false, predicates: Vec::new(), span },
span,
}
} }
} }

View File

@ -20,8 +20,29 @@ pub fn expand_panic<'cx>(
sp: Span, sp: Span,
tts: TokenStream, tts: TokenStream,
) -> Box<dyn MacResult + 'cx> { ) -> Box<dyn MacResult + 'cx> {
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<dyn MacResult + 'cx> {
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<dyn MacResult + 'cx> {
let sp = cx.with_call_site_ctxt(sp); let sp = cx.with_call_site_ctxt(sp);
MacEager::expr( MacEager::expr(
@ -31,7 +52,7 @@ pub fn expand_panic<'cx>(
path: Path { path: Path {
span: sp, span: sp,
segments: cx segments: cx
.std_path(&[sym::panic, panic]) .std_path(&[sym::panic, mac])
.into_iter() .into_iter()
.map(|ident| PathSegment::from_ident(ident)) .map(|ident| PathSegment::from_ident(ident))
.collect(), .collect(),

View File

@ -80,11 +80,11 @@ pub fn expand_env<'cx>(
} }
let sp = cx.with_def_site_ctxt(sp); 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)); cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value));
let e = match value { let e = match value {
None => { None => {
cx.span_err(sp, &msg.as_str()); cx.span_err(sp, msg.as_str());
return DummyResult::any(sp); return DummyResult::any(sp);
} }
Some(value) => cx.expr_str(sp, value), Some(value) => cx.expr_str(sp, value),

View File

@ -23,6 +23,7 @@ enum ArgumentType {
enum Position { enum Position {
Exact(usize), Exact(usize),
Capture(usize),
Named(Symbol), Named(Symbol),
} }
@ -47,6 +48,8 @@ struct Context<'a, 'b> {
/// * `arg_unique_types` (in simplified JSON): `[["o", "x"], ["o", "x"], ["o", "x"]]` /// * `arg_unique_types` (in simplified JSON): `[["o", "x"], ["o", "x"], ["o", "x"]]`
/// * `names` (in JSON): `{"foo": 2}` /// * `names` (in JSON): `{"foo": 2}`
args: Vec<P<ast::Expr>>, args: Vec<P<ast::Expr>>,
/// The number of arguments that were added by implicit capturing.
num_captured_args: usize,
/// Placeholder slot numbers indexed by argument. /// Placeholder slot numbers indexed by argument.
arg_types: Vec<Vec<usize>>, arg_types: Vec<Vec<usize>>,
/// Unique format specs seen for each argument. /// 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$}"` /// * Implicit argument resolution: `"{1:.0$} {2:.foo$} {1:.3$} {4:.0$}"`
/// * Name resolution: `"{1:.0$} {2:.5$} {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_positions` (in JSON): `{0: 0, 5: 1, 3: 2}`
/// * `count_args`: `vec![Exact(0), Exact(5), Exact(3)]` /// * `count_args`: `vec![0, 5, 3]`
count_args: Vec<Position>, count_args: Vec<usize>,
/// Relative slot numbers for count arguments. /// Relative slot numbers for count arguments.
count_positions: FxHashMap<usize, usize>, count_positions: FxHashMap<usize, usize>,
/// Number of count slots assigned. /// Number of count slots assigned.
@ -229,6 +232,11 @@ fn parse_args<'a>(
} }
impl<'a, 'b> Context<'a, 'b> { 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<'_>) { fn resolve_name_inplace(&self, p: &mut parse::Piece<'_>) {
// NOTE: the `unwrap_or` branch is needed in case of invalid format // NOTE: the `unwrap_or` branch is needed in case of invalid format
// arguments, e.g., `format_args!("{foo}")`. // arguments, e.g., `format_args!("{foo}")`.
@ -343,7 +351,7 @@ impl<'a, 'b> Context<'a, 'b> {
} }
fn describe_num_args(&self) -> Cow<'_, str> { fn describe_num_args(&self) -> Cow<'_, str> {
match self.args.len() { match self.num_args() {
0 => "no arguments were given".into(), 0 => "no arguments were given".into(),
1 => "there is 1 argument".into(), 1 => "there is 1 argument".into(),
x => format!("there are {} arguments", x).into(), x => format!("there are {} arguments", x).into(),
@ -369,7 +377,7 @@ impl<'a, 'b> Context<'a, 'b> {
let count = self.pieces.len() let count = self.pieces.len()
+ self.arg_with_formatting.iter().filter(|fmt| fmt.precision_span.is_some()).count(); + 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( e = self.ecx.struct_span_err(
sp, sp,
&format!( &format!(
@ -417,7 +425,7 @@ impl<'a, 'b> Context<'a, 'b> {
if let Some(span) = fmt.precision_span { if let Some(span) = fmt.precision_span {
let span = self.fmtsp.from_inner(span); let span = self.fmtsp.from_inner(span);
match fmt.precision { match fmt.precision {
parse::CountIsParam(pos) if pos > self.args.len() => { parse::CountIsParam(pos) if pos > self.num_args() => {
e.span_label( e.span_label(
span, span,
&format!( &format!(
@ -460,7 +468,7 @@ impl<'a, 'b> Context<'a, 'b> {
if let Some(span) = fmt.width_span { if let Some(span) = fmt.width_span {
let span = self.fmtsp.from_inner(span); let span = self.fmtsp.from_inner(span);
match fmt.width { match fmt.width {
parse::CountIsParam(pos) if pos > self.args.len() => { parse::CountIsParam(pos) if pos > self.num_args() => {
e.span_label( e.span_label(
span, span,
&format!( &format!(
@ -492,12 +500,15 @@ impl<'a, 'b> Context<'a, 'b> {
/// Actually verifies and tracks a given format placeholder /// Actually verifies and tracks a given format placeholder
/// (a.k.a. argument). /// (a.k.a. argument).
fn verify_arg_type(&mut self, arg: Position, ty: ArgumentType) { 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 { match arg {
Exact(arg) => { Exact(arg) | Capture(arg) => {
if self.args.len() <= arg {
self.invalid_refs.push((arg, self.curpiece));
return;
}
match ty { match ty {
Placeholder(_) => { Placeholder(_) => {
// record every (position, type) combination only once // 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) { if let Entry::Vacant(e) = self.count_positions.entry(arg) {
let i = self.count_positions_count; let i = self.count_positions_count;
e.insert(i); e.insert(i);
self.count_args.push(Exact(arg)); self.count_args.push(arg);
self.count_positions_count += 1; self.count_positions_count += 1;
} }
} }
@ -524,7 +535,7 @@ impl<'a, 'b> Context<'a, 'b> {
match self.names.get(&name) { match self.names.get(&name) {
Some(&idx) => { Some(&idx) => {
// Treat as positional arg. // Treat as positional arg.
self.verify_arg_type(Exact(idx), ty) self.verify_arg_type(Capture(idx), ty)
} }
None => { None => {
// For the moment capturing variables from format strings expanded from macros is // For the moment capturing variables from format strings expanded from macros is
@ -539,9 +550,10 @@ impl<'a, 'b> Context<'a, 'b> {
} else { } else {
self.fmtsp self.fmtsp
}; };
self.num_captured_args += 1;
self.args.push(self.ecx.expr_ident(span, Ident::new(name, span))); self.args.push(self.ecx.expr_ident(span, Ident::new(name, span)));
self.names.insert(name, idx); self.names.insert(name, idx);
self.verify_arg_type(Exact(idx), ty) self.verify_arg_type(Capture(idx), ty)
} else { } else {
let msg = format!("there is no argument named `{}`", name); let msg = format!("there is no argument named `{}`", name);
let sp = if self.is_literal { let sp = if self.is_literal {
@ -549,7 +561,7 @@ impl<'a, 'b> Context<'a, 'b> {
} else { } else {
self.fmtsp 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!( err.note(&format!(
"did you intend to capture a variable `{}` from \ "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() { for arg_ty in self.arg_unique_types[i].iter() {
args.push(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty, i)); 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 { for index in self.count_args {
let index = match pos {
Exact(i) => i,
_ => panic!("should never happen"),
};
let span = spans_pos[index]; let span = spans_pos[index];
args.push(Context::format_arg(self.ecx, self.macsp, span, &Count, 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), 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 fmt_snippet = ecx.source_map().span_to_snippet(fmt_sp).ok();
let mut parser = parse::Parser::new( let mut parser = parse::Parser::new(
fmt_str, fmt_str,
@ -996,8 +1007,9 @@ pub fn expand_preparsed_format_args(
e.note(&note); e.note(&note);
} }
if let Some((label, span)) = err.secondary_label { if let Some((label, span)) = err.secondary_label {
let sp = fmt_span.from_inner(span); if efmt_kind_is_lit {
e.span_label(sp, label); e.span_label(fmt_span.from_inner(span), label);
}
} }
e.emit(); e.emit();
return DummyResult::raw_expr(sp, true); return DummyResult::raw_expr(sp, true);
@ -1010,6 +1022,7 @@ pub fn expand_preparsed_format_args(
let mut cx = Context { let mut cx = Context {
ecx, ecx,
args, args,
num_captured_args: 0,
arg_types, arg_types,
arg_unique_types, arg_unique_types,
names, names,

View File

@ -7,28 +7,29 @@ pub(crate) mod printf {
pub enum Substitution<'a> { pub enum Substitution<'a> {
/// A formatted output substitution with its internal byte offset. /// A formatted output substitution with its internal byte offset.
Format(Format<'a>), Format(Format<'a>),
/// A literal `%%` escape. /// A literal `%%` escape, with its start and end indices.
Escape, Escape((usize, usize)),
} }
impl<'a> Substitution<'a> { impl<'a> Substitution<'a> {
pub fn as_str(&self) -> &str { pub fn as_str(&self) -> &str {
match *self { match *self {
Substitution::Format(ref fmt) => fmt.span, Substitution::Format(ref fmt) => fmt.span,
Substitution::Escape => "%%", Substitution::Escape(_) => "%%",
} }
} }
pub fn position(&self) -> Option<InnerSpan> { pub fn position(&self) -> Option<InnerSpan> {
match *self { match *self {
Substitution::Format(ref fmt) => Some(fmt.position), 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) { pub fn set_position(&mut self, start: usize, end: usize) {
if let Substitution::Format(ref mut fmt) = self { match self {
fmt.position = InnerSpan::new(start, end); 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<String, Option<String>> { pub fn translate(&self) -> Result<String, Option<String>> {
match *self { match *self {
Substitution::Format(ref fmt) => fmt.translate(), 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<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let (mut sub, tail) = parse_next_substitution(self.s)?; let (mut sub, tail) = parse_next_substitution(self.s)?;
self.s = tail; self.s = tail;
match sub { if let Some(InnerSpan { start, end }) = sub.position() {
Substitution::Format(_) => { sub.set_position(start + self.pos, end + self.pos);
if let Some(inner_span) = sub.position() { self.pos += end;
sub.set_position(inner_span.start + self.pos, inner_span.end + self.pos);
self.pos += inner_span.end;
}
}
Substitution::Escape => self.pos += 2,
} }
Some(sub) Some(sub)
} }
@ -340,7 +336,7 @@ pub(crate) mod printf {
let at = { let at = {
let start = s.find('%')?; let start = s.find('%')?;
if let '%' = s[start + 1..].chars().next()? { 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) Cur::new_at(s, start)

View File

@ -13,9 +13,9 @@ macro_rules! assert_eq_pnsat {
fn test_escape() { fn test_escape() {
assert_eq!(pns("has no escapes"), None); assert_eq!(pns("has no escapes"), None);
assert_eq!(pns("has no escapes, either %"), None); assert_eq!(pns("has no escapes, either %"), None);
assert_eq!(pns("*so* has a %% escape"), Some((S::Escape, " escape"))); assert_eq!(pns("*so* has a %% escape"), Some((S::Escape((11, 13)), " escape")));
assert_eq!(pns("%% leading escape"), Some((S::Escape, " leading escape"))); assert_eq!(pns("%% leading escape"), Some((S::Escape((0, 2)), " leading escape")));
assert_eq!(pns("trailing escape %%"), Some((S::Escape, ""))); assert_eq!(pns("trailing escape %%"), Some((S::Escape((16, 18)), "")));
} }
#[test] #[test]

View File

@ -6,7 +6,6 @@
#![feature(bool_to_option)] #![feature(bool_to_option)]
#![feature(crate_visibility_modifier)] #![feature(crate_visibility_modifier)]
#![feature(decl_macro)] #![feature(decl_macro)]
#![feature(iter_zip)]
#![feature(nll)] #![feature(nll)]
#![feature(proc_macro_internals)] #![feature(proc_macro_internals)]
#![feature(proc_macro_quote)] #![feature(proc_macro_quote)]
@ -20,28 +19,29 @@ use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind};
use rustc_expand::proc_macro::BangProcMacro; use rustc_expand::proc_macro::BangProcMacro;
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
mod asm;
mod assert; mod assert;
mod cfg; mod cfg;
mod cfg_accessible; mod cfg_accessible;
mod cfg_eval; mod cfg_eval;
mod compile_error; mod compile_error;
mod concat; mod concat;
mod concat_bytes;
mod concat_idents; mod concat_idents;
mod derive; mod derive;
mod deriving; mod deriving;
mod edition_panic;
mod env; mod env;
mod format; mod format;
mod format_foreign; mod format_foreign;
mod global_allocator; mod global_allocator;
mod llvm_asm; mod llvm_asm;
mod log_syntax; mod log_syntax;
mod panic;
mod source_util; mod source_util;
mod test; mod test;
mod trace_macros; mod trace_macros;
mod util; mod util;
pub mod asm;
pub mod cmdline_attrs; pub mod cmdline_attrs;
pub mod proc_macro_harness; pub mod proc_macro_harness;
pub mod standard_library_imports; pub mod standard_library_imports;
@ -65,6 +65,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
cfg: cfg::expand_cfg, cfg: cfg::expand_cfg,
column: source_util::expand_column, column: source_util::expand_column,
compile_error: compile_error::expand_compile_error, compile_error: compile_error::expand_compile_error,
concat_bytes: concat_bytes::expand_concat_bytes,
concat_idents: concat_idents::expand_concat_idents, concat_idents: concat_idents::expand_concat_idents,
concat: concat::expand_concat, concat: concat::expand_concat,
env: env::expand_env, env: env::expand_env,
@ -81,8 +82,9 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
log_syntax: log_syntax::expand_log_syntax, log_syntax: log_syntax::expand_log_syntax,
module_path: source_util::expand_mod, module_path: source_util::expand_mod,
option_env: env::expand_option_env, option_env: env::expand_option_env,
core_panic: panic::expand_panic, core_panic: edition_panic::expand_panic,
std_panic: panic::expand_panic, std_panic: edition_panic::expand_panic,
unreachable: edition_panic::expand_unreachable,
stringify: source_util::expand_stringify, stringify: source_util::expand_stringify,
trace_macros: trace_macros::expand_trace_macros, trace_macros: trace_macros::expand_trace_macros,
} }

View File

@ -1,6 +1,6 @@
/// The expansion from a test function to the appropriate test struct for libtest /// 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. /// 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 as ast;
use rustc_ast::attr; use rustc_ast::attr;
@ -27,6 +27,7 @@ pub fn expand_test_case(
anno_item: Annotatable, anno_item: Annotatable,
) -> Vec<Annotatable> { ) -> Vec<Annotatable> {
check_builtin_macro_attribute(ecx, meta_item, sym::test_case); 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 { if !ecx.ecfg.should_test {
return vec![]; return vec![];
@ -55,6 +56,7 @@ pub fn expand_test(
item: Annotatable, item: Annotatable,
) -> Vec<Annotatable> { ) -> Vec<Annotatable> {
check_builtin_macro_attribute(cx, meta_item, sym::test); 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) expand_test_or_bench(cx, attr_sp, item, false)
} }
@ -65,6 +67,7 @@ pub fn expand_bench(
item: Annotatable, item: Annotatable,
) -> Vec<Annotatable> { ) -> Vec<Annotatable> {
check_builtin_macro_attribute(cx, meta_item, sym::bench); 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) expand_test_or_bench(cx, attr_sp, item, true)
} }

View File

@ -84,9 +84,35 @@ struct TestHarnessGenerator<'a> {
tests: Vec<Test>, tests: Vec<Test>,
} }
impl TestHarnessGenerator<'_> {
fn add_test_cases(&mut self, node_id: ast::NodeId, span: Span, prev_tests: Vec<Test>) {
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> { impl<'a> MutVisitor for TestHarnessGenerator<'a> {
fn visit_crate(&mut self, c: &mut ast::Crate) { fn visit_crate(&mut self, c: &mut ast::Crate) {
let prev_tests = mem::take(&mut self.tests);
noop_visit_crate(c, self); 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 // Create a main function to run our tests
c.items.push(mk_main(&mut self.cx)); 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 // We don't want to recurse into anything other than mods, since
// mods or tests inside of functions will break things // mods or tests inside of functions will break things
if let ast::ItemKind::Mod(..) = item.kind { if let ast::ItemKind::Mod(_, ModKind::Loaded(.., span)) = item.kind {
let tests = mem::take(&mut self.tests); let prev_tests = mem::take(&mut self.tests);
noop_visit_item_kind(&mut item.kind, self); noop_visit_item_kind(&mut item.kind, self);
let mut tests = mem::replace(&mut self.tests, tests); self.add_test_cases(item.id, span, prev_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);
}
} }
smallvec![P(item)] 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) { } else if sess.contains_name(&item.attrs, sym::rustc_main) {
EntryPointType::MainAttr EntryPointType::MainAttr
} else if item.ident.name == sym::main { } else if item.ident.name == sym::main {
if depth == 1 { if depth == 0 {
// This is a top-level function so can be 'main' // This is a top-level function so can be 'main'
EntryPointType::MainNamed EntryPointType::MainNamed
} else { } else {

View File

@ -1,6 +1,7 @@
use rustc_ast::MetaItem; use rustc_ast::{Attribute, MetaItem};
use rustc_expand::base::ExtCtxt; use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_feature::AttributeTemplate; use rustc_feature::AttributeTemplate;
use rustc_lint_defs::builtin::DUPLICATE_MACRO_ATTRIBUTES;
use rustc_parse::validate_attr; use rustc_parse::validate_attr;
use rustc_span::Symbol; 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()); let attr = ecx.attribute(meta_item.clone());
validate_attr::check_builtin_attribute(&ecx.sess.parse_sess, &attr, name, template); 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(&param.attrs),
Annotatable::Param(param) => Some(&param.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",
);
}
}
}

View File

@ -5,6 +5,21 @@ on:
- pull_request - pull_request
jobs: 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: build:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
timeout-minutes: 60 timeout-minutes: 60
@ -65,6 +80,12 @@ jobs:
git config --global user.name "User" git config --global user.name "User"
./y.rs prepare ./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 - name: Build
run: ./y.rs build --sysroot none run: ./y.rs build --sysroot none
@ -152,11 +173,12 @@ jobs:
./y.exe build ./y.exe build
#- name: Package prebuilt cg_clif - name: Package prebuilt cg_clif
# run: tar cvfJ cg_clif.tar.xz build # 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 - name: Upload prebuilt cg_clif
# uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v2
# with: with:
# name: cg_clif-${{ runner.os }} name: cg_clif-${{ runner.os }}
# path: cg_clif.tar.xz path: cg_clif.tar

View File

@ -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

View File

@ -5,6 +5,7 @@
"rust-analyzer.assist.importEnforceGranularity": true, "rust-analyzer.assist.importEnforceGranularity": true,
"rust-analyzer.assist.importPrefix": "crate", "rust-analyzer.assist.importPrefix": "crate",
"rust-analyzer.cargo.runBuildScripts": true, "rust-analyzer.cargo.runBuildScripts": true,
"rust-analyzer.cargo.features": ["unstable-features"]
"rust-analyzer.linkedProjects": [ "rust-analyzer.linkedProjects": [
"./Cargo.toml", "./Cargo.toml",
//"./build_sysroot/sysroot_src/src/libstd/Cargo.toml", //"./build_sysroot/sysroot_src/src/libstd/Cargo.toml",

View File

@ -4,9 +4,9 @@ version = 3
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.42" version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486" checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203"
[[package]] [[package]]
name = "ar" name = "ar"
@ -21,9 +21,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.2.1" version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
@ -33,16 +33,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "cranelift-bforest" name = "cranelift-bforest"
version = "0.76.0" version = "0.78.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc0cb7df82c8cf8f2e6a8dd394a0932a71369c160cc9b027dca414fced242513"
dependencies = [ dependencies = [
"cranelift-entity", "cranelift-entity",
] ]
[[package]] [[package]]
name = "cranelift-codegen" name = "cranelift-codegen"
version = "0.76.0" version = "0.78.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe4463c15fa42eee909e61e5eac4866b7c6d22d0d8c621e57a0c5380753bfa8c"
dependencies = [ dependencies = [
"cranelift-bforest", "cranelift-bforest",
"cranelift-codegen-meta", "cranelift-codegen-meta",
@ -57,8 +59,9 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-codegen-meta" name = "cranelift-codegen-meta"
version = "0.76.0" version = "0.78.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793f6a94a053a55404ea16e1700202a88101672b8cd6b4df63e13cde950852bf"
dependencies = [ dependencies = [
"cranelift-codegen-shared", "cranelift-codegen-shared",
"cranelift-entity", "cranelift-entity",
@ -66,18 +69,21 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-codegen-shared" name = "cranelift-codegen-shared"
version = "0.76.0" version = "0.78.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44aa1846df275bce5eb30379d65964c7afc63c05a117076e62a119c25fe174be"
[[package]] [[package]]
name = "cranelift-entity" name = "cranelift-entity"
version = "0.76.0" version = "0.78.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3a45d8d6318bf8fc518154d9298eab2a8154ec068a8885ff113f6db8d69bb3a"
[[package]] [[package]]
name = "cranelift-frontend" name = "cranelift-frontend"
version = "0.76.0" version = "0.78.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e07339bd461766deb7605169de039e01954768ff730fa1254e149001884a8525"
dependencies = [ dependencies = [
"cranelift-codegen", "cranelift-codegen",
"log", "log",
@ -87,8 +93,9 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-jit" name = "cranelift-jit"
version = "0.76.0" version = "0.78.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e8f0d60fb5d67f7a1e5c49db38ba96d1c846921faef02085fc5590b74781747"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cranelift-codegen", "cranelift-codegen",
@ -104,8 +111,9 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-module" name = "cranelift-module"
version = "0.76.0" version = "0.78.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "825ac7e0959cbe7ddc9cc21209f0319e611a57f9fcb2b723861fe7ef2017e651"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cranelift-codegen", "cranelift-codegen",
@ -115,8 +123,9 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-native" name = "cranelift-native"
version = "0.76.0" version = "0.78.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03e2fca76ff57e0532936a71e3fc267eae6a19a86656716479c66e7f912e3d7b"
dependencies = [ dependencies = [
"cranelift-codegen", "cranelift-codegen",
"libc", "libc",
@ -125,8 +134,9 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-object" name = "cranelift-object"
version = "0.76.0" version = "0.78.0"
source = "git+https://github.com/bytecodealliance/wasmtime.git#9c550fcf41425942ed97c747f0169b2ca81f9c1b" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55500d0fc9bb05c0944fc4506649249d28f55bd4fe95b87f0e55bf41058f0e6d"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cranelift-codegen", "cranelift-codegen",
@ -138,9 +148,9 @@ dependencies = [
[[package]] [[package]]
name = "crc32fast" name = "crc32fast"
version = "1.2.1" version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" checksum = "738c290dfaea84fc1ca15ad9c168d083b05a714e1efddd8edaab678dc28d2836"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
] ]
@ -172,9 +182,9 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.98" version = "0.2.112"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
[[package]] [[package]]
name = "libloading" name = "libloading"
@ -206,15 +216,15 @@ dependencies = [
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.4.0" version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]] [[package]]
name = "object" name = "object"
version = "0.26.0" version = "0.27.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c55827317fb4c08822499848a14237d2874d6f139828893017237e7ab93eb386" checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9"
dependencies = [ dependencies = [
"crc32fast", "crc32fast",
"indexmap", "indexmap",
@ -223,9 +233,9 @@ dependencies = [
[[package]] [[package]]
name = "regalloc" name = "regalloc"
version = "0.0.31" version = "0.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "571f7f397d61c4755285cd37853fe8e03271c243424a907415909379659381c5" checksum = "a6304468554ed921da3d32c355ea107b8d13d7b8996c3adfb7aab48d3bc321f4"
dependencies = [ dependencies = [
"log", "log",
"rustc-hash", "rustc-hash",
@ -271,15 +281,15 @@ dependencies = [
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.6.1" version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
[[package]] [[package]]
name = "target-lexicon" name = "target-lexicon"
version = "0.12.1" version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0652da4c4121005e9ed22b79f6c5f2d9e2752906b53a33e9490489ba421a6fb" checksum = "d9bffcddbc2458fa3e6058414599e3c838a022abae82e5c67b4f7f80298d5bff"
[[package]] [[package]]
name = "winapi" name = "winapi"

View File

@ -8,23 +8,23 @@ crate-type = ["dylib"]
[dependencies] [dependencies]
# These have to be in sync with each other # These have to be in sync with each other
cranelift-codegen = { git = "https://github.com/bytecodealliance/wasmtime.git", features = ["unwind", "all-arch"] } cranelift-codegen = { version = "0.78.0", features = ["unwind", "all-arch"] }
cranelift-frontend = { git = "https://github.com/bytecodealliance/wasmtime.git" } cranelift-frontend = "0.78.0"
cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime.git" } cranelift-module = "0.78.0"
cranelift-native = { git = "https://github.com/bytecodealliance/wasmtime.git" } cranelift-native = "0.78.0"
cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime.git", optional = true } cranelift-jit = { version = "0.78.0", optional = true }
cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime.git" } cranelift-object = "0.78.0"
target-lexicon = "0.12.0" target-lexicon = "0.12.0"
gimli = { version = "0.25.0", default-features = false, features = ["write"]} 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" } ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "do_not_remove_cg_clif_ranlib" }
indexmap = "1.0.2" indexmap = "1.0.2"
libloading = { version = "0.6.0", optional = true } libloading = { version = "0.6.0", optional = true }
smallvec = "1.6.1" smallvec = "1.6.1"
[patch.crates-io]
# Uncomment to use local checkout of cranelift # Uncomment to use local checkout of cranelift
#[patch."https://github.com/bytecodealliance/wasmtime.git"]
#cranelift-codegen = { path = "../wasmtime/cranelift/codegen" } #cranelift-codegen = { path = "../wasmtime/cranelift/codegen" }
#cranelift-frontend = { path = "../wasmtime/cranelift/frontend" } #cranelift-frontend = { path = "../wasmtime/cranelift/frontend" }
#cranelift-module = { path = "../wasmtime/cranelift/module" } #cranelift-module = { path = "../wasmtime/cranelift/module" }
@ -32,7 +32,6 @@ smallvec = "1.6.1"
#cranelift-jit = { path = "../wasmtime/cranelift/jit" } #cranelift-jit = { path = "../wasmtime/cranelift/jit" }
#cranelift-object = { path = "../wasmtime/cranelift/object" } #cranelift-object = { path = "../wasmtime/cranelift/object" }
#[patch.crates-io]
#gimli = { path = "../" } #gimli = { path = "../" }
[features] [features]
@ -41,31 +40,12 @@ unstable-features = ["jit", "inline_asm"]
jit = ["cranelift-jit", "libloading"] jit = ["cranelift-jit", "libloading"]
inline_asm = [] 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 # 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. # 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] [profile.release.build-override]
opt-level = 0 opt-level = 0
debug = false debug = false
[profile.dev.package.cranelift-codegen-meta]
opt-level = 0
debug = false
[profile.release.package.cranelift-codegen-meta] [profile.release.package.cranelift-codegen-meta]
opt-level = 0 opt-level = 0
debug = false debug = false

View File

@ -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: In the directory with your project (where you can do the usual `cargo build`), run:
```bash ```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. This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend.

View File

@ -40,9 +40,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.70" version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0" checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
@ -56,7 +56,7 @@ dependencies = [
[[package]] [[package]]
name = "compiler_builtins" name = "compiler_builtins"
version = "0.1.50" version = "0.1.66"
dependencies = [ dependencies = [
"rustc-std-workspace-core", "rustc-std-workspace-core",
] ]
@ -67,9 +67,9 @@ version = "0.0.0"
[[package]] [[package]]
name = "dlmalloc" name = "dlmalloc"
version = "0.2.1" version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "332570860c2edf2d57914987bf9e24835425f75825086b6ba7d1e6a3e4f1f254" checksum = "a6fe28e0bf9357092740362502f5cc7955d8dc125ebda71dec72336c2e15c62e"
dependencies = [ dependencies = [
"compiler_builtins", "compiler_builtins",
"libc", "libc",
@ -132,9 +132,9 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.102" version = "0.2.112"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103" checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
dependencies = [ dependencies = [
"rustc-std-workspace-core", "rustc-std-workspace-core",
] ]

View File

@ -2,9 +2,29 @@ use std::env;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process::Command; 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"); 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 { match channel {
"debug" => {} "debug" => {}
@ -14,25 +34,20 @@ pub(crate) fn build_backend(channel: &str, host_triple: &str) -> PathBuf {
_ => unreachable!(), _ => unreachable!(),
} }
// Set the rpath to make the cg_clif executable find librustc_codegen_cranelift without changing
// LD_LIBRARY_PATH
if cfg!(unix) { if cfg!(unix) {
if cfg!(target_os = "macos") { if cfg!(target_os = "macos") {
cmd.env( rustflags += " -Csplit-debuginfo=unpacked \
"RUSTFLAGS",
"-Csplit-debuginfo=unpacked \
-Clink-arg=-Wl,-rpath,@loader_path/../lib \ -Clink-arg=-Wl,-rpath,@loader_path/../lib \
-Zosx-rpath-install-name" -Zosx-rpath-install-name";
.to_string()
+ env::var("RUSTFLAGS").as_deref().unwrap_or(""),
);
} else { } else {
cmd.env( rustflags += " -Clink-arg=-Wl,-rpath=$ORIGIN/../lib ";
"RUSTFLAGS",
"-Clink-arg=-Wl,-rpath=$ORIGIN/../lib ".to_string()
+ env::var("RUSTFLAGS").as_deref().unwrap_or(""),
);
} }
} }
cmd.env("RUSTFLAGS", rustflags);
eprintln!("[BUILD] rustc_codegen_cranelift"); eprintln!("[BUILD] rustc_codegen_cranelift");
crate::utils::spawn_and_wait(cmd); crate::utils::spawn_and_wait(cmd);

View File

@ -46,9 +46,9 @@ pub(crate) fn build_sysroot(
// Build and copy cargo wrapper // Build and copy cargo wrapper
let mut build_cargo_wrapper_cmd = Command::new("rustc"); let mut build_cargo_wrapper_cmd = Command::new("rustc");
build_cargo_wrapper_cmd build_cargo_wrapper_cmd
.arg("scripts/cargo.rs") .arg("scripts/cargo-clif.rs")
.arg("-o") .arg("-o")
.arg(target_dir.join("cargo")) .arg(target_dir.join("cargo-clif"))
.arg("-g"); .arg("-g");
spawn_and_wait(build_cargo_wrapper_cmd); spawn_and_wait(build_cargo_wrapper_cmd);
@ -193,8 +193,7 @@ fn build_clif_sysroot_for_triple(
"RUSTC", "RUSTC",
env::current_dir().unwrap().join(target_dir).join("bin").join("cg_clif_build_sysroot"), 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_DEFAULT_LIB_METADATA", "cg_clif");
build_cmd.env("CARGO_INCREMENTAL", "0").env("__CARGO_DEFAULT_LIB_METADATA", "cg_clif");
spawn_and_wait(build_cmd); spawn_and_wait(build_cmd);
// Copy all relevant files to the sysroot // Copy all relevant files to the sysroot

View File

@ -30,7 +30,7 @@ pub(crate) fn prepare() {
clone_repo( clone_repo(
"portable-simd", "portable-simd",
"https://github.com/rust-lang/portable-simd", "https://github.com/rust-lang/portable-simd",
"8cf7a62e5d2552961df51e5200aaa5b7c890a4bf", "b8d6b6844602f80af79cd96401339ec594d472d8",
); );
apply_patches("portable-simd", Path::new("portable-simd")); apply_patches("portable-simd", Path::new("portable-simd"));
@ -92,7 +92,7 @@ fn prepare_sysroot() {
clone_repo( clone_repo(
"build_sysroot/compiler-builtins", "build_sysroot/compiler-builtins",
"https://github.com/rust-lang/compiler-builtins.git", "https://github.com/rust-lang/compiler-builtins.git",
"0.1.50", "0.1.66",
); );
apply_patches("compiler-builtins", Path::new("build_sysroot/compiler-builtins")); apply_patches("compiler-builtins", Path::new("build_sysroot/compiler-builtins"));
} }

View File

@ -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: In the directory with your project (where you can do the usual `cargo build`), run:
```bash ```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. 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. > The jit mode will probably need cargo integration to make this possible.
```bash ```bash
$ $cg_clif_dir/build/cargo jit $ $cg_clif_dir/build/cargo-clif jit
``` ```
or or
@ -45,7 +45,7 @@ There is also an experimental lazy jit mode. In this mode functions are only com
first called. first called.
```bash ```bash
$ $cg_clif_dir/build/cargo lazy-jit $ $cg_clif_dir/build/cargo-clif lazy-jit
``` ```
## Shell ## Shell

View File

@ -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<T> {
len: usize,
data: [T; 0],
tail: Opaque,
}
#[repr(C)]
pub struct ListImpl<T, const N: usize> {
len: usize,
data: [T; N],
}
impl<T> List<T> {
const fn as_slice(&self) -> &[T] {
unsafe { std::slice::from_raw_parts(self.data.as_ptr(), self.len) }
}
}
impl<T, const N: usize> ListImpl<T, N> {
const fn as_list(&self) -> &List<T> {
unsafe { std::mem::transmute(self) }
}
}
pub static A: ListImpl<u128, 3> = ListImpl {
len: 3,
data: [5, 6, 7],
};
pub static A_REF: &'static List<u128> = A.as_list();
pub static A_TAIL_OFFSET: isize = tail_offset(A.as_list());
const fn tail_offset<T>(list: &List<T>) -> isize {
unsafe { (addr_of!(list.tail) as *const u8).offset_from(list as *const List<T> 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));
}

View File

@ -129,6 +129,7 @@ fn call_return_u128_pair() {
return_u128_pair(); return_u128_pair();
} }
#[allow(unreachable_code)] // FIXME false positive
fn main() { fn main() {
take_unique(Unique { take_unique(Unique {
pointer: 0 as *const (), pointer: 0 as *const (),

View File

@ -1,41 +1,20 @@
From 6bfce5dc2cbf834c74dbccb7538adc08c6eb57e7 Mon Sep 17 00:00:00 2001 From 97c473937382a5b5858d9cce3c947855d23b2dc5 Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com> From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Sun, 25 Jul 2021 18:39:31 +0200 Date: Thu, 18 Nov 2021 19:28:40 +0100
Subject: [PATCH] Disable unsupported tests Subject: [PATCH] Disable unsupported tests
--- ---
crates/core_simd/src/vector.rs | 2 ++ crates/core_simd/src/math.rs | 6 ++++++
crates/core_simd/src/math.rs | 4 ++++ crates/core_simd/src/vector.rs | 2 ++
crates/core_simd/tests/masks.rs | 12 ------------ crates/core_simd/tests/masks.rs | 2 ++
crates/core_simd/tests/ops_macros.rs | 6 ++++++ crates/core_simd/tests/ops_macros.rs | 4 ++++
crates/core_simd/tests/round.rs | 2 ++ 4 files changed, 14 insertions(+)
6 files changed, 15 insertions(+), 13 deletions(-)
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<T, const LANES: usize> Copy for Simd<T, LANES>
diff --git a/crates/core_simd/src/math.rs b/crates/core_simd/src/math.rs 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 --- a/crates/core_simd/src/math.rs
+++ b/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),+) => { ($($ty:ty),+) => {
$( impl<const LANES: usize> Simd<$ty, LANES> where LaneCount<LANES>: SupportedLaneCount { $( impl<const LANES: usize> Simd<$ty, LANES> where LaneCount<LANES>: SupportedLaneCount {
@ -43,15 +22,15 @@ index 7290a28..e394730 100644
/// Lanewise saturating add. /// Lanewise saturating add.
/// ///
/// # Examples /// # 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 { 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),+) => { ($($ty:ty),+) => {
$( impl<const LANES: usize> Simd<$ty, LANES> where LaneCount<LANES>: SupportedLaneCount { $( impl<const LANES: usize> Simd<$ty, LANES> where LaneCount<LANES>: SupportedLaneCount {
@ -59,7 +38,23 @@ index 7290a28..e394730 100644
/// Lanewise saturating add. /// Lanewise saturating add.
/// ///
/// # Examples /// # 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 { pub fn saturating_neg(self) -> Self {
Self::splat(0).saturating_sub(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<T, const LANES: usize> Copy for Simd<T, LANES>
diff --git a/crates/core_simd/tests/masks.rs b/crates/core_simd/tests/masks.rs 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 --- a/crates/core_simd/tests/masks.rs
+++ b/crates/core_simd/tests/masks.rs +++ b/crates/core_simd/tests/masks.rs
@@ -67,19 +67,6 @@ macro_rules! test_mask_api { @@ -68,6 +68,7 @@ macro_rules! test_mask_api {
assert_eq!(int.to_array(), [-1, 0, 0, -1, 0, 0, -1, 0]);
assert_eq!(core_simd::Mask::<$type, 8>::from_int(int), mask); assert_eq!(core_simd::Mask::<$type, 8>::from_int(int), mask);
} }
-
- #[cfg(feature = "generic_const_exprs")] + /*
- #[test] #[cfg(feature = "generic_const_exprs")]
- fn roundtrip_bitmask_conversion() { #[test]
- let values = [ fn roundtrip_bitmask_conversion() {
- true, false, false, true, false, false, true, false, @@ -80,6 +81,7 @@ macro_rules! test_mask_api {
- true, true, false, false, false, false, false, true, assert_eq!(bitmask, [0b01001001, 0b10000011]);
- ]; assert_eq!(core_simd::Mask::<$type, 16>::from_bitmask(bitmask), mask);
- 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);
- }
} }
} }
} }
diff --git a/crates/core_simd/tests/ops_macros.rs b/crates/core_simd/tests/ops_macros.rs 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 --- a/crates/core_simd/tests/ops_macros.rs
+++ b/crates/core_simd/tests/ops_macros.rs +++ b/crates/core_simd/tests/ops_macros.rs
@@ -435,6 +435,7 @@ macro_rules! impl_float_tests { @@ -567,6 +567,7 @@ macro_rules! impl_float_tests {
)
}
+ /*
fn mul_add<const LANES: usize>() {
test_helpers::test_ternary_elementwise(
&Vector::<LANES>::mul_add,
@@ -442,6 +443,7 @@ macro_rules! impl_float_tests {
&|_, _, _| true,
)
}
+ */
fn recip<const LANES: usize>() {
test_helpers::test_unary_elementwise(
@@ -581,6 +585,7 @@ macro_rules! impl_float_tests {
}); });
} }
@ -119,7 +114,7 @@ index cb39e73..fc0ebe1 100644
fn horizontal_max<const LANES: usize>() { fn horizontal_max<const LANES: usize>() {
test_helpers::test_1(&|x| { test_helpers::test_1(&|x| {
let vmax = Vector::<LANES>::from_array(x).horizontal_max(); let vmax = Vector::<LANES>::from_array(x).horizontal_max();
@@ -604,6 +609,7 @@ macro_rules! impl_float_tests { @@ -590,6 +591,7 @@ macro_rules! impl_float_tests {
Ok(()) Ok(())
}); });
} }
@ -127,26 +122,22 @@ index cb39e73..fc0ebe1 100644
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
diff --git a/crates/core_simd/tests/round.rs b/crates/core_simd/tests/round.rs @@ -604,6 +606,7 @@ macro_rules! impl_float_tests {
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 {
)
}
+ /* + /*
fn round<const LANES: usize>() { fn mul_add<const LANES: usize>() {
test_helpers::test_unary_elementwise( test_helpers::test_ternary_elementwise(
&Vector::<LANES>::round, &Vector::<LANES>::mul_add,
@@ -32,6 +33,7 @@ macro_rules! float_rounding_test { @@ -611,6 +614,7 @@ macro_rules! impl_float_tests {
&|_| true, &|_, _, _| true,
) )
}
+ */
} }
+ */ }
}
fn trunc<const LANES: usize>() {
test_helpers::test_unary_elementwise(
-- --
2.26.2.7.g19db9cfb68 2.26.2.7.g19db9cfb68

View File

@ -107,7 +107,7 @@ index fa96b7a..2854f9c 100644
inner::monotonize(raw) 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")] +#[cfg(target_has_atomic = "64")]
pub mod inner { pub mod inner {
use crate::sync::atomic::AtomicU64; 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 { pub mod inner {
use crate::sync::atomic::AtomicU128; use crate::sync::atomic::AtomicU128;
@@ -94,8 +95,9 @@ pub mod inner { @@ -94,8 +95,9 @@ pub mod inner {

View File

@ -0,0 +1,30 @@
From 0ffdd8eda8df364391c8ac6e1ce92c73ba9254d4 Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
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

View File

@ -1,3 +1,3 @@
[toolchain] [toolchain]
channel = "nightly-2021-09-19" channel = "nightly-2021-12-30"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"] components = ["rust-src", "rustc-dev", "llvm-tools-preview"]

View File

@ -42,7 +42,7 @@ fn main() {
"RUSTFLAGS", "RUSTFLAGS",
env::var("RUSTFLAGS").unwrap_or(String::new()) + " -Cprefer-dynamic", 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(env::args().skip(2))
.chain([ .chain([
"--".to_string(), "--".to_string(),
@ -56,7 +56,7 @@ fn main() {
"RUSTFLAGS", "RUSTFLAGS",
env::var("RUSTFLAGS").unwrap_or(String::new()) + " -Cprefer-dynamic", 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(env::args().skip(2))
.chain([ .chain([
"--".to_string(), "--".to_string(),

View File

@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
set -e set -e
./y.rs build ./y.rs build --no-unstable-features
source scripts/config.sh source scripts/config.sh
echo "[SETUP] Rust fork" echo "[SETUP] Rust fork"
@ -33,7 +33,7 @@ index d95b5b7f17f..00b6f0e3635 100644
[dependencies] [dependencies]
core = { path = "../core" } core = { path = "../core" }
-compiler_builtins = { version = "0.1.40", features = ['rustc-dep-of-std'] } -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] [dev-dependencies]
rand = "0.7" rand = "0.7"
@ -53,5 +53,6 @@ local-rebuild = true
[rust] [rust]
codegen-backends = ["cranelift"] codegen-backends = ["cranelift"]
deny-warnings = false deny-warnings = false
verbose-tests = false
EOF EOF
popd popd

View File

@ -10,7 +10,7 @@ pushd rust
cargo install ripgrep 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 for test in $(rg --files-with-matches "asm!|catch_unwind|should_panic|lto|// needs-asm-support" src/test/ui); do
rm $test rm $test
done 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-26655.rs
rm src/test/ui/issues/issue-29485.rs rm src/test/ui/issues/issue-29485.rs
rm src/test/ui/issues/issue-30018-panic.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/sepcomp/sepcomp-unwind.rs
rm src/test/ui/structs-enums/unit-like-struct-drop-run.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/threads-sendsync/task-stderr.rs
rm src/test/ui/numbers-arithmetic/int-abs-overflow.rs rm src/test/ui/numbers-arithmetic/int-abs-overflow.rs
rm src/test/ui/drop/drop-trait-enum.rs rm src/test/ui/drop/drop-trait-enum.rs
rm src/test/ui/numbers-arithmetic/issue-8460.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/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/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/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-33992.rs # unsupported linkages
rm src/test/ui/issues/issue-51947.rs # same 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/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_misc_casts.rs # depends on deduplication of constants
rm src/test/ui/mir/mir_raw_fat_ptr.rs # same 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/hashes/inline_asm.rs # inline asm
rm src/test/incremental/issue-72386.rs # same 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/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/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/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 -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 -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-multifile.rs # differing warning
rm src/test/ui/json-bom-plus-crlf.rs # same 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/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/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 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/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/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" 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 popd

View File

@ -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" $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 $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" echo "[AOT] alloc_system"
$MY_RUSTC example/alloc_system.rs --crate-type lib --target "$TARGET_TRIPLE" $MY_RUSTC example/alloc_system.rs --crate-type lib --target "$TARGET_TRIPLE"
@ -76,73 +80,73 @@ function base_sysroot_tests() {
function extended_sysroot_tests() { function extended_sysroot_tests() {
pushd rand pushd rand
../build/cargo clean ../build/cargo-clif clean
if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
echo "[TEST] rust-random/rand" echo "[TEST] rust-random/rand"
../build/cargo test --workspace ../build/cargo-clif test --workspace
else else
echo "[AOT] rust-random/rand" echo "[AOT] rust-random/rand"
../build/cargo build --workspace --target $TARGET_TRIPLE --tests ../build/cargo-clif build --workspace --target $TARGET_TRIPLE --tests
fi fi
popd popd
pushd simple-raytracer pushd simple-raytracer
if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
echo "[BENCH COMPILE] ebobby/simple-raytracer" 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" \ "RUSTC=rustc RUSTFLAGS='' cargo build" \
"../build/cargo build" "../build/cargo-clif build"
echo "[BENCH RUN] ebobby/simple-raytracer" echo "[BENCH RUN] ebobby/simple-raytracer"
cp ./target/debug/main ./raytracer_cg_clif cp ./target/debug/main ./raytracer_cg_clif
hyperfine --runs "${RUN_RUNS:-10}" ./raytracer_cg_llvm ./raytracer_cg_clif hyperfine --runs "${RUN_RUNS:-10}" ./raytracer_cg_llvm ./raytracer_cg_clif
else else
../build/cargo clean ../build/cargo-clif clean
echo "[BENCH COMPILE] ebobby/simple-raytracer (skipped)" echo "[BENCH COMPILE] ebobby/simple-raytracer (skipped)"
echo "[COMPILE] ebobby/simple-raytracer" 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)" echo "[BENCH RUN] ebobby/simple-raytracer (skipped)"
fi fi
popd popd
pushd build_sysroot/sysroot_src/library/core/tests pushd build_sysroot/sysroot_src/library/core/tests
echo "[TEST] libcore" echo "[TEST] libcore"
../../../../../build/cargo clean ../../../../../build/cargo-clif clean
if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
../../../../../build/cargo test ../../../../../build/cargo-clif test
else else
../../../../../build/cargo build --target $TARGET_TRIPLE --tests ../../../../../build/cargo-clif build --target $TARGET_TRIPLE --tests
fi fi
popd popd
pushd regex pushd regex
echo "[TEST] rust-lang/regex example shootout-regex-dna" 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 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 # 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 if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
cat examples/regexdna-input.txt \ 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 | grep -v "Spawned thread" > res.txt
diff -u res.txt examples/regexdna-output.txt diff -u res.txt examples/regexdna-output.txt
fi fi
if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
echo "[TEST] rust-lang/regex tests" 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 else
echo "[AOT] rust-lang/regex tests" echo "[AOT] rust-lang/regex tests"
../build/cargo build --tests --target $TARGET_TRIPLE ../build/cargo-clif build --tests --target $TARGET_TRIPLE
fi fi
popd popd
pushd portable-simd pushd portable-simd
echo "[TEST] rust-lang/portable-simd" echo "[TEST] rust-lang/portable-simd"
../build/cargo clean ../build/cargo-clif clean
../build/cargo build --all-targets --target $TARGET_TRIPLE ../build/cargo-clif build --all-targets --target $TARGET_TRIPLE
if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
../build/cargo test -q ../build/cargo-clif test -q
fi fi
popd popd
} }

View File

@ -18,11 +18,11 @@ pub(crate) use self::returning::codegen_return;
fn clif_sig_from_fn_abi<'tcx>( fn clif_sig_from_fn_abi<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
triple: &target_lexicon::Triple, default_call_conv: CallConv,
fn_abi: &FnAbi<'tcx, Ty<'tcx>>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
) -> Signature { ) -> Signature {
let call_conv = match fn_abi.conv { 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_64SysV => CallConv::SystemV,
Conv::X86_64Win64 => CallConv::WindowsFastcall, Conv::X86_64Win64 => CallConv::WindowsFastcall,
Conv::ArmAapcs Conv::ArmAapcs
@ -55,7 +55,7 @@ pub(crate) fn get_function_sig<'tcx>(
assert!(!inst.substs.needs_infer()); assert!(!inst.substs.needs_infer());
clif_sig_from_fn_abi( clif_sig_from_fn_abi(
tcx, tcx,
triple, CallConv::triple_default(triple),
&RevealAllLayoutCx(tcx).fn_abi_of_instance(inst, ty::List::empty()), &RevealAllLayoutCx(tcx).fn_abi_of_instance(inst, ty::List::empty()),
) )
} }
@ -91,7 +91,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
returns: Vec<AbiParam>, returns: Vec<AbiParam>,
args: &[Value], args: &[Value],
) -> &[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_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 func_ref = self.module.declare_func_in_func(func_id, &mut self.bcx.func);
let call_inst = self.bcx.ins().call(func_ref, args); 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 (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); let sig = fx.bcx.import_signature(sig);
(CallTarget::Indirect(sig, method), Some(ptr)) (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 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); let sig = fx.bcx.import_signature(sig);
(CallTarget::Indirect(sig, func), None) (CallTarget::Indirect(sig, func), None)
@ -531,7 +531,7 @@ pub(crate) fn codegen_drop<'tcx>(
let fn_abi = let fn_abi =
RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(virtual_drop, ty::List::empty()); 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); let sig = fx.bcx.import_signature(sig);
fx.bcx.ins().call_indirect(sig, drop_fn, &[ptr]); fx.bcx.ins().call_indirect(sig, drop_fn, &[ptr]);
} }

View File

@ -71,7 +71,7 @@ fn cast_target_to_abi_params(cast: CastTarget) -> SmallVec<[AbiParam; 2]> {
.prefix .prefix
.iter() .iter()
.flatten() .flatten()
.map(|&kind| reg_to_abi_param(Reg { kind, size: cast.prefix_chunk_size })) .map(|&reg| reg_to_abi_param(reg))
.chain((0..rest_count).map(|_| reg_to_abi_param(cast.rest.unit))) .chain((0..rest_count).map(|_| reg_to_abi_param(cast.rest.unit)))
.collect::<SmallVec<_>>(); .collect::<SmallVec<_>>();
@ -117,7 +117,9 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
PassMode::Cast(cast) => cast_target_to_abi_params(cast), PassMode::Cast(cast) => cast_target_to_abi_params(cast),
PassMode::Indirect { attrs, extra_attrs: None, on_stack } => { PassMode::Indirect { attrs, extra_attrs: None, on_stack } => {
if 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( smallvec![apply_arg_attrs_to_abi_param(
AbiParam::special(pointer_ty(tcx), ArgumentPurpose::StructArgument(size),), AbiParam::special(pointer_ty(tcx), ArgumentPurpose::StructArgument(size),),
attrs 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 // It may also be smaller for example when the type is a wrapper around an integer with a
// larger alignment than the integer. // larger alignment than the integer.
size: (std::cmp::max(abi_param_size, layout_size) + 15) / 16 * 16, 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 ptr = Pointer::new(fx.bcx.ins().stack_addr(pointer_ty(fx.tcx), stack_slot, 0));
let mut offset = 0; let mut offset = 0;

View File

@ -1,7 +1,6 @@
//! Creation of ar archives like for the lib and staticlib crate type //! Creation of ar archives like for the lib and staticlib crate type
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::convert::TryFrom;
use std::fs::File; use std::fs::File;
use std::io::{self, Read, Seek}; use std::io::{self, Read, Seek};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
@ -10,7 +9,7 @@ use rustc_codegen_ssa::back::archive::ArchiveBuilder;
use rustc_session::Session; use rustc_session::Session;
use object::read::archive::ArchiveFile; use object::read::archive::ArchiveFile;
use object::{Object, ObjectSymbol, ReadCache, SymbolKind}; use object::{Object, ObjectSymbol, ReadCache};
#[derive(Debug)] #[derive(Debug)]
enum ArchiveEntry { enum ArchiveEntry {
@ -150,12 +149,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
object object
.symbols() .symbols()
.filter_map(|symbol| { .filter_map(|symbol| {
if symbol.is_undefined() if symbol.is_undefined() || symbol.is_local() {
|| symbol.is_local()
|| symbol.kind() != SymbolKind::Data
&& symbol.kind() != SymbolKind::Text
&& symbol.kind() != SymbolKind::Tls
{
None None
} else { } else {
symbol.name().map(|name| name.as_bytes().to_vec()).ok() symbol.name().map(|name| name.as_bytes().to_vec()).ok()

View File

@ -1,6 +1,7 @@
//! Codegen of a single function //! Codegen of a single function
use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink}; use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
use rustc_ast::InlineAsmOptions;
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::adjustment::PointerCast;
use rustc_middle::ty::layout::FnAbiOf; 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(); (0..mir.basic_blocks().len()).map(|_| bcx.create_block()).collect();
// Make FunctionCx // 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 clif_comments = crate::pretty_clif::CommentWriter::new(tcx, instance);
let mut fx = FunctionCx { let mut fx = FunctionCx {
cx, cx,
module, module,
tcx, tcx,
target_config,
pointer_type, pointer_type,
constants_cx: ConstantCx::new(), constants_cx: ConstantCx::new(),
@ -71,8 +74,6 @@ pub(crate) fn codegen_fn<'tcx>(
clif_comments, clif_comments,
source_info_set: indexmap::IndexSet::new(), source_info_set: indexmap::IndexSet::new(),
next_ssa_var: 0, next_ssa_var: 0,
inline_asm_index: 0,
}; };
let arg_uninhabited = fx let arg_uninhabited = fx
@ -203,7 +204,6 @@ pub(crate) fn verify_func(
tcx.sess.err(&format!("{:?}", err)); tcx.sess.err(&format!("{:?}", err));
let pretty_error = cranelift_codegen::print_errors::pretty_verifier_error( let pretty_error = cranelift_codegen::print_errors::pretty_verifier_error(
&func, &func,
None,
Some(Box::new(writer)), Some(Box::new(writer)),
err, err,
); );
@ -239,7 +239,8 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) {
fx.add_comment(inst, terminator_head); 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 { match &bb_data.terminator().kind {
TerminatorKind::Goto { target } => { TerminatorKind::Goto { target } => {
@ -294,20 +295,18 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) {
AssertKind::BoundsCheck { ref len, ref index } => { AssertKind::BoundsCheck { ref len, ref index } => {
let len = codegen_operand(fx, len).load_scalar(fx); let len = codegen_operand(fx, len).load_scalar(fx);
let index = codegen_operand(fx, index).load_scalar(fx); let index = codegen_operand(fx, index).load_scalar(fx);
let location = fx let location = fx.get_caller_location(source_info.span).load_scalar(fx);
.get_caller_location(bb_data.terminator().source_info.span)
.load_scalar(fx);
codegen_panic_inner( codegen_panic_inner(
fx, fx,
rustc_hir::LangItem::PanicBoundsCheck, rustc_hir::LangItem::PanicBoundsCheck,
&[index, len, location], &[index, len, location],
bb_data.terminator().source_info.span, source_info.span,
); );
} }
_ => { _ => {
let msg_str = msg.description(); 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, options,
destination, destination,
line_spans: _, 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( crate::inline_asm::codegen_inline_asm(
fx, fx,
bb_data.terminator().source_info.span, source_info.span,
template, template,
operands, operands,
*options, *options,
@ -415,7 +422,7 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) {
} }
TerminatorKind::Drop { place, target, unwind: _ } => { TerminatorKind::Drop { place, target, unwind: _ } => {
let drop_place = codegen_place(fx, *place); 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); let target_block = fx.get_block(*target);
fx.bcx.ins().jump(target_block, &[]); fx.bcx.ins().jump(target_block, &[]);
@ -671,7 +678,7 @@ fn codegen_stmt<'tcx>(
// FIXME use emit_small_memset where possible // FIXME use emit_small_memset where possible
let addr = lval.to_ptr().get_addr(fx); let addr = lval.to_ptr().get_addr(fx);
let val = operand.load_scalar(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 { } else {
let loop_block = fx.bcx.create_block(); let loop_block = fx.bcx.create_block();
let loop_block2 = 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); let operand = operand.load_scalar(fx);
lval.write_cvalue(fx, CValue::by_val(operand, box_layout)); 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) => { Rvalue::NullaryOp(null_op, ty) => {
assert!( assert!(
lval.layout() lval.layout()
@ -742,10 +725,8 @@ fn codegen_stmt<'tcx>(
let val = match null_op { let val = match null_op {
NullOp::SizeOf => layout.size.bytes(), NullOp::SizeOf => layout.size.bytes(),
NullOp::AlignOf => layout.align.abi.bytes(), NullOp::AlignOf => layout.align.abi.bytes(),
NullOp::Box => unreachable!(),
}; };
let val = let val = CValue::const_val(fx, fx.layout_of(fx.tcx.types.usize), val.into());
CValue::const_val(fx, fx.layout_of(fx.tcx.types.usize), val.into());
lval.write_cvalue(fx, val); lval.write_cvalue(fx, val);
} }
Rvalue::Aggregate(ref kind, ref operands) => match kind.as_ref() { 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 elem_size: u64 = pointee.size.bytes();
let bytes = let bytes =
if elem_size != 1 { fx.bcx.ins().imul_imm(count, elem_size as i64) } else { count }; 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);
} }
} }
} }

View File

@ -1,3 +1,4 @@
use cranelift_codegen::isa::TargetFrontendConfig;
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
use rustc_middle::ty::layout::{ use rustc_middle::ty::layout::{
FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, 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) cx: &'clif mut crate::CodegenCx<'tcx>,
pub(crate) module: &'m mut dyn Module, pub(crate) module: &'m mut dyn Module,
pub(crate) tcx: TyCtxt<'tcx>, 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) constants_cx: ConstantCx,
pub(crate) instance: Instance<'tcx>, 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`. /// This should only be accessed by `CPlace::new_var`.
pub(crate) next_ssa_var: u32, pub(crate) next_ssa_var: u32,
pub(crate) inline_asm_index: u32,
} }
impl<'tcx> LayoutOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> { 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()) 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 { pub(crate) fn anonymous_str(&mut self, msg: &str) -> Value {
let mut data_ctx = DataContext::new(); let mut data_ctx = DataContext::new();
data_ctx.define(msg.as_bytes().to_vec().into_boxed_slice()); data_ctx.define(msg.as_bytes().to_vec().into_boxed_slice());

View File

@ -369,7 +369,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
TodoItem::Static(def_id) => { TodoItem::Static(def_id) => {
//println!("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(); 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 { if let Some(section_name) = section_name {
let (segment_name, section_name) = if tcx.sess.target.is_like_osx { 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(',') { if let Some(names) = section_name.split_once(',') {
names names
} else { } else {
@ -397,7 +398,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
)); ));
} }
} else { } else {
("", &*section_name) ("", section_name.as_str())
}; };
data_ctx.set_segment_section(segment_name, section_name); data_ctx.set_segment_section(segment_name, section_name);
} }

View File

@ -67,10 +67,8 @@ impl WriterRelocate {
} }
/// Perform the collected relocations to be usable for JIT usage. /// 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<u8> { pub(super) fn relocate_for_jit(mut self, jit_module: &cranelift_jit::JITModule) -> Vec<u8> {
use std::convert::TryInto;
for reloc in self.relocs.drain(..) { for reloc in self.relocs.drain(..) {
match reloc.name { match reloc.name {
super::DebugRelocName::Section(_) => unreachable!(), super::DebugRelocName::Section(_) => unreachable!(),

View File

@ -10,7 +10,7 @@ use crate::prelude::*;
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
use cranelift_codegen::entity::EntityRef; 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::isa::TargetIsa;
use cranelift_codegen::ValueLocRange; 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 emit::{DebugReloc, DebugRelocName};
pub(crate) use unwind::UnwindContext; 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> { pub(crate) struct DebugContext<'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
@ -60,6 +51,11 @@ impl<'tcx> DebugContext<'tcx> {
address_size: isa.frontend_config().pointer_bytes(), 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 mut dwarf = DwarfUnit::new(encoding);
let producer = format!( let producer = format!(
@ -67,7 +63,12 @@ impl<'tcx> DebugContext<'tcx> {
rustc_interface::util::version_str().unwrap_or("unknown version"), rustc_interface::util::version_str().unwrap_or("unknown version"),
cranelift_codegen::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() { let (name, file_info) = match tcx.sess.local_crate_source_file.clone() {
Some(path) => { Some(path) => {
let name = path.to_string_lossy().into_owned(); let name = path.to_string_lossy().into_owned();
@ -103,7 +104,7 @@ impl<'tcx> DebugContext<'tcx> {
DebugContext { DebugContext {
tcx, tcx,
endian: target_endian(tcx), endian,
dwarf, dwarf,
unit_range_list: RangeList(Vec::new()), 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. // FIXME make it more reliable and implement scopes before re-enabling this.
if false { 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() { for (local, _local_decl) in mir.local_decls.iter_enumerated() {
let ty = self.tcx.subst_and_normalize_erasing_regions( let ty = self.tcx.subst_and_normalize_erasing_regions(
@ -264,7 +265,6 @@ impl<'tcx> DebugContext<'tcx> {
self, self,
isa, isa,
symbol, symbol,
context,
&local_map, &local_map,
&value_labels_ranges, &value_labels_ranges,
Place { local, projection: ty::List::empty() }, Place { local, projection: ty::List::empty() },
@ -283,7 +283,6 @@ fn place_location<'tcx>(
debug_context: &mut DebugContext<'tcx>, debug_context: &mut DebugContext<'tcx>,
isa: &dyn TargetIsa, isa: &dyn TargetIsa,
symbol: usize, symbol: usize,
context: &Context,
local_map: &IndexVec<mir::Local, CPlace<'tcx>>, local_map: &IndexVec<mir::Local, CPlace<'tcx>>,
#[allow(rustc::default_hash_types)] value_labels_ranges: &std::collections::HashMap< #[allow(rustc::default_hash_types)] value_labels_ranges: &std::collections::HashMap<
ValueLabel, ValueLabel,
@ -306,12 +305,7 @@ fn place_location<'tcx>(
addend: i64::from(value_loc_range.start), addend: i64::from(value_loc_range.start),
}, },
end: Address::Symbol { symbol, addend: i64::from(value_loc_range.end) }, end: Address::Symbol { symbol, addend: i64::from(value_loc_range.end) },
data: translate_loc( data: translate_loc(isa, value_loc_range.loc).unwrap(),
isa,
value_loc_range.loc,
&context.func.stack_slots,
)
.unwrap(),
}) })
.collect(), .collect(),
); );
@ -340,34 +334,14 @@ fn place_location<'tcx>(
AttributeValue::Exprloc(Expression::new()) AttributeValue::Exprloc(Expression::new())
// For PointerBase::Stack: // 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 // Adapted from https://github.com/CraneStation/wasmtime/blob/5a1845b4caf7a5dba8eda1fef05213a532ed4259/crates/debug/src/transform/expression.rs#L59-L137
fn translate_loc( fn translate_loc(isa: &dyn TargetIsa, loc: LabelValueLoc) -> Option<Expression> {
isa: &dyn TargetIsa,
loc: LabelValueLoc,
stack_slots: &StackSlots,
) -> Option<Expression> {
match loc { 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) => { LabelValueLoc::Reg(reg) => {
let machine_reg = isa.map_regalloc_reg_to_dwarf(reg).unwrap(); let machine_reg = isa.map_regalloc_reg_to_dwarf(reg).unwrap();
let mut expr = Expression::new(); let mut expr = Expression::new();

View File

@ -1,5 +1,3 @@
use std::convert::{TryFrom, TryInto};
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use cranelift_module::FuncId; use cranelift_module::FuncId;

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