Merge from rustc

This commit is contained in:
The Miri Cronjob Bot 2024-06-17 05:10:34 +00:00
commit 6b19af8060
859 changed files with 11721 additions and 6201 deletions

View file

@ -1,3 +1,4 @@
<!-- homu-ignore:start -->
<!--
If this PR is related to an unstable feature or an otherwise tracked effort,
please link to the relevant tracking issue here. If you don't know of a related
@ -7,4 +8,5 @@ This PR will get automatically assigned to a reviewer. In case you would like
a specific user to review your work, you can assign it to them by using
r? <reviewer name>
-->
-->
<!-- homu-ignore:end -->

View file

@ -95,8 +95,6 @@ jobs:
path-type: inherit
install: >
make
dos2unix
diffutils
- name: disable git crlf conversion
run: git config --global core.autocrlf false

View file

@ -379,6 +379,7 @@ Markus Westerlind <marwes91@gmail.com> Markus <marwes91@gmail.com>
Martin Carton <cartonmartin+git@gmail.com>
Martin Habovštiak <martin.habovstiak@gmail.com>
Martin Hafskjold Thoresen <martinhath@gmail.com>
Martin Nordholts <martin.nordholts@codetale.se> <enselic@gmail.com>
Matej Lach <matej.lach@gmail.com> Matej Ľach <matej.lach@gmail.com>
Mateusz Mikuła <mati865@gmail.com>
Mateusz Mikuła <mati865@gmail.com> <mati865@users.noreply.github.com>

View file

@ -87,7 +87,7 @@ version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ab99eae5ee58501ab236beb6f20f6ca39be615267b014899c89b2f0bc18a459"
dependencies = [
"html5ever 0.27.0",
"html5ever",
"maplit",
"once_cell",
"tendril",
@ -131,9 +131,9 @@ dependencies = [
[[package]]
name = "annotate-snippets"
version = "0.11.3"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "086b0afab3b349e5691143adbfb26983821e3eec4ba4c51957104d372c2e1b7d"
checksum = "24e35ed54e5ea7997c14ed4c70ba043478db1112e98263b3b035907aa197d991"
dependencies = [
"anstyle",
"unicode-width",
@ -542,7 +542,7 @@ checksum = "93698b29de5e97ad0ae26447b344c482a7284c737d9ddc5f9e52b74a336671bb"
dependencies = [
"chrono",
"chrono-tz-build",
"phf 0.11.2",
"phf",
]
[[package]]
@ -552,8 +552,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c088aee841df9c3041febbb73934cfc39708749bf96dc827e3359cd39ef11b1"
dependencies = [
"parse-zoneinfo",
"phf 0.11.2",
"phf_codegen 0.11.2",
"phf",
"phf_codegen",
]
[[package]]
@ -568,9 +568,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.6"
version = "4.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9689a29b593160de5bc4aacab7b5d54fb52231de70122626c178e6a368994c7"
checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f"
dependencies = [
"clap_builder",
"clap_derive",
@ -588,9 +588,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.6"
version = "4.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e5387378c84f6faa26890ebf9f0a92989f8873d4d380467bcd0d8d8620424df"
checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f"
dependencies = [
"anstream",
"anstyle",
@ -628,7 +628,7 @@ checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70"
[[package]]
name = "clippy"
version = "0.1.80"
version = "0.1.81"
dependencies = [
"anstream",
"clippy_config",
@ -655,7 +655,7 @@ dependencies = [
[[package]]
name = "clippy_config"
version = "0.1.80"
version = "0.1.81"
dependencies = [
"rustc-semver",
"serde",
@ -678,7 +678,7 @@ dependencies = [
[[package]]
name = "clippy_lints"
version = "0.1.80"
version = "0.1.81"
dependencies = [
"arrayvec",
"cargo_metadata 0.18.1",
@ -688,7 +688,7 @@ dependencies = [
"itertools 0.12.1",
"quine-mc_cluskey",
"regex",
"regex-syntax 0.8.3",
"regex-syntax 0.8.4",
"rustc-semver",
"semver",
"serde",
@ -703,7 +703,7 @@ dependencies = [
[[package]]
name = "clippy_utils"
version = "0.1.80"
version = "0.1.81"
dependencies = [
"arrayvec",
"clippy_config",
@ -1023,7 +1023,7 @@ dependencies = [
[[package]]
name = "declare_clippy_lint"
version = "0.1.80"
version = "0.1.81"
dependencies = [
"itertools 0.12.1",
"quote",
@ -1083,13 +1083,13 @@ dependencies = [
[[package]]
name = "derive_more"
version = "0.99.17"
version = "0.99.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
"syn 2.0.66",
]
[[package]]
@ -1694,6 +1694,12 @@ name = "hermit-abi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "hermit-abi"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-alloc",
@ -1732,20 +1738,6 @@ dependencies = [
"utf8-width",
]
[[package]]
name = "html5ever"
version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7"
dependencies = [
"log",
"mac",
"markup5ever 0.11.0",
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "html5ever"
version = "0.27.0"
@ -1754,7 +1746,7 @@ checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4"
dependencies = [
"log",
"mac",
"markup5ever 0.12.1",
"markup5ever",
"proc-macro2",
"quote",
"syn 2.0.66",
@ -1798,6 +1790,18 @@ dependencies = [
"cc",
]
[[package]]
name = "icu_collections"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
dependencies = [
"displaydoc",
"yoke",
"zerofrom",
"zerovec",
]
[[package]]
name = "icu_list"
version = "1.5.0"
@ -1851,6 +1855,51 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
[[package]]
name = "icu_normalizer"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
dependencies = [
"displaydoc",
"icu_collections",
"icu_normalizer_data",
"icu_properties",
"icu_provider",
"smallvec",
"utf16_iter",
"utf8_iter",
"write16",
"zerovec",
]
[[package]]
name = "icu_normalizer_data"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
[[package]]
name = "icu_properties"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036"
dependencies = [
"displaydoc",
"icu_collections",
"icu_locid_transform",
"icu_properties_data",
"icu_provider",
"tinystr",
"zerovec",
]
[[package]]
name = "icu_properties_data"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
[[package]]
name = "icu_provider"
version = "1.5.0"
@ -1900,12 +1949,14 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "idna"
version = "0.5.0"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed"
dependencies = [
"unicode-bidi",
"unicode-normalization",
"icu_normalizer",
"icu_properties",
"smallvec",
"utf8_iter",
]
[[package]]
@ -2175,7 +2226,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
dependencies = [
"cfg-if",
"windows-targets 0.52.5",
"windows-targets 0.48.5",
]
[[package]]
@ -2225,7 +2276,7 @@ dependencies = [
name = "linkchecker"
version = "0.1.0"
dependencies = [
"html5ever 0.26.0",
"html5ever",
"regex",
]
@ -2310,20 +2361,6 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
[[package]]
name = "markup5ever"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016"
dependencies = [
"log",
"phf 0.10.1",
"phf_codegen 0.10.0",
"string_cache",
"string_cache_codegen",
"tendril",
]
[[package]]
name = "markup5ever"
version = "0.12.1"
@ -2331,8 +2368,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45"
dependencies = [
"log",
"phf 0.11.2",
"phf_codegen 0.11.2",
"phf",
"phf_codegen",
"string_cache",
"string_cache_codegen",
"tendril",
@ -2387,9 +2424,9 @@ dependencies = [
[[package]]
name = "mdbook-i18n-helpers"
version = "0.3.3"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1f71f5961d6f3376e1ff3e5989c2e3ecccc3e8a00f3a3acde446847f84852e4"
checksum = "8c8f972ab672d366c3dad77ea5aa7bae68db2d25fbeb889849f97469d7b658e4"
dependencies = [
"anyhow",
"chrono",
@ -2636,7 +2673,7 @@ version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi",
"hermit-abi 0.3.9",
"libc",
]
@ -2865,7 +2902,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
dependencies = [
"cfg-if",
"libc",
"redox_syscall 0.5.1",
"redox_syscall 0.5.2",
"smallvec",
"windows-targets 0.52.5",
]
@ -2945,15 +2982,6 @@ dependencies = [
"sha2",
]
[[package]]
name = "phf"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259"
dependencies = [
"phf_shared 0.10.0",
]
[[package]]
name = "phf"
version = "0.11.2"
@ -2963,16 +2991,6 @@ dependencies = [
"phf_shared 0.11.2",
]
[[package]]
name = "phf_codegen"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd"
dependencies = [
"phf_generator 0.10.0",
"phf_shared 0.10.0",
]
[[package]]
name = "phf_codegen"
version = "0.11.2"
@ -3344,9 +3362,9 @@ dependencies = [
[[package]]
name = "redox_syscall"
version = "0.5.1"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd"
dependencies = [
"bitflags 2.5.0",
]
@ -3405,9 +3423,9 @@ dependencies = [
[[package]]
name = "regex-lite"
version = "0.1.5"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30b661b2f27137bdbc16f00eda72866a92bb28af1753ffbd56744fb6e2e9cd8e"
checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a"
[[package]]
name = "regex-syntax"
@ -3423,9 +3441,9 @@ checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
[[package]]
name = "regex-syntax"
version = "0.8.3"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
[[package]]
name = "remote-test-client"
@ -3452,7 +3470,7 @@ dependencies = [
[[package]]
name = "run_make_support"
version = "0.1.0"
version = "0.2.0"
dependencies = [
"gimli 0.28.1",
"object 0.34.0",
@ -4205,7 +4223,6 @@ dependencies = [
"rustc_middle",
"rustc_span",
"rustc_target",
"rustc_type_ir",
"smallvec",
"tracing",
]
@ -5346,7 +5363,7 @@ dependencies = [
"dlmalloc",
"fortanix-sgx-abi",
"hashbrown",
"hermit-abi",
"hermit-abi 0.4.0",
"libc",
"miniz_oxide",
"object 0.36.0",
@ -5479,7 +5496,7 @@ dependencies = [
"once_cell",
"onig",
"plist",
"regex-syntax 0.8.3",
"regex-syntax 0.8.4",
"serde",
"serde_derive",
"serde_json",
@ -5992,7 +6009,7 @@ version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29e5f4ffcbab82453958fbf59990e981b8e8a177dcd60c2bd8f9b52c3036a6e1"
dependencies = [
"annotate-snippets 0.11.3",
"annotate-snippets 0.11.4",
"anyhow",
"bstr",
"cargo-platform",
@ -6073,12 +6090,6 @@ dependencies = [
"ucd-parse",
]
[[package]]
name = "unicode-bidi"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
[[package]]
name = "unicode-ident"
version = "1.0.12"
@ -6180,9 +6191,9 @@ dependencies = [
[[package]]
name = "url"
version = "2.5.0"
version = "2.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56"
dependencies = [
"form_urlencoded",
"idna",
@ -6195,12 +6206,24 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]]
name = "utf16_iter"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
[[package]]
name = "utf8-width"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3"
[[package]]
name = "utf8_iter"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]]
name = "utf8parse"
version = "0.2.2"
@ -6380,9 +6403,9 @@ dependencies = [
[[package]]
name = "windows-bindgen"
version = "0.56.0"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28e3ea6330cf17fdcdce8bf08d0549ce93769dca9bedc6c39c36c8c0e17db46"
checksum = "1ccb96113d6277ba543c0f77e1c5494af8094bf9daf9b85acdc3f1b620e7c7b4"
dependencies = [
"proc-macro2",
"rayon",
@ -6403,9 +6426,9 @@ dependencies = [
[[package]]
name = "windows-metadata"
version = "0.56.0"
version = "0.57.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3993f7827fff10c454e3a24847075598c7c08108304b8b07943c2c73d78f3b34"
checksum = "8308d076825b9d9e5abc64f8113e96d02b2aeeba869b20fdd65c7e70cda13dfc"
[[package]]
name = "windows-sys"
@ -6564,6 +6587,12 @@ dependencies = [
"memchr",
]
[[package]]
name = "write16"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
[[package]]
name = "writeable"
version = "0.5.5"

View file

@ -100,12 +100,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
move_site_vec.iter().map(|move_site| move_site.moi).collect();
if move_out_indices.is_empty() {
let root_place = PlaceRef { projection: &[], ..used_place };
let root_local = used_place.local;
if !self.uninitialized_error_reported.insert(root_place) {
if !self.uninitialized_error_reported.insert(root_local) {
debug!(
"report_use_of_moved_or_uninitialized place: error about {:?} suppressed",
root_place
root_local
);
return;
}
@ -284,7 +284,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
&& let CallKind::FnCall { fn_trait_id, self_ty } = kind
&& let ty::Param(_) = self_ty.kind()
&& ty == self_ty
&& Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait()
&& self.infcx.tcx.is_lang_item(fn_trait_id, LangItem::FnOnce)
{
// this is a type parameter `T: FnOnce()`, don't suggest `T: FnOnce() + Clone`.
true
@ -708,9 +708,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if let ty::ClauseKind::Trait(pred) = pred.kind().skip_binder()
&& pred.self_ty() == ty
{
if Some(pred.def_id()) == tcx.lang_items().fn_trait() {
if tcx.is_lang_item(pred.def_id(), LangItem::Fn) {
return Some(hir::Mutability::Not);
} else if Some(pred.def_id()) == tcx.lang_items().fn_mut_trait() {
} else if tcx.is_lang_item(pred.def_id(), LangItem::FnMut) {
return Some(hir::Mutability::Mut);
}
}
@ -1832,7 +1832,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if let hir::ExprKind::MethodCall(..) = ex.kind
&& let Some(method_def_id) =
self.typeck_results.type_dependent_def_id(ex.hir_id)
&& self.tcx.lang_items().clone_trait() == Some(self.tcx.parent(method_def_id))
&& self.tcx.is_lang_item(self.tcx.parent(method_def_id), LangItem::Clone)
{
self.clones.push(ex);
}
@ -2888,7 +2888,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
..
} = explanation
{
if let Some(diag) = self.try_report_cannot_return_reference_to_local(
if let Err(diag) = self.try_report_cannot_return_reference_to_local(
borrow,
borrow_span,
span,
@ -3075,7 +3075,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if let BorrowExplanation::MustBeValidFor { category, span, from_closure: false, .. } =
explanation
{
if let Some(diag) = self.try_report_cannot_return_reference_to_local(
if let Err(diag) = self.try_report_cannot_return_reference_to_local(
borrow,
proper_span,
span,
@ -3159,8 +3159,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let is_format_arguments_item = if let Some(expr_ty) = expr_ty
&& let ty::Adt(adt, _) = expr_ty.kind()
{
self.infcx.tcx.lang_items().get(LangItem::FormatArguments)
== Some(adt.did())
self.infcx.tcx.is_lang_item(adt.did(), LangItem::FormatArguments)
} else {
false
};
@ -3237,11 +3236,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
return_span: Span,
category: ConstraintCategory<'tcx>,
opt_place_desc: Option<&String>,
) -> Option<Diag<'tcx>> {
) -> Result<(), Diag<'tcx>> {
let return_kind = match category {
ConstraintCategory::Return(_) => "return",
ConstraintCategory::Yield => "yield",
_ => return None,
_ => return Ok(()),
};
// FIXME use a better heuristic than Spans
@ -3317,7 +3316,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}
Some(err)
Err(err)
}
#[instrument(level = "debug", skip(self))]

View file

@ -6,9 +6,9 @@ use crate::session_diagnostics::{
};
use rustc_errors::{Applicability, Diag};
use rustc_errors::{DiagCtxt, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, Namespace};
use rustc_hir::CoroutineKind;
use rustc_hir::{self as hir, LangItem};
use rustc_index::IndexSlice;
use rustc_infer::infer::BoundRegionConversionTime;
use rustc_infer::traits::SelectionError;
@ -116,7 +116,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
{
if let ty::FnDef(id, _) = *const_.ty().kind() {
debug!("add_moved_or_invoked_closure_note: id={:?}", id);
if Some(self.infcx.tcx.parent(id)) == self.infcx.tcx.lang_items().fn_once_trait() {
if self.infcx.tcx.is_lang_item(self.infcx.tcx.parent(id), LangItem::FnOnce) {
let closure = match args.first() {
Some(Spanned {
node: Operand::Copy(place) | Operand::Move(place), ..
@ -767,13 +767,12 @@ impl<'tcx> BorrowedContentSource<'tcx> {
ty::FnDef(def_id, args) => {
let trait_id = tcx.trait_of_item(def_id)?;
let lang_items = tcx.lang_items();
if Some(trait_id) == lang_items.deref_trait()
|| Some(trait_id) == lang_items.deref_mut_trait()
if tcx.is_lang_item(trait_id, LangItem::Deref)
|| tcx.is_lang_item(trait_id, LangItem::DerefMut)
{
Some(BorrowedContentSource::OverloadedDeref(args.type_at(0)))
} else if Some(trait_id) == lang_items.index_trait()
|| Some(trait_id) == lang_items.index_mut_trait()
} else if tcx.is_lang_item(trait_id, LangItem::Index)
|| tcx.is_lang_item(trait_id, LangItem::IndexMut)
{
Some(BorrowedContentSource::OverloadedIndex(args.type_at(0)))
} else {
@ -1041,7 +1040,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
.unwrap_or_else(|| "value".to_owned());
match kind {
CallKind::FnCall { fn_trait_id, self_ty }
if Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait() =>
if self.infcx.tcx.is_lang_item(fn_trait_id, LangItem::FnOnce) =>
{
err.subdiagnostic(
self.dcx(),
@ -1268,7 +1267,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let ty = moved_place.ty(self.body, tcx).ty;
if let ty::Adt(def, args) = ty.peel_refs().kind()
&& Some(def.did()) == tcx.lang_items().pin_type()
&& tcx.is_lang_item(def.did(), LangItem::Pin)
&& let ty::Ref(_, _, hir::Mutability::Mut) = args.type_at(0).kind()
&& let self_ty = self.infcx.instantiate_binder_with_fresh_vars(
fn_call_span,

View file

@ -566,7 +566,7 @@ struct MirBorrowckCtxt<'cx, 'tcx> {
fn_self_span_reported: FxIndexSet<Span>,
/// This field keeps track of errors reported in the checking of uninitialized variables,
/// so that we don't report seemingly duplicate errors.
uninitialized_error_reported: FxIndexSet<PlaceRef<'tcx>>,
uninitialized_error_reported: FxIndexSet<Local>,
/// This field keeps track of all the local variables that are declared mut and are mutated.
/// Used for the warning issued by an unused mutable local variable.
used_mut: FxIndexSet<Local>,

View file

@ -113,7 +113,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for RegionRenumberer<'a, 'tcx> {
}
#[instrument(skip(self), level = "debug")]
fn visit_constant(&mut self, constant: &mut ConstOperand<'tcx>, location: Location) {
fn visit_const_operand(&mut self, constant: &mut ConstOperand<'tcx>, location: Location) {
let const_ = constant.const_;
constant.const_ = self.renumber_regions(const_, || RegionCtxt::Location(location));
debug!("constant: {:#?}", constant);

View file

@ -301,10 +301,10 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
self.sanitize_place(place, location, context);
}
fn visit_constant(&mut self, constant: &ConstOperand<'tcx>, location: Location) {
debug!(?constant, ?location, "visit_constant");
fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, location: Location) {
debug!(?constant, ?location, "visit_const_operand");
self.super_constant(constant, location);
self.super_const_operand(constant, location);
let ty = self.sanitize_type(constant, constant.const_.ty());
self.cx.infcx.tcx.for_each_free_region(&ty, |live_region| {
@ -328,7 +328,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
if let Some(annotation_index) = constant.user_ty {
if let Err(terr) = self.cx.relate_type_and_user_type(
constant.const_.ty(),
ty::Variance::Invariant,
ty::Invariant,
&UserTypeProjection { base: annotation_index, projs: vec![] },
locations,
ConstraintCategory::Boring,
@ -451,7 +451,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
if let Err(terr) = self.cx.relate_type_and_user_type(
ty,
ty::Variance::Invariant,
ty::Invariant,
user_ty,
Locations::All(*span),
ConstraintCategory::TypeAnnotation,
@ -1095,7 +1095,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
) -> Result<(), NoSolution> {
// Use this order of parameters because the sup type is usually the
// "expected" type in diagnostics.
self.relate_types(sup, ty::Variance::Contravariant, sub, locations, category)
self.relate_types(sup, ty::Contravariant, sub, locations, category)
}
#[instrument(skip(self, category), level = "debug")]
@ -1106,7 +1106,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
locations: Locations,
category: ConstraintCategory<'tcx>,
) -> Result<(), NoSolution> {
self.relate_types(expected, ty::Variance::Invariant, found, locations, category)
self.relate_types(expected, ty::Invariant, found, locations, category)
}
#[instrument(skip(self), level = "debug")]
@ -1146,7 +1146,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
trace!(?curr_projected_ty);
let ty = curr_projected_ty.ty;
self.relate_types(ty, v.xform(ty::Variance::Contravariant), a, locations, category)?;
self.relate_types(ty, v.xform(ty::Contravariant), a, locations, category)?;
Ok(())
}
@ -1248,7 +1248,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
if let Some(annotation_index) = self.rvalue_user_ty(rv) {
if let Err(terr) = self.relate_type_and_user_type(
rv_ty,
ty::Variance::Invariant,
ty::Invariant,
&UserTypeProjection { base: annotation_index, projs: vec![] },
location.to_locations(),
ConstraintCategory::Boring,

View file

@ -50,14 +50,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
locations: Locations,
category: ConstraintCategory<'tcx>,
) -> Result<(), NoSolution> {
NllTypeRelating::new(
self,
locations,
category,
UniverseInfo::other(),
ty::Variance::Invariant,
)
.relate(a, b)?;
NllTypeRelating::new(self, locations, category, UniverseInfo::other(), ty::Invariant)
.relate(a, b)?;
Ok(())
}
}
@ -106,15 +100,15 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
fn ambient_covariance(&self) -> bool {
match self.ambient_variance {
ty::Variance::Covariant | ty::Variance::Invariant => true,
ty::Variance::Contravariant | ty::Variance::Bivariant => false,
ty::Covariant | ty::Invariant => true,
ty::Contravariant | ty::Bivariant => false,
}
}
fn ambient_contravariance(&self) -> bool {
match self.ambient_variance {
ty::Variance::Contravariant | ty::Variance::Invariant => true,
ty::Variance::Covariant | ty::Variance::Bivariant => false,
ty::Contravariant | ty::Invariant => true,
ty::Covariant | ty::Bivariant => false,
}
}
@ -336,11 +330,7 @@ impl<'bccx, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx
debug!(?self.ambient_variance);
// In a bivariant context this always succeeds.
let r = if self.ambient_variance == ty::Variance::Bivariant {
Ok(a)
} else {
self.relate(a, b)
};
let r = if self.ambient_variance == ty::Bivariant { Ok(a) } else { self.relate(a, b) };
self.ambient_variance = old_ambient_variance;
@ -474,7 +464,7 @@ impl<'bccx, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx
}
match self.ambient_variance {
ty::Variance::Covariant => {
ty::Covariant => {
// Covariance, so we want `for<..> A <: for<..> B` --
// therefore we compare any instantiation of A (i.e., A
// instantiated with existentials) against every
@ -489,7 +479,7 @@ impl<'bccx, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx
})?;
}
ty::Variance::Contravariant => {
ty::Contravariant => {
// Contravariance, so we want `for<..> A :> for<..> B` --
// therefore we compare every instantiation of A (i.e., A
// instantiated with universals) against any
@ -504,7 +494,7 @@ impl<'bccx, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx
})?;
}
ty::Variance::Invariant => {
ty::Invariant => {
// Invariant, so we want `for<..> A == for<..> B` --
// therefore we want `exists<..> A == for<..> B` and
// `exists<..> B == for<..> A`.
@ -525,7 +515,7 @@ impl<'bccx, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx
})?;
}
ty::Variance::Bivariant => {}
ty::Bivariant => {}
}
Ok(a)
@ -584,23 +574,23 @@ impl<'bccx, 'tcx> PredicateEmittingRelation<'tcx> for NllTypeRelating<'_, 'bccx,
fn register_alias_relate_predicate(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
self.register_predicates([ty::Binder::dummy(match self.ambient_variance {
ty::Variance::Covariant => ty::PredicateKind::AliasRelate(
ty::Covariant => ty::PredicateKind::AliasRelate(
a.into(),
b.into(),
ty::AliasRelationDirection::Subtype,
),
// a :> b is b <: a
ty::Variance::Contravariant => ty::PredicateKind::AliasRelate(
ty::Contravariant => ty::PredicateKind::AliasRelate(
b.into(),
a.into(),
ty::AliasRelationDirection::Subtype,
),
ty::Variance::Invariant => ty::PredicateKind::AliasRelate(
ty::Invariant => ty::PredicateKind::AliasRelate(
a.into(),
b.into(),
ty::AliasRelationDirection::Equate,
),
ty::Variance::Bivariant => {
ty::Bivariant => {
unreachable!("cannot defer an alias-relate goal with Bivariant variance (yet?)")
}
})]);

View file

@ -4,6 +4,7 @@ use std::fmt::Write;
use cranelift_codegen::isa::CallConv;
use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_hir::LangItem;
use rustc_span::sym;
use rustc_target::asm::*;
use target_lexicon::BinaryFormat;
@ -927,7 +928,7 @@ fn call_inline_asm<'tcx>(
fn asm_clif_type<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> Option<types::Type> {
match ty.kind() {
// Adapted from https://github.com/rust-lang/rust/blob/f3c66088610c1b80110297c2d9a8b5f9265b013f/compiler/rustc_hir_analysis/src/check/intrinsicck.rs#L136-L151
ty::Adt(adt, args) if Some(adt.did()) == fx.tcx.lang_items().maybe_uninit() => {
ty::Adt(adt, args) if fx.tcx.is_lang_item(adt.did(), LangItem::MaybeUninit) => {
let fields = &adt.non_enum_variant().fields;
let ty = fields[FieldIdx::from_u32(1)].ty(fx.tcx, args);
let ty::Adt(ty, args) = ty.kind() else {

View file

@ -39,8 +39,7 @@ pub(crate) fn unsized_info<'tcx>(
}
// trait upcasting coercion
let vptr_entry_idx =
fx.tcx.vtable_trait_upcasting_coercion_new_vptr_slot((source, target));
let vptr_entry_idx = fx.tcx.supertrait_vtable_slot((source, target));
if let Some(entry_idx) = vptr_entry_idx {
let entry_idx = u32::try_from(entry_idx).unwrap();

View file

@ -959,6 +959,43 @@ fn llvm_fixup_input<'ll, 'tcx>(
InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg | X86InlineAsmRegClass::zmm_reg),
Abi::Vector { .. },
) if layout.size.bytes() == 64 => bx.bitcast(value, bx.cx.type_vector(bx.cx.type_f64(), 8)),
(
InlineAsmRegClass::X86(
X86InlineAsmRegClass::xmm_reg
| X86InlineAsmRegClass::ymm_reg
| X86InlineAsmRegClass::zmm_reg,
),
Abi::Scalar(s),
) if bx.sess().asm_arch == Some(InlineAsmArch::X86)
&& s.primitive() == Primitive::Float(Float::F128) =>
{
bx.bitcast(value, bx.type_vector(bx.type_i32(), 4))
}
(
InlineAsmRegClass::X86(
X86InlineAsmRegClass::xmm_reg
| X86InlineAsmRegClass::ymm_reg
| X86InlineAsmRegClass::zmm_reg,
),
Abi::Scalar(s),
) if s.primitive() == Primitive::Float(Float::F16) => {
let value = bx.insert_element(
bx.const_undef(bx.type_vector(bx.type_f16(), 8)),
value,
bx.const_usize(0),
);
bx.bitcast(value, bx.type_vector(bx.type_i16(), 8))
}
(
InlineAsmRegClass::X86(
X86InlineAsmRegClass::xmm_reg
| X86InlineAsmRegClass::ymm_reg
| X86InlineAsmRegClass::zmm_reg,
),
Abi::Vector { element, count: count @ (8 | 16) },
) if element.primitive() == Primitive::Float(Float::F16) => {
bx.bitcast(value, bx.type_vector(bx.type_i16(), count))
}
(
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16),
Abi::Scalar(s),
@ -1036,6 +1073,39 @@ fn llvm_fixup_output<'ll, 'tcx>(
InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg | X86InlineAsmRegClass::zmm_reg),
Abi::Vector { .. },
) if layout.size.bytes() == 64 => bx.bitcast(value, layout.llvm_type(bx.cx)),
(
InlineAsmRegClass::X86(
X86InlineAsmRegClass::xmm_reg
| X86InlineAsmRegClass::ymm_reg
| X86InlineAsmRegClass::zmm_reg,
),
Abi::Scalar(s),
) if bx.sess().asm_arch == Some(InlineAsmArch::X86)
&& s.primitive() == Primitive::Float(Float::F128) =>
{
bx.bitcast(value, bx.type_f128())
}
(
InlineAsmRegClass::X86(
X86InlineAsmRegClass::xmm_reg
| X86InlineAsmRegClass::ymm_reg
| X86InlineAsmRegClass::zmm_reg,
),
Abi::Scalar(s),
) if s.primitive() == Primitive::Float(Float::F16) => {
let value = bx.bitcast(value, bx.type_vector(bx.type_f16(), 8));
bx.extract_element(value, bx.const_usize(0))
}
(
InlineAsmRegClass::X86(
X86InlineAsmRegClass::xmm_reg
| X86InlineAsmRegClass::ymm_reg
| X86InlineAsmRegClass::zmm_reg,
),
Abi::Vector { element, count: count @ (8 | 16) },
) if element.primitive() == Primitive::Float(Float::F16) => {
bx.bitcast(value, bx.type_vector(bx.type_f16(), count))
}
(
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16),
Abi::Scalar(s),
@ -1109,6 +1179,36 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg | X86InlineAsmRegClass::zmm_reg),
Abi::Vector { .. },
) if layout.size.bytes() == 64 => cx.type_vector(cx.type_f64(), 8),
(
InlineAsmRegClass::X86(
X86InlineAsmRegClass::xmm_reg
| X86InlineAsmRegClass::ymm_reg
| X86InlineAsmRegClass::zmm_reg,
),
Abi::Scalar(s),
) if cx.sess().asm_arch == Some(InlineAsmArch::X86)
&& s.primitive() == Primitive::Float(Float::F128) =>
{
cx.type_vector(cx.type_i32(), 4)
}
(
InlineAsmRegClass::X86(
X86InlineAsmRegClass::xmm_reg
| X86InlineAsmRegClass::ymm_reg
| X86InlineAsmRegClass::zmm_reg,
),
Abi::Scalar(s),
) if s.primitive() == Primitive::Float(Float::F16) => cx.type_vector(cx.type_i16(), 8),
(
InlineAsmRegClass::X86(
X86InlineAsmRegClass::xmm_reg
| X86InlineAsmRegClass::ymm_reg
| X86InlineAsmRegClass::zmm_reg,
),
Abi::Vector { element, count: count @ (8 | 16) },
) if element.primitive() == Primitive::Float(Float::F16) => {
cx.type_vector(cx.type_i16(), count)
}
(
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16),
Abi::Scalar(s),

View file

@ -36,7 +36,7 @@ use rustc_middle::ty::{
};
use rustc_session::config::{self, DebugInfo, Lto};
use rustc_span::symbol::Symbol;
use rustc_span::FileName;
use rustc_span::{hygiene, FileName, DUMMY_SP};
use rustc_span::{FileNameDisplayPreference, SourceFile};
use rustc_symbol_mangling::typeid_for_trait_ref;
use rustc_target::abi::{Align, Size};
@ -1306,7 +1306,7 @@ pub fn build_global_var_di_node<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId, glo
// We may want to remove the namespace scope if we're in an extern block (see
// https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952).
let var_scope = get_namespace_for_item(cx, def_id);
let span = tcx.def_span(def_id);
let span = hygiene::walk_chain_collapsed(tcx.def_span(def_id), DUMMY_SP);
let (file_metadata, line_number) = if !span.is_dummy() {
let loc = cx.lookup_debug_loc(span.lo());

View file

@ -394,10 +394,15 @@ fn print_target_features(out: &mut dyn PrintBackendInfo, sess: &Session, tm: &ll
(*feature, desc)
})
.collect::<Vec<_>>();
// Since we add this at the end ...
rustc_target_features.extend_from_slice(&[(
"crt-static",
"Enables C Run-time Libraries to be statically linked",
)]);
// ... we need to sort the list again.
rustc_target_features.sort();
llvm_target_features.retain(|(f, _d)| !known_llvm_target_features.contains(f));
let max_feature_len = llvm_target_features

View file

@ -163,8 +163,7 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
// trait upcasting coercion
let vptr_entry_idx =
cx.tcx().vtable_trait_upcasting_coercion_new_vptr_slot((source, target));
let vptr_entry_idx = cx.tcx().supertrait_vtable_slot((source, target));
if let Some(entry_idx) = vptr_entry_idx {
let ptr_size = bx.data_layout().pointer_size;

View file

@ -1,8 +1,8 @@
//! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations.
use rustc_errors::{Diag, ErrorGuaranteed};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::{self as hir, LangItem};
use rustc_index::bit_set::BitSet;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::ObligationCause;
@ -801,7 +801,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
// const-eval.
// const-eval of the `begin_panic` fn assumes the argument is `&str`
if Some(callee) == tcx.lang_items().begin_panic_fn() {
if tcx.is_lang_item(callee, LangItem::BeginPanic) {
match args[0].node.ty(&self.ccx.body.local_decls, tcx).kind() {
ty::Ref(_, ty, _) if ty.is_str() => return,
_ => self.check_op(ops::PanicNonStr),
@ -819,7 +819,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
}
}
if Some(callee) == tcx.lang_items().exchange_malloc_fn() {
if tcx.is_lang_item(callee, LangItem::ExchangeMalloc) {
self.check_op(ops::HeapAllocation);
return;
}

View file

@ -218,7 +218,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
} else {
let mut sugg = None;
if Some(trait_id) == ccx.tcx.lang_items().eq_trait() {
if ccx.tcx.is_lang_item(trait_id, LangItem::PartialEq) {
match (args[0].unpack(), args[1].unpack()) {
(GenericArgKind::Type(self_ty), GenericArgKind::Type(rhs_ty))
if self_ty == rhs_ty

View file

@ -1,7 +1,6 @@
use std::mem;
use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, Diagnostic, IntoDiagArg};
use rustc_hir::CRATE_HIR_ID;
use rustc_middle::mir::interpret::{Provenance, ReportedErrorInfo};
use rustc_middle::mir::AssertKind;
use rustc_middle::query::TyCtxtAt;
@ -9,7 +8,7 @@ use rustc_middle::ty::TyCtxt;
use rustc_middle::ty::{layout::LayoutError, ConstInt};
use rustc_span::{Span, Symbol};
use super::CompileTimeInterpreter;
use super::CompileTimeMachine;
use crate::errors::{self, FrameNote, ReportErrorExt};
use crate::interpret::{err_inval, err_machine_stop};
use crate::interpret::{ErrorHandled, Frame, InterpError, InterpErrorInfo, MachineStopType};
@ -156,11 +155,11 @@ where
}
}
/// Emit a lint from a const-eval situation.
/// Emit a lint from a const-eval situation, with a backtrace.
// Even if this is unused, please don't remove it -- chances are we will need to emit a lint during const-eval again in the future!
pub(super) fn lint<'tcx, L>(
tcx: TyCtxtAt<'tcx>,
machine: &CompileTimeInterpreter<'tcx>,
machine: &CompileTimeMachine<'tcx>,
lint: &'static rustc_session::lint::Lint,
decorator: impl FnOnce(Vec<errors::FrameNote>) -> L,
) where
@ -168,12 +167,5 @@ pub(super) fn lint<'tcx, L>(
{
let (span, frames) = get_span_and_frames(tcx, &machine.stack);
tcx.emit_node_span_lint(
lint,
// We use the root frame for this so the crate that defines the const defines whether the
// lint is emitted.
machine.stack.first().and_then(|frame| frame.lint_root()).unwrap_or(CRATE_HIR_ID),
span,
decorator(frames),
);
tcx.emit_node_span_lint(lint, machine.best_lint_scope(*tcx), span, decorator(frames));
}

View file

@ -17,7 +17,7 @@ use rustc_span::def_id::LocalDefId;
use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::{self, Abi};
use super::{CanAccessMutGlobal, CompileTimeEvalContext, CompileTimeInterpreter};
use super::{CanAccessMutGlobal, CompileTimeInterpCx, CompileTimeMachine};
use crate::const_eval::CheckAlignment;
use crate::errors::ConstEvalError;
use crate::errors::{self, DanglingPtrInFinal};
@ -32,7 +32,7 @@ use crate::CTRL_C_RECEIVED;
// Returns a pointer to where the result lives
#[instrument(level = "trace", skip(ecx, body))]
fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
ecx: &mut CompileTimeEvalContext<'tcx>,
ecx: &mut CompileTimeInterpCx<'tcx>,
cid: GlobalId<'tcx>,
body: &'tcx mir::Body<'tcx>,
) -> InterpResult<'tcx, R> {
@ -114,7 +114,7 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
let err_diag = errors::MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind };
ecx.tcx.emit_node_span_lint(
lint::builtin::CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE,
ecx.best_lint_scope(),
ecx.machine.best_lint_scope(*ecx.tcx),
err_diag.span,
err_diag,
)
@ -139,13 +139,13 @@ pub(crate) fn mk_eval_cx_to_read_const_val<'tcx>(
root_span: Span,
param_env: ty::ParamEnv<'tcx>,
can_access_mut_global: CanAccessMutGlobal,
) -> CompileTimeEvalContext<'tcx> {
) -> CompileTimeInterpCx<'tcx> {
debug!("mk_eval_cx: {:?}", param_env);
InterpCx::new(
tcx,
root_span,
param_env,
CompileTimeInterpreter::new(can_access_mut_global, CheckAlignment::No),
CompileTimeMachine::new(can_access_mut_global, CheckAlignment::No),
)
}
@ -156,7 +156,7 @@ pub fn mk_eval_cx_for_const_val<'tcx>(
param_env: ty::ParamEnv<'tcx>,
val: mir::ConstValue<'tcx>,
ty: Ty<'tcx>,
) -> Option<(CompileTimeEvalContext<'tcx>, OpTy<'tcx>)> {
) -> Option<(CompileTimeInterpCx<'tcx>, OpTy<'tcx>)> {
let ecx = mk_eval_cx_to_read_const_val(tcx.tcx, tcx.span, param_env, CanAccessMutGlobal::No);
let op = ecx.const_val_to_op(val, ty, None).ok()?;
Some((ecx, op))
@ -170,7 +170,7 @@ pub fn mk_eval_cx_for_const_val<'tcx>(
/// encounter an `Indirect` they cannot handle.
#[instrument(skip(ecx), level = "debug")]
pub(super) fn op_to_const<'tcx>(
ecx: &CompileTimeEvalContext<'tcx>,
ecx: &CompileTimeInterpCx<'tcx>,
op: &OpTy<'tcx>,
for_diagnostics: bool,
) -> ConstValue<'tcx> {
@ -328,14 +328,14 @@ pub trait InterpretationResult<'tcx> {
/// evaluation query.
fn make_result(
mplace: MPlaceTy<'tcx>,
ecx: &mut InterpCx<'tcx, CompileTimeInterpreter<'tcx>>,
ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
) -> Self;
}
impl<'tcx> InterpretationResult<'tcx> for ConstAlloc<'tcx> {
fn make_result(
mplace: MPlaceTy<'tcx>,
_ecx: &mut InterpCx<'tcx, CompileTimeInterpreter<'tcx>>,
_ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
) -> Self {
ConstAlloc { alloc_id: mplace.ptr().provenance.unwrap().alloc_id(), ty: mplace.layout.ty }
}
@ -383,7 +383,7 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
// they do not have to behave "as if" they were evaluated at runtime.
// For consts however we want to ensure they behave "as if" they were evaluated at runtime,
// so we have to reject reading mutable global memory.
CompileTimeInterpreter::new(CanAccessMutGlobal::from(is_static), CheckAlignment::Error),
CompileTimeMachine::new(CanAccessMutGlobal::from(is_static), CheckAlignment::Error),
);
let res = ecx.load_mir(cid.instance.def, cid.promoted);
res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, body)).map_err(|error| {
@ -417,7 +417,7 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
#[inline(always)]
fn const_validate_mplace<'tcx>(
ecx: &InterpCx<'tcx, CompileTimeInterpreter<'tcx>>,
ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
mplace: &MPlaceTy<'tcx>,
cid: GlobalId<'tcx>,
) -> Result<(), ErrorHandled> {
@ -447,7 +447,7 @@ fn const_validate_mplace<'tcx>(
#[inline(always)]
fn report_validation_error<'tcx>(
ecx: &InterpCx<'tcx, CompileTimeInterpreter<'tcx>>,
ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
error: InterpErrorInfo<'tcx>,
alloc_id: AllocId,
) -> ErrorHandled {

View file

@ -9,12 +9,13 @@ use rustc_data_structures::fx::IndexEntry;
use rustc_hir::def_id::DefId;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::LangItem;
use rustc_hir::{self as hir, CRATE_HIR_ID};
use rustc_middle::bug;
use rustc_middle::mir;
use rustc_middle::mir::AssertMessage;
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty;
use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout};
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::lint::builtin::WRITES_THROUGH_IMMUTABLE_POINTER;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
@ -44,7 +45,7 @@ const TINY_LINT_TERMINATOR_LIMIT: usize = 20;
const PROGRESS_INDICATOR_START: usize = 4_000_000;
/// Extra machine state for CTFE, and the Machine instance
pub struct CompileTimeInterpreter<'tcx> {
pub struct CompileTimeMachine<'tcx> {
/// The number of terminators that have been evaluated.
///
/// This is used to produce lints informing the user that the compiler is not stuck.
@ -89,12 +90,12 @@ impl From<bool> for CanAccessMutGlobal {
}
}
impl<'tcx> CompileTimeInterpreter<'tcx> {
impl<'tcx> CompileTimeMachine<'tcx> {
pub(crate) fn new(
can_access_mut_global: CanAccessMutGlobal,
check_alignment: CheckAlignment,
) -> Self {
CompileTimeInterpreter {
CompileTimeMachine {
num_evaluated_steps: 0,
stack: Vec::new(),
can_access_mut_global,
@ -163,7 +164,7 @@ impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxIndexMap<K, V> {
}
}
pub(crate) type CompileTimeEvalContext<'tcx> = InterpCx<'tcx, CompileTimeInterpreter<'tcx>>;
pub(crate) type CompileTimeInterpCx<'tcx> = InterpCx<'tcx, CompileTimeMachine<'tcx>>;
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum MemoryKind {
@ -195,7 +196,7 @@ impl interpret::MayLeak for ! {
}
}
impl<'tcx> CompileTimeEvalContext<'tcx> {
impl<'tcx> CompileTimeInterpCx<'tcx> {
fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) {
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());
@ -229,7 +230,7 @@ impl<'tcx> CompileTimeEvalContext<'tcx> {
let def_id = instance.def_id();
if self.tcx.has_attr(def_id, sym::rustc_const_panic_str)
|| Some(def_id) == self.tcx.lang_items().begin_panic_fn()
|| self.tcx.is_lang_item(def_id, LangItem::BeginPanic)
{
let args = self.copy_fn_args(args);
// &str or &&str
@ -244,7 +245,7 @@ impl<'tcx> CompileTimeEvalContext<'tcx> {
let span = self.find_closest_untracked_caller_location();
let (file, line, col) = self.location_triple_for_span(span);
return Err(ConstEvalErrKind::Panic { msg, file, line, col }.into());
} else if Some(def_id) == self.tcx.lang_items().panic_fmt() {
} else if self.tcx.is_lang_item(def_id, LangItem::PanicFmt) {
// For panic_fmt, call const_panic_fmt instead.
let const_def_id = self.tcx.require_lang_item(LangItem::ConstPanicFmt, None);
let new_instance = ty::Instance::expect_resolve(
@ -255,7 +256,7 @@ impl<'tcx> CompileTimeEvalContext<'tcx> {
);
return Ok(Some(new_instance));
} else if Some(def_id) == self.tcx.lang_items().align_offset_fn() {
} else if self.tcx.is_lang_item(def_id, LangItem::AlignOffset) {
let args = self.copy_fn_args(args);
// For align_offset, we replace the function call if the pointer has no address.
match self.align_offset(instance, &args, dest, ret)? {
@ -369,7 +370,16 @@ impl<'tcx> CompileTimeEvalContext<'tcx> {
}
}
impl<'tcx> interpret::Machine<'tcx> for CompileTimeInterpreter<'tcx> {
impl<'tcx> CompileTimeMachine<'tcx> {
#[inline(always)]
/// Find the first stack frame that is within the current crate, if any.
/// Otherwise, return the crate's HirId
pub fn best_lint_scope(&self, tcx: TyCtxt<'tcx>) -> hir::HirId {
self.stack.iter().find_map(|frame| frame.lint_root(tcx)).unwrap_or(CRATE_HIR_ID)
}
}
impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
compile_time_machine!(<'tcx>);
type MemoryKind = MemoryKind;
@ -600,7 +610,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeInterpreter<'tcx> {
// By default, we stop after a million steps, but the user can disable this lint
// to be able to run until the heat death of the universe or power loss, whichever
// comes first.
let hir_id = ecx.best_lint_scope();
let hir_id = ecx.machine.best_lint_scope(*ecx.tcx);
let is_error = ecx
.tcx
.lint_level_at_node(

View file

@ -9,7 +9,7 @@ use rustc_target::abi::{Abi, VariantIdx};
use tracing::{debug, instrument, trace};
use super::eval_queries::{mk_eval_cx_to_read_const_val, op_to_const};
use super::machine::CompileTimeEvalContext;
use super::machine::CompileTimeInterpCx;
use super::{ValTreeCreationError, ValTreeCreationResult, VALTREE_MAX_NODES};
use crate::const_eval::CanAccessMutGlobal;
use crate::errors::MaxNumNodesInConstErr;
@ -21,7 +21,7 @@ use crate::interpret::{
#[instrument(skip(ecx), level = "debug")]
fn branches<'tcx>(
ecx: &CompileTimeEvalContext<'tcx>,
ecx: &CompileTimeInterpCx<'tcx>,
place: &MPlaceTy<'tcx>,
n: usize,
variant: Option<VariantIdx>,
@ -59,7 +59,7 @@ fn branches<'tcx>(
#[instrument(skip(ecx), level = "debug")]
fn slice_branches<'tcx>(
ecx: &CompileTimeEvalContext<'tcx>,
ecx: &CompileTimeInterpCx<'tcx>,
place: &MPlaceTy<'tcx>,
num_nodes: &mut usize,
) -> ValTreeCreationResult<'tcx> {
@ -77,7 +77,7 @@ fn slice_branches<'tcx>(
#[instrument(skip(ecx), level = "debug")]
fn const_to_valtree_inner<'tcx>(
ecx: &CompileTimeEvalContext<'tcx>,
ecx: &CompileTimeInterpCx<'tcx>,
place: &MPlaceTy<'tcx>,
num_nodes: &mut usize,
) -> ValTreeCreationResult<'tcx> {
@ -219,7 +219,7 @@ fn reconstruct_place_meta<'tcx>(
#[instrument(skip(ecx), level = "debug", ret)]
fn create_valtree_place<'tcx>(
ecx: &mut CompileTimeEvalContext<'tcx>,
ecx: &mut CompileTimeInterpCx<'tcx>,
layout: TyAndLayout<'tcx>,
valtree: ty::ValTree<'tcx>,
) -> MPlaceTy<'tcx> {
@ -364,7 +364,7 @@ pub fn valtree_to_const_value<'tcx>(
/// Put a valtree into memory and return a reference to that.
fn valtree_to_ref<'tcx>(
ecx: &mut CompileTimeEvalContext<'tcx>,
ecx: &mut CompileTimeInterpCx<'tcx>,
valtree: ty::ValTree<'tcx>,
pointee_ty: Ty<'tcx>,
) -> Immediate {
@ -380,7 +380,7 @@ fn valtree_to_ref<'tcx>(
#[instrument(skip(ecx), level = "debug")]
fn valtree_into_mplace<'tcx>(
ecx: &mut CompileTimeEvalContext<'tcx>,
ecx: &mut CompileTimeInterpCx<'tcx>,
place: &MPlaceTy<'tcx>,
valtree: ty::ValTree<'tcx>,
) {
@ -457,6 +457,6 @@ fn valtree_into_mplace<'tcx>(
}
}
fn dump_place<'tcx>(ecx: &CompileTimeEvalContext<'tcx>, place: &MPlaceTy<'tcx>) {
fn dump_place<'tcx>(ecx: &CompileTimeInterpCx<'tcx>, place: &MPlaceTy<'tcx>) {
trace!("{:?}", ecx.dump_place(&PlaceTy::from(place.clone())));
}

View file

@ -241,10 +241,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
variant_index: VariantIdx,
) -> InterpResult<'tcx, Option<(ScalarInt, usize)>> {
match self.layout_of(ty)?.variants {
abi::Variants::Single { index } => {
assert_eq!(index, variant_index);
Ok(None)
}
abi::Variants::Single { .. } => Ok(None),
abi::Variants::Multiple {
tag_encoding: TagEncoding::Direct,

View file

@ -4,7 +4,6 @@ use std::{fmt, mem};
use either::{Either, Left, Right};
use tracing::{debug, info, info_span, instrument, trace};
use hir::CRATE_HIR_ID;
use rustc_errors::DiagCtxt;
use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData};
use rustc_index::IndexVec;
@ -250,7 +249,7 @@ impl<'tcx, Prov: Provenance> Frame<'tcx, Prov> {
impl<'tcx, Prov: Provenance, Extra> Frame<'tcx, Prov, Extra> {
/// Get the current location within the Frame.
///
/// If this is `Left`, we are not currently executing any particular statement in
/// If this is `Right`, we are not currently executing any particular statement in
/// this frame (can happen e.g. during frame initialization, and during unwinding on
/// frames without cleanup code).
///
@ -271,13 +270,18 @@ impl<'tcx, Prov: Provenance, Extra> Frame<'tcx, Prov, Extra> {
}
}
pub fn lint_root(&self) -> Option<hir::HirId> {
self.current_source_info().and_then(|source_info| {
match &self.body.source_scopes[source_info.scope].local_data {
pub fn lint_root(&self, tcx: TyCtxt<'tcx>) -> Option<hir::HirId> {
// We first try to get a HirId via the current source scope,
// and fall back to `body.source`.
self.current_source_info()
.and_then(|source_info| match &self.body.source_scopes[source_info.scope].local_data {
mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
mir::ClearCrossCrate::Clear => None,
}
})
})
.or_else(|| {
let def_id = self.body.source.def_id().as_local();
def_id.map(|def_id| tcx.local_def_id_to_hir_id(def_id))
})
}
/// Returns the address of the buffer where the locals are stored. This is used by `Place` as a
@ -500,6 +504,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
}
}
/// Returns the span of the currently executed statement/terminator.
/// This is the span typically used for error reporting.
#[inline(always)]
pub fn cur_span(&self) -> Span {
// This deliberately does *not* honor `requires_caller_location` since it is used for much
@ -507,16 +513,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
self.stack().last().map_or(self.tcx.span, |f| f.current_span())
}
#[inline(always)]
/// Find the first stack frame that is within the current crate, if any, otherwise return the crate's HirId
pub fn best_lint_scope(&self) -> hir::HirId {
self.stack()
.iter()
.find_map(|frame| frame.body.source.def_id().as_local())
.map_or(CRATE_HIR_ID, |def_id| self.tcx.local_def_id_to_hir_id(def_id))
}
#[inline(always)]
pub(crate) fn stack(&self) -> &[Frame<'tcx, M::Provenance, M::FrameExtra>] {
M::stack(self)
}
@ -632,7 +628,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
}
/// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
/// frame which is not `#[track_caller]`. This is the fancy version of `cur_span`.
/// frame which is not `#[track_caller]`. This matches the `caller_location` intrinsic,
/// and is primarily intended for the panic machinery.
pub(crate) fn find_closest_untracked_caller_location(&self) -> Span {
for frame in self.stack().iter().rev() {
debug!("find_closest_untracked_caller_location: checking frame {:?}", frame.instance);
@ -1057,7 +1054,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
ty::Str | ty::Slice(_) | ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => false,
ty::Tuple(tys) => tys.last().iter().all(|ty| is_very_trivially_sized(**ty)),
ty::Tuple(tys) => tys.last().is_none_or(|ty| is_very_trivially_sized(*ty)),
ty::Pat(ty, ..) => is_very_trivially_sized(*ty),

View file

@ -45,7 +45,7 @@ pub trait HasStaticRootDefId {
fn static_def_id(&self) -> Option<LocalDefId>;
}
impl HasStaticRootDefId for const_eval::CompileTimeInterpreter<'_> {
impl HasStaticRootDefId for const_eval::CompileTimeMachine<'_> {
fn static_def_id(&self) -> Option<LocalDefId> {
Some(self.static_root_ids?.1)
}

View file

@ -446,7 +446,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
let (alloc_size, _alloc_align, ret_val) = alloc_size(alloc_id, offset, prov)?;
// Test bounds.
// It is sufficient to check this for the end pointer. Also check for overflow!
if offset.checked_add(size, &self.tcx).map_or(true, |end| end > alloc_size) {
if offset.checked_add(size, &self.tcx).is_none_or(|end| end > alloc_size) {
throw_ub!(PointerOutOfBounds {
alloc_id,
alloc_size,

View file

@ -112,25 +112,20 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// Shift ops can have an RHS with a different numeric type.
if matches!(bin_op, Shl | ShlUnchecked | Shr | ShrUnchecked) {
let size = left.layout.size.bits();
let l_bits = left.layout.size.bits();
// Compute the equivalent shift modulo `size` that is in the range `0..size`. (This is
// the one MIR operator that does *not* directly map to a single LLVM operation.)
let (shift_amount, overflow) = if right.layout.abi.is_signed() {
let shift_amount = r_signed();
let overflow = shift_amount < 0 || shift_amount >= i128::from(size);
// Deliberately wrapping `as` casts: shift_amount *can* be negative, but the result
// of the `as` will be equal modulo `size` (since it is a power of two).
let masked_amount = (shift_amount as u128) % u128::from(size);
assert_eq!(overflow, shift_amount != i128::try_from(masked_amount).unwrap());
(masked_amount, overflow)
let rem = shift_amount.rem_euclid(l_bits.into());
// `rem` is guaranteed positive, so the `unwrap` cannot fail
(u128::try_from(rem).unwrap(), rem != shift_amount)
} else {
let shift_amount = r_unsigned();
let overflow = shift_amount >= u128::from(size);
let masked_amount = shift_amount % u128::from(size);
assert_eq!(overflow, shift_amount != masked_amount);
(masked_amount, overflow)
let rem = shift_amount.rem_euclid(l_bits.into());
(rem, rem != shift_amount)
};
let shift_amount = u32::try_from(shift_amount).unwrap(); // we masked so this will always fit
let shift_amount = u32::try_from(shift_amount).unwrap(); // we brought this in the range `0..size` so this will always fit
// Compute the shifted result.
let result = if left.layout.abi.is_signed() {
let l = l_signed();
@ -362,14 +357,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
let left = left.to_scalar();
let right = right.to_scalar();
Ok(match fty {
FloatTy::F16 => unimplemented!("f16_f128"),
FloatTy::F16 => {
self.binary_float_op(bin_op, layout, left.to_f16()?, right.to_f16()?)
}
FloatTy::F32 => {
self.binary_float_op(bin_op, layout, left.to_f32()?, right.to_f32()?)
}
FloatTy::F64 => {
self.binary_float_op(bin_op, layout, left.to_f64()?, right.to_f64()?)
}
FloatTy::F128 => unimplemented!("f16_f128"),
FloatTy::F128 => {
self.binary_float_op(bin_op, layout, left.to_f128()?, right.to_f128()?)
}
})
}
_ if left.layout.ty.is_integral() => {
@ -429,11 +428,16 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
}
ty::Float(fty) => {
let val = val.to_scalar();
if un_op != Neg {
span_bug!(self.cur_span(), "Invalid float op {:?}", un_op);
}
// No NaN adjustment here, `-` is a bitwise operation!
let res = match (un_op, fty) {
(Neg, FloatTy::F32) => Scalar::from_f32(-val.to_f32()?),
(Neg, FloatTy::F64) => Scalar::from_f64(-val.to_f64()?),
_ => span_bug!(self.cur_span(), "Invalid float op {:?}", un_op),
let res = match fty {
FloatTy::F16 => Scalar::from_f16(-val.to_f16()?),
FloatTy::F32 => Scalar::from_f32(-val.to_f32()?),
FloatTy::F64 => Scalar::from_f64(-val.to_f64()?),
FloatTy::F128 => Scalar::from_f128(-val.to_f128()?),
};
Ok(ImmTy::from_scalar(res, layout))
}

View file

@ -300,7 +300,7 @@ where
) -> InterpResult<'tcx, P> {
let len = base.len(self)?; // also asserts that we have a type where this makes sense
let actual_to = if from_end {
if from.checked_add(to).map_or(true, |to| to > len) {
if from.checked_add(to).is_none_or(|to| to > len) {
// This can only be reached in ConstProp and non-rustc-MIR.
throw_ub!(BoundsCheckFailed { len: len, index: from.saturating_add(to) });
}

View file

@ -1,4 +1,4 @@
use crate::const_eval::{CompileTimeEvalContext, CompileTimeInterpreter, InterpretationResult};
use crate::const_eval::{CompileTimeInterpCx, CompileTimeMachine, InterpretationResult};
use rustc_hir::def_id::LocalDefId;
use rustc_middle::mir;
use rustc_middle::mir::interpret::{Allocation, InterpResult, Pointer};
@ -84,7 +84,7 @@ where
impl<'tcx> InterpretationResult<'tcx> for mir::interpret::ConstAllocation<'tcx> {
fn make_result(
mplace: MPlaceTy<'tcx>,
ecx: &mut InterpCx<'tcx, CompileTimeInterpreter<'tcx>>,
ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>,
) -> Self {
let alloc_id = mplace.ptr().provenance.unwrap().alloc_id();
let alloc = ecx.memory.alloc_map.swap_remove(&alloc_id).unwrap().1;
@ -93,7 +93,7 @@ impl<'tcx> InterpretationResult<'tcx> for mir::interpret::ConstAllocation<'tcx>
}
pub(crate) fn create_static_alloc<'tcx>(
ecx: &mut CompileTimeEvalContext<'tcx>,
ecx: &mut CompileTimeInterpCx<'tcx>,
static_def_id: LocalDefId,
layout: TyAndLayout<'tcx>,
) -> InterpResult<'tcx, MPlaceTy<'tcx>> {

View file

@ -29,7 +29,7 @@ use rustc_target::abi::{
use std::hash::Hash;
use super::{
err_ub, format_interp_error, machine::AllocMap, throw_ub, AllocId, CheckInAllocMsg,
err_ub, format_interp_error, machine::AllocMap, throw_ub, AllocId, AllocKind, CheckInAllocMsg,
GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy,
Pointer, Projectable, Scalar, ValueVisitor,
};
@ -413,8 +413,6 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
Ub(PointerOutOfBounds { .. }) => DanglingPtrOutOfBounds {
ptr_kind
},
// This cannot happen during const-eval (because interning already detects
// dangling pointers), but it can happen in Miri.
Ub(PointerUseAfterFree(..)) => DanglingPtrUseAfterFree {
ptr_kind,
},
@ -493,9 +491,17 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
}
}
// Mutability check.
// Dangling and Mutability check.
let (size, _align, alloc_kind) = self.ecx.get_alloc_info(alloc_id);
if alloc_kind == AllocKind::Dead {
// This can happen for zero-sized references. We can't have *any* references to non-existing
// allocations though, interning rejects them all as the rest of rustc isn't happy with them...
// so we throw an error, even though this isn't really UB.
// A potential future alternative would be to resurrect this as a zero-sized allocation
// (which codegen will then compile to an aligned dummy pointer anyway).
throw_validation_failure!(self.path, DanglingPtrUseAfterFree { ptr_kind });
}
// If this allocation has size zero, there is no actual mutability here.
let (size, _align, _alloc_kind) = self.ecx.get_alloc_info(alloc_id);
if size != Size::ZERO {
let alloc_actual_mutbl = mutability(self.ecx, alloc_id);
// Mutable pointer to immutable memory is no good.

View file

@ -6,6 +6,7 @@
#![feature(box_patterns)]
#![feature(decl_macro)]
#![feature(if_let_guard)]
#![feature(is_none_or)]
#![feature(let_chains)]
#![feature(never_type)]
#![feature(rustdoc_internals)]

View file

@ -7,12 +7,12 @@ use rustc_middle::ty::{self, Mutability};
use rustc_span::symbol::Symbol;
use tracing::trace;
use crate::const_eval::{mk_eval_cx_to_read_const_val, CanAccessMutGlobal, CompileTimeEvalContext};
use crate::const_eval::{mk_eval_cx_to_read_const_val, CanAccessMutGlobal, CompileTimeInterpCx};
use crate::interpret::*;
/// Allocate a `const core::panic::Location` with the provided filename and line/column numbers.
fn alloc_caller_location<'tcx>(
ecx: &mut CompileTimeEvalContext<'tcx>,
ecx: &mut CompileTimeInterpCx<'tcx>,
filename: Symbol,
line: u32,
col: u32,

View file

@ -3,7 +3,7 @@ use rustc_middle::ty::layout::{LayoutCx, LayoutError, LayoutOf, TyAndLayout, Val
use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Ty, TyCtxt};
use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants};
use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeInterpreter};
use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeMachine};
use crate::interpret::{InterpCx, MemoryKind, OpTy};
/// Determines if this type permits "raw" initialization by just transmuting some memory into an
@ -45,7 +45,7 @@ fn might_permit_raw_init_strict<'tcx>(
tcx: TyCtxt<'tcx>,
kind: ValidityRequirement,
) -> Result<bool, &'tcx LayoutError<'tcx>> {
let machine = CompileTimeInterpreter::new(CanAccessMutGlobal::No, CheckAlignment::Error);
let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error);
let mut cx = InterpCx::new(tcx, rustc_span::DUMMY_SP, ParamEnv::reveal_all(), machine);

View file

@ -12,7 +12,6 @@ elsa = "=1.7.1"
ena = "0.14.3"
indexmap = { version = "2.0.0" }
jobserver_crate = { version = "0.1.28", package = "jobserver" }
libc = "0.2"
measureme = "11"
rustc-hash = "1.1.0"
rustc-rayon = { version = "0.5.0", optional = true }
@ -41,6 +40,11 @@ features = [
"Win32_System_Threading",
]
[target.'cfg(unix)'.dependencies]
# tidy-alphabetical-start
libc = "0.2"
# tidy-alphabetical-end
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
# tidy-alphabetical-start
memmap2 = "0.2.1"

View file

@ -9,6 +9,10 @@ cfg_match! {
mod linux;
use linux as imp;
}
cfg(target_os = "redox") => {
mod linux;
use linux as imp;
}
cfg(unix) => {
mod unix;
use unix as imp;

View file

@ -8,9 +8,14 @@ use rustc_session::parse::ParseSess;
use rustc_span::symbol::Ident;
use rustc_span::Span;
pub(crate) const RAW_IDENT_ERR: &str = "`${concat(..)}` currently does not support raw identifiers";
/// A meta-variable expression, for expansions based on properties of meta-variables.
#[derive(Debug, Clone, PartialEq, Encodable, Decodable)]
#[derive(Debug, PartialEq, Encodable, Decodable)]
pub(crate) enum MetaVarExpr {
/// Unification of two or more identifiers.
Concat(Box<[MetaVarExprConcatElem]>),
/// The number of repetitions of an identifier.
Count(Ident, usize),
@ -42,6 +47,31 @@ impl MetaVarExpr {
check_trailing_token(&mut tts, psess)?;
let mut iter = args.trees();
let rslt = match ident.as_str() {
"concat" => {
let mut result = Vec::new();
loop {
let is_var = try_eat_dollar(&mut iter);
let element_ident = parse_ident(&mut iter, psess, outer_span)?;
let element = if is_var {
MetaVarExprConcatElem::Var(element_ident)
} else {
MetaVarExprConcatElem::Ident(element_ident)
};
result.push(element);
if iter.look_ahead(0).is_none() {
break;
}
if !try_eat_comma(&mut iter) {
return Err(psess.dcx.struct_span_err(outer_span, "expected comma"));
}
}
if result.len() < 2 {
return Err(psess
.dcx
.struct_span_err(ident.span, "`concat` must have at least two elements"));
}
MetaVarExpr::Concat(result.into())
}
"count" => parse_count(&mut iter, psess, ident.span)?,
"ignore" => {
eat_dollar(&mut iter, psess, ident.span)?;
@ -68,11 +98,21 @@ impl MetaVarExpr {
pub(crate) fn ident(&self) -> Option<Ident> {
match *self {
MetaVarExpr::Count(ident, _) | MetaVarExpr::Ignore(ident) => Some(ident),
MetaVarExpr::Index(..) | MetaVarExpr::Len(..) => None,
MetaVarExpr::Concat { .. } | MetaVarExpr::Index(..) | MetaVarExpr::Len(..) => None,
}
}
}
#[derive(Debug, Decodable, Encodable, PartialEq)]
pub(crate) enum MetaVarExprConcatElem {
/// There is NO preceding dollar sign, which means that this identifier should be interpreted
/// as a literal.
Ident(Ident),
/// There is a preceding dollar sign, which means that this identifier should be expanded
/// and interpreted as a variable.
Var(Ident),
}
// Checks if there are any remaining tokens. For example, `${ignore(ident ... a b c ...)}`
fn check_trailing_token<'psess>(
iter: &mut RefTokenTreeCursor<'_>,
@ -138,26 +178,30 @@ fn parse_depth<'psess>(
fn parse_ident<'psess>(
iter: &mut RefTokenTreeCursor<'_>,
psess: &'psess ParseSess,
span: Span,
fallback_span: Span,
) -> PResult<'psess, Ident> {
if let Some(tt) = iter.next()
&& let TokenTree::Token(token, _) = tt
{
if let Some((elem, IdentIsRaw::No)) = token.ident() {
return Ok(elem);
let Some(tt) = iter.next() else {
return Err(psess.dcx.struct_span_err(fallback_span, "expected identifier"));
};
let TokenTree::Token(token, _) = tt else {
return Err(psess.dcx.struct_span_err(tt.span(), "expected identifier"));
};
if let Some((elem, is_raw)) = token.ident() {
if let IdentIsRaw::Yes = is_raw {
return Err(psess.dcx.struct_span_err(elem.span, RAW_IDENT_ERR));
}
let token_str = pprust::token_to_string(token);
let mut err =
psess.dcx.struct_span_err(span, format!("expected identifier, found `{}`", &token_str));
err.span_suggestion(
token.span,
format!("try removing `{}`", &token_str),
"",
Applicability::MaybeIncorrect,
);
return Err(err);
return Ok(elem);
}
Err(psess.dcx.struct_span_err(span, "expected identifier"))
let token_str = pprust::token_to_string(token);
let mut err =
psess.dcx.struct_span_err(token.span, format!("expected identifier, found `{token_str}`"));
err.span_suggestion(
token.span,
format!("try removing `{token_str}`"),
"",
Applicability::MaybeIncorrect,
);
Err(err)
}
/// Tries to move the iterator forward returning `true` if there is a comma. If not, then the
@ -170,6 +214,17 @@ fn try_eat_comma(iter: &mut RefTokenTreeCursor<'_>) -> bool {
false
}
/// Tries to move the iterator forward returning `true` if there is a dollar sign. If not, then the
/// iterator is not modified and the result is `false`.
fn try_eat_dollar(iter: &mut RefTokenTreeCursor<'_>) -> bool {
if let Some(TokenTree::Token(token::Token { kind: token::Dollar, .. }, _)) = iter.look_ahead(0)
{
let _ = iter.next();
return true;
}
false
}
/// Expects that the next item is a dollar sign.
fn eat_dollar<'psess>(
iter: &mut RefTokenTreeCursor<'_>,

View file

@ -155,6 +155,13 @@ fn maybe_emit_macro_metavar_expr_feature(features: &Features, sess: &Session, sp
}
}
fn maybe_emit_macro_metavar_expr_concat_feature(features: &Features, sess: &Session, span: Span) {
if !features.macro_metavar_expr_concat {
let msg = "the `concat` meta-variable expression is unstable";
feature_err(sess, sym::macro_metavar_expr_concat, span, msg).emit();
}
}
/// Takes a `tokenstream::TokenTree` and returns a `self::TokenTree`. Specifically, this takes a
/// generic `TokenTree`, such as is used in the rest of the compiler, and returns a `TokenTree`
/// for use in parsing a macro.
@ -217,11 +224,19 @@ fn parse_tree<'a>(
return TokenTree::token(token::Dollar, dollar_span);
}
Ok(elem) => {
maybe_emit_macro_metavar_expr_feature(
features,
sess,
delim_span.entire(),
);
if let MetaVarExpr::Concat(_) = elem {
maybe_emit_macro_metavar_expr_concat_feature(
features,
sess,
delim_span.entire(),
);
} else {
maybe_emit_macro_metavar_expr_feature(
features,
sess,
delim_span.entire(),
);
}
return TokenTree::MetaVarExpr(delim_span, elem);
}
}

View file

@ -3,18 +3,19 @@ use crate::errors::{
NoSyntaxVarsExprRepeat, VarStillRepeating,
};
use crate::mbe::macro_parser::{NamedMatch, NamedMatch::*};
use crate::mbe::metavar_expr::{MetaVarExprConcatElem, RAW_IDENT_ERR};
use crate::mbe::{self, KleeneOp, MetaVarExpr};
use rustc_ast::mut_visit::{self, MutVisitor};
use rustc_ast::token::IdentIsRaw;
use rustc_ast::token::{self, Delimiter, Token, TokenKind};
use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{pluralize, Diag, DiagCtxt, PResult};
use rustc_parse::parser::ParseNtResult;
use rustc_session::parse::ParseSess;
use rustc_span::hygiene::{LocalExpnId, Transparency};
use rustc_span::symbol::{sym, Ident, MacroRulesNormalizedIdent};
use rustc_span::{with_metavar_spans, Span, SyntaxContext};
use rustc_session::parse::ParseSess;
use rustc_span::{with_metavar_spans, Span, Symbol, SyntaxContext};
use smallvec::{smallvec, SmallVec};
use std::mem;
@ -30,7 +31,7 @@ impl MutVisitor for Marker {
// it's some advanced case with macro-generated macros. So if we cache the marked version
// of that context once, we'll typically have a 100% cache hit rate after that.
let Marker(expn_id, transparency, ref mut cache) = *self;
span.update_ctxt(|ctxt| {
*span = span.map_ctxt(|ctxt| {
*cache
.entry(ctxt)
.or_insert_with(|| ctxt.apply_mark(expn_id.to_expn_id(), transparency))
@ -675,6 +676,23 @@ fn transcribe_metavar_expr<'a>(
span
};
match *expr {
MetaVarExpr::Concat(ref elements) => {
let mut concatenated = String::new();
for element in elements.into_iter() {
let string = match element {
MetaVarExprConcatElem::Ident(ident) => ident.to_string(),
MetaVarExprConcatElem::Var(ident) => extract_ident(dcx, *ident, interp)?,
};
concatenated.push_str(&string);
}
// The current implementation marks the span as coming from the macro regardless of
// contexts of the concatenated identifiers but this behavior may change in the
// future.
result.push(TokenTree::Token(
Token::from_ast_ident(Ident::new(Symbol::intern(&concatenated), visited_span())),
Spacing::Alone,
));
}
MetaVarExpr::Count(original_ident, depth) => {
let matched = matched_from_ident(dcx, original_ident, interp)?;
let count = count_repetitions(dcx, depth, matched, repeats, sp)?;
@ -709,3 +727,33 @@ fn transcribe_metavar_expr<'a>(
}
Ok(())
}
/// Extracts an identifier that can be originated from a `$var:ident` variable or from a token tree.
fn extract_ident<'a>(
dcx: &'a DiagCtxt,
ident: Ident,
interp: &FxHashMap<MacroRulesNormalizedIdent, NamedMatch>,
) -> PResult<'a, String> {
if let NamedMatch::MatchedSingle(pnr) = matched_from_ident(dcx, ident, interp)? {
if let ParseNtResult::Ident(nt_ident, is_raw) = pnr {
if let IdentIsRaw::Yes = is_raw {
return Err(dcx.struct_span_err(ident.span, RAW_IDENT_ERR));
}
return Ok(nt_ident.to_string());
}
if let ParseNtResult::Tt(TokenTree::Token(
Token { kind: TokenKind::Ident(token_ident, is_raw), .. },
_,
)) = pnr
{
if let IdentIsRaw::Yes = is_raw {
return Err(dcx.struct_span_err(ident.span, RAW_IDENT_ERR));
}
return Ok(token_ident.to_string());
}
}
Err(dcx.struct_span_err(
ident.span,
"`${concat(..)}` currently only accepts identifiers or meta-variables as parameters",
))
}

View file

@ -516,6 +516,8 @@ declare_features! (
(unstable, lint_reasons, "1.31.0", Some(54503)),
/// Give access to additional metadata about declarative macro meta-variables.
(unstable, macro_metavar_expr, "1.61.0", Some(83527)),
/// Provides a way to concatenate identifiers using metavariable expressions.
(unstable, macro_metavar_expr_concat, "CURRENT_RUSTC_VERSION", Some(124225)),
/// Allows `#[marker]` on certain traits allowing overlapping implementations.
(unstable, marker_trait_attr, "1.30.0", Some(29864)),
/// Allows exhaustive pattern matching on types that contain uninhabited types in cases that are

View file

@ -1633,6 +1633,13 @@ pub struct ConstBlock {
}
/// An expression.
///
/// For more details, see the [rust lang reference].
/// Note that the reference does not document nightly-only features.
/// There may be also slight differences in the names and representation of AST nodes between
/// the compiler and the reference.
///
/// [rust lang reference]: https://doc.rust-lang.org/reference/expressions.html
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub struct Expr<'hir> {
pub hir_id: HirId,
@ -2464,6 +2471,15 @@ pub enum AssocItemConstraintKind<'hir> {
Bound { bounds: &'hir [GenericBound<'hir>] },
}
impl<'hir> AssocItemConstraintKind<'hir> {
pub fn descr(&self) -> &'static str {
match self {
AssocItemConstraintKind::Equality { .. } => "binding",
AssocItemConstraintKind::Bound { .. } => "constraint",
}
}
}
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub struct Ty<'hir> {
pub hir_id: HirId,
@ -3147,6 +3163,13 @@ impl ItemId {
/// An item
///
/// The name might be a dummy name in case of anonymous items
///
/// For more details, see the [rust lang reference].
/// Note that the reference does not document nightly-only features.
/// There may be also slight differences in the names and representation of AST nodes between
/// the compiler and the reference.
///
/// [rust lang reference]: https://doc.rust-lang.org/reference/items.html
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub struct Item<'hir> {
pub ident: Ident,
@ -3749,6 +3772,21 @@ impl<'hir> Node<'hir> {
}
}
/// Get a `hir::Impl` if the node is an impl block for the given `trait_def_id`.
pub fn impl_block_of_trait(self, trait_def_id: DefId) -> Option<&'hir Impl<'hir>> {
match self {
Node::Item(Item { kind: ItemKind::Impl(impl_block), .. })
if impl_block
.of_trait
.and_then(|trait_ref| trait_ref.trait_def_id())
.is_some_and(|trait_id| trait_id == trait_def_id) =>
{
Some(impl_block)
}
_ => None,
}
}
pub fn fn_sig(self) -> Option<&'hir FnSig<'hir>> {
match self {
Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })

View file

@ -244,7 +244,9 @@ language_item_table! {
AsyncIterator, sym::async_iterator, async_iterator_trait, Target::Trait, GenericRequirement::Exact(0);
CoroutineState, sym::coroutine_state, coroutine_state, Target::Enum, GenericRequirement::None;
Coroutine, sym::coroutine, coroutine_trait, Target::Trait, GenericRequirement::Minimum(1);
Coroutine, sym::coroutine, coroutine_trait, Target::Trait, GenericRequirement::Exact(1);
CoroutineReturn, sym::coroutine_return, coroutine_return, Target::AssocTy, GenericRequirement::Exact(1);
CoroutineYield, sym::coroutine_yield, coroutine_yield, Target::AssocTy, GenericRequirement::Exact(1);
CoroutineResume, sym::coroutine_resume, coroutine_resume, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
Unpin, sym::unpin, unpin_trait, Target::Trait, GenericRequirement::None;

View file

@ -53,7 +53,7 @@ impl<'tcx> Bounds<'tcx> {
span,
);
// FIXME(-Znext-solver): We can likely remove this hack once the new trait solver lands.
if tcx.lang_items().sized_trait() == Some(trait_ref.def_id()) {
if tcx.is_lang_item(trait_ref.def_id(), LangItem::Sized) {
self.clauses.insert(0, clause);
} else {
self.clauses.push(clause);

View file

@ -1,6 +1,6 @@
use rustc_ast::InlineAsmTemplatePiece;
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
use rustc_hir::{self as hir, LangItem};
use rustc_middle::bug;
use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy};
use rustc_session::lint;
@ -62,8 +62,10 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
ty::Int(IntTy::I64) | ty::Uint(UintTy::U64) => Some(InlineAsmType::I64),
ty::Int(IntTy::I128) | ty::Uint(UintTy::U128) => Some(InlineAsmType::I128),
ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => Some(asm_ty_isize),
ty::Float(FloatTy::F16) => Some(InlineAsmType::F16),
ty::Float(FloatTy::F32) => Some(InlineAsmType::F32),
ty::Float(FloatTy::F64) => Some(InlineAsmType::F64),
ty::Float(FloatTy::F128) => Some(InlineAsmType::F128),
ty::FnPtr(_) => Some(asm_ty_isize),
ty::RawPtr(ty, _) if self.is_thin_ptr_ty(ty) => Some(asm_ty_isize),
ty::Adt(adt, args) if adt.repr().simd() => {
@ -105,8 +107,10 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
width => bug!("unsupported pointer width: {width}"),
})
}
ty::Float(FloatTy::F16) => Some(InlineAsmType::VecF16(size)),
ty::Float(FloatTy::F32) => Some(InlineAsmType::VecF32(size)),
ty::Float(FloatTy::F64) => Some(InlineAsmType::VecF64(size)),
ty::Float(FloatTy::F128) => Some(InlineAsmType::VecF128(size)),
_ => None,
}
}
@ -134,7 +138,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
// `!` is allowed for input but not for output (issue #87802)
ty::Never if is_input => return None,
_ if ty.references_error() => return None,
ty::Adt(adt, args) if Some(adt.did()) == self.tcx.lang_items().maybe_uninit() => {
ty::Adt(adt, args) if self.tcx.is_lang_item(adt.did(), LangItem::MaybeUninit) => {
let fields = &adt.non_enum_variant().fields;
let ty = fields[FieldIdx::from_u32(1)].ty(self.tcx, args);
// FIXME: Are we just trying to map to the `T` in `MaybeUninit<T>`?

View file

@ -8,6 +8,7 @@
use crate::errors;
use rustc_errors::{codes::*, struct_span_code_err};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::LangItem;
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
use rustc_session::parse::feature_err;
@ -49,7 +50,7 @@ fn enforce_trait_manually_implementable(
) -> Result<(), ErrorGuaranteed> {
let impl_header_span = tcx.def_span(impl_def_id);
if tcx.lang_items().freeze_trait() == Some(trait_def_id) {
if tcx.is_lang_item(trait_def_id, LangItem::Freeze) {
if !tcx.features().freeze_impls {
feature_err(
&tcx.sess,
@ -75,7 +76,7 @@ fn enforce_trait_manually_implementable(
// Maintain explicit error code for `Unsize`, since it has a useful
// explanation about using `CoerceUnsized` instead.
if Some(trait_def_id) == tcx.lang_items().unsize_trait() {
if tcx.is_lang_item(trait_def_id, LangItem::Unsize) {
err.code(E0328);
}

View file

@ -1217,7 +1217,6 @@ pub fn prohibit_assoc_item_constraint(
// otherwise suggest the removal of the binding.
if let Some((def_id, segment, _)) = segment
&& segment.args().parenthesized == hir::GenericArgsParentheses::No
&& let hir::AssocItemConstraintKind::Equality { term } = constraint.kind
{
// Suggests removal of the offending binding
let suggest_removal = |e: &mut Diag<'_>| {
@ -1263,7 +1262,7 @@ pub fn prohibit_assoc_item_constraint(
if let Ok(suggestion) = tcx.sess.source_map().span_to_snippet(removal_span) {
e.span_suggestion_verbose(
removal_span,
"consider removing this associated item binding",
format!("consider removing this associated item {}", constraint.kind.descr()),
suggestion,
Applicability::MaybeIncorrect,
);
@ -1286,19 +1285,73 @@ pub fn prohibit_assoc_item_constraint(
// Check if the type has a generic param with the same name
// as the assoc type name in the associated item binding.
let generics = tcx.generics_of(def_id);
let matching_param =
generics.own_params.iter().find(|p| p.name.as_str() == constraint.ident.as_str());
let matching_param = generics.own_params.iter().find(|p| p.name == constraint.ident.name);
// Now emit the appropriate suggestion
if let Some(matching_param) = matching_param {
match (&matching_param.kind, term) {
(GenericParamDefKind::Type { .. }, hir::Term::Ty(ty)) => {
suggest_direct_use(&mut err, ty.span);
}
(GenericParamDefKind::Const { .. }, hir::Term::Const(c)) => {
match (constraint.kind, &matching_param.kind) {
(
hir::AssocItemConstraintKind::Equality { term: hir::Term::Ty(ty) },
GenericParamDefKind::Type { .. },
) => suggest_direct_use(&mut err, ty.span),
(
hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(c) },
GenericParamDefKind::Const { .. },
) => {
let span = tcx.hir().span(c.hir_id);
suggest_direct_use(&mut err, span);
}
(hir::AssocItemConstraintKind::Bound { bounds }, _) => {
// Suggest `impl<T: Bound> Trait<T> for Foo` when finding
// `impl Trait<T: Bound> for Foo`
// Get the parent impl block based on the binding we have
// and the trait DefId
let impl_block = tcx
.hir()
.parent_iter(constraint.hir_id)
.find_map(|(_, node)| node.impl_block_of_trait(def_id));
let type_with_constraints =
tcx.sess.source_map().span_to_snippet(constraint.span);
if let Some(impl_block) = impl_block
&& let Ok(type_with_constraints) = type_with_constraints
{
// Filter out the lifetime parameters because
// they should be declared before the type parameter
let lifetimes: String = bounds
.iter()
.filter_map(|bound| {
if let hir::GenericBound::Outlives(lifetime) = bound {
Some(format!("{lifetime}, "))
} else {
None
}
})
.collect();
// Figure out a span and suggestion string based on
// whether there are any existing parameters
let param_decl = if let Some(param_span) =
impl_block.generics.span_for_param_suggestion()
{
(param_span, format!(", {lifetimes}{type_with_constraints}"))
} else {
(
impl_block.generics.span.shrink_to_lo(),
format!("<{lifetimes}{type_with_constraints}>"),
)
};
let suggestions =
vec![param_decl, (constraint.span, format!("{}", matching_param.name))];
err.multipart_suggestion_verbose(
format!("declare the type parameter right after the `impl` keyword"),
suggestions,
Applicability::MaybeIncorrect,
);
}
}
_ => suggest_removal(&mut err),
}
} else {

View file

@ -531,6 +531,7 @@ pub(crate) fn check_generic_arg_count(
let num_default_params = expected_max - expected_min;
let mut all_params_are_binded = false;
let gen_args_info = if provided > expected_max {
invalid_args.extend((expected_max..provided).map(|i| i + args_offset));
let num_redundant_args = provided - expected_max;
@ -547,6 +548,20 @@ pub(crate) fn check_generic_arg_count(
} else {
let num_missing_args = expected_max - provided;
let constraint_names: Vec<_> =
gen_args.constraints.iter().map(|b| b.ident.name).collect();
let param_names: Vec<_> = gen_params
.own_params
.iter()
.filter(|param| !has_self || param.index != 0) // Assumes `Self` will always be the first parameter
.map(|param| param.name)
.collect();
if constraint_names == param_names {
// We set this to true and delay emitting `WrongNumberOfGenericArgs`
// to provide a succinct error for cases like issue #113073
all_params_are_binded = true;
};
GenericArgsInfo::MissingTypesOrConsts {
num_missing_args,
num_default_params,
@ -567,7 +582,7 @@ pub(crate) fn check_generic_arg_count(
def_id,
)
.diagnostic()
.emit()
.emit_unless(all_params_are_binded)
});
Err(reported)

View file

@ -44,6 +44,10 @@ hir_typeck_convert_using_method = try using `{$sugg}` to convert `{$found}` to `
hir_typeck_ctor_is_private = tuple struct constructor `{$def}` is private
hir_typeck_dependency_on_unit_never_type_fallback = this function depends on never type fallback being `()`
.note = in edition 2024, the requirement `{$obligation}` will fail
.help = specify the types explicitly
hir_typeck_deref_is_empty = this expression `Deref`s to `{$deref_ty}` which implements `is_empty`
hir_typeck_expected_default_return_type = expected `()` because of default return type

View file

@ -234,7 +234,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ret_ty = ret_coercion.borrow().expected_ty();
let ret_ty = self.infcx.shallow_resolve(ret_ty);
self.can_coerce(arm_ty, ret_ty)
&& prior_arm.map_or(true, |(_, ty, _)| self.can_coerce(ty, ret_ty))
&& prior_arm.is_none_or(|(_, ty, _)| self.can_coerce(ty, ret_ty))
// The match arms need to unify for the case of `impl Trait`.
&& !matches!(ret_ty.kind(), ty::Alias(ty::Opaque, ..))
}

View file

@ -5,9 +5,9 @@ use super::{Expectation, FnCtxt, TupleArgumentsFlag};
use crate::errors;
use rustc_ast::util::parser::PREC_POSTFIX;
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey};
use rustc_hir as hir;
use rustc_hir::def::{self, CtorKind, Namespace, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::{self as hir, LangItem};
use rustc_hir_analysis::autoderef::Autoderef;
use rustc_infer::traits::ObligationCauseCode;
use rustc_infer::{
@ -41,7 +41,7 @@ pub fn check_legal_trait_for_method_call(
trait_id: DefId,
body_id: DefId,
) -> Result<(), ErrorGuaranteed> {
if tcx.lang_items().drop_trait() == Some(trait_id)
if tcx.is_lang_item(trait_id, LangItem::Drop)
&& tcx.lang_items().fallback_surface_drop_fn() != Some(body_id)
{
let sugg = if let Some(receiver) = receiver.filter(|s| !s.is_empty()) {
@ -628,7 +628,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return;
};
let pick = self.confirm_method(
let pick = self.confirm_method_for_diagnostic(
call_expr.span,
callee_expr,
call_expr,

View file

@ -913,7 +913,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
if self
.tcx
.upvars_mentioned(closure_def_id_a.expect_local())
.map_or(true, |u| u.is_empty()) =>
.is_none_or(|u| u.is_empty()) =>
{
// We coerce the closure, which has fn type
// `extern "rust-call" fn((arg0,arg1,...)) -> _`

View file

@ -4,7 +4,7 @@ use rustc_errors::{Applicability, Diag};
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::intravisit::Visitor;
use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
use rustc_infer::infer::DefineOpaqueTypes;
use rustc_middle::bug;
use rustc_middle::ty::adjustment::AllowTwoPhase;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
@ -166,7 +166,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Requires that the two types unify, and prints an error message if
/// they don't.
pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
if let Some(e) = self.demand_suptype_diag(sp, expected, actual) {
if let Err(e) = self.demand_suptype_diag(sp, expected, actual) {
e.emit();
}
}
@ -176,7 +176,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sp: Span,
expected: Ty<'tcx>,
actual: Ty<'tcx>,
) -> Option<Diag<'tcx>> {
) -> Result<(), Diag<'tcx>> {
self.demand_suptype_with_origin(&self.misc(sp), expected, actual)
}
@ -186,18 +186,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
cause: &ObligationCause<'tcx>,
expected: Ty<'tcx>,
actual: Ty<'tcx>,
) -> Option<Diag<'tcx>> {
match self.at(cause, self.param_env).sup(DefineOpaqueTypes::Yes, expected, actual) {
Ok(InferOk { obligations, value: () }) => {
self.register_predicates(obligations);
None
}
Err(e) => Some(self.err_ctxt().report_mismatched_types(cause, expected, actual, e)),
}
) -> Result<(), Diag<'tcx>> {
self.at(cause, self.param_env)
.sup(DefineOpaqueTypes::Yes, expected, actual)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
.map_err(|e| self.err_ctxt().report_mismatched_types(cause, expected, actual, e))
}
pub fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
if let Some(err) = self.demand_eqtype_diag(sp, expected, actual) {
if let Err(err) = self.demand_eqtype_diag(sp, expected, actual) {
err.emit();
}
}
@ -207,7 +204,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sp: Span,
expected: Ty<'tcx>,
actual: Ty<'tcx>,
) -> Option<Diag<'tcx>> {
) -> Result<(), Diag<'tcx>> {
self.demand_eqtype_with_origin(&self.misc(sp), expected, actual)
}
@ -216,14 +213,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
cause: &ObligationCause<'tcx>,
expected: Ty<'tcx>,
actual: Ty<'tcx>,
) -> Option<Diag<'tcx>> {
match self.at(cause, self.param_env).eq(DefineOpaqueTypes::Yes, expected, actual) {
Ok(InferOk { obligations, value: () }) => {
self.register_predicates(obligations);
None
}
Err(e) => Some(self.err_ctxt().report_mismatched_types(cause, expected, actual, e)),
}
) -> Result<(), Diag<'tcx>> {
self.at(cause, self.param_env)
.eq(DefineOpaqueTypes::Yes, expected, actual)
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
.map_err(|e| self.err_ctxt().report_mismatched_types(cause, expected, actual, e))
}
pub fn demand_coerce(
@ -234,12 +228,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
allow_two_phase: AllowTwoPhase,
) -> Ty<'tcx> {
let (ty, err) =
self.demand_coerce_diag(expr, checked_ty, expected, expected_ty_expr, allow_two_phase);
if let Some(err) = err {
err.emit();
match self.demand_coerce_diag(expr, checked_ty, expected, expected_ty_expr, allow_two_phase)
{
Ok(ty) => ty,
Err(err) => {
err.emit();
// Return the original type instead of an error type here, otherwise the type of `x` in
// `let x: u32 = ();` will be a type error, causing all subsequent usages of `x` to not
// report errors, even though `x` is definitely `u32`.
expected
}
}
ty
}
/// Checks that the type of `expr` can be coerced to `expected`.
@ -254,11 +253,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected: Ty<'tcx>,
mut expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
allow_two_phase: AllowTwoPhase,
) -> (Ty<'tcx>, Option<Diag<'tcx>>) {
) -> Result<Ty<'tcx>, Diag<'tcx>> {
let expected = self.resolve_vars_with_obligations(expected);
let e = match self.coerce(expr, checked_ty, expected, allow_two_phase, None) {
Ok(ty) => return (ty, None),
Ok(ty) => return Ok(ty),
Err(e) => e,
};
@ -275,7 +274,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr, Some(e));
(expected, Some(err))
Err(err)
}
/// Notes the point at which a variable is constrained to some type incompatible

View file

@ -7,7 +7,7 @@ use rustc_errors::{
SubdiagMessageOp, Subdiagnostic,
};
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::Ty;
use rustc_middle::ty::{self, Ty};
use rustc_span::{
edition::{Edition, LATEST_STABLE_EDITION},
symbol::Ident,
@ -183,6 +183,15 @@ pub enum NeverTypeFallbackFlowingIntoUnsafe {
Deref,
}
#[derive(LintDiagnostic)]
#[help]
#[diag(hir_typeck_dependency_on_unit_never_type_fallback)]
pub struct DependencyOnUnitNeverTypeFallback<'tcx> {
#[note]
pub obligation_span: Span,
pub obligation: ty::Predicate<'tcx>,
}
#[derive(Subdiagnostic)]
#[multipart_suggestion(
hir_typeck_add_missing_parentheses_in_range,

View file

@ -87,7 +87,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty = adj_ty;
}
if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
if let Err(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
let _ = self.emit_type_mismatch_suggestions(
&mut err,
expr.peel_drop_temps(),
@ -1132,7 +1132,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// say that the user intended to write `lhs == rhs` instead of `lhs = rhs`.
// The likely cause of this is `if foo = bar { .. }`.
let actual_ty = self.tcx.types.unit;
let mut err = self.demand_suptype_diag(expr.span, expected_ty, actual_ty).unwrap();
let mut err = self.demand_suptype_diag(expr.span, expected_ty, actual_ty).unwrap_err();
let lhs_ty = self.check_expr(lhs);
let rhs_ty = self.check_expr(rhs);
let refs_can_coerce = |lhs: Ty<'tcx>, rhs: Ty<'tcx>| {
@ -1236,7 +1236,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// This is (basically) inlined `check_expr_coercible_to_type`, but we want
// to suggest an additional fixup here in `suggest_deref_binop`.
let rhs_ty = self.check_expr_with_hint(rhs, lhs_ty);
if let (_, Some(mut diag)) =
if let Err(mut diag) =
self.demand_coerce_diag(rhs, rhs_ty, lhs_ty, Some(lhs), AllowTwoPhase::No)
{
suggest_deref_binop(&mut diag, rhs_ty);
@ -1557,7 +1557,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If the length is 0, we don't create any elements, so we don't copy any. If the length is 1, we
// don't copy that one element, we move it. Only check for Copy if the length is larger.
if count.try_eval_target_usize(tcx, self.param_env).map_or(true, |len| len > 1) {
if count.try_eval_target_usize(tcx, self.param_env).is_none_or(|len| len > 1) {
let lang_item = self.tcx.require_lang_item(LangItem::Copy, None);
let code = traits::ObligationCauseCode::RepeatElementCopy {
is_constable,
@ -1738,10 +1738,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Make sure to give a type to the field even if there's
// an error, so we can continue type-checking.
let ty = self.check_expr_with_hint(field.expr, field_type);
let (_, diag) =
self.demand_coerce_diag(field.expr, ty, field_type, None, AllowTwoPhase::No);
let diag = self.demand_coerce_diag(field.expr, ty, field_type, None, AllowTwoPhase::No);
if let Some(diag) = diag {
if let Err(diag) = diag {
if idx == hir_fields.len() - 1 {
if remaining_fields.is_empty() {
self.suggest_fru_from_range_and_emit(field, variant, args, diag);
@ -3151,7 +3150,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
error.obligation.predicate.kind().skip_binder(),
) {
(ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)), _)
if self.tcx.lang_items().index_trait() == Some(predicate.trait_ref.def_id) =>
if self.tcx.is_lang_item(predicate.trait_ref.def_id, LangItem::Index) =>
{
seen_preds.insert(error.obligation.predicate.kind().skip_binder());
}

View file

@ -14,6 +14,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
use rustc_session::lint;
use rustc_span::DUMMY_SP;
use rustc_span::{def_id::LocalDefId, Span};
use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
#[derive(Copy, Clone)]
pub enum DivergingFallbackBehavior {
@ -344,6 +345,9 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
// `!`.
let mut diverging_fallback = UnordMap::with_capacity(diverging_vids.len());
let unsafe_infer_vars = OnceCell::new();
self.lint_obligations_broken_by_never_type_fallback_change(behavior, &diverging_vids);
for &diverging_vid in &diverging_vids {
let diverging_ty = Ty::new_var(self.tcx, diverging_vid);
let root_vid = self.root_var(diverging_vid);
@ -468,6 +472,56 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
}
}
fn lint_obligations_broken_by_never_type_fallback_change(
&self,
behavior: DivergingFallbackBehavior,
diverging_vids: &[ty::TyVid],
) {
let DivergingFallbackBehavior::ToUnit = behavior else { return };
// Fallback happens if and only if there are diverging variables
if diverging_vids.is_empty() {
return;
}
// Returns errors which happen if fallback is set to `fallback`
let remaining_errors_if_fallback_to = |fallback| {
self.probe(|_| {
let obligations = self.fulfillment_cx.borrow().pending_obligations();
let ocx = ObligationCtxt::new_with_diagnostics(&self.infcx);
ocx.register_obligations(obligations.iter().cloned());
for &diverging_vid in diverging_vids {
let diverging_ty = Ty::new_var(self.tcx, diverging_vid);
ocx.eq(&ObligationCause::dummy(), self.param_env, diverging_ty, fallback)
.expect("expected diverging var to be unconstrained");
}
ocx.select_where_possible()
})
};
// If we have no errors with `fallback = ()`, but *do* have errors with `fallback = !`,
// then this code will be broken by the never type fallback change.qba
let unit_errors = remaining_errors_if_fallback_to(self.tcx.types.unit);
if unit_errors.is_empty()
&& let mut never_errors = remaining_errors_if_fallback_to(self.tcx.types.never)
&& let [ref mut never_error, ..] = never_errors.as_mut_slice()
{
self.adjust_fulfillment_error_for_expr_obligation(never_error);
self.tcx.emit_node_span_lint(
lint::builtin::DEPENDENCY_ON_UNIT_NEVER_TYPE_FALLBACK,
self.tcx.local_def_id_to_hir_id(self.body_id),
self.tcx.def_span(self.body_id),
errors::DependencyOnUnitNeverTypeFallback {
obligation_span: never_error.obligation.cause.span,
obligation: never_error.obligation.predicate,
},
)
}
}
/// Returns a graph whose nodes are (unresolved) inference variables and where
/// an edge `?A -> ?B` indicates that the variable `?A` is coerced to `?B`.
fn create_coercion_graph(&self) -> VecGraph<ty::TyVid, true> {

View file

@ -1418,7 +1418,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let impl_ty = self.normalize(span, tcx.type_of(impl_def_id).instantiate(tcx, args));
let self_ty = self.normalize(span, self_ty);
match self.at(&self.misc(span), self.param_env).eq(
DefineOpaqueTypes::No,
DefineOpaqueTypes::Yes,
impl_ty,
self_ty,
) {

View file

@ -1578,7 +1578,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// type of the place it is referencing, and not some
// supertype thereof.
let init_ty = self.check_expr_with_needs(init, Needs::maybe_mut_place(m));
if let Some(mut diag) = self.demand_eqtype_diag(init.span, local_ty, init_ty) {
if let Err(mut diag) = self.demand_eqtype_diag(init.span, local_ty, init_ty) {
self.emit_type_mismatch_suggestions(
&mut diag,
init.peel_drop_temps(),
@ -1624,7 +1624,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let previous_diverges = self.diverges.get();
let else_ty = self.check_block_with_expected(blk, NoExpectation);
let cause = self.cause(blk.span, ObligationCauseCode::LetElse);
if let Some(err) = self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
if let Err(err) = self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty)
{
err.emit();
}
@ -2240,7 +2240,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
for (idx, (generic_param, param)) in
params_with_generics.iter().enumerate().filter(|(idx, _)| {
check_for_matched_generics
|| expected_idx.map_or(true, |expected_idx| expected_idx == *idx)
|| expected_idx.is_none_or(|expected_idx| expected_idx == *idx)
})
{
let Some(generic_param) = generic_param else {

View file

@ -440,7 +440,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
// Given `Result<_, E>`, check our expected ty is `Result<_, &E>` for
// `as_ref` and `as_deref` compatibility.
let error_tys_equate_as_ref = error_tys.map_or(true, |(found, expected)| {
let error_tys_equate_as_ref = error_tys.is_none_or(|(found, expected)| {
self.can_eq(
self.param_env,
Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, found),
@ -489,10 +489,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
return true;
} else if let ty::Adt(adt, _) = found_ty_inner.peel_refs().kind()
&& Some(adt.did()) == self.tcx.lang_items().string()
&& self.tcx.is_lang_item(adt.did(), LangItem::String)
&& peeled.is_str()
// `Result::map`, conversely, does not take ref of the error type.
&& error_tys.map_or(true, |(found, expected)| {
&& error_tys.is_none_or(|(found, expected)| {
self.can_eq(self.param_env, found, expected)
})
{
@ -3147,7 +3147,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return;
}
if let ty::Adt(adt, _) = expected_ty.kind()
&& self.tcx.lang_items().range_struct() == Some(adt.did())
&& self.tcx.is_lang_item(adt.did(), LangItem::Range)
{
return;
}

View file

@ -4,6 +4,7 @@
#![feature(box_patterns)]
#![feature(control_flow_enum)]
#![feature(if_let_guard)]
#![feature(is_none_or)]
#![feature(let_chains)]
#![feature(never_type)]
#![feature(try_blocks)]

View file

@ -497,7 +497,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
args,
})),
);
match self.at(&cause, self.param_env).sup(DefineOpaqueTypes::No, method_self_ty, self_ty) {
match self.at(&cause, self.param_env).sup(DefineOpaqueTypes::Yes, method_self_ty, self_ty) {
Ok(InferOk { obligations, value: () }) => {
self.register_predicates(obligations);
}

View file

@ -634,8 +634,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}
}
#[instrument(level = "debug", skip(self))]
fn assemble_probe(&mut self, self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>) {
debug!("assemble_probe: self_ty={:?}", self_ty);
let raw_self_ty = self_ty.value.value;
match *raw_self_ty.kind() {
ty::Dynamic(data, ..) if let Some(p) = data.principal() => {
@ -713,13 +713,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}
}
#[instrument(level = "debug", skip(self))]
fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) {
if !self.impl_dups.insert(impl_def_id) {
return; // already visited
}
debug!("assemble_inherent_impl_probe {:?}", impl_def_id);
for item in self.impl_or_trait_item(impl_def_id) {
if !self.has_applicable_self(&item) {
// No receiver declared. Not a candidate.
@ -737,9 +736,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}
}
#[instrument(level = "debug", skip(self))]
fn assemble_inherent_candidates_from_object(&mut self, self_ty: Ty<'tcx>) {
debug!("assemble_inherent_candidates_from_object(self_ty={:?})", self_ty);
let principal = match self_ty.kind() {
ty::Dynamic(ref data, ..) => Some(data),
_ => None,
@ -768,9 +766,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
});
}
#[instrument(level = "debug", skip(self))]
fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) {
// FIXME: do we want to commit to this behavior for param bounds?
debug!("assemble_inherent_candidates_from_param(param_ty={:?})", param_ty);
let bounds = self.param_env.caller_bounds().iter().filter_map(|predicate| {
let bound_predicate = predicate.kind();
@ -826,6 +824,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}
}
#[instrument(level = "debug", skip(self))]
fn assemble_extension_candidates_for_traits_in_scope(&mut self) {
let mut duplicates = FxHashSet::default();
let opt_applicable_traits = self.tcx.in_scope_traits(self.scope_expr_id);
@ -842,6 +841,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}
}
#[instrument(level = "debug", skip(self))]
fn assemble_extension_candidates_for_all_traits(&mut self) {
let mut duplicates = FxHashSet::default();
for trait_info in suggest::all_traits(self.tcx) {
@ -863,12 +863,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}
}
#[instrument(level = "debug", skip(self))]
fn assemble_extension_candidates_for_trait(
&mut self,
import_ids: &SmallVec<[LocalDefId; 1]>,
trait_def_id: DefId,
) {
debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})", trait_def_id);
let trait_args = self.fresh_args_for_item(self.span, trait_def_id);
let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, trait_args);
@ -958,6 +958,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
///////////////////////////////////////////////////////////////////////////
// THE ACTUAL SEARCH
#[instrument(level = "debug", skip(self))]
fn pick(mut self) -> PickResult<'tcx> {
assert!(self.method_name.is_some());
@ -1386,6 +1387,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}
}
#[instrument(level = "trace", skip(self, possibly_unsatisfied_predicates), ret)]
fn consider_probe(
&self,
self_ty: Ty<'tcx>,
@ -1415,15 +1417,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
(xform_self_ty, xform_ret_ty) =
self.xform_self_ty(probe.item, impl_ty, impl_args);
xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
// FIXME: Make this `ocx.sup` once we define opaques more eagerly.
match self.at(cause, self.param_env).sup(
DefineOpaqueTypes::No,
xform_self_ty,
self_ty,
) {
Ok(infer_ok) => {
ocx.register_infer_ok_obligations(infer_ok);
}
match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
Ok(()) => {}
Err(err) => {
debug!("--> cannot relate self-types {:?}", err);
return ProbeResult::NoMatch;
@ -1484,19 +1479,23 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
(xform_self_ty, xform_ret_ty) =
self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
// FIXME: Make this `ocx.sup` once we define opaques more eagerly.
match self.at(cause, self.param_env).sup(
DefineOpaqueTypes::No,
xform_self_ty,
self_ty,
) {
Ok(infer_ok) => {
ocx.register_infer_ok_obligations(infer_ok);
}
Err(err) => {
debug!("--> cannot relate self-types {:?}", err);
match self_ty.kind() {
// HACK: opaque types will match anything for which their bounds hold.
// Thus we need to prevent them from trying to match the `&_` autoref
// candidates that get created for `&self` trait methods.
ty::Alias(ty::Opaque, alias_ty)
if self.infcx.can_define_opaque_ty(alias_ty.def_id)
&& !xform_self_ty.is_ty_var() =>
{
return ProbeResult::NoMatch;
}
_ => match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
Ok(()) => {}
Err(err) => {
debug!("--> cannot relate self-types {:?}", err);
return ProbeResult::NoMatch;
}
},
}
let obligation = traits::Obligation::new(
self.tcx,
@ -1536,15 +1535,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
(xform_self_ty, xform_ret_ty) =
self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
// FIXME: Make this `ocx.sup` once we define opaques more eagerly.
match self.at(cause, self.param_env).sup(
DefineOpaqueTypes::No,
xform_self_ty,
self_ty,
) {
Ok(infer_ok) => {
ocx.register_infer_ok_obligations(infer_ok);
}
match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
Ok(()) => {}
Err(err) => {
debug!("--> cannot relate self-types {:?}", err);
return ProbeResult::NoMatch;
@ -1665,6 +1657,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
/// Similarly to `probe_for_return_type`, this method attempts to find the best matching
/// candidate method where the method name may have been misspelled. Similarly to other
/// edit distance based suggestions, we provide at most one such suggestion.
#[instrument(level = "debug", skip(self))]
pub(crate) fn probe_for_similar_candidate(
&mut self,
) -> Result<Option<ty::AssocItem>, MethodError<'tcx>> {

View file

@ -1102,7 +1102,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
unsatisfied_predicates.iter().any(|(pred, _, _)| {
match pred.kind().skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
Some(pred.def_id()) == self.tcx.lang_items().sized_trait()
self.tcx.is_lang_item(pred.def_id(), LangItem::Sized)
&& pred.polarity == ty::PredicatePolarity::Positive
}
_ => false,
@ -1375,10 +1375,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty.is_str()
|| matches!(
ty.kind(),
ty::Adt(adt, _) if Some(adt.did()) == self.tcx.lang_items().string()
ty::Adt(adt, _) if self.tcx.is_lang_item(adt.did(), LangItem::String)
)
}
ty::Adt(adt, _) => Some(adt.did()) == self.tcx.lang_items().string(),
ty::Adt(adt, _) => self.tcx.is_lang_item(adt.did(), LangItem::String),
_ => false,
};
if is_string_or_ref_str && item_name.name == sym::iter {
@ -2723,7 +2723,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
err.help("use `with` or `try_with` to access thread local storage");
} else if Some(kind.did()) == tcx.lang_items().maybe_uninit() {
} else if tcx.is_lang_item(kind.did(), LangItem::MaybeUninit) {
err.help(format!(
"if this `{name}` has been initialized, \
use one of the `assume_init` methods to access the inner value"

View file

@ -7,7 +7,7 @@ use rustc_errors::{
};
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::pat_util::EnumerateAndAdjustIterator;
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability, Pat, PatKind};
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, LangItem, Mutability, Pat, PatKind};
use rustc_infer::infer;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
@ -105,15 +105,16 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
expected: Ty<'tcx>,
actual: Ty<'tcx>,
ti: &TopInfo<'tcx>,
) -> Option<Diag<'tcx>> {
let mut diag =
self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)?;
if let Some(expr) = ti.origin_expr {
self.suggest_fn_call(&mut diag, expr, expected, |output| {
self.can_eq(self.param_env, output, actual)
});
}
Some(diag)
) -> Result<(), Diag<'tcx>> {
self.demand_eqtype_with_origin(&self.pattern_cause(ti, cause_span), expected, actual)
.map_err(|mut diag| {
if let Some(expr) = ti.origin_expr {
self.suggest_fn_call(&mut diag, expr, expected, |output| {
self.can_eq(self.param_env, output, actual)
});
}
diag
})
}
fn demand_eqtype_pat(
@ -122,10 +123,8 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
expected: Ty<'tcx>,
actual: Ty<'tcx>,
ti: &TopInfo<'tcx>,
) {
if let Some(err) = self.demand_eqtype_pat_diag(cause_span, expected, actual, ti) {
err.emit();
}
) -> Result<(), ErrorGuaranteed> {
self.demand_eqtype_pat_diag(cause_span, expected, actual, ti).map_err(|err| err.emit())
}
}
@ -492,7 +491,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let tcx = self.tcx;
let expected = self.resolve_vars_if_possible(expected);
pat_ty = match expected.kind() {
ty::Adt(def, _) if Some(def.did()) == tcx.lang_items().string() => expected,
ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::String) => expected,
ty::Str => Ty::new_static_str(tcx),
_ => pat_ty,
};
@ -509,7 +508,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
//
// then that's equivalent to there existing a LUB.
let cause = self.pattern_cause(ti, span);
if let Some(err) = self.demand_suptype_with_origin(&cause, expected, pat_ty) {
if let Err(err) = self.demand_suptype_with_origin(&cause, expected, pat_ty) {
err.emit_unless(
ti.span
.filter(|&s| {
@ -562,7 +561,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Subtyping doesn't matter here, as the value is some kind of scalar.
let demand_eqtype = |x: &mut _, y| {
if let Some((ref mut fail, x_ty, x_span)) = *x
&& let Some(mut err) = self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti)
&& let Err(mut err) = self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti)
{
if let Some((_, y_ty, y_span)) = y {
self.endpoint_has_type(&mut err, y_span, y_ty);
@ -736,7 +735,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Otherwise, the type of x is the expected type `T`.
ByRef::No => expected, // As above, `T <: typeof(x)` is required, but we use equality, see (note_1).
};
self.demand_eqtype_pat(pat.span, eq_ty, local_ty, ti);
// We have a concrete type for the local, so we do not need to taint it and hide follow up errors *using* the local.
let _ = self.demand_eqtype_pat(pat.span, eq_ty, local_ty, ti);
// If there are multiple arms, make sure they all agree on
// what the type of the binding `x` ought to be.
@ -763,7 +764,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ti: &TopInfo<'tcx>,
) {
let var_ty = self.local_ty(span, var_id);
if let Some(mut err) = self.demand_eqtype_pat_diag(span, var_ty, ty, ti) {
if let Err(mut err) = self.demand_eqtype_pat_diag(span, var_ty, ty, ti) {
let hir = self.tcx.hir();
let var_ty = self.resolve_vars_if_possible(var_ty);
let msg = format!("first introduced with type `{var_ty}` here");
@ -986,13 +987,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
// Type-check the path.
self.demand_eqtype_pat(pat.span, expected, pat_ty, pat_info.top_info);
let _ = self.demand_eqtype_pat(pat.span, expected, pat_ty, pat_info.top_info);
// Type-check subpatterns.
if self.check_struct_pat_fields(pat_ty, pat, variant, fields, has_rest_pat, pat_info) {
pat_ty
} else {
Ty::new_misc_error(self.tcx)
match self.check_struct_pat_fields(pat_ty, pat, variant, fields, has_rest_pat, pat_info) {
Ok(()) => pat_ty,
Err(guar) => Ty::new_error(self.tcx, guar),
}
}
@ -1050,7 +1050,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Type-check the path.
let (pat_ty, pat_res) =
self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.span, pat.hir_id);
if let Some(err) =
if let Err(err) =
self.demand_suptype_with_origin(&self.pattern_cause(ti, pat.span), expected, pat_ty)
{
self.emit_bad_pat_path(err, pat, res, pat_res, pat_ty, segments);
@ -1223,12 +1223,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Type-check the tuple struct pattern against the expected type.
let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, pat_info.top_info);
let had_err = if let Some(err) = diag {
err.emit();
true
} else {
false
};
let had_err = diag.map_err(|diag| diag.emit());
// Type-check subpatterns.
if subpats.len() == variant.fields.len()
@ -1249,6 +1244,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
None,
);
}
if let Err(e) = had_err {
on_error(e);
return Ty::new_error(tcx, e);
}
} else {
let e = self.emit_err_pat_wrong_number_of_fields(
pat.span,
@ -1273,7 +1272,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
subpats: &'tcx [Pat<'tcx>],
fields: &'tcx [ty::FieldDef],
expected: Ty<'tcx>,
had_err: bool,
had_err: Result<(), ErrorGuaranteed>,
) -> ErrorGuaranteed {
let subpats_ending = pluralize!(subpats.len());
let fields_ending = pluralize!(fields.len());
@ -1330,7 +1329,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// #67037: only do this if we could successfully type-check the expected type against
// the tuple struct pattern. Otherwise the args could get out of range on e.g.,
// `let P() = U;` where `P != U` with `struct P<T>(T);`.
(ty::Adt(_, args), [field], false) => {
(ty::Adt(_, args), [field], Ok(())) => {
let field_ty = self.field_ty(pat_span, field, args);
match field_ty.kind() {
ty::Tuple(fields) => fields.len() == subpats.len(),
@ -1445,8 +1444,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let element_tys_iter = (0..max_len).map(|_| self.next_ty_var(span));
let element_tys = tcx.mk_type_list_from_iter(element_tys_iter);
let pat_ty = Ty::new_tup(tcx, element_tys);
if let Some(err) = self.demand_eqtype_pat_diag(span, expected, pat_ty, pat_info.top_info) {
let reported = err.emit();
if let Err(reported) = self.demand_eqtype_pat(span, expected, pat_ty, pat_info.top_info) {
// Walk subpatterns with an expected type of `err` in this case to silence
// further errors being emitted when using the bindings. #50333
let element_tys_iter = (0..max_len).map(|_| Ty::new_error(tcx, reported));
@ -1470,7 +1468,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fields: &'tcx [hir::PatField<'tcx>],
has_rest_pat: bool,
pat_info: PatInfo<'tcx, '_>,
) -> bool {
) -> Result<(), ErrorGuaranteed> {
let tcx = self.tcx;
let ty::Adt(adt, args) = adt_ty.kind() else {
@ -1486,7 +1484,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Keep track of which fields have already appeared in the pattern.
let mut used_fields = FxHashMap::default();
let mut no_field_errors = true;
let mut result = Ok(());
let mut inexistent_fields = vec![];
// Typecheck each field.
@ -1495,8 +1493,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ident = tcx.adjust_ident(field.ident, variant.def_id);
let field_ty = match used_fields.entry(ident) {
Occupied(occupied) => {
no_field_errors = false;
let guar = self.error_field_already_bound(span, field.ident, *occupied.get());
result = Err(guar);
Ty::new_error(tcx, guar)
}
Vacant(vacant) => {
@ -1511,7 +1509,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
})
.unwrap_or_else(|| {
inexistent_fields.push(field);
no_field_errors = false;
Ty::new_misc_error(tcx)
})
}
@ -1585,37 +1582,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
match (inexistent_fields_err, unmentioned_err) {
(Some(i), Some(u)) => {
if let Some(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
if let Err(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
// We don't want to show the nonexistent fields error when this was
// `Foo { a, b }` when it should have been `Foo(a, b)`.
i.delay_as_bug();
u.delay_as_bug();
e.emit();
Err(e)
} else {
i.emit();
u.emit();
Err(u.emit())
}
}
(None, Some(u)) => {
if let Some(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
if let Err(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) {
u.delay_as_bug();
e.emit();
Err(e)
} else {
u.emit();
Err(u.emit())
}
}
(Some(err), None) => {
err.emit();
(Some(err), None) => Err(err.emit()),
(None, None) => {
self.error_tuple_variant_index_shorthand(variant, pat, fields)?;
result
}
(None, None)
if let Some(err) =
self.error_tuple_variant_index_shorthand(variant, pat, fields) =>
{
err.emit();
}
(None, None) => {}
}
no_field_errors
}
fn error_tuple_variant_index_shorthand(
@ -1623,7 +1614,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
variant: &VariantDef,
pat: &'_ Pat<'_>,
fields: &[hir::PatField<'_>],
) -> Option<Diag<'_>> {
) -> Result<(), ErrorGuaranteed> {
// if this is a tuple struct, then all field names will be numbers
// so if any fields in a struct pattern use shorthand syntax, they will
// be invalid identifiers (for example, Foo { 0, 1 }).
@ -1645,10 +1636,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
format!("({})", self.get_suggested_tuple_struct_pattern(fields, variant)),
Applicability::MaybeIncorrect,
);
return Some(err);
return Err(err.emit());
}
}
None
Ok(())
}
fn error_foreign_non_exhaustive_spat(&self, pat: &Pat<'_>, descr: &str, no_fields: bool) {
@ -1804,14 +1795,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pat: &Pat<'_>,
fields: &'tcx [hir::PatField<'tcx>],
variant: &ty::VariantDef,
) -> Option<Diag<'tcx>> {
) -> Result<(), ErrorGuaranteed> {
if let (Some(CtorKind::Fn), PatKind::Struct(qpath, pattern_fields, ..)) =
(variant.ctor_kind(), &pat.kind)
{
let is_tuple_struct_match = !pattern_fields.is_empty()
&& pattern_fields.iter().map(|field| field.ident.name.as_str()).all(is_number);
if is_tuple_struct_match {
return None;
return Ok(());
}
let path = rustc_hir_pretty::qpath_to_string(&self.tcx, qpath);
@ -1839,9 +1830,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
format!("({sugg})"),
appl,
);
return Some(err);
return Err(err.emit());
}
None
Ok(())
}
fn get_suggested_tuple_struct_pattern(
@ -2065,20 +2056,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pat_info: PatInfo<'tcx, '_>,
) -> Ty<'tcx> {
let tcx = self.tcx;
let (box_ty, inner_ty) = match self.check_dereferenceable(span, expected, inner) {
Ok(()) => {
let (box_ty, inner_ty) = self
.check_dereferenceable(span, expected, inner)
.and_then(|()| {
// Here, `demand::subtype` is good enough, but I don't
// think any errors can be introduced by using `demand::eqtype`.
let inner_ty = self.next_ty_var(inner.span);
let box_ty = Ty::new_box(tcx, inner_ty);
self.demand_eqtype_pat(span, expected, box_ty, pat_info.top_info);
(box_ty, inner_ty)
}
Err(guar) => {
self.demand_eqtype_pat(span, expected, box_ty, pat_info.top_info)?;
Ok((box_ty, inner_ty))
})
.unwrap_or_else(|guar| {
let err = Ty::new_error(tcx, guar);
(err, err)
}
};
});
self.check_pat(inner, inner_ty, pat_info);
box_ty
}
@ -2222,7 +2213,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Look for a case like `fn foo(&foo: u32)` and suggest
// `fn foo(foo: &u32)`
if let Some(mut err) = err {
if let Err(mut err) = err {
self.borrow_pat_suggestion(&mut err, pat);
err.emit();
}
@ -2327,7 +2318,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.try_resolve_slice_ty_to_array_ty(before, slice, span)
{
debug!(?resolved_arr_ty);
self.demand_eqtype(span, expected, resolved_arr_ty);
let _ = self.demand_eqtype(span, expected, resolved_arr_ty);
}
}

View file

@ -205,6 +205,21 @@ impl Parse for Newtype {
}
}
/// Creates a new index from a given `u16`.
///
/// # Panics
///
/// Will panic if `value` exceeds `MAX`.
#[inline]
#vis const fn from_u16(value: u16) -> Self {
let value = value as u32;
assert!(value <= #max);
// SAFETY: We just checked that `value <= max`.
unsafe {
Self::from_u32_unchecked(value)
}
}
/// Creates a new index from a given `u32`.
///
/// # Safety

View file

@ -18,7 +18,6 @@ rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
rustc_type_ir = { path = "../rustc_type_ir" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
tracing = "0.1"
# tidy-alphabetical-end

View file

@ -212,19 +212,63 @@ impl<'a, 'tcx> At<'a, 'tcx> {
T: ToTrace<'tcx>,
{
match variance {
ty::Variance::Covariant => self.sub(define_opaque_types, expected, actual),
ty::Variance::Invariant => self.eq(define_opaque_types, expected, actual),
ty::Variance::Contravariant => self.sup(define_opaque_types, expected, actual),
ty::Covariant => self.sub(define_opaque_types, expected, actual),
ty::Invariant => self.eq(define_opaque_types, expected, actual),
ty::Contravariant => self.sup(define_opaque_types, expected, actual),
// We could make this make sense but it's not readily
// exposed and I don't feel like dealing with it. Note
// that bivariance in general does a bit more than just
// *nothing*, it checks that the types are the same
// "modulo variance" basically.
ty::Variance::Bivariant => panic!("Bivariant given to `relate()`"),
ty::Bivariant => panic!("Bivariant given to `relate()`"),
}
}
/// Used in the new solver since we don't care about tracking an `ObligationCause`.
pub fn relate_no_trace<T>(
self,
expected: T,
variance: ty::Variance,
actual: T,
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution>
where
T: Relate<TyCtxt<'tcx>>,
{
let mut fields = CombineFields::new(
self.infcx,
TypeTrace::dummy(self.cause),
self.param_env,
DefineOpaqueTypes::Yes,
);
fields.sub().relate_with_variance(
variance,
ty::VarianceDiagInfo::default(),
expected,
actual,
)?;
Ok(fields.goals)
}
/// Used in the new solver since we don't care about tracking an `ObligationCause`.
pub fn eq_structurally_relating_aliases_no_trace<T>(
self,
expected: T,
actual: T,
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution>
where
T: Relate<TyCtxt<'tcx>>,
{
let mut fields = CombineFields::new(
self.infcx,
TypeTrace::dummy(self.cause),
self.param_env,
DefineOpaqueTypes::Yes,
);
fields.equate(StructurallyRelateAliases::Yes).relate(expected, actual)?;
Ok(fields.goals)
}
/// Computes the least-upper-bound, or mutual supertype, of two
/// values. The order of the arguments doesn't matter, but since
/// this can result in an error (e.g., if asked to compute LUB of
@ -303,7 +347,7 @@ impl<'tcx> ToTrace<'tcx> for Ty<'tcx> {
) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
}
}
}
@ -315,7 +359,10 @@ impl<'tcx> ToTrace<'tcx> for ty::Region<'tcx> {
a: Self,
b: Self,
) -> TypeTrace<'tcx> {
TypeTrace { cause: cause.clone(), values: Regions(ExpectedFound::new(a_is_expected, a, b)) }
TypeTrace {
cause: cause.clone(),
values: ValuePairs::Regions(ExpectedFound::new(a_is_expected, a, b)),
}
}
}
@ -328,7 +375,7 @@ impl<'tcx> ToTrace<'tcx> for Const<'tcx> {
) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
}
}
}
@ -344,13 +391,13 @@ impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> {
cause: cause.clone(),
values: match (a.unpack(), b.unpack()) {
(GenericArgKind::Lifetime(a), GenericArgKind::Lifetime(b)) => {
Regions(ExpectedFound::new(a_is_expected, a, b))
ValuePairs::Regions(ExpectedFound::new(a_is_expected, a, b))
}
(GenericArgKind::Type(a), GenericArgKind::Type(b)) => {
Terms(ExpectedFound::new(a_is_expected, a.into(), b.into()))
ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into()))
}
(GenericArgKind::Const(a), GenericArgKind::Const(b)) => {
Terms(ExpectedFound::new(a_is_expected, a.into(), b.into()))
ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into()))
}
(
@ -379,7 +426,10 @@ impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> {
a: Self,
b: Self,
) -> TypeTrace<'tcx> {
TypeTrace { cause: cause.clone(), values: Terms(ExpectedFound::new(a_is_expected, a, b)) }
TypeTrace {
cause: cause.clone(),
values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a, b)),
}
}
}
@ -392,7 +442,7 @@ impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> {
) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: TraitRefs(ExpectedFound::new(a_is_expected, a, b)),
values: ValuePairs::TraitRefs(ExpectedFound::new(a_is_expected, a, b)),
}
}
}
@ -406,7 +456,7 @@ impl<'tcx> ToTrace<'tcx> for ty::AliasTy<'tcx> {
) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: Aliases(ExpectedFound::new(a_is_expected, a.into(), b.into())),
values: ValuePairs::Aliases(ExpectedFound::new(a_is_expected, a.into(), b.into())),
}
}
}
@ -418,7 +468,10 @@ impl<'tcx> ToTrace<'tcx> for ty::AliasTerm<'tcx> {
a: Self,
b: Self,
) -> TypeTrace<'tcx> {
TypeTrace { cause: cause.clone(), values: Aliases(ExpectedFound::new(a_is_expected, a, b)) }
TypeTrace {
cause: cause.clone(),
values: ValuePairs::Aliases(ExpectedFound::new(a_is_expected, a, b)),
}
}
}
@ -431,7 +484,7 @@ impl<'tcx> ToTrace<'tcx> for ty::FnSig<'tcx> {
) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: PolySigs(ExpectedFound::new(
values: ValuePairs::PolySigs(ExpectedFound::new(
a_is_expected,
ty::Binder::dummy(a),
ty::Binder::dummy(b),
@ -449,7 +502,7 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyFnSig<'tcx> {
) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: PolySigs(ExpectedFound::new(a_is_expected, a, b)),
values: ValuePairs::PolySigs(ExpectedFound::new(a_is_expected, a, b)),
}
}
}
@ -463,7 +516,7 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialTraitRef<'tcx> {
) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: ExistentialTraitRef(ExpectedFound::new(a_is_expected, a, b)),
values: ValuePairs::ExistentialTraitRef(ExpectedFound::new(a_is_expected, a, b)),
}
}
}
@ -477,7 +530,7 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialProjection<'tcx> {
) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: ExistentialProjection(ExpectedFound::new(a_is_expected, a, b)),
values: ValuePairs::ExistentialProjection(ExpectedFound::new(a_is_expected, a, b)),
}
}
}

View file

@ -64,11 +64,11 @@ use rustc_errors::{
codes::*, pluralize, struct_span_code_err, Applicability, Diag, DiagCtxt, DiagStyledString,
ErrorGuaranteed, IntoDiagArg, StringPart,
};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{self as hir, ParamName};
use rustc_macros::extension;
use rustc_middle::bug;
use rustc_middle::dep_graph::DepContext;
@ -1707,6 +1707,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
ValuePairs::ExistentialProjection(_) => {
(false, Mismatch::Fixed("existential projection"))
}
ValuePairs::Dummy => {
bug!("do not expect to report a type error from a ValuePairs::Dummy")
}
};
let Some(vals) = self.values_str(values) else {
// Derived error. Cancel the emitter.
@ -2250,12 +2253,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
values: ValuePairs<'tcx>,
) -> Option<(DiagStyledString, DiagStyledString, Option<PathBuf>)> {
match values {
infer::Regions(exp_found) => self.expected_found_str(exp_found),
infer::Terms(exp_found) => self.expected_found_str_term(exp_found),
infer::Aliases(exp_found) => self.expected_found_str(exp_found),
infer::ExistentialTraitRef(exp_found) => self.expected_found_str(exp_found),
infer::ExistentialProjection(exp_found) => self.expected_found_str(exp_found),
infer::TraitRefs(exp_found) => {
ValuePairs::Regions(exp_found) => self.expected_found_str(exp_found),
ValuePairs::Terms(exp_found) => self.expected_found_str_term(exp_found),
ValuePairs::Aliases(exp_found) => self.expected_found_str(exp_found),
ValuePairs::ExistentialTraitRef(exp_found) => self.expected_found_str(exp_found),
ValuePairs::ExistentialProjection(exp_found) => self.expected_found_str(exp_found),
ValuePairs::TraitRefs(exp_found) => {
let pretty_exp_found = ty::error::ExpectedFound {
expected: exp_found.expected.print_trait_sugared(),
found: exp_found.found.print_trait_sugared(),
@ -2267,7 +2270,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
ret => ret,
}
}
infer::PolySigs(exp_found) => {
ValuePairs::PolySigs(exp_found) => {
let exp_found = self.resolve_vars_if_possible(exp_found);
if exp_found.references_error() {
return None;
@ -2275,6 +2278,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let (exp, fnd) = self.cmp_fn_sig(&exp_found.expected, &exp_found.found);
Some((exp, fnd, None))
}
ValuePairs::Dummy => {
bug!("do not expect to report a type error from a ValuePairs::Dummy")
}
}
}
@ -2423,7 +2429,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let (type_scope, type_param_sugg_span) = match bound_kind {
GenericKind::Param(param) => {
let generics = self.tcx.generics_of(generic_param_scope);
let def_id = generics.type_param(param, self.tcx).def_id.expect_local();
let type_param = generics.type_param(param, self.tcx);
let def_id = type_param.def_id.expect_local();
let scope = self.tcx.local_def_id_to_hir_id(def_id).owner.def_id;
// Get the `hir::Param` to verify whether it already has any bounds.
// We do this to avoid suggesting code that ends up as `T: 'a'b`,
@ -2433,7 +2440,18 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
Some((span, open_paren_sp)) => Some((span, true, open_paren_sp)),
// If `param` corresponds to `Self`, no usable suggestion span.
None if generics.has_self && param.index == 0 => None,
None => Some((self.tcx.def_span(def_id).shrink_to_hi(), false, None)),
None => {
let span = if let Some(param) =
hir_generics.params.iter().find(|param| param.def_id == def_id)
&& let ParamName::Plain(ident) = param.name
{
ident.span.shrink_to_hi()
} else {
let span = self.tcx.def_span(def_id);
span.shrink_to_hi()
};
Some((span, false, None))
}
};
(scope, sugg_span)
}

View file

@ -546,7 +546,7 @@ impl<T> Trait<T> for X {
for pred in hir_generics.bounds_for_param(def_id) {
if self.constrain_generic_bound_associated_type_structured_suggestion(
diag,
&trait_ref,
trait_ref,
pred.bounds,
assoc,
assoc_args,
@ -715,7 +715,7 @@ fn foo(&self) -> Self::T { String::new() }
self.constrain_generic_bound_associated_type_structured_suggestion(
diag,
&trait_ref,
trait_ref,
opaque_hir_ty.bounds,
assoc,
assoc_args,
@ -869,7 +869,7 @@ fn foo(&self) -> Self::T { String::new() }
fn constrain_generic_bound_associated_type_structured_suggestion(
&self,
diag: &mut Diag<'_>,
trait_ref: &ty::TraitRef<'tcx>,
trait_ref: ty::TraitRef<'tcx>,
bounds: hir::GenericBounds<'_>,
assoc: ty::AssocItem,
assoc_args: &[ty::GenericArg<'tcx>],

View file

@ -9,9 +9,8 @@ pub use rustc_middle::ty::IntVarValue;
pub use BoundRegionConversionTime::*;
pub use RegionVariableOrigin::*;
pub use SubregionOrigin::*;
pub use ValuePairs::*;
use crate::infer::relate::RelateResult;
use crate::infer::relate::{Relate, RelateResult};
use crate::traits::{self, ObligationCause, ObligationInspector, PredicateObligation, TraitEngine};
use error_reporting::TypeErrCtxt;
use free_regions::RegionRelations;
@ -35,6 +34,7 @@ use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey};
use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::traits::select;
use rustc_middle::traits::solve::{Goal, NoSolution};
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::fold::BoundVarReplacerDelegate;
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
@ -44,7 +44,7 @@ use rustc_middle::ty::{ConstVid, EffectVid, FloatVid, IntVid, TyVid};
use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgs, GenericArgsRef};
use rustc_middle::{bug, span_bug};
use rustc_span::symbol::Symbol;
use rustc_span::Span;
use rustc_span::{Span, DUMMY_SP};
use snapshot::undo_log::InferCtxtUndoLogs;
use std::cell::{Cell, RefCell};
use std::fmt;
@ -352,6 +352,13 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
}
}
fn universe_of_lt(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex> {
match self.inner.borrow_mut().unwrap_region_constraints().probe_value(lt) {
Err(universe) => Some(universe),
Ok(_) => None,
}
}
fn universe_of_ct(&self, ct: ConstVid) -> Option<ty::UniverseIndex> {
// Same issue as with `universe_of_ty`
match self.probe_const_var(ct) {
@ -360,19 +367,12 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
}
}
fn universe_of_lt(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex> {
match self.inner.borrow_mut().unwrap_region_constraints().probe_value(lt) {
Err(universe) => Some(universe),
Ok(_) => None,
}
fn root_ty_var(&self, var: TyVid) -> TyVid {
self.root_var(var)
}
fn opportunistic_resolve_lt_var(&self, vid: ty::RegionVid) -> ty::Region<'tcx> {
self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid)
}
fn defining_opaque_types(&self) -> &'tcx ty::List<LocalDefId> {
self.defining_opaque_types
fn root_const_var(&self, var: ConstVid) -> ConstVid {
self.root_const_var(var)
}
fn opportunistic_resolve_ty_var(&self, vid: TyVid) -> Ty<'tcx> {
@ -405,6 +405,76 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
}
}
}
fn opportunistic_resolve_lt_var(&self, vid: ty::RegionVid) -> ty::Region<'tcx> {
self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid)
}
fn defining_opaque_types(&self) -> &'tcx ty::List<LocalDefId> {
self.defining_opaque_types
}
fn next_ty_infer(&self) -> Ty<'tcx> {
self.next_ty_var(DUMMY_SP)
}
fn next_const_infer(&self) -> ty::Const<'tcx> {
self.next_const_var(DUMMY_SP)
}
fn fresh_args_for_item(&self, def_id: DefId) -> ty::GenericArgsRef<'tcx> {
self.fresh_args_for_item(DUMMY_SP, def_id)
}
fn instantiate_binder_with_infer<T: TypeFoldable<Self::Interner> + Copy>(
&self,
value: ty::Binder<'tcx, T>,
) -> T {
self.instantiate_binder_with_fresh_vars(
DUMMY_SP,
BoundRegionConversionTime::HigherRankedType,
value,
)
}
fn enter_forall<T: TypeFoldable<TyCtxt<'tcx>> + Copy, U>(
&self,
value: ty::Binder<'tcx, T>,
f: impl FnOnce(T) -> U,
) -> U {
self.enter_forall(value, f)
}
fn relate<T: Relate<TyCtxt<'tcx>>>(
&self,
param_env: ty::ParamEnv<'tcx>,
lhs: T,
variance: ty::Variance,
rhs: T,
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
self.at(&ObligationCause::dummy(), param_env).relate_no_trace(lhs, variance, rhs)
}
fn eq_structurally_relating_aliases<T: Relate<TyCtxt<'tcx>>>(
&self,
param_env: ty::ParamEnv<'tcx>,
lhs: T,
rhs: T,
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
self.at(&ObligationCause::dummy(), param_env)
.eq_structurally_relating_aliases_no_trace(lhs, rhs)
}
fn resolve_vars_if_possible<T>(&self, value: T) -> T
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
self.resolve_vars_if_possible(value)
}
fn probe<T>(&self, probe: impl FnOnce() -> T) -> T {
self.probe(|_| probe())
}
}
/// See the `error_reporting` module for more details.
@ -417,6 +487,7 @@ pub enum ValuePairs<'tcx> {
PolySigs(ExpectedFound<ty::PolyFnSig<'tcx>>),
ExistentialTraitRef(ExpectedFound<ty::PolyExistentialTraitRef<'tcx>>),
ExistentialProjection(ExpectedFound<ty::PolyExistentialProjection<'tcx>>),
Dummy,
}
impl<'tcx> ValuePairs<'tcx> {
@ -810,13 +881,13 @@ impl<'tcx> InferCtxt<'tcx> {
.collect();
vars.extend(
(0..inner.int_unification_table().len())
.map(|i| ty::IntVid::from_u32(i as u32))
.map(|i| ty::IntVid::from_usize(i))
.filter(|&vid| inner.int_unification_table().probe_value(vid).is_unknown())
.map(|v| Ty::new_int_var(self.tcx, v)),
);
vars.extend(
(0..inner.float_unification_table().len())
.map(|i| ty::FloatVid::from_u32(i as u32))
.map(|i| ty::FloatVid::from_usize(i))
.filter(|&vid| inner.float_unification_table().probe_value(vid).is_unknown())
.map(|v| Ty::new_float_var(self.tcx, v)),
);
@ -1812,7 +1883,7 @@ impl<'tcx> TypeTrace<'tcx> {
) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
}
}
@ -1824,7 +1895,7 @@ impl<'tcx> TypeTrace<'tcx> {
) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: TraitRefs(ExpectedFound::new(a_is_expected, a, b)),
values: ValuePairs::TraitRefs(ExpectedFound::new(a_is_expected, a, b)),
}
}
@ -1836,9 +1907,13 @@ impl<'tcx> TypeTrace<'tcx> {
) -> TypeTrace<'tcx> {
TypeTrace {
cause: cause.clone(),
values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
}
}
fn dummy(cause: &ObligationCause<'tcx>) -> TypeTrace<'tcx> {
TypeTrace { cause: cause.clone(), values: ValuePairs::Dummy }
}
}
impl<'tcx> SubregionOrigin<'tcx> {

View file

@ -345,7 +345,7 @@ impl<'tcx> InferCtxt<'tcx> {
.args
.iter()
.enumerate()
.filter(|(i, _)| variances[*i] == ty::Variance::Invariant)
.filter(|(i, _)| variances[*i] == ty::Invariant)
.filter_map(|(_, arg)| match arg.unpack() {
GenericArgKind::Lifetime(r) => Some(r),
GenericArgKind::Type(_) | GenericArgKind::Const(_) => None,
@ -441,7 +441,7 @@ where
let variances = self.tcx.variances_of(*def_id);
for (v, s) in std::iter::zip(variances, args.iter()) {
if *v != ty::Variance::Bivariant {
if *v != ty::Bivariant {
s.visit_with(self);
}
}

View file

@ -102,9 +102,7 @@ where
};
for (idx, s) in args.iter().enumerate() {
if variances.map(|variances| variances[idx])
!= Some(ty::Variance::Bivariant)
{
if variances.map(|variances| variances[idx]) != Some(ty::Bivariant) {
s.visit_with(self);
}
}

View file

@ -83,16 +83,16 @@ impl<'tcx> InferCtxt<'tcx> {
// mention `?0`.
if self.next_trait_solver() {
let (lhs, rhs, direction) = match instantiation_variance {
ty::Variance::Invariant => {
ty::Invariant => {
(generalized_ty.into(), source_ty.into(), AliasRelationDirection::Equate)
}
ty::Variance::Covariant => {
ty::Covariant => {
(generalized_ty.into(), source_ty.into(), AliasRelationDirection::Subtype)
}
ty::Variance::Contravariant => {
ty::Contravariant => {
(source_ty.into(), generalized_ty.into(), AliasRelationDirection::Subtype)
}
ty::Variance::Bivariant => unreachable!("bivariant generalization"),
ty::Bivariant => unreachable!("bivariant generalization"),
};
relation.register_predicates([ty::PredicateKind::AliasRelate(lhs, rhs, direction)]);
@ -192,7 +192,7 @@ impl<'tcx> InferCtxt<'tcx> {
relation.span(),
relation.structurally_relate_aliases(),
target_vid,
ty::Variance::Invariant,
ty::Invariant,
source_ct,
)?;
@ -210,14 +210,14 @@ impl<'tcx> InferCtxt<'tcx> {
// generalized const and the source.
if target_is_expected {
relation.relate_with_variance(
ty::Variance::Invariant,
ty::Invariant,
ty::VarianceDiagInfo::default(),
generalized_ct,
source_ct,
)?;
} else {
relation.relate_with_variance(
ty::Variance::Invariant,
ty::Invariant,
ty::VarianceDiagInfo::default(),
source_ct,
generalized_ct,
@ -411,7 +411,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
a_arg: ty::GenericArgsRef<'tcx>,
b_arg: ty::GenericArgsRef<'tcx>,
) -> RelateResult<'tcx, ty::GenericArgsRef<'tcx>> {
if self.ambient_variance == ty::Variance::Invariant {
if self.ambient_variance == ty::Invariant {
// Avoid fetching the variance if we are in an invariant
// context; no need, and it can induce dependency cycles
// (e.g., #41849).
@ -667,7 +667,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
// structural.
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) => {
let args = self.relate_with_variance(
ty::Variance::Invariant,
ty::Invariant,
ty::VarianceDiagInfo::default(),
args,
args,

View file

@ -94,12 +94,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Glb<'_, '_, 'tcx> {
// When higher-ranked types are involved, computing the GLB is
// very challenging, switch to invariance. This is obviously
// overly conservative but works ok in practice.
self.relate_with_variance(
ty::Variance::Invariant,
ty::VarianceDiagInfo::default(),
a,
b,
)?;
self.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b)?;
Ok(a)
} else {
Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?))

View file

@ -94,12 +94,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Lub<'_, '_, 'tcx> {
// When higher-ranked types are involved, computing the LUB is
// very challenging, switch to invariance. This is obviously
// overly conservative but works ok in practice.
self.relate_with_variance(
ty::Variance::Invariant,
ty::VarianceDiagInfo::default(),
a,
b,
)?;
self.relate_with_variance(ty::Invariant, ty::VarianceDiagInfo::default(), a, b)?;
Ok(a)
} else {
Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?))

View file

@ -4,11 +4,9 @@
pub use rustc_middle::ty::relate::*;
pub use self::_match::MatchAgainstFreshVars;
pub use self::combine::CombineFields;
pub use self::combine::PredicateEmittingRelation;
pub mod _match;
pub(super) mod combine;
mod generalize;
mod glb;

View file

@ -42,7 +42,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, '_, 'tcx> {
a_arg: ty::GenericArgsRef<'tcx>,
b_arg: ty::GenericArgsRef<'tcx>,
) -> RelateResult<'tcx, ty::GenericArgsRef<'tcx>> {
if self.ambient_variance == ty::Variance::Invariant {
if self.ambient_variance == ty::Invariant {
// Avoid fetching the variance if we are in an invariant
// context; no need, and it can induce dependency cycles
// (e.g., #41849).
@ -325,23 +325,23 @@ impl<'tcx> PredicateEmittingRelation<'tcx> for TypeRelating<'_, '_, 'tcx> {
fn register_alias_relate_predicate(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
self.register_predicates([ty::Binder::dummy(match self.ambient_variance {
ty::Variance::Covariant => ty::PredicateKind::AliasRelate(
ty::Covariant => ty::PredicateKind::AliasRelate(
a.into(),
b.into(),
ty::AliasRelationDirection::Subtype,
),
// a :> b is b <: a
ty::Variance::Contravariant => ty::PredicateKind::AliasRelate(
ty::Contravariant => ty::PredicateKind::AliasRelate(
b.into(),
a.into(),
ty::AliasRelationDirection::Subtype,
),
ty::Variance::Invariant => ty::PredicateKind::AliasRelate(
ty::Invariant => ty::PredicateKind::AliasRelate(
a.into(),
b.into(),
ty::AliasRelationDirection::Equate,
),
ty::Variance::Bivariant => {
ty::Bivariant => {
unreachable!("Expected bivariance to be handled in relate_with_variance")
}
})]);

View file

@ -285,8 +285,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> {
let obligations =
predicates.predicates.iter().enumerate().map(|(index, &(clause, span))| {
elaboratable.child_with_derived_cause(
clause
.instantiate_supertrait(tcx, &bound_clause.rebind(data.trait_ref)),
clause.instantiate_supertrait(tcx, bound_clause.rebind(data.trait_ref)),
span,
bound_clause.rebind(data),
index,

View file

@ -550,6 +550,7 @@ lint_non_local_definitions_impl = non-local `impl` definition, `impl` blocks sho
.bounds = `impl` may be usable in bounds, etc. from outside the expression, which might e.g. make something constructible that previously wasn't, because it's still on a publicly-visible type
.exception = items in an anonymous const item (`const _: () = {"{"} ... {"}"}`) are treated as in the same scope as the anonymous const's declaration
.const_anon = use a const-anon item to suppress this lint
.macro_to_change = the {$macro_kind} `{$macro_to_change}` defines the non-local `impl`, and may need to be changed
lint_non_local_definitions_impl_move_help =
move the `impl` block outside of this {$body_kind_descr} {$depth ->

View file

@ -3,7 +3,7 @@ use crate::{
LateContext, LateLintPass, LintContext,
};
use rustc_hir as hir;
use rustc_hir::{self as hir, LangItem};
use rustc_middle::ty;
use rustc_session::lint::FutureIncompatibilityReason;
use rustc_session::{declare_lint, declare_lint_pass};
@ -66,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait {
// the trait is a `Deref` implementation
&& let Some(trait_) = &impl_.of_trait
&& let Some(did) = trait_.trait_def_id()
&& Some(did) == tcx.lang_items().deref_trait()
&& tcx.is_lang_item(did, LangItem::Deref)
// the self type is `dyn t_principal`
&& let self_ty = tcx.type_of(item.owner_id).instantiate_identity()
&& let ty::Dynamic(data, _, ty::Dyn) = self_ty.kind()

View file

@ -1362,6 +1362,7 @@ pub enum NonLocalDefinitionsDiag {
has_trait: bool,
self_ty_str: String,
of_trait_str: Option<String>,
macro_to_change: Option<(String, &'static str)>,
},
MacroRules {
depth: u32,
@ -1387,6 +1388,7 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
has_trait,
self_ty_str,
of_trait_str,
macro_to_change,
} => {
diag.primary_message(fluent::lint_non_local_definitions_impl);
diag.arg("depth", depth);
@ -1397,6 +1399,15 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
diag.arg("of_trait_str", of_trait_str);
}
if let Some((macro_to_change, macro_kind)) = macro_to_change {
diag.arg("macro_to_change", macro_to_change);
diag.arg("macro_kind", macro_kind);
diag.note(fluent::lint_macro_to_change);
}
if let Some(cargo_update) = cargo_update {
diag.subdiagnostic(&diag.dcx, cargo_update);
}
if has_trait {
diag.note(fluent::lint_bounds);
diag.note(fluent::lint_with_trait);
@ -1422,9 +1433,6 @@ impl<'a> LintDiagnostic<'a, ()> for NonLocalDefinitionsDiag {
);
}
if let Some(cargo_update) = cargo_update {
diag.subdiagnostic(&diag.dcx, cargo_update);
}
if let Some(const_anon) = const_anon {
diag.note(fluent::lint_exception);
if let Some(const_anon) = const_anon {

View file

@ -2,7 +2,7 @@ use crate::lints::{NonFmtPanicBraces, NonFmtPanicUnused};
use crate::{fluent_generated as fluent, LateContext, LateLintPass, LintContext};
use rustc_ast as ast;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::{self as hir, LangItem};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::bug;
use rustc_middle::lint::in_external_macro;
@ -53,8 +53,8 @@ impl<'tcx> LateLintPass<'tcx> for NonPanicFmt {
if let &ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(f).kind() {
let f_diagnostic_name = cx.tcx.get_diagnostic_name(def_id);
if Some(def_id) == cx.tcx.lang_items().begin_panic_fn()
|| Some(def_id) == cx.tcx.lang_items().panic_fn()
if cx.tcx.is_lang_item(def_id, LangItem::BeginPanic)
|| cx.tcx.is_lang_item(def_id, LangItem::Panic)
|| f_diagnostic_name == Some(sym::panic_str_2015)
{
if let Some(id) = f.span.ctxt().outer_expn_data().macro_def_id {
@ -153,7 +153,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
ty::Ref(_, r, _) if r.is_str(),
) || matches!(
ty.ty_adt_def(),
Some(ty_def) if Some(ty_def.did()) == cx.tcx.lang_items().string(),
Some(ty_def) if cx.tcx.is_lang_item(ty_def.did(), LangItem::String),
);
let infcx = cx.tcx.infer_ctxt().build();

View file

@ -258,6 +258,13 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
Some((cx.tcx.def_span(parent), may_move))
};
let macro_to_change =
if let ExpnKind::Macro(kind, name) = item.span.ctxt().outer_expn_data().kind {
Some((name.to_string(), kind.descr()))
} else {
None
};
cx.emit_span_lint(
NON_LOCAL_DEFINITIONS,
ms,
@ -274,6 +281,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
move_to,
may_remove,
has_trait: impl_.of_trait.is_some(),
macro_to_change,
},
)
}

View file

@ -52,7 +52,7 @@ declare_lint! {
/// Since Rust 1.80.0, boxed slices implement `IntoIterator`. However, to avoid
/// breakage, `boxed_slice.into_iter()` in Rust 2015, 2018, and 2021 code will still
/// behave as `(&boxed_slice).into_iter()`, returning an iterator over
/// references, just like in Rust 1.80.0 and earlier.
/// references, just like in Rust 1.79.0 and earlier.
/// This only applies to the method call syntax `boxed_slice.into_iter()`, not to
/// any other syntax such as `for _ in boxed_slice` or `IntoIterator::into_iter(boxed_slice)`.
pub BOXED_SLICE_INTO_ITER,

View file

@ -2,7 +2,7 @@ use crate::lints::{DropGlue, DropTraitConstraintsDiag};
use crate::LateContext;
use crate::LateLintPass;
use crate::LintContext;
use rustc_hir as hir;
use rustc_hir::{self as hir, LangItem};
use rustc_session::{declare_lint, declare_lint_pass};
use rustc_span::symbol::sym;
@ -96,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
continue;
};
let def_id = trait_predicate.trait_ref.def_id;
if cx.tcx.lang_items().drop_trait() == Some(def_id) {
if cx.tcx.is_lang_item(def_id, LangItem::Drop) {
// Explicitly allow `impl Drop`, a drop-guards-as-unnameable-type pattern.
if trait_predicate.trait_ref.self_ty().is_impl_trait() {
continue;

View file

@ -10,9 +10,9 @@ use rustc_ast as ast;
use rustc_ast::util::{classify, parser};
use rustc_ast::{ExprKind, StmtKind};
use rustc_errors::{pluralize, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::{self as hir, LangItem};
use rustc_infer::traits::util::elaborate;
use rustc_middle::ty::adjustment;
use rustc_middle::ty::{self, Ty};
@ -289,7 +289,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
is_ty_must_use(cx, boxed_ty, expr, span)
.map(|inner| MustUsePath::Boxed(Box::new(inner)))
}
ty::Adt(def, args) if cx.tcx.lang_items().pin_type() == Some(def.did()) => {
ty::Adt(def, args) if cx.tcx.is_lang_item(def.did(), LangItem::Pin) => {
let pinned_ty = args.type_at(0);
is_ty_must_use(cx, pinned_ty, expr, span)
.map(|inner| MustUsePath::Pinned(Box::new(inner)))

View file

@ -34,6 +34,7 @@ declare_lint_pass! {
CONST_EVALUATABLE_UNCHECKED,
CONST_ITEM_MUTATION,
DEAD_CODE,
DEPENDENCY_ON_UNIT_NEVER_TYPE_FALLBACK,
DEPRECATED,
DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
DEPRECATED_IN_FUTURE,
@ -3257,7 +3258,11 @@ declare_lint! {
/// See the [Checking Conditional Configurations][check-cfg] section for more
/// details.
///
/// See the [Cargo Specifics][unexpected_cfgs_lint_config] section for configuring this lint in
/// `Cargo.toml`.
///
/// [check-cfg]: https://doc.rust-lang.org/nightly/rustc/check-cfg.html
/// [unexpected_cfgs_lint_config]: https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html#check-cfg-in-lintsrust-table
pub UNEXPECTED_CFGS,
Warn,
"detects unexpected names and values in `#[cfg]` conditions",
@ -4195,6 +4200,59 @@ declare_lint! {
report_in_external_macro
}
declare_lint! {
/// The `dependency_on_unit_never_type_fallback` lint detects cases where code compiles with
/// [never type fallback] being [`()`], but will stop compiling with fallback being [`!`].
///
/// [never type fallback]: https://doc.rust-lang.org/nightly/core/primitive.never.html#never-type-fallback
/// [`!`]: https://doc.rust-lang.org/core/primitive.never.html
/// [`()`]: https://doc.rust-lang.org/core/primitive.unit.html
///
/// ### Example
///
/// ```rust,compile_fail
/// #![deny(dependency_on_unit_never_type_fallback)]
/// fn main() {
/// if true {
/// // return has type `!` which, is some cases, causes never type fallback
/// return
/// } else {
/// // the type produced by this call is not specified explicitly,
/// // so it will be inferred from the previous branch
/// Default::default()
/// };
/// // depending on the fallback, this may compile (because `()` implements `Default`),
/// // or it may not (because `!` does not implement `Default`)
/// }
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Due to historic reasons never type fallback was `()`, meaning that `!` got spontaneously
/// coerced to `()`. There are plans to change that, but they may make the code such as above
/// not compile. Instead of depending on the fallback, you should specify the type explicitly:
/// ```
/// if true {
/// return
/// } else {
/// // type is explicitly specified, fallback can't hurt us no more
/// <() as Default>::default()
/// };
/// ```
///
/// See [Tracking Issue for making `!` fall back to `!`](https://github.com/rust-lang/rust/issues/123748).
pub DEPENDENCY_ON_UNIT_NEVER_TYPE_FALLBACK,
Warn,
"never type fallback affecting unsafe function calls",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
reference: "issue #123748 <https://github.com/rust-lang/rust/issues/123748>",
};
report_in_external_macro
}
declare_lint! {
/// The `byte_slice_in_packed_struct_with_derive` lint detects cases where a byte slice field
/// (`[u8]`) or string slice field (`str`) is used in a `packed` struct that derives one or

View file

@ -539,7 +539,7 @@ impl<'a, 'tcx> SpanDecoder for DecodeContext<'a, 'tcx> {
} else {
SpanData::decode(self)
};
Span::new(data.lo, data.hi, data.ctxt, data.parent)
data.span()
}
fn decode_symbol(&mut self) -> Symbol {
@ -669,7 +669,7 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SpanData {
let lo = lo + source_file.translated_source_file.start_pos;
let hi = hi + source_file.translated_source_file.start_pos;
// Do not try to decode parent for foreign spans.
// Do not try to decode parent for foreign spans (it wasn't encoded in the first place).
SpanData { lo, hi, ctxt, parent: None }
}
}

View file

@ -2020,7 +2020,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
// if this is an impl of `CoerceUnsized`, create its
// "unsized info", else just store None
if Some(trait_ref.def_id) == tcx.lang_items().coerce_unsized_trait() {
if tcx.is_lang_item(trait_ref.def_id, LangItem::CoerceUnsized) {
let coerce_unsized_info = tcx.coerce_unsized_info(def_id).unwrap();
record!(self.tables.coerce_unsized_info[def_id] <- coerce_unsized_info);
}

View file

@ -23,6 +23,10 @@ impl<'tcx> TyCtxt<'tcx> {
})
}
pub fn is_lang_item(self, def_id: DefId, lang_item: LangItem) -> bool {
self.lang_items().get(lang_item) == Some(def_id)
}
/// Given a [`DefId`] of one of the [`Fn`], [`FnMut`] or [`FnOnce`] traits,
/// returns a corresponding [`ty::ClosureKind`].
/// For any other [`DefId`] return `None`.

View file

@ -69,6 +69,13 @@ impl<Prov: Provenance> fmt::LowerHex for Scalar<Prov> {
}
}
impl<Prov> From<Half> for Scalar<Prov> {
#[inline(always)]
fn from(f: Half) -> Self {
Scalar::from_f16(f)
}
}
impl<Prov> From<Single> for Scalar<Prov> {
#[inline(always)]
fn from(f: Single) -> Self {
@ -83,6 +90,13 @@ impl<Prov> From<Double> for Scalar<Prov> {
}
}
impl<Prov> From<Quad> for Scalar<Prov> {
#[inline(always)]
fn from(f: Quad) -> Self {
Scalar::from_f128(f)
}
}
impl<Prov> From<ScalarInt> for Scalar<Prov> {
#[inline(always)]
fn from(ptr: ScalarInt) -> Self {

View file

@ -1287,7 +1287,7 @@ fn use_verbose(ty: Ty<'_>, fn_def: bool) -> bool {
}
impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
fn visit_constant(&mut self, constant: &ConstOperand<'tcx>, _location: Location) {
fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, _location: Location) {
let ConstOperand { span, user_ty, const_ } = constant;
if use_verbose(const_.ty(), true) {
self.push("mir::ConstOperand");
@ -1415,7 +1415,7 @@ pub fn write_allocations<'tcx>(
struct CollectAllocIds(BTreeSet<AllocId>);
impl<'tcx> Visitor<'tcx> for CollectAllocIds {
fn visit_constant(&mut self, c: &ConstOperand<'tcx>, _: Location) {
fn visit_const_operand(&mut self, c: &ConstOperand<'tcx>, _: Location) {
match c.const_ {
Const::Ty(_, _) | Const::Unevaluated(..) => {}
Const::Val(val, _) => {

View file

@ -1490,7 +1490,8 @@ pub enum BinOp {
BitOr,
/// The `<<` operator (shift left)
///
/// The offset is (uniquely) determined as follows:
/// The offset is given by `RHS.rem_euclid(LHS::BITS)`.
/// In other words, it is (uniquely) determined as follows:
/// - it is "equal modulo LHS::BITS" to the RHS
/// - it is in the range `0..LHS::BITS`
Shl,
@ -1498,7 +1499,8 @@ pub enum BinOp {
ShlUnchecked,
/// The `>>` operator (shift right)
///
/// The offset is (uniquely) determined as follows:
/// The offset is given by `RHS.rem_euclid(LHS::BITS)`.
/// In other words, it is (uniquely) determined as follows:
/// - it is "equal modulo LHS::BITS" to the RHS
/// - it is in the range `0..LHS::BITS`
///

View file

@ -184,12 +184,12 @@ macro_rules! make_mir_visitor {
/// This is called for every constant in the MIR body and every `required_consts`
/// (i.e., including consts that have been dead-code-eliminated).
fn visit_constant(
fn visit_const_operand(
&mut self,
constant: & $($mutability)? ConstOperand<'tcx>,
location: Location,
) {
self.super_constant(constant, location);
self.super_const_operand(constant, location);
}
fn visit_ty_const(
@ -597,7 +597,7 @@ macro_rules! make_mir_visitor {
}
InlineAsmOperand::Const { value }
| InlineAsmOperand::SymFn { value } => {
self.visit_constant(value, location);
self.visit_const_operand(value, location);
}
InlineAsmOperand::Out { place: None, .. }
| InlineAsmOperand::SymStatic { def_id: _ }
@ -788,7 +788,7 @@ macro_rules! make_mir_visitor {
);
}
Operand::Constant(constant) => {
self.visit_constant(constant, location);
self.visit_const_operand(constant, location);
}
}
}
@ -867,7 +867,7 @@ macro_rules! make_mir_visitor {
}
}
match value {
VarDebugInfoContents::Const(c) => self.visit_constant(c, location),
VarDebugInfoContents::Const(c) => self.visit_const_operand(c, location),
VarDebugInfoContents::Place(place) =>
self.visit_place(
place,
@ -882,7 +882,7 @@ macro_rules! make_mir_visitor {
_scope: $(& $mutability)? SourceScope
) {}
fn super_constant(
fn super_const_operand(
&mut self,
constant: & $($mutability)? ConstOperand<'tcx>,
location: Location
@ -1057,7 +1057,7 @@ macro_rules! super_body {
for const_ in &$($mutability)? $body.required_consts {
let location = Location::START;
$self.visit_constant(const_, location);
$self.visit_const_operand(const_, location);
}
}
}

View file

@ -360,6 +360,14 @@ impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>) {
}
}
impl<'tcx> Key for ty::TraitRef<'tcx> {
type Cache<V> = DefaultCache<Self, V>;
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
tcx.def_span(self.def_id)
}
}
impl<'tcx> Key for ty::PolyTraitRef<'tcx> {
type Cache<V> = DefaultCache<Self, V>;

View file

@ -46,6 +46,7 @@ use crate::traits::{
};
use crate::ty::fast_reject::SimplifiedType;
use crate::ty::layout::ValidityRequirement;
use crate::ty::print::PrintTraitRefExt;
use crate::ty::util::AlwaysRequiresDrop;
use crate::ty::TyCtxtFeed;
use crate::ty::{
@ -1271,7 +1272,11 @@ rustc_queries! {
desc { |tcx| "finding all vtable entries for trait `{}`", tcx.def_path_str(key.def_id()) }
}
query vtable_trait_upcasting_coercion_new_vptr_slot(key: (Ty<'tcx>, Ty<'tcx>)) -> Option<usize> {
query first_method_vtable_slot(key: ty::TraitRef<'tcx>) -> usize {
desc { |tcx| "finding the slot within the vtable of `{}` for the implementation of `{}`", key.self_ty(), key.print_only_trait_name() }
}
query supertrait_vtable_slot(key: (Ty<'tcx>, Ty<'tcx>)) -> Option<usize> {
desc { |tcx| "finding the slot within vtable for trait object `{}` vtable ptr during trait upcasting coercion from `{}` vtable",
key.1, key.0 }
}

View file

@ -156,7 +156,7 @@ pub struct CandidateStep<'tcx> {
#[derive(Copy, Clone, Debug, HashStable)]
pub struct MethodAutoderefStepsResult<'tcx> {
/// The valid autoderef steps that could be find.
/// The valid autoderef steps that could be found.
pub steps: &'tcx [CandidateStep<'tcx>],
/// If Some(T), a type autoderef reported an error on.
pub opt_bad_ty: Option<&'tcx MethodAutoderefBadTy<'tcx>>,

View file

@ -37,7 +37,7 @@ impl<'tcx> Elaborator<'tcx> {
let super_predicates =
self.tcx.super_predicates_of(trait_ref.def_id()).predicates.iter().filter_map(
|&(pred, _)| {
let clause = pred.instantiate_supertrait(self.tcx, &trait_ref);
let clause = pred.instantiate_supertrait(self.tcx, trait_ref);
self.visited.insert(clause).then_some(clause)
},
);

View file

@ -8,9 +8,9 @@ use rustc_data_structures::intern::Interned;
use rustc_data_structures::stable_hasher::HashingControls;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::{self as hir, LangItem};
use rustc_index::{IndexSlice, IndexVec};
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
use rustc_query_system::ich::StableHashingContext;
@ -204,6 +204,23 @@ impl<'tcx> rustc_type_ir::inherent::AdtDef<TyCtxt<'tcx>> for AdtDef<'tcx> {
fn def_id(self) -> DefId {
self.did()
}
fn is_phantom_data(self) -> bool {
self.is_phantom_data()
}
fn all_field_tys(
self,
tcx: TyCtxt<'tcx>,
) -> ty::EarlyBinder<'tcx, impl Iterator<Item = Ty<'tcx>>> {
ty::EarlyBinder::bind(
self.all_fields().map(move |field| tcx.type_of(field.did).skip_binder()),
)
}
fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
self.sized_constraint(tcx)
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, HashStable, TyEncodable, TyDecodable)]
@ -257,16 +274,16 @@ impl AdtDefData {
if tcx.has_attr(did, sym::fundamental) {
flags |= AdtFlags::IS_FUNDAMENTAL;
}
if Some(did) == tcx.lang_items().phantom_data() {
if tcx.is_lang_item(did, LangItem::PhantomData) {
flags |= AdtFlags::IS_PHANTOM_DATA;
}
if Some(did) == tcx.lang_items().owned_box() {
if tcx.is_lang_item(did, LangItem::OwnedBox) {
flags |= AdtFlags::IS_BOX;
}
if Some(did) == tcx.lang_items().manually_drop() {
if tcx.is_lang_item(did, LangItem::ManuallyDrop) {
flags |= AdtFlags::IS_MANUALLY_DROP;
}
if Some(did) == tcx.lang_items().unsafe_cell_type() {
if tcx.is_lang_item(did, LangItem::UnsafeCell) {
flags |= AdtFlags::IS_UNSAFE_CELL;
}
if is_anonymous {

View file

@ -70,9 +70,9 @@ use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx};
use rustc_target::spec::abi;
use rustc_type_ir::fold::TypeFoldable;
use rustc_type_ir::lang_items::TraitSolverLangItem;
use rustc_type_ir::TyKind::*;
use rustc_type_ir::WithCachedTypeInfo;
use rustc_type_ir::{CollectAndApply, Interner, TypeFlags};
use rustc_type_ir::{CollectAndApply, Interner, TypeFlags, WithCachedTypeInfo};
use tracing::{debug, instrument};
use std::assert_matches::assert_matches;
@ -154,7 +154,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
type VariancesOf = &'tcx [ty::Variance];
fn variances_of(self, def_id: Self::DefId) -> Self::VariancesOf {
fn variances_of(self, def_id: DefId) -> Self::VariancesOf {
self.variances_of(def_id)
}
@ -198,7 +198,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
fn trait_ref_and_own_args_for_alias(
self,
def_id: Self::DefId,
def_id: DefId,
args: Self::GenericArgs,
) -> (rustc_type_ir::TraitRef<Self>, Self::GenericArgsSlice) {
assert_matches!(self.def_kind(def_id), DefKind::AssocTy | DefKind::AssocConst);
@ -246,7 +246,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
self.mk_type_list_from_iter(args)
}
fn parent(self, def_id: Self::DefId) -> Self::DefId {
fn parent(self, def_id: DefId) -> DefId {
self.parent(def_id)
}
@ -259,15 +259,85 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
fn features(self) -> Self::Features {
self.features()
}
fn bound_coroutine_hidden_types(
self,
def_id: DefId,
) -> impl IntoIterator<Item = ty::EarlyBinder<'tcx, ty::Binder<'tcx, Ty<'tcx>>>> {
self.bound_coroutine_hidden_types(def_id)
}
fn fn_sig(self, def_id: DefId) -> ty::EarlyBinder<'tcx, ty::PolyFnSig<'tcx>> {
self.fn_sig(def_id)
}
fn coroutine_movability(self, def_id: DefId) -> rustc_ast::Movability {
self.coroutine_movability(def_id)
}
fn coroutine_for_closure(self, def_id: DefId) -> DefId {
self.coroutine_for_closure(def_id)
}
fn generics_require_sized_self(self, def_id: DefId) -> bool {
self.generics_require_sized_self(def_id)
}
fn item_bounds(
self,
def_id: DefId,
) -> ty::EarlyBinder<'tcx, impl IntoIterator<Item = ty::Clause<'tcx>>> {
self.item_bounds(def_id).map_bound(IntoIterator::into_iter)
}
fn super_predicates_of(
self,
def_id: DefId,
) -> ty::EarlyBinder<'tcx, impl IntoIterator<Item = ty::Clause<'tcx>>> {
ty::EarlyBinder::bind(
self.super_predicates_of(def_id).instantiate_identity(self).predicates.into_iter(),
)
}
fn has_target_features(self, def_id: DefId) -> bool {
!self.codegen_fn_attrs(def_id).target_features.is_empty()
}
fn require_lang_item(self, lang_item: TraitSolverLangItem) -> DefId {
self.require_lang_item(
match lang_item {
TraitSolverLangItem::Future => hir::LangItem::Future,
TraitSolverLangItem::FutureOutput => hir::LangItem::FutureOutput,
TraitSolverLangItem::AsyncFnKindHelper => hir::LangItem::AsyncFnKindHelper,
TraitSolverLangItem::AsyncFnKindUpvars => hir::LangItem::AsyncFnKindUpvars,
},
None,
)
}
fn associated_type_def_ids(self, def_id: DefId) -> impl IntoIterator<Item = DefId> {
self.associated_items(def_id)
.in_definition_order()
.filter(|assoc_item| matches!(assoc_item.kind, ty::AssocKind::Type))
.map(|assoc_item| assoc_item.def_id)
}
}
impl<'tcx> rustc_type_ir::inherent::Abi<TyCtxt<'tcx>> for abi::Abi {
fn rust() -> Self {
abi::Abi::Rust
}
fn is_rust(self) -> bool {
matches!(self, abi::Abi::Rust)
}
}
impl<'tcx> rustc_type_ir::inherent::Safety<TyCtxt<'tcx>> for hir::Safety {
fn safe() -> Self {
hir::Safety::Safe
}
fn is_safe(self) -> bool {
matches!(self, hir::Safety::Safe)
}
@ -281,6 +351,10 @@ impl<'tcx> rustc_type_ir::inherent::Features<TyCtxt<'tcx>> for &'tcx rustc_featu
fn generic_const_exprs(self) -> bool {
self.generic_const_exprs
}
fn coroutine_clone(self) -> bool {
self.coroutine_clone
}
}
type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;

View file

@ -41,6 +41,8 @@ pub struct GenericArg<'tcx> {
marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>)>,
}
impl<'tcx> rustc_type_ir::inherent::GenericArg<TyCtxt<'tcx>> for GenericArg<'tcx> {}
impl<'tcx> rustc_type_ir::inherent::GenericArgs<TyCtxt<'tcx>> for ty::GenericArgsRef<'tcx> {
fn type_at(self, i: usize) -> Ty<'tcx> {
self.type_at(i)

View file

@ -699,26 +699,25 @@ impl<'tcx> Instance<'tcx> {
};
let coroutine_kind = tcx.coroutine_kind(coroutine_def_id).unwrap();
let lang_items = tcx.lang_items();
let coroutine_callable_item = if Some(trait_id) == lang_items.future_trait() {
let coroutine_callable_item = if tcx.is_lang_item(trait_id, LangItem::Future) {
assert_matches!(
coroutine_kind,
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)
);
hir::LangItem::FuturePoll
} else if Some(trait_id) == lang_items.iterator_trait() {
} else if tcx.is_lang_item(trait_id, LangItem::Iterator) {
assert_matches!(
coroutine_kind,
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
);
hir::LangItem::IteratorNext
} else if Some(trait_id) == lang_items.async_iterator_trait() {
} else if tcx.is_lang_item(trait_id, LangItem::AsyncIterator) {
assert_matches!(
coroutine_kind,
hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)
);
hir::LangItem::AsyncIteratorPollNext
} else if Some(trait_id) == lang_items.coroutine_trait() {
} else if tcx.is_lang_item(trait_id, LangItem::Coroutine) {
assert_matches!(coroutine_kind, hir::CoroutineKind::Coroutine(_));
hir::LangItem::CoroutineResume
} else {

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