New upstream version 1.66.0+dfsg1

This commit is contained in:
Fabian Grünbichler 2023-04-23 19:45:23 +02:00
parent f2b60f7d56
commit 2b03887add
5777 changed files with 135516 additions and 93949 deletions

396
COPYRIGHT
View File

@ -23,65 +23,251 @@ The Rust Project includes packages written by third parties.
The following third party packages are included, and carry The following third party packages are included, and carry
their own copyright notices and license terms: their own copyright notices and license terms:
* LLVM. Code for this package is found in src/llvm-project. * LLVM, located in src/llvm-project, is licensed under the following
terms.
Copyright (c) 2003-2013 University of Illinois at ==============================================================================
Urbana-Champaign. All rights reserved. The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
==============================================================================
Developed by: Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
LLVM Team TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
University of Illinois at Urbana-Champaign 1. Definitions.
http://llvm.org "License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
Permission is hereby granted, free of charge, to any "Licensor" shall mean the copyright owner or entity authorized by
person obtaining a copy of this software and associated the copyright owner that is granting the License.
documentation files (the "Software"), to deal with the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
* Redistributions of source code must retain the "Legal Entity" shall mean the union of the acting entity and all
above copyright notice, this list of conditions other entities that control, are controlled by, or are under common
and the following disclaimers. control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
* Redistributions in binary form must reproduce the "You" (or "Your") shall mean an individual or Legal Entity
above copyright notice, this list of conditions exercising permissions granted by this License.
and the following disclaimers in the documentation
and/or other materials provided with the
distribution.
* Neither the names of the LLVM Team, University of "Source" form shall mean the preferred form for making modifications,
Illinois at Urbana-Champaign, nor the names of its including but not limited to software source code, documentation
contributors may be used to endorse or promote source, and configuration files.
products derived from this Software without
specific prior written permission.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF "Object" form shall mean any form resulting from mechanical
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED transformation or translation of a Source form, including but
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A not limited to compiled object code, generated documentation,
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT and conversions to other media types.
SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS WITH THE SOFTWARE.
* Additional libraries included in LLVM carry separate "Work" shall mean the work of authorship, whether in Source or
BSD-compatible licenses. See src/llvm-project/llvm/LICENSE.TXT Object form, made available under the License, as indicated by a
for details. copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
* compiler-rt, in src/compiler-rt is dual licensed under "Derivative Works" shall mean any work, whether in Source or Object
LLVM's license and MIT: form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
Copyright (c) 2009-2014 by the contributors listed in "Contribution" shall mean any work of authorship, including
CREDITS.TXT the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
---- LLVM Exceptions to the Apache 2.0 License ----
As an exception, if, as a result of your compiling your source code, portions
of this Software are embedded into an Object form of such source code, you
may redistribute such embedded portions in such Object form without complying
with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
In addition, if you combine or link compiled forms of this Software with
software that is licensed under the GPLv2 ("Combined Software") and if a
court of competent jurisdiction determines that the patent provision (Section
3), the indemnity provision (Section 9) or other Section of the License
conflicts with the conditions of the GPLv2, you may retroactively and
prospectively choose to deem waived or otherwise exclude such Section(s) of
the License, but only in their entirety and only with respect to the Combined
Software.
==============================================================================
Software from third parties included in the LLVM Project:
==============================================================================
The LLVM Project contains third party software which is under different license
terms. All such code will be identified clearly using at least one of two
mechanisms:
1) It will be in a separate directory tree with its own `LICENSE.txt` or
`LICENSE` file at the top containing the specific license and restrictions
which apply to that software, or
2) It will contain specific license and restriction terms at the top of every
file.
==============================================================================
Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
==============================================================================
University of Illinois/NCSA
Open Source License
Copyright (c) 2003-2019 University of Illinois at Urbana-Champaign.
All rights reserved. All rights reserved.
Developed by: Developed by:
@ -92,70 +278,32 @@ their own copyright notices and license terms:
http://llvm.org http://llvm.org
Permission is hereby granted, free of charge, to any Permission is hereby granted, free of charge, to any person obtaining a copy of
person obtaining a copy of this software and associated this software and associated documentation files (the "Software"), to deal with
documentation files (the "Software"), to deal with the the Software without restriction, including without limitation the rights to
Software without restriction, including without use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
limitation the rights to use, copy, modify, merge, of the Software, and to permit persons to whom the Software is furnished to do
publish, distribute, sublicense, and/or sell copies of so, subject to the following conditions:
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
* Redistributions of source code must retain the * Redistributions of source code must retain the above copyright notice,
above copyright notice, this list of conditions this list of conditions and the following disclaimers.
and the following disclaimers.
* Redistributions in binary form must reproduce the * Redistributions in binary form must reproduce the above copyright notice,
above copyright notice, this list of conditions this list of conditions and the following disclaimers in the
and the following disclaimers in the documentation documentation and/or other materials provided with the distribution.
and/or other materials provided with the
distribution.
* Neither the names of the LLVM Team, University of * Neither the names of the LLVM Team, University of Illinois at
Illinois at Urbana-Champaign, nor the names of its Urbana-Champaign, nor the names of its contributors may be used to
contributors may be used to endorse or promote endorse or promote products derived from this Software without specific
products derived from this Software without prior written permission.
specific prior written permission.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT SOFTWARE.
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS WITH THE SOFTWARE.
========================================================
Copyright (c) 2009-2014 by the contributors listed in
CREDITS.TXT
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
* Portions of the FFI code for interacting with the native ABI * Portions of the FFI code for interacting with the native ABI
is derived from the Clay programming language, which carries is derived from the Clay programming language, which carries
@ -191,41 +339,3 @@ their own copyright notices and license terms:
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE. OF SUCH DAMAGE.
* libbacktrace, under src/libbacktrace:
Copyright (C) 2012-2014 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with
or without modification, are permitted provided that the
following conditions are met:
(1) Redistributions of source code must retain the
above copyright notice, this list of conditions and
the following disclaimer.
(2) Redistributions in binary form must reproduce
the above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the
distribution.
(3) The name of the author may not be used to
endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE. */

350
Cargo.lock generated
View File

@ -288,7 +288,7 @@ dependencies = [
[[package]] [[package]]
name = "cargo" name = "cargo"
version = "0.66.0" version = "0.67.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"atty", "atty",
@ -297,7 +297,7 @@ dependencies = [
"cargo-test-macro", "cargo-test-macro",
"cargo-test-support", "cargo-test-support",
"cargo-util", "cargo-util",
"clap", "clap 4.0.15",
"crates-io", "crates-io",
"curl", "curl",
"curl-sys", "curl-sys",
@ -330,8 +330,10 @@ dependencies = [
"pretty_env_logger", "pretty_env_logger",
"rustc-workspace-hack", "rustc-workspace-hack",
"rustfix", "rustfix",
"same-file",
"semver", "semver",
"serde", "serde",
"serde-value",
"serde_ignored", "serde_ignored",
"serde_json", "serde_json",
"shell-escape", "shell-escape",
@ -383,11 +385,12 @@ version = "0.1.0"
dependencies = [ dependencies = [
"cargo_metadata 0.15.0", "cargo_metadata 0.15.0",
"directories", "directories",
"rustc-build-sysroot",
"rustc-workspace-hack", "rustc-workspace-hack",
"rustc_tools_util",
"rustc_version", "rustc_version",
"serde", "serde",
"serde_json", "serde_json",
"vergen",
] ]
[[package]] [[package]]
@ -417,6 +420,7 @@ dependencies = [
"anyhow", "anyhow",
"cargo-test-macro", "cargo-test-macro",
"cargo-util", "cargo-util",
"crates-io",
"filetime", "filetime",
"flate2", "flate2",
"git2", "git2",
@ -507,6 +511,10 @@ name = "cfg-if"
version = "1.0.0" version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-core",
]
[[package]] [[package]]
name = "chalk-derive" name = "chalk-derive"
@ -584,7 +592,7 @@ dependencies = [
"atty", "atty",
"bitflags", "bitflags",
"clap_derive", "clap_derive",
"clap_lex", "clap_lex 0.2.2",
"indexmap", "indexmap",
"once_cell", "once_cell",
"strsim", "strsim",
@ -592,13 +600,26 @@ dependencies = [
"textwrap", "textwrap",
] ]
[[package]]
name = "clap"
version = "4.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bf8832993da70a4c6d13c581f4463c2bdda27b9bf1c5498dc4365543abe6d6f"
dependencies = [
"atty",
"bitflags",
"clap_lex 0.3.0",
"strsim",
"termcolor",
]
[[package]] [[package]]
name = "clap_complete" name = "clap_complete"
version = "3.1.1" version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df6f3613c0a3cddfd78b41b10203eb322cb29b600cbdf808a7d3db95691b8e25" checksum = "df6f3613c0a3cddfd78b41b10203eb322cb29b600cbdf808a7d3db95691b8e25"
dependencies = [ dependencies = [
"clap", "clap 3.2.20",
] ]
[[package]] [[package]]
@ -623,9 +644,18 @@ dependencies = [
"os_str_bytes", "os_str_bytes",
] ]
[[package]]
name = "clap_lex"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
dependencies = [
"os_str_bytes",
]
[[package]] [[package]]
name = "clippy" name = "clippy"
version = "0.1.65" version = "0.1.66"
dependencies = [ dependencies = [
"clippy_lints", "clippy_lints",
"clippy_utils", "clippy_utils",
@ -657,7 +687,7 @@ name = "clippy_dev"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"clap", "clap 3.2.20",
"indoc", "indoc",
"itertools", "itertools",
"opener", "opener",
@ -668,7 +698,7 @@ dependencies = [
[[package]] [[package]]
name = "clippy_lints" name = "clippy_lints"
version = "0.1.65" version = "0.1.66"
dependencies = [ dependencies = [
"cargo_metadata 0.14.0", "cargo_metadata 0.14.0",
"clippy_utils", "clippy_utils",
@ -690,7 +720,7 @@ dependencies = [
[[package]] [[package]]
name = "clippy_utils" name = "clippy_utils"
version = "0.1.65" version = "0.1.66"
dependencies = [ dependencies = [
"arrayvec", "arrayvec",
"if_chain", "if_chain",
@ -766,9 +796,9 @@ dependencies = [
[[package]] [[package]]
name = "compiler_builtins" name = "compiler_builtins"
version = "0.1.79" version = "0.1.82"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f873ce2bd3550b0b565f878b3d04ea8253f4259dc3d20223af2e1ba86f5ecca" checksum = "18cd7635fea7bb481ea543b392789844c1ad581299da70184c7175ce3af76603"
dependencies = [ dependencies = [
"cc", "cc",
"rustc-std-workspace-core", "rustc-std-workspace-core",
@ -799,9 +829,9 @@ dependencies = [
[[package]] [[package]]
name = "compiletest_rs" name = "compiletest_rs"
version = "0.8.0" version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "262134ef87408da1ddfe45e33daa0ca43b75286d6b1076446e602d264cf9847e" checksum = "70489bbb718aea4f92e5f48f2e3b5be670c2051de30e57cb6e5377b4aa08b372"
dependencies = [ dependencies = [
"diff", "diff",
"filetime", "filetime",
@ -1075,9 +1105,9 @@ dependencies = [
[[package]] [[package]]
name = "directories" name = "directories"
version = "3.0.2" version = "4.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e69600ff1703123957937708eb27f7a564e48885c537782722ed0ba3189ce1d7" checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210"
dependencies = [ dependencies = [
"dirs-sys", "dirs-sys",
] ]
@ -1167,26 +1197,6 @@ dependencies = [
"log", "log",
] ]
[[package]]
name = "enum-iterator"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c79a6321a1197d7730510c7e3f6cb80432dfefecb32426de8cea0aa19b4bb8d7"
dependencies = [
"enum-iterator-derive",
]
[[package]]
name = "enum-iterator-derive"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e94aa31f7c0dc764f57896dc615ddd76fc13b0d5dca7eb6cc5e018a5a09ec06"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "env_logger" name = "env_logger"
version = "0.7.1" version = "0.7.1"
@ -1524,18 +1534,6 @@ dependencies = [
"wasi 0.9.0+wasi-snapshot-preview1", "wasi 0.9.0+wasi-snapshot-preview1",
] ]
[[package]]
name = "getset"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24b328c01a4d71d2d8173daa93562a73ab0fe85616876f02500f53d82948c504"
dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "gimli" name = "gimli"
version = "0.25.0" version = "0.25.0"
@ -1802,7 +1800,7 @@ name = "installer"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"clap", "clap 3.2.20",
"flate2", "flate2",
"lazy_static", "lazy_static",
"num_cpus", "num_cpus",
@ -1845,9 +1843,9 @@ dependencies = [
[[package]] [[package]]
name = "itertools" name = "itertools"
version = "0.10.1" version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [ dependencies = [
"either", "either",
] ]
@ -1937,9 +1935,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.131" version = "0.2.135"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04c3b4822ccebfa39c02fc03d1534441b22ead323fa0f48bb7ddd8e6ba076a40" checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
dependencies = [ dependencies = [
"rustc-std-workspace-core", "rustc-std-workspace-core",
] ]
@ -2145,7 +2143,7 @@ dependencies = [
"ammonia", "ammonia",
"anyhow", "anyhow",
"chrono", "chrono",
"clap", "clap 3.2.20",
"clap_complete", "clap_complete",
"elasticlunr-rs", "elasticlunr-rs",
"env_logger 0.9.0", "env_logger 0.9.0",
@ -2264,6 +2262,7 @@ dependencies = [
"rand 0.8.5", "rand 0.8.5",
"regex", "regex",
"rustc-workspace-hack", "rustc-workspace-hack",
"rustc_version",
"shell-escape", "shell-escape",
"smallvec", "smallvec",
"ui_test", "ui_test",
@ -2414,6 +2413,15 @@ dependencies = [
"vcpkg", "vcpkg",
] ]
[[package]]
name = "ordered-float"
version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87"
dependencies = [
"num-traits",
]
[[package]] [[package]]
name = "os_info" name = "os_info"
version = "3.5.0" version = "3.5.0"
@ -2645,9 +2653,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]] [[package]]
name = "pkg-config" name = "pkg-config"
version = "0.3.18" version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d36492546b6af1463394d46f0c834346f31548646f6ba10849802c9c9a27ac33" checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
[[package]] [[package]]
name = "polonius-engine" name = "polonius-engine"
@ -2714,11 +2722,11 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.37" version = "1.0.46"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b"
dependencies = [ dependencies = [
"unicode-xid", "unicode-ident",
] ]
[[package]] [[package]]
@ -3008,11 +3016,22 @@ dependencies = [
name = "rustbook" name = "rustbook"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"clap", "clap 3.2.20",
"env_logger 0.7.1", "env_logger 0.7.1",
"mdbook", "mdbook",
] ]
[[package]]
name = "rustc-build-sysroot"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec5f3689b6c560d6a3a17fcbe54204cd870b4fcf46342d60de16715b660d2c92"
dependencies = [
"anyhow",
"rustc_version",
"tempfile",
]
[[package]] [[package]]
name = "rustc-demangle" name = "rustc-demangle"
version = "0.1.21" version = "0.1.21"
@ -3095,7 +3114,7 @@ name = "rustc-workspace-hack"
version = "1.0.0" version = "1.0.0"
dependencies = [ dependencies = [
"bstr", "bstr",
"clap", "clap 3.2.20",
"libz-sys", "libz-sys",
"regex", "regex",
"serde_json", "serde_json",
@ -3259,7 +3278,6 @@ dependencies = [
"bitflags", "bitflags",
"cstr", "cstr",
"libc", "libc",
"libloading",
"measureme", "measureme",
"object 0.29.0", "object 0.29.0",
"rustc-demangle", "rustc-demangle",
@ -3282,6 +3300,7 @@ dependencies = [
"rustc_symbol_mangling", "rustc_symbol_mangling",
"rustc_target", "rustc_target",
"smallvec", "smallvec",
"tempfile",
"tracing", "tracing",
] ]
@ -3391,6 +3410,7 @@ dependencies = [
"rustc_errors", "rustc_errors",
"rustc_feature", "rustc_feature",
"rustc_hir", "rustc_hir",
"rustc_hir_analysis",
"rustc_hir_pretty", "rustc_hir_pretty",
"rustc_interface", "rustc_interface",
"rustc_lint", "rustc_lint",
@ -3404,7 +3424,6 @@ dependencies = [
"rustc_session", "rustc_session",
"rustc_span", "rustc_span",
"rustc_target", "rustc_target",
"rustc_typeck",
"serde_json", "serde_json",
"tracing", "tracing",
"winapi", "winapi",
@ -3435,6 +3454,8 @@ version = "0.0.0"
dependencies = [ dependencies = [
"annotate-snippets", "annotate-snippets",
"atty", "atty",
"rustc_ast",
"rustc_ast_pretty",
"rustc_data_structures", "rustc_data_structures",
"rustc_error_messages", "rustc_error_messages",
"rustc_hir", "rustc_hir",
@ -3509,6 +3530,34 @@ dependencies = [
"tracing", "tracing",
] ]
[[package]]
name = "rustc_hir_analysis"
version = "0.0.0"
dependencies = [
"rustc_arena",
"rustc_ast",
"rustc_attr",
"rustc_data_structures",
"rustc_errors",
"rustc_feature",
"rustc_graphviz",
"rustc_hir",
"rustc_hir_pretty",
"rustc_index",
"rustc_infer",
"rustc_lint",
"rustc_macros",
"rustc_middle",
"rustc_serialize",
"rustc_session",
"rustc_span",
"rustc_target",
"rustc_trait_selection",
"rustc_type_ir",
"smallvec",
"tracing",
]
[[package]] [[package]]
name = "rustc_hir_pretty" name = "rustc_hir_pretty"
version = "0.0.0" version = "0.0.0"
@ -3520,6 +3569,32 @@ dependencies = [
"rustc_target", "rustc_target",
] ]
[[package]]
name = "rustc_hir_typeck"
version = "0.1.0"
dependencies = [
"rustc_ast",
"rustc_data_structures",
"rustc_errors",
"rustc_graphviz",
"rustc_hir",
"rustc_hir_analysis",
"rustc_hir_pretty",
"rustc_index",
"rustc_infer",
"rustc_lint",
"rustc_macros",
"rustc_middle",
"rustc_serialize",
"rustc_session",
"rustc_span",
"rustc_target",
"rustc_trait_selection",
"rustc_type_ir",
"smallvec",
"tracing",
]
[[package]] [[package]]
name = "rustc_incremental" name = "rustc_incremental"
version = "0.0.0" version = "0.0.0"
@ -3588,6 +3663,8 @@ dependencies = [
"rustc_errors", "rustc_errors",
"rustc_expand", "rustc_expand",
"rustc_hir", "rustc_hir",
"rustc_hir_analysis",
"rustc_hir_typeck",
"rustc_incremental", "rustc_incremental",
"rustc_lint", "rustc_lint",
"rustc_macros", "rustc_macros",
@ -3610,7 +3687,6 @@ dependencies = [
"rustc_trait_selection", "rustc_trait_selection",
"rustc_traits", "rustc_traits",
"rustc_ty_utils", "rustc_ty_utils",
"rustc_typeck",
"smallvec", "smallvec",
"tracing", "tracing",
"winapi", "winapi",
@ -3735,8 +3811,6 @@ dependencies = [
"either", "either",
"gsgdt", "gsgdt",
"polonius-engine", "polonius-engine",
"rand 0.8.5",
"rand_xoshiro",
"rustc-rayon", "rustc-rayon",
"rustc-rayon-core", "rustc-rayon-core",
"rustc_apfloat", "rustc_apfloat",
@ -3920,12 +3994,12 @@ dependencies = [
"rustc_data_structures", "rustc_data_structures",
"rustc_errors", "rustc_errors",
"rustc_hir", "rustc_hir",
"rustc_hir_analysis",
"rustc_macros", "rustc_macros",
"rustc_middle", "rustc_middle",
"rustc_session", "rustc_session",
"rustc_span", "rustc_span",
"rustc_trait_selection", "rustc_trait_selection",
"rustc_typeck",
"tracing", "tracing",
] ]
@ -4106,6 +4180,7 @@ version = "0.0.0"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"rustc_data_structures", "rustc_data_structures",
"rustc_feature",
"rustc_index", "rustc_index",
"rustc_macros", "rustc_macros",
"rustc_serialize", "rustc_serialize",
@ -4116,7 +4191,9 @@ dependencies = [
[[package]] [[package]]
name = "rustc_tools_util" name = "rustc_tools_util"
version = "0.2.0" version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "598f48ce2a421542b3e64828aa742b687cc1b91d2f96591cfdb7ac5988cd6366"
[[package]] [[package]]
name = "rustc_trait_selection" name = "rustc_trait_selection"
@ -4181,6 +4258,8 @@ dependencies = [
name = "rustc_ty_utils" name = "rustc_ty_utils"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"rand 0.8.5",
"rand_xoshiro",
"rustc_data_structures", "rustc_data_structures",
"rustc_errors", "rustc_errors",
"rustc_hir", "rustc_hir",
@ -4208,35 +4287,6 @@ dependencies = [
"smallvec", "smallvec",
] ]
[[package]]
name = "rustc_typeck"
version = "0.0.0"
dependencies = [
"rustc_arena",
"rustc_ast",
"rustc_attr",
"rustc_data_structures",
"rustc_errors",
"rustc_feature",
"rustc_graphviz",
"rustc_hir",
"rustc_hir_pretty",
"rustc_index",
"rustc_infer",
"rustc_lint",
"rustc_macros",
"rustc_middle",
"rustc_serialize",
"rustc_session",
"rustc_span",
"rustc_target",
"rustc_trait_selection",
"rustc_ty_utils",
"rustc_type_ir",
"smallvec",
"tracing",
]
[[package]] [[package]]
name = "rustc_version" name = "rustc_version"
version = "0.4.0" version = "0.4.0"
@ -4320,7 +4370,7 @@ dependencies = [
"anyhow", "anyhow",
"bytecount", "bytecount",
"cargo_metadata 0.14.0", "cargo_metadata 0.14.0",
"clap", "clap 3.2.20",
"derive-new", "derive-new",
"diff", "diff",
"dirs", "dirs",
@ -4426,18 +4476,28 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.143" version = "1.0.147"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553" checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde-value"
version = "1.0.143" version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391" checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c"
dependencies = [
"ordered-float",
"serde",
]
[[package]]
name = "serde_derive"
version = "1.0.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -4613,7 +4673,7 @@ version = "0.0.0"
dependencies = [ dependencies = [
"addr2line 0.16.0", "addr2line 0.16.0",
"alloc", "alloc",
"cfg-if 0.1.10", "cfg-if 1.0.0",
"compiler_builtins", "compiler_builtins",
"core", "core",
"dlmalloc", "dlmalloc",
@ -4637,7 +4697,7 @@ dependencies = [
name = "std_detect" name = "std_detect"
version = "0.1.5" version = "0.1.5"
dependencies = [ dependencies = [
"cfg-if 0.1.10", "cfg-if 1.0.0",
"compiler_builtins", "compiler_builtins",
"libc", "libc",
"rustc-std-workspace-alloc", "rustc-std-workspace-alloc",
@ -4687,13 +4747,13 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.91" version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d" checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"unicode-xid", "unicode-ident",
] ]
[[package]] [[package]]
@ -4886,9 +4946,18 @@ checksum = "29738eedb4388d9ea620eeab9384884fc3f06f586a2eddb56bedc5885126c7c1"
[[package]] [[package]]
name = "tinyvec" name = "tinyvec"
version = "0.3.4" version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117" checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]] [[package]]
name = "tokio" name = "tokio"
@ -4912,16 +4981,26 @@ dependencies = [
] ]
[[package]] [[package]]
name = "toml_edit" name = "toml_datetime"
version = "0.14.3" version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba98375fd631b83696f87c64e4ed8e29e6a1f3404d6aed95fa95163bad38e705" checksum = "808b51e57d0ef8f71115d8f3a01e7d3750d01c79cac4b3eda910f4389fdf92fd"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1541ba70885967e662f69d31ab3aeca7b1aaecfcd58679590b893e9239c3646"
dependencies = [ dependencies = [
"combine", "combine",
"indexmap", "indexmap",
"itertools", "itertools",
"kstring", "kstring",
"serde", "serde",
"toml_datetime",
] ]
[[package]] [[package]]
@ -5175,25 +5254,31 @@ dependencies = [
] ]
[[package]] [[package]]
name = "unicode-normalization" name = "unicode-ident"
version = "0.1.13" version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977" checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
[[package]]
name = "unicode-normalization"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
dependencies = [ dependencies = [
"tinyvec", "tinyvec",
] ]
[[package]] [[package]]
name = "unicode-script" name = "unicode-script"
version = "0.5.3" version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "098ec66172ce21cd55f8bcc786ee209dd20e04eff70acfca30cb79924d173ae9" checksum = "7d817255e1bed6dfd4ca47258685d14d2bdcfbc64fdc9e3819bd5848057b8ecc"
[[package]] [[package]]
name = "unicode-security" name = "unicode-security"
version = "0.0.5" version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d87c28edc5b263377e448d6cdcb935c06b95413d8013ba6fae470558ccab18f" checksum = "9ef5756b3097992b934b06608c69f48448a0fbe804bb1e72b982f6d7983e9e63"
dependencies = [ dependencies = [
"unicode-normalization", "unicode-normalization",
"unicode-script", "unicode-script",
@ -5201,15 +5286,15 @@ dependencies = [
[[package]] [[package]]
name = "unicode-segmentation" name = "unicode-segmentation"
version = "1.9.0" version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a"
[[package]] [[package]]
name = "unicode-width" name = "unicode-width"
version = "0.1.8" version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
dependencies = [ dependencies = [
"compiler_builtins", "compiler_builtins",
"rustc-std-workspace-core", "rustc-std-workspace-core",
@ -5218,9 +5303,9 @@ dependencies = [
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
version = "0.2.2" version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]] [[package]]
name = "unicode_categories" name = "unicode_categories"
@ -5293,21 +5378,6 @@ version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c" checksum = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c"
[[package]]
name = "vergen"
version = "5.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfbc87f9a7a9d61b15d51d1d3547284f67b6b4f1494ce3fc5814c101f35a5183"
dependencies = [
"anyhow",
"chrono",
"enum-iterator",
"getset",
"git2",
"rustversion",
"thiserror",
]
[[package]] [[package]]
name = "version_check" name = "version_check"
version = "0.9.3" version = "0.9.3"

View File

@ -1,3 +1,94 @@
Version 1.66.0 (2022-12-15)
==========================
Language
--------
- [Permit specifying explicit discriminants on all `repr(Int)` enums](https://github.com/rust-lang/rust/pull/95710/)
```rust
#[repr(u8)]
enum Foo {
A(u8) = 0,
B(i8) = 1,
C(bool) = 42,
}
```
- [Allow transmutes between the same type differing only in lifetimes](https://github.com/rust-lang/rust/pull/101520/)
- [Change constant evaluation errors from a deny-by-default lint to a hard error](https://github.com/rust-lang/rust/pull/102091/)
- [Trigger `must_use` on `impl Trait` for supertraits](https://github.com/rust-lang/rust/pull/102287/)
This makes `impl ExactSizeIterator` respect the existing `#[must_use]` annotation on `Iterator`.
- [Allow `..X` and `..=X` in patterns](https://github.com/rust-lang/rust/pull/102275/)
- [Uplift `clippy::for_loops_over_fallibles` lint into rustc](https://github.com/rust-lang/rust/pull/99696/)
- [Stabilize `sym` operands in inline assembly](https://github.com/rust-lang/rust/pull/103168/)
- [Update to Unicode 15](https://github.com/rust-lang/rust/pull/101912/)
- [Opaque types no longer imply lifetime bounds](https://github.com/rust-lang/rust/pull/95474/)
This is a soundness fix which may break code that was erroneously relying on this behavior.
Compiler
--------
- [Add armv5te-none-eabi and thumbv5te-none-eabi tier 3 targets](https://github.com/rust-lang/rust/pull/101329/)
- Refer to Rust's [platform support page][platform-support-doc] for more
information on Rust's tiered platform support.
- [Add support for linking against macOS universal libraries](https://github.com/rust-lang/rust/pull/98736)
Libraries
---------
- [Fix `#[derive(Default)]` on a generic `#[default]` enum adding unnecessary `Default` bounds](https://github.com/rust-lang/rust/pull/101040/)
- [Update to Unicode 15](https://github.com/rust-lang/rust/pull/101821/)
Stabilized APIs
---------------
- [`proc_macro::Span::source_text`](https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.source_text)
- [`uX::{checked_add_signed, overflowing_add_signed, saturating_add_signed, wrapping_add_signed}`](https://doc.rust-lang.org/stable/std/primitive.u8.html#method.checked_add_signed)
- [`iX::{checked_add_unsigned, overflowing_add_unsigned, saturating_add_unsigned, wrapping_add_unsigned}`](https://doc.rust-lang.org/stable/std/primitive.i8.html#method.checked_add_unsigned)
- [`iX::{checked_sub_unsigned, overflowing_sub_unsigned, saturating_sub_unsigned, wrapping_sub_unsigned}`](https://doc.rust-lang.org/stable/std/primitive.i8.html#method.checked_sub_unsigned)
- [`BTreeSet::{first, last, pop_first, pop_last}`](https://doc.rust-lang.org/stable/std/collections/struct.BTreeSet.html#method.first)
- [`BTreeMap::{first_key_value, last_key_value, first_entry, last_entry, pop_first, pop_last}`](https://doc.rust-lang.org/stable/std/collections/struct.BTreeMap.html#method.first_key_value)
- [Add `AsFd` implementations for stdio lock types on WASI.](https://github.com/rust-lang/rust/pull/101768/)
- [`impl TryFrom<Vec<T>> for Box<[T; N]>`](https://doc.rust-lang.org/stable/std/boxed/struct.Box.html#impl-TryFrom%3CVec%3CT%2C%20Global%3E%3E-for-Box%3C%5BT%3B%20N%5D%2C%20Global%3E)
- [`core::hint::black_box`](https://doc.rust-lang.org/stable/std/hint/fn.black_box.html)
- [`Duration::try_from_secs_{f32,f64}`](https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.try_from_secs_f32)
- [`Option::unzip`](https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.unzip)
- [`std::os::fd`](https://doc.rust-lang.org/stable/std/os/fd/index.html)
Rustdoc
-------
- [Add Rustdoc warning for invalid HTML tags in the documentation](https://github.com/rust-lang/rust/pull/101720/)
Cargo
-----
- [Added `cargo remove` to remove dependencies from Cargo.toml](https://doc.rust-lang.org/nightly/cargo/commands/cargo-remove.html)
- [`cargo publish` now waits for the new version to be downloadable before exiting](https://github.com/rust-lang/cargo/pull/11062)
See [detailed release notes](https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md#cargo-166-2022-12-15) for more.
Compatibility Notes
-------------------
- [Only apply `ProceduralMasquerade` hack to older versions of `rental`](https://github.com/rust-lang/rust/pull/94063/)
- [Don't export `__heap_base` and `__data_end` on wasm32-wasi.](https://github.com/rust-lang/rust/pull/102385/)
- [Don't export `__wasm_init_memory` on WebAssembly.](https://github.com/rust-lang/rust/pull/102426/)
- [Only export `__tls_*` on wasm32-unknown-unknown.](https://github.com/rust-lang/rust/pull/102440/)
- [Don't link to `libresolv` in libstd on Darwin](https://github.com/rust-lang/rust/pull/102766/)
- [Update libstd's libc to 0.2.135 (to make `libstd` no longer pull in `libiconv.dylib` on Darwin)](https://github.com/rust-lang/rust/pull/103277/)
- [Opaque types no longer imply lifetime bounds](https://github.com/rust-lang/rust/pull/95474/)
This is a soundness fix which may break code that was erroneously relying on this behavior.
- [Make `order_dependent_trait_objects` show up in future-breakage reports](https://github.com/rust-lang/rust/pull/102635/)
- [Change std::process::Command spawning to default to inheriting the parent's signal mask](https://github.com/rust-lang/rust/pull/101077/)
Internal Changes
----------------
These changes do not affect any public interfaces of Rust, but they represent
significant improvements to the performance or internals of rustc and related
tools.
- [Enable BOLT for LLVM compilation](https://github.com/rust-lang/rust/pull/94381/)
- [Enable LTO for rustc_driver.so](https://github.com/rust-lang/rust/pull/101403/)
Version 1.65.0 (2022-11-03) Version 1.65.0 (2022-11-03)
========================== ==========================
@ -6,7 +97,7 @@ Language
- [Error on `as` casts of enums with `#[non_exhaustive]` variants](https://github.com/rust-lang/rust/pull/92744/) - [Error on `as` casts of enums with `#[non_exhaustive]` variants](https://github.com/rust-lang/rust/pull/92744/)
- [Stabilize `let else`](https://github.com/rust-lang/rust/pull/93628/) - [Stabilize `let else`](https://github.com/rust-lang/rust/pull/93628/)
- [Stabilize generic associated types (GATs)](https://github.com/rust-lang/rust/pull/96709/) - [Stabilize generic associated types (GATs)](https://github.com/rust-lang/rust/pull/96709/)
- [Add lints `let_underscore_drop`, `let_underscore_lock`, and `let_underscore_must_use` from Clippy](https://github.com/rust-lang/rust/pull/97739/) - [Add lints `let_underscore_drop` and `let_underscore_lock` from Clippy](https://github.com/rust-lang/rust/pull/97739/)
- [Stabilize `break`ing from arbitrary labeled blocks ("label-break-value")](https://github.com/rust-lang/rust/pull/99332/) - [Stabilize `break`ing from arbitrary labeled blocks ("label-break-value")](https://github.com/rust-lang/rust/pull/99332/)
- [Uninitialized integers, floats, and raw pointers are now considered immediate UB](https://github.com/rust-lang/rust/pull/98919/). - [Uninitialized integers, floats, and raw pointers are now considered immediate UB](https://github.com/rust-lang/rust/pull/98919/).
Usage of `MaybeUninit` is the correct way to work with uninitialized memory. Usage of `MaybeUninit` is the correct way to work with uninitialized memory.
@ -87,6 +178,9 @@ Compatibility Notes
This strengthens the forward compatibility lint deprecated_cfg_attr_crate_type_name to deny. This strengthens the forward compatibility lint deprecated_cfg_attr_crate_type_name to deny.
- [`llvm-has-rust-patches` allows setting the build system to treat the LLVM as having Rust-specific patches](https://github.com/rust-lang/rust/pull/101072) - [`llvm-has-rust-patches` allows setting the build system to treat the LLVM as having Rust-specific patches](https://github.com/rust-lang/rust/pull/101072)
This option may need to be set for distributions that are building Rust with a patched LLVM via `llvm-config`, not the built-in LLVM. This option may need to be set for distributions that are building Rust with a patched LLVM via `llvm-config`, not the built-in LLVM.
- Combining three or more languages (e.g. Objective C, C++ and Rust) into one binary may hit linker limitations when using `lld`. For more information, see [issue 102754][102754].
[102754]: https://github.com/rust-lang/rust/issues/102754
Internal Changes Internal Changes
---------------- ----------------

View File

@ -1,3 +1,5 @@
#![feature(unix_sigpipe)]
// A note about jemalloc: rustc uses jemalloc when built for CI and // A note about jemalloc: rustc uses jemalloc when built for CI and
// distribution. The obvious way to do this is with the `#[global_allocator]` // distribution. The obvious way to do this is with the `#[global_allocator]`
// mechanism. However, for complicated reasons (see // mechanism. However, for complicated reasons (see
@ -23,6 +25,7 @@
// libraries. So we must reference jemalloc symbols one way or another, because // libraries. So we must reference jemalloc symbols one way or another, because
// this file is the only object code in the rustc executable. // this file is the only object code in the rustc executable.
#[unix_sigpipe = "sig_dfl"]
fn main() { fn main() {
// See the comment at the top of this file for an explanation of this. // See the comment at the top of this file for an explanation of this.
#[cfg(feature = "jemalloc-sys")] #[cfg(feature = "jemalloc-sys")]
@ -58,6 +61,5 @@ fn main() {
} }
} }
rustc_driver::set_sigpipe_handler();
rustc_driver::main() rustc_driver::main()
} }

View File

@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021" edition = "2021"
[lib] [lib]
doctest = false
[dependencies] [dependencies]
bitflags = "1.2.1" bitflags = "1.2.1"

View File

@ -1112,24 +1112,6 @@ pub struct Expr {
} }
impl Expr { impl Expr {
/// Returns `true` if this expression would be valid somewhere that expects a value;
/// for example, an `if` condition.
pub fn returns(&self) -> bool {
if let ExprKind::Block(ref block, _) = self.kind {
match block.stmts.last().map(|last_stmt| &last_stmt.kind) {
// Implicit return
Some(StmtKind::Expr(_)) => true,
// Last statement is an explicit return?
Some(StmtKind::Semi(expr)) => matches!(expr.kind, ExprKind::Ret(_)),
// This is a block that doesn't end in either an implicit or explicit return.
_ => false,
}
} else {
// This is not a block, it is a value.
true
}
}
/// Is this expr either `N`, or `{ N }`. /// Is this expr either `N`, or `{ N }`.
/// ///
/// If this is not the case, name resolution does not resolve `N` when using /// If this is not the case, name resolution does not resolve `N` when using
@ -1338,14 +1320,13 @@ pub enum ExprKind {
/// ///
/// The `PathSegment` represents the method name and its generic arguments /// The `PathSegment` represents the method name and its generic arguments
/// (within the angle brackets). /// (within the angle brackets).
/// The first element of the vector of an `Expr` is the expression that evaluates /// The standalone `Expr` is the receiver expression.
/// to the object on which the method is being called on (the receiver), /// The vector of `Expr` is the arguments.
/// and the remaining elements are the rest of the arguments. /// `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
/// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, x, [a, b, c, d])`.
/// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`.
/// This `Span` is the span of the function, without the dot and receiver /// This `Span` is the span of the function, without the dot and receiver
/// (e.g. `foo(a, b)` in `x.foo(a, b)` /// (e.g. `foo(a, b)` in `x.foo(a, b)`
MethodCall(PathSegment, Vec<P<Expr>>, Span), MethodCall(PathSegment, P<Expr>, Vec<P<Expr>>, Span),
/// A tuple (e.g., `(a, b, c, d)`). /// A tuple (e.g., `(a, b, c, d)`).
Tup(Vec<P<Expr>>), Tup(Vec<P<Expr>>),
/// A binary operation (e.g., `a + b`, `a * b`). /// A binary operation (e.g., `a + b`, `a * b`).
@ -2957,7 +2938,7 @@ pub enum AssocItemKind {
/// An associated function. /// An associated function.
Fn(Box<Fn>), Fn(Box<Fn>),
/// An associated type. /// An associated type.
TyAlias(Box<TyAlias>), Type(Box<TyAlias>),
/// A macro expanding to associated items. /// A macro expanding to associated items.
MacCall(P<MacCall>), MacCall(P<MacCall>),
} }
@ -2967,7 +2948,7 @@ impl AssocItemKind {
match *self { match *self {
Self::Const(defaultness, ..) Self::Const(defaultness, ..)
| Self::Fn(box Fn { defaultness, .. }) | Self::Fn(box Fn { defaultness, .. })
| Self::TyAlias(box TyAlias { defaultness, .. }) => defaultness, | Self::Type(box TyAlias { defaultness, .. }) => defaultness,
Self::MacCall(..) => Defaultness::Final, Self::MacCall(..) => Defaultness::Final,
} }
} }
@ -2978,7 +2959,7 @@ impl From<AssocItemKind> for ItemKind {
match assoc_item_kind { match assoc_item_kind {
AssocItemKind::Const(a, b, c) => ItemKind::Const(a, b, c), AssocItemKind::Const(a, b, c) => ItemKind::Const(a, b, c),
AssocItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind), AssocItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind),
AssocItemKind::TyAlias(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind), AssocItemKind::Type(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
AssocItemKind::MacCall(a) => ItemKind::MacCall(a), AssocItemKind::MacCall(a) => ItemKind::MacCall(a),
} }
} }
@ -2991,7 +2972,7 @@ impl TryFrom<ItemKind> for AssocItemKind {
Ok(match item_kind { Ok(match item_kind {
ItemKind::Const(a, b, c) => AssocItemKind::Const(a, b, c), ItemKind::Const(a, b, c) => AssocItemKind::Const(a, b, c),
ItemKind::Fn(fn_kind) => AssocItemKind::Fn(fn_kind), ItemKind::Fn(fn_kind) => AssocItemKind::Fn(fn_kind),
ItemKind::TyAlias(ty_alias_kind) => AssocItemKind::TyAlias(ty_alias_kind), ItemKind::TyAlias(ty_kind) => AssocItemKind::Type(ty_kind),
ItemKind::MacCall(a) => AssocItemKind::MacCall(a), ItemKind::MacCall(a) => AssocItemKind::MacCall(a),
_ => return Err(item_kind), _ => return Err(item_kind),
}) })
@ -3043,14 +3024,13 @@ pub type ForeignItem = Item<ForeignItemKind>;
mod size_asserts { mod size_asserts {
use super::*; use super::*;
use rustc_data_structures::static_assert_size; use rustc_data_structures::static_assert_size;
// These are in alphabetical order, which is easy to maintain. // tidy-alphabetical-start
static_assert_size!(AssocItem, 104); static_assert_size!(AssocItem, 104);
static_assert_size!(AssocItemKind, 32); static_assert_size!(AssocItemKind, 32);
static_assert_size!(Attribute, 32); static_assert_size!(Attribute, 32);
static_assert_size!(Block, 48); static_assert_size!(Block, 48);
static_assert_size!(Expr, 104); static_assert_size!(Expr, 104);
static_assert_size!(ExprKind, 72); static_assert_size!(ExprKind, 72);
#[cfg(not(bootstrap))]
static_assert_size!(Fn, 184); static_assert_size!(Fn, 184);
static_assert_size!(ForeignItem, 96); static_assert_size!(ForeignItem, 96);
static_assert_size!(ForeignItemKind, 24); static_assert_size!(ForeignItemKind, 24);
@ -3065,11 +3045,12 @@ mod size_asserts {
static_assert_size!(Local, 72); static_assert_size!(Local, 72);
static_assert_size!(Param, 40); static_assert_size!(Param, 40);
static_assert_size!(Pat, 120); static_assert_size!(Pat, 120);
static_assert_size!(PatKind, 96);
static_assert_size!(Path, 40); static_assert_size!(Path, 40);
static_assert_size!(PathSegment, 24); static_assert_size!(PathSegment, 24);
static_assert_size!(PatKind, 96);
static_assert_size!(Stmt, 32); static_assert_size!(Stmt, 32);
static_assert_size!(StmtKind, 16); static_assert_size!(StmtKind, 16);
static_assert_size!(Ty, 96); static_assert_size!(Ty, 96);
static_assert_size!(TyKind, 72); static_assert_size!(TyKind, 72);
// tidy-alphabetical-end
} }

View File

@ -13,9 +13,7 @@
#![feature(const_default_impls)] #![feature(const_default_impls)]
#![feature(const_trait_impl)] #![feature(const_trait_impl)]
#![feature(if_let_guard)] #![feature(if_let_guard)]
#![cfg_attr(bootstrap, feature(label_break_value))]
#![feature(let_chains)] #![feature(let_chains)]
#![cfg_attr(bootstrap, feature(let_else))]
#![feature(min_specialization)] #![feature(min_specialization)]
#![feature(negative_impls)] #![feature(negative_impls)]
#![feature(slice_internals)] #![feature(slice_internals)]

View File

@ -152,6 +152,12 @@ pub trait MutVisitor: Sized {
noop_visit_expr(e, self); noop_visit_expr(e, self);
} }
/// This method is a hack to workaround unstable of `stmt_expr_attributes`.
/// It can be removed once that feature is stabilized.
fn visit_method_receiver_expr(&mut self, ex: &mut P<Expr>) {
self.visit_expr(ex)
}
fn filter_map_expr(&mut self, e: P<Expr>) -> Option<P<Expr>> { fn filter_map_expr(&mut self, e: P<Expr>) -> Option<P<Expr>> {
noop_filter_map_expr(e, self) noop_filter_map_expr(e, self)
} }
@ -1106,7 +1112,7 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
visit_fn_sig(sig, visitor); visit_fn_sig(sig, visitor);
visit_opt(body, |body| visitor.visit_block(body)); visit_opt(body, |body| visitor.visit_block(body));
} }
AssocItemKind::TyAlias(box TyAlias { AssocItemKind::Type(box TyAlias {
defaultness, defaultness,
generics, generics,
where_clauses, where_clauses,
@ -1297,10 +1303,11 @@ pub fn noop_visit_expr<T: MutVisitor>(
vis.visit_expr(f); vis.visit_expr(f);
visit_exprs(args, vis); visit_exprs(args, vis);
} }
ExprKind::MethodCall(PathSegment { ident, id, args }, exprs, span) => { ExprKind::MethodCall(PathSegment { ident, id, args }, receiver, exprs, span) => {
vis.visit_ident(ident); vis.visit_ident(ident);
vis.visit_id(id); vis.visit_id(id);
visit_opt(args, |args| vis.visit_generic_args(args)); visit_opt(args, |args| vis.visit_generic_args(args));
vis.visit_method_receiver_expr(receiver);
visit_exprs(exprs, vis); visit_exprs(exprs, vis);
vis.visit_span(span); vis.visit_span(span);
} }
@ -1588,3 +1595,9 @@ impl DummyAstNode for Crate {
} }
} }
} }
impl<N: DummyAstNode, T: DummyAstNode> DummyAstNode for crate::ast_traits::AstNodeWrapper<N, T> {
fn dummy() -> Self {
crate::ast_traits::AstNodeWrapper::new(N::dummy(), T::dummy())
}
}

View File

@ -13,7 +13,7 @@ use rustc_span::symbol::{kw, sym};
use rustc_span::symbol::{Ident, Symbol}; use rustc_span::symbol::{Ident, Symbol};
use rustc_span::{self, edition::Edition, Span, DUMMY_SP}; use rustc_span::{self, edition::Edition, Span, DUMMY_SP};
use std::borrow::Cow; use std::borrow::Cow;
use std::{fmt, mem}; use std::fmt;
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] #[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum CommentKind { pub enum CommentKind {
@ -256,10 +256,6 @@ pub enum TokenKind {
Eof, Eof,
} }
// `TokenKind` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(TokenKind, 16);
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] #[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct Token { pub struct Token {
pub kind: TokenKind, pub kind: TokenKind,
@ -335,11 +331,6 @@ impl Token {
Token::new(Ident(ident.name, ident.is_raw_guess()), ident.span) Token::new(Ident(ident.name, ident.is_raw_guess()), ident.span)
} }
/// Return this token by value and leave a dummy token in its place.
pub fn take(&mut self) -> Self {
mem::replace(self, Token::dummy())
}
/// For interpolated tokens, returns a span of the fragment to which the interpolated /// For interpolated tokens, returns a span of the fragment to which the interpolated
/// token refers. For all other tokens this is just a regular span. /// token refers. For all other tokens this is just a regular span.
/// It is particularly important to use this for identifiers and lifetimes /// It is particularly important to use this for identifiers and lifetimes
@ -354,17 +345,14 @@ impl Token {
} }
pub fn is_op(&self) -> bool { pub fn is_op(&self) -> bool {
!matches!( match self.kind {
self.kind, Eq | Lt | Le | EqEq | Ne | Ge | Gt | AndAnd | OrOr | Not | Tilde | BinOp(_)
OpenDelim(..) | BinOpEq(_) | At | Dot | DotDot | DotDotDot | DotDotEq | Comma | Semi | Colon
| CloseDelim(..) | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar | Question | SingleQuote => true,
| Literal(..)
| DocComment(..) OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) | Ident(..)
| Ident(..) | Lifetime(..) | Interpolated(..) | Eof => false,
| Lifetime(..) }
| Interpolated(..)
| Eof
)
} }
pub fn is_like_plus(&self) -> bool { pub fn is_like_plus(&self) -> bool {
@ -733,6 +721,7 @@ impl Token {
} }
impl PartialEq<TokenKind> for Token { impl PartialEq<TokenKind> for Token {
#[inline]
fn eq(&self, rhs: &TokenKind) -> bool { fn eq(&self, rhs: &TokenKind) -> bool {
self.kind == *rhs self.kind == *rhs
} }
@ -756,10 +745,6 @@ pub enum Nonterminal {
NtVis(P<ast::Visibility>), NtVis(P<ast::Visibility>),
} }
// `Nonterminal` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(Nonterminal, 16);
#[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable)] #[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable)]
pub enum NonterminalKind { pub enum NonterminalKind {
Item, Item,
@ -898,3 +883,17 @@ where
panic!("interpolated tokens should not be present in the HIR") panic!("interpolated tokens should not be present in the HIR")
} }
} }
// Some types are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;
// tidy-alphabetical-start
static_assert_size!(Lit, 12);
static_assert_size!(LitKind, 2);
static_assert_size!(Nonterminal, 16);
static_assert_size!(Token, 24);
static_assert_size!(TokenKind, 16);
// tidy-alphabetical-end
}

View File

@ -47,10 +47,6 @@ pub enum TokenTree {
Delimited(DelimSpan, Delimiter, TokenStream), Delimited(DelimSpan, Delimiter, TokenStream),
} }
// This type is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(TokenTree, 32);
// Ensure all fields of `TokenTree` is `Send` and `Sync`. // Ensure all fields of `TokenTree` is `Send` and `Sync`.
#[cfg(parallel_compiler)] #[cfg(parallel_compiler)]
fn _dummy() fn _dummy()
@ -249,12 +245,12 @@ impl AttrTokenStream {
// properly implemented - we always synthesize fake tokens, // properly implemented - we always synthesize fake tokens,
// so we never reach this code. // so we never reach this code.
let mut builder = TokenStreamBuilder::new(); let mut stream = TokenStream::default();
for inner_attr in inner_attrs { for inner_attr in inner_attrs {
builder.push(inner_attr.tokens()); stream.push_stream(inner_attr.tokens());
} }
builder.push(delim_tokens.clone()); stream.push_stream(delim_tokens.clone());
*tree = TokenTree::Delimited(*span, *delim, builder.build()); *tree = TokenTree::Delimited(*span, *delim, stream);
found = true; found = true;
break; break;
} }
@ -308,13 +304,20 @@ pub struct AttributesData {
#[derive(Clone, Debug, Default, Encodable, Decodable)] #[derive(Clone, Debug, Default, Encodable, Decodable)]
pub struct TokenStream(pub(crate) Lrc<Vec<TokenTree>>); pub struct TokenStream(pub(crate) Lrc<Vec<TokenTree>>);
// `TokenStream` is used a lot. Make sure it doesn't unintentionally get bigger. /// Similar to `proc_macro::Spacing`, but for tokens.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] ///
rustc_data_structures::static_assert_size!(TokenStream, 8); /// Note that all `ast::TokenTree::Token` instances have a `Spacing`, but when
/// we convert to `proc_macro::TokenTree` for proc macros only `Punct`
/// `TokenTree`s have a `proc_macro::Spacing`.
#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)] #[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)]
pub enum Spacing { pub enum Spacing {
/// The token is not immediately followed by an operator token (as
/// determined by `Token::is_op`). E.g. a `+` token is `Alone` in `+ =`,
/// `+/*foo*/=`, `+ident`, and `+()`.
Alone, Alone,
/// The token is immediately followed by an operator token. E.g. a `+`
/// token is `Joint` in `+=` and `++`.
Joint, Joint,
} }
@ -502,77 +505,50 @@ impl TokenStream {
self.trees().map(|tree| TokenStream::flatten_token_tree(tree)).collect() self.trees().map(|tree| TokenStream::flatten_token_tree(tree)).collect()
} }
}
// 99.5%+ of the time we have 1 or 2 elements in this vector. // If `vec` is not empty, try to glue `tt` onto its last token. The return
#[derive(Clone)] // value indicates if gluing took place.
pub struct TokenStreamBuilder(SmallVec<[TokenStream; 2]>); fn try_glue_to_last(vec: &mut Vec<TokenTree>, tt: &TokenTree) -> bool {
if let Some(TokenTree::Token(last_tok, Spacing::Joint)) = vec.last()
impl TokenStreamBuilder { && let TokenTree::Token(tok, spacing) = tt
pub fn new() -> TokenStreamBuilder {
TokenStreamBuilder(SmallVec::new())
}
pub fn push(&mut self, stream: TokenStream) {
self.0.push(stream);
}
pub fn build(self) -> TokenStream {
let mut streams = self.0;
match streams.len() {
0 => TokenStream::default(),
1 => streams.pop().unwrap(),
_ => {
// We will extend the first stream in `streams` with the
// elements from the subsequent streams. This requires using
// `make_mut()` on the first stream, and in practice this
// doesn't cause cloning 99.9% of the time.
//
// One very common use case is when `streams` has two elements,
// where the first stream has any number of elements within
// (often 1, but sometimes many more) and the second stream has
// a single element within.
// Determine how much the first stream will be extended.
// Needed to avoid quadratic blow up from on-the-fly
// reallocations (#57735).
let num_appends = streams.iter().skip(1).map(|ts| ts.len()).sum();
// Get the first stream, which will become the result stream.
// If it's `None`, create an empty stream.
let mut iter = streams.into_iter();
let mut res_stream_lrc = iter.next().unwrap().0;
// Append the subsequent elements to the result stream, after
// reserving space for them.
let res_vec_mut = Lrc::make_mut(&mut res_stream_lrc);
res_vec_mut.reserve(num_appends);
for stream in iter {
let stream_iter = stream.0.iter().cloned();
// If (a) `res_mut_vec` is not empty and the last tree
// within it is a token tree marked with `Joint`, and (b)
// `stream` is not empty and the first tree within it is a
// token tree, and (c) the two tokens can be glued
// together...
if let Some(TokenTree::Token(last_tok, Spacing::Joint)) = res_vec_mut.last()
&& let Some(TokenTree::Token(tok, spacing)) = stream.0.first()
&& let Some(glued_tok) = last_tok.glue(&tok) && let Some(glued_tok) = last_tok.glue(&tok)
{ {
// ...then overwrite the last token tree in // ...then overwrite the last token tree in `vec` with the
// `res_vec_mut` with the glued token, and skip the // glued token, and skip the first token tree from `stream`.
// first token tree from `stream`. *vec.last_mut().unwrap() = TokenTree::Token(glued_tok, *spacing);
*res_vec_mut.last_mut().unwrap() = TokenTree::Token(glued_tok, *spacing); true
res_vec_mut.extend(stream_iter.skip(1));
} else { } else {
// Append all of `stream`. false
res_vec_mut.extend(stream_iter);
} }
} }
TokenStream(res_stream_lrc) // Push `tt` onto the end of the stream, possibly gluing it to the last
// token. Uses `make_mut` to maximize efficiency.
pub fn push_tree(&mut self, tt: TokenTree) {
let vec_mut = Lrc::make_mut(&mut self.0);
if Self::try_glue_to_last(vec_mut, &tt) {
// nothing else to do
} else {
vec_mut.push(tt);
} }
} }
// Push `stream` onto the end of the stream, possibly gluing the first
// token tree to the last token. (No other token trees will be glued.)
// Uses `make_mut` to maximize efficiency.
pub fn push_stream(&mut self, stream: TokenStream) {
let vec_mut = Lrc::make_mut(&mut self.0);
let stream_iter = stream.0.iter().cloned();
if let Some(first) = stream.0.first() && Self::try_glue_to_last(vec_mut, first) {
// Now skip the first token tree from `stream`.
vec_mut.extend(stream_iter.skip(1));
} else {
// Append all of `stream`.
vec_mut.extend(stream_iter);
}
} }
} }
@ -664,3 +640,17 @@ impl DelimSpan {
self.open.with_hi(self.close.hi()) self.open.with_hi(self.close.hi())
} }
} }
// Some types are used a lot. Make sure they don't unintentionally get bigger.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;
// tidy-alphabetical-start
static_assert_size!(AttrTokenStream, 8);
static_assert_size!(AttrTokenTree, 32);
static_assert_size!(LazyAttrTokenStream, 8);
static_assert_size!(TokenStream, 8);
static_assert_size!(TokenTree, 32);
// tidy-alphabetical-end
}

View File

@ -396,9 +396,9 @@ pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool {
contains_exterior_struct_lit(&x) contains_exterior_struct_lit(&x)
} }
ast::ExprKind::MethodCall(.., ref exprs, _) => { ast::ExprKind::MethodCall(_, ref receiver, _, _) => {
// X { y: 1 }.bar(...) // X { y: 1 }.bar(...)
contains_exterior_struct_lit(&exprs[0]) contains_exterior_struct_lit(&receiver)
} }
_ => false, _ => false,

View File

@ -140,6 +140,11 @@ pub trait Visitor<'ast>: Sized {
fn visit_expr(&mut self, ex: &'ast Expr) { fn visit_expr(&mut self, ex: &'ast Expr) {
walk_expr(self, ex) walk_expr(self, ex)
} }
/// This method is a hack to workaround unstable of `stmt_expr_attributes`.
/// It can be removed once that feature is stabilized.
fn visit_method_receiver_expr(&mut self, ex: &'ast Expr) {
self.visit_expr(ex)
}
fn visit_expr_post(&mut self, _ex: &'ast Expr) {} fn visit_expr_post(&mut self, _ex: &'ast Expr) {}
fn visit_ty(&mut self, t: &'ast Ty) { fn visit_ty(&mut self, t: &'ast Ty) {
walk_ty(self, t) walk_ty(self, t)
@ -244,14 +249,12 @@ pub trait Visitor<'ast>: Sized {
#[macro_export] #[macro_export]
macro_rules! walk_list { macro_rules! walk_list {
($visitor: expr, $method: ident, $list: expr) => { ($visitor: expr, $method: ident, $list: expr $(, $($extra_args: expr),* )?) => {
{
#[cfg_attr(not(bootstrap), allow(for_loops_over_fallibles))]
for elem in $list { for elem in $list {
$visitor.$method(elem) $visitor.$method(elem $(, $($extra_args,)* )?)
} }
};
($visitor: expr, $method: ident, $list: expr, $($extra_args: expr),*) => {
for elem in $list {
$visitor.$method(elem, $($extra_args,)*)
} }
} }
} }
@ -685,7 +688,7 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem,
let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, generics, body.as_deref()); let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, generics, body.as_deref());
visitor.visit_fn(kind, span, id); visitor.visit_fn(kind, span, id);
} }
AssocItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => { AssocItemKind::Type(box TyAlias { generics, bounds, ty, .. }) => {
visitor.visit_generics(generics); visitor.visit_generics(generics);
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
walk_list!(visitor, visit_ty, ty); walk_list!(visitor, visit_ty, ty);
@ -795,8 +798,9 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
visitor.visit_expr(callee_expression); visitor.visit_expr(callee_expression);
walk_list!(visitor, visit_expr, arguments); walk_list!(visitor, visit_expr, arguments);
} }
ExprKind::MethodCall(ref segment, ref arguments, _span) => { ExprKind::MethodCall(ref segment, ref receiver, ref arguments, _span) => {
visitor.visit_path_segment(segment); visitor.visit_path_segment(segment);
visitor.visit_expr(receiver);
walk_list!(visitor, visit_expr, arguments); walk_list!(visitor, visit_expr, arguments);
} }
ExprKind::Binary(_, ref left_expression, ref right_expression) => { ExprKind::Binary(_, ref left_expression, ref right_expression) => {

View File

@ -192,26 +192,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
} }
InlineAsmOperand::Sym { ref sym } => { InlineAsmOperand::Sym { ref sym } => {
if !self.tcx.features().asm_sym {
feature_err(
&sess.parse_sess,
sym::asm_sym,
*op_sp,
"sym operands for inline assembly are unstable",
)
.emit();
}
let static_def_id = self let static_def_id = self
.resolver .resolver
.get_partial_res(sym.id) .get_partial_res(sym.id)
.filter(|res| res.unresolved_segments() == 0) .and_then(|res| res.full_res())
.and_then(|res| { .and_then(|res| match res {
if let Res::Def(DefKind::Static(_), def_id) = res.base_res() { Res::Def(DefKind::Static(_), def_id) => Some(def_id),
Some(def_id) _ => None,
} else {
None
}
}); });
if let Some(def_id) = static_def_id { if let Some(def_id) = static_def_id {
@ -237,7 +224,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Wrap the expression in an AnonConst. // Wrap the expression in an AnonConst.
let parent_def_id = self.current_hir_id_owner; let parent_def_id = self.current_hir_id_owner;
let node_id = self.next_node_id(); let node_id = self.next_node_id();
self.create_def(parent_def_id, node_id, DefPathData::AnonConst); self.create_def(parent_def_id.def_id, node_id, DefPathData::AnonConst);
let anon_const = AnonConst { id: node_id, value: P(expr) }; let anon_const = AnonConst { id: node_id, value: P(expr) };
hir::InlineAsmOperand::SymFn { hir::InlineAsmOperand::SymFn {
anon_const: self.lower_anon_const(&anon_const), anon_const: self.lower_anon_const(&anon_const),

View File

@ -1,9 +1,9 @@
use rustc_errors::{fluent, AddSubdiagnostic, Applicability, Diagnostic, DiagnosticArgFromDisplay}; use rustc_errors::DiagnosticArgFromDisplay;
use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic}; use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::{symbol::Ident, Span, Symbol}; use rustc_span::{symbol::Ident, Span, Symbol};
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering::generic_type_with_parentheses, code = "E0214")] #[diag(ast_lowering_generic_type_with_parentheses, code = "E0214")]
pub struct GenericTypeWithParentheses { pub struct GenericTypeWithParentheses {
#[primary_span] #[primary_span]
#[label] #[label]
@ -12,35 +12,42 @@ pub struct GenericTypeWithParentheses {
pub sub: Option<UseAngleBrackets>, pub sub: Option<UseAngleBrackets>,
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy, Subdiagnostic)]
#[multipart_suggestion(ast_lowering_use_angle_brackets, applicability = "maybe-incorrect")]
pub struct UseAngleBrackets { pub struct UseAngleBrackets {
#[suggestion_part(code = "<")]
pub open_param: Span, pub open_param: Span,
#[suggestion_part(code = ">")]
pub close_param: Span, pub close_param: Span,
} }
impl AddSubdiagnostic for UseAngleBrackets { #[derive(Diagnostic)]
fn add_to_diagnostic(self, diag: &mut Diagnostic) { #[diag(ast_lowering_invalid_abi, code = "E0703")]
diag.multipart_suggestion( #[note]
fluent::ast_lowering::use_angle_brackets,
vec![(self.open_param, String::from("<")), (self.close_param, String::from(">"))],
Applicability::MaybeIncorrect,
);
}
}
#[derive(SessionDiagnostic)]
#[help]
#[diag(ast_lowering::invalid_abi, code = "E0703")]
pub struct InvalidAbi { pub struct InvalidAbi {
#[primary_span] #[primary_span]
#[label] #[label]
pub span: Span, pub span: Span,
pub abi: Symbol, pub abi: Symbol,
pub valid_abis: String, pub command: String,
#[subdiagnostic]
pub suggestion: Option<InvalidAbiSuggestion>,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Subdiagnostic)]
#[diag(ast_lowering::assoc_ty_parentheses)] #[suggestion(
ast_lowering_invalid_abi_suggestion,
code = "{suggestion}",
applicability = "maybe-incorrect"
)]
pub struct InvalidAbiSuggestion {
#[primary_span]
pub span: Span,
pub suggestion: String,
}
#[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering_assoc_ty_parentheses)]
pub struct AssocTyParentheses { pub struct AssocTyParentheses {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
@ -48,123 +55,116 @@ pub struct AssocTyParentheses {
pub sub: AssocTyParenthesesSub, pub sub: AssocTyParenthesesSub,
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy, Subdiagnostic)]
pub enum AssocTyParenthesesSub { pub enum AssocTyParenthesesSub {
Empty { parentheses_span: Span }, #[multipart_suggestion(ast_lowering_remove_parentheses)]
NotEmpty { open_param: Span, close_param: Span }, Empty {
#[suggestion_part(code = "")]
parentheses_span: Span,
},
#[multipart_suggestion(ast_lowering_use_angle_brackets)]
NotEmpty {
#[suggestion_part(code = "<")]
open_param: Span,
#[suggestion_part(code = ">")]
close_param: Span,
},
} }
impl AddSubdiagnostic for AssocTyParenthesesSub { #[derive(Diagnostic)]
fn add_to_diagnostic(self, diag: &mut Diagnostic) { #[diag(ast_lowering_misplaced_impl_trait, code = "E0562")]
match self {
Self::Empty { parentheses_span } => diag.multipart_suggestion(
fluent::ast_lowering::remove_parentheses,
vec![(parentheses_span, String::new())],
Applicability::MaybeIncorrect,
),
Self::NotEmpty { open_param, close_param } => diag.multipart_suggestion(
fluent::ast_lowering::use_angle_brackets,
vec![(open_param, String::from("<")), (close_param, String::from(">"))],
Applicability::MaybeIncorrect,
),
};
}
}
#[derive(SessionDiagnostic)]
#[diag(ast_lowering::misplaced_impl_trait, code = "E0562")]
pub struct MisplacedImplTrait<'a> { pub struct MisplacedImplTrait<'a> {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
pub position: DiagnosticArgFromDisplay<'a>, pub position: DiagnosticArgFromDisplay<'a>,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering::rustc_box_attribute_error)] #[diag(ast_lowering_rustc_box_attribute_error)]
pub struct RustcBoxAttributeError { pub struct RustcBoxAttributeError {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering::underscore_expr_lhs_assign)] #[diag(ast_lowering_underscore_expr_lhs_assign)]
pub struct UnderscoreExprLhsAssign { pub struct UnderscoreExprLhsAssign {
#[primary_span] #[primary_span]
#[label] #[label]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering::base_expression_double_dot)] #[diag(ast_lowering_base_expression_double_dot)]
pub struct BaseExpressionDoubleDot { pub struct BaseExpressionDoubleDot {
#[primary_span] #[primary_span]
#[label] #[label]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering::await_only_in_async_fn_and_blocks, code = "E0728")] #[diag(ast_lowering_await_only_in_async_fn_and_blocks, code = "E0728")]
pub struct AwaitOnlyInAsyncFnAndBlocks { pub struct AwaitOnlyInAsyncFnAndBlocks {
#[primary_span] #[primary_span]
#[label] #[label]
pub dot_await_span: Span, pub dot_await_span: Span,
#[label(ast_lowering::this_not_async)] #[label(ast_lowering_this_not_async)]
pub item_span: Option<Span>, pub item_span: Option<Span>,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering::generator_too_many_parameters, code = "E0628")] #[diag(ast_lowering_generator_too_many_parameters, code = "E0628")]
pub struct GeneratorTooManyParameters { pub struct GeneratorTooManyParameters {
#[primary_span] #[primary_span]
pub fn_decl_span: Span, pub fn_decl_span: Span,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering::closure_cannot_be_static, code = "E0697")] #[diag(ast_lowering_closure_cannot_be_static, code = "E0697")]
pub struct ClosureCannotBeStatic { pub struct ClosureCannotBeStatic {
#[primary_span] #[primary_span]
pub fn_decl_span: Span, pub fn_decl_span: Span,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[help] #[help]
#[diag(ast_lowering::async_non_move_closure_not_supported, code = "E0708")] #[diag(ast_lowering_async_non_move_closure_not_supported, code = "E0708")]
pub struct AsyncNonMoveClosureNotSupported { pub struct AsyncNonMoveClosureNotSupported {
#[primary_span] #[primary_span]
pub fn_decl_span: Span, pub fn_decl_span: Span,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering::functional_record_update_destructuring_assignment)] #[diag(ast_lowering_functional_record_update_destructuring_assignment)]
pub struct FunctionalRecordUpdateDestructuringAssignemnt { pub struct FunctionalRecordUpdateDestructuringAssignemnt {
#[primary_span] #[primary_span]
#[suggestion(code = "", applicability = "machine-applicable")] #[suggestion(code = "", applicability = "machine-applicable")]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering::async_generators_not_supported, code = "E0727")] #[diag(ast_lowering_async_generators_not_supported, code = "E0727")]
pub struct AsyncGeneratorsNotSupported { pub struct AsyncGeneratorsNotSupported {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering::inline_asm_unsupported_target, code = "E0472")] #[diag(ast_lowering_inline_asm_unsupported_target, code = "E0472")]
pub struct InlineAsmUnsupportedTarget { pub struct InlineAsmUnsupportedTarget {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering::att_syntax_only_x86)] #[diag(ast_lowering_att_syntax_only_x86)]
pub struct AttSyntaxOnlyX86 { pub struct AttSyntaxOnlyX86 {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering::abi_specified_multiple_times)] #[diag(ast_lowering_abi_specified_multiple_times)]
pub struct AbiSpecifiedMultipleTimes { pub struct AbiSpecifiedMultipleTimes {
#[primary_span] #[primary_span]
pub abi_span: Span, pub abi_span: Span,
@ -175,24 +175,24 @@ pub struct AbiSpecifiedMultipleTimes {
pub equivalent: Option<()>, pub equivalent: Option<()>,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering::clobber_abi_not_supported)] #[diag(ast_lowering_clobber_abi_not_supported)]
pub struct ClobberAbiNotSupported { pub struct ClobberAbiNotSupported {
#[primary_span] #[primary_span]
pub abi_span: Span, pub abi_span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[note] #[note]
#[diag(ast_lowering::invalid_abi_clobber_abi)] #[diag(ast_lowering_invalid_abi_clobber_abi)]
pub struct InvalidAbiClobberAbi { pub struct InvalidAbiClobberAbi {
#[primary_span] #[primary_span]
pub abi_span: Span, pub abi_span: Span,
pub supported_abis: String, pub supported_abis: String,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering::invalid_register)] #[diag(ast_lowering_invalid_register)]
pub struct InvalidRegister<'a> { pub struct InvalidRegister<'a> {
#[primary_span] #[primary_span]
pub op_span: Span, pub op_span: Span,
@ -200,8 +200,8 @@ pub struct InvalidRegister<'a> {
pub error: &'a str, pub error: &'a str,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering::invalid_register_class)] #[diag(ast_lowering_invalid_register_class)]
pub struct InvalidRegisterClass<'a> { pub struct InvalidRegisterClass<'a> {
#[primary_span] #[primary_span]
pub op_span: Span, pub op_span: Span,
@ -209,61 +209,61 @@ pub struct InvalidRegisterClass<'a> {
pub error: &'a str, pub error: &'a str,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(ast_lowering::invalid_asm_template_modifier_reg_class)] #[diag(ast_lowering_invalid_asm_template_modifier_reg_class)]
pub struct InvalidAsmTemplateModifierRegClass { pub struct InvalidAsmTemplateModifierRegClass {
#[primary_span] #[primary_span]
#[label(ast_lowering::template_modifier)] #[label(ast_lowering_template_modifier)]
pub placeholder_span: Span, pub placeholder_span: Span,
#[label(ast_lowering::argument)] #[label(ast_lowering_argument)]
pub op_span: Span, pub op_span: Span,
#[subdiagnostic] #[subdiagnostic]
pub sub: InvalidAsmTemplateModifierRegClassSub, pub sub: InvalidAsmTemplateModifierRegClassSub,
} }
#[derive(SessionSubdiagnostic)] #[derive(Subdiagnostic)]
pub enum InvalidAsmTemplateModifierRegClassSub { pub enum InvalidAsmTemplateModifierRegClassSub {
#[note(ast_lowering::support_modifiers)] #[note(ast_lowering_support_modifiers)]
SupportModifier { class_name: Symbol, modifiers: String }, SupportModifier { class_name: Symbol, modifiers: String },
#[note(ast_lowering::does_not_support_modifiers)] #[note(ast_lowering_does_not_support_modifiers)]
DoesNotSupportModifier { class_name: Symbol }, DoesNotSupportModifier { class_name: Symbol },
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering::invalid_asm_template_modifier_const)] #[diag(ast_lowering_invalid_asm_template_modifier_const)]
pub struct InvalidAsmTemplateModifierConst { pub struct InvalidAsmTemplateModifierConst {
#[primary_span] #[primary_span]
#[label(ast_lowering::template_modifier)] #[label(ast_lowering_template_modifier)]
pub placeholder_span: Span, pub placeholder_span: Span,
#[label(ast_lowering::argument)] #[label(ast_lowering_argument)]
pub op_span: Span, pub op_span: Span,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering::invalid_asm_template_modifier_sym)] #[diag(ast_lowering_invalid_asm_template_modifier_sym)]
pub struct InvalidAsmTemplateModifierSym { pub struct InvalidAsmTemplateModifierSym {
#[primary_span] #[primary_span]
#[label(ast_lowering::template_modifier)] #[label(ast_lowering_template_modifier)]
pub placeholder_span: Span, pub placeholder_span: Span,
#[label(ast_lowering::argument)] #[label(ast_lowering_argument)]
pub op_span: Span, pub op_span: Span,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering::register_class_only_clobber)] #[diag(ast_lowering_register_class_only_clobber)]
pub struct RegisterClassOnlyClobber { pub struct RegisterClassOnlyClobber {
#[primary_span] #[primary_span]
pub op_span: Span, pub op_span: Span,
pub reg_class_name: Symbol, pub reg_class_name: Symbol,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering::register_conflict)] #[diag(ast_lowering_register_conflict)]
pub struct RegisterConflict<'a> { pub struct RegisterConflict<'a> {
#[primary_span] #[primary_span]
#[label(ast_lowering::register1)] #[label(ast_lowering_register1)]
pub op_span1: Span, pub op_span1: Span,
#[label(ast_lowering::register2)] #[label(ast_lowering_register2)]
pub op_span2: Span, pub op_span2: Span,
pub reg1_name: &'a str, pub reg1_name: &'a str,
pub reg2_name: &'a str, pub reg2_name: &'a str,
@ -271,14 +271,14 @@ pub struct RegisterConflict<'a> {
pub in_out: Option<Span>, pub in_out: Option<Span>,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[help] #[help]
#[diag(ast_lowering::sub_tuple_binding)] #[diag(ast_lowering_sub_tuple_binding)]
pub struct SubTupleBinding<'a> { pub struct SubTupleBinding<'a> {
#[primary_span] #[primary_span]
#[label] #[label]
#[suggestion_verbose( #[suggestion_verbose(
ast_lowering::sub_tuple_binding_suggestion, ast_lowering_sub_tuple_binding_suggestion,
code = "..", code = "..",
applicability = "maybe-incorrect" applicability = "maybe-incorrect"
)] )]
@ -288,57 +288,57 @@ pub struct SubTupleBinding<'a> {
pub ctx: &'a str, pub ctx: &'a str,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering::extra_double_dot)] #[diag(ast_lowering_extra_double_dot)]
pub struct ExtraDoubleDot<'a> { pub struct ExtraDoubleDot<'a> {
#[primary_span] #[primary_span]
#[label] #[label]
pub span: Span, pub span: Span,
#[label(ast_lowering::previously_used_here)] #[label(ast_lowering_previously_used_here)]
pub prev_span: Span, pub prev_span: Span,
pub ctx: &'a str, pub ctx: &'a str,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[note] #[note]
#[diag(ast_lowering::misplaced_double_dot)] #[diag(ast_lowering_misplaced_double_dot)]
pub struct MisplacedDoubleDot { pub struct MisplacedDoubleDot {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering::misplaced_relax_trait_bound)] #[diag(ast_lowering_misplaced_relax_trait_bound)]
pub struct MisplacedRelaxTraitBound { pub struct MisplacedRelaxTraitBound {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering::not_supported_for_lifetime_binder_async_closure)] #[diag(ast_lowering_not_supported_for_lifetime_binder_async_closure)]
pub struct NotSupportedForLifetimeBinderAsyncClosure { pub struct NotSupportedForLifetimeBinderAsyncClosure {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering::arbitrary_expression_in_pattern)] #[diag(ast_lowering_arbitrary_expression_in_pattern)]
pub struct ArbitraryExpressionInPattern { pub struct ArbitraryExpressionInPattern {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering::inclusive_range_with_no_end)] #[diag(ast_lowering_inclusive_range_with_no_end)]
pub struct InclusiveRangeWithNoEnd { pub struct InclusiveRangeWithNoEnd {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic, Clone, Copy)] #[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering::trait_fn_async, code = "E0706")] #[diag(ast_lowering_trait_fn_async, code = "E0706")]
#[note] #[note]
#[note(ast_lowering::note2)] #[note(note2)]
pub struct TraitFnAsync { pub struct TraitFnAsync {
#[primary_span] #[primary_span]
pub fn_span: Span, pub fn_span: Span,

View File

@ -60,7 +60,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::ExprKind::Call(f, self.lower_exprs(args)) hir::ExprKind::Call(f, self.lower_exprs(args))
} }
} }
ExprKind::MethodCall(ref seg, ref args, span) => { ExprKind::MethodCall(ref seg, ref receiver, ref args, span) => {
let hir_seg = self.arena.alloc(self.lower_path_segment( let hir_seg = self.arena.alloc(self.lower_path_segment(
e.span, e.span,
seg, seg,
@ -68,9 +68,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
ParenthesizedGenericArgs::Err, ParenthesizedGenericArgs::Err,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path), &ImplTraitContext::Disallowed(ImplTraitPosition::Path),
)); ));
let receiver = self.lower_expr(&args[0]); let receiver = self.lower_expr(receiver);
let args = let args =
self.arena.alloc_from_iter(args[1..].iter().map(|x| self.lower_expr_mut(x))); self.arena.alloc_from_iter(args.iter().map(|x| self.lower_expr_mut(x)));
hir::ExprKind::MethodCall(hir_seg, receiver, args, self.lower_span(span)) hir::ExprKind::MethodCall(hir_seg, receiver, args, self.lower_span(span))
} }
ExprKind::Binary(binop, ref lhs, ref rhs) => { ExprKind::Binary(binop, ref lhs, ref rhs) => {
@ -359,7 +359,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let node_id = self.next_node_id(); let node_id = self.next_node_id();
// Add a definition for the in-band const def. // Add a definition for the in-band const def.
self.create_def(parent_def_id, node_id, DefPathData::AnonConst); self.create_def(parent_def_id.def_id, node_id, DefPathData::AnonConst);
let anon_const = AnonConst { id: node_id, value: arg }; let anon_const = AnonConst { id: node_id, value: arg };
generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const))); generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const)));
@ -387,34 +387,60 @@ impl<'hir> LoweringContext<'_, 'hir> {
then: &Block, then: &Block,
else_opt: Option<&Expr>, else_opt: Option<&Expr>,
) -> hir::ExprKind<'hir> { ) -> hir::ExprKind<'hir> {
let lowered_cond = self.lower_expr(cond); let lowered_cond = self.lower_cond(cond);
let new_cond = self.manage_let_cond(lowered_cond);
let then_expr = self.lower_block_expr(then); let then_expr = self.lower_block_expr(then);
if let Some(rslt) = else_opt { if let Some(rslt) = else_opt {
hir::ExprKind::If(new_cond, self.arena.alloc(then_expr), Some(self.lower_expr(rslt))) hir::ExprKind::If(
lowered_cond,
self.arena.alloc(then_expr),
Some(self.lower_expr(rslt)),
)
} else { } else {
hir::ExprKind::If(new_cond, self.arena.alloc(then_expr), None) hir::ExprKind::If(lowered_cond, self.arena.alloc(then_expr), None)
} }
} }
// If `cond` kind is `let`, returns `let`. Otherwise, wraps and returns `cond` // Lowers a condition (i.e. `cond` in `if cond` or `while cond`), wrapping it in a terminating scope
// in a temporary block. // so that temporaries created in the condition don't live beyond it.
fn manage_let_cond(&mut self, cond: &'hir hir::Expr<'hir>) -> &'hir hir::Expr<'hir> { fn lower_cond(&mut self, cond: &Expr) -> &'hir hir::Expr<'hir> {
fn has_let_expr<'hir>(expr: &'hir hir::Expr<'hir>) -> bool { fn has_let_expr(expr: &Expr) -> bool {
match expr.kind { match &expr.kind {
hir::ExprKind::Binary(_, lhs, rhs) => has_let_expr(lhs) || has_let_expr(rhs), ExprKind::Binary(_, lhs, rhs) => has_let_expr(lhs) || has_let_expr(rhs),
hir::ExprKind::Let(..) => true, ExprKind::Let(..) => true,
_ => false, _ => false,
} }
} }
if has_let_expr(cond) {
cond // We have to take special care for `let` exprs in the condition, e.g. in
} else { // `if let pat = val` or `if foo && let pat = val`, as we _do_ want `val` to live beyond the
// condition in this case.
//
// In order to mantain the drop behavior for the non `let` parts of the condition,
// we still wrap them in terminating scopes, e.g. `if foo && let pat = val` essentially
// gets transformed into `if { let _t = foo; _t } && let pat = val`
match &cond.kind {
ExprKind::Binary(op @ Spanned { node: ast::BinOpKind::And, .. }, lhs, rhs)
if has_let_expr(cond) =>
{
let op = self.lower_binop(*op);
let lhs = self.lower_cond(lhs);
let rhs = self.lower_cond(rhs);
self.arena.alloc(self.expr(
cond.span,
hir::ExprKind::Binary(op, lhs, rhs),
AttrVec::new(),
))
}
ExprKind::Let(..) => self.lower_expr(cond),
_ => {
let cond = self.lower_expr(cond);
let reason = DesugaringKind::CondTemporary; let reason = DesugaringKind::CondTemporary;
let span_block = self.mark_span_with_reason(reason, cond.span, None); let span_block = self.mark_span_with_reason(reason, cond.span, None);
self.expr_drop_temps(span_block, cond, AttrVec::new()) self.expr_drop_temps(span_block, cond, AttrVec::new())
} }
} }
}
// We desugar: `'label: while $cond $body` into: // We desugar: `'label: while $cond $body` into:
// //
@ -439,14 +465,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
body: &Block, body: &Block,
opt_label: Option<Label>, opt_label: Option<Label>,
) -> hir::ExprKind<'hir> { ) -> hir::ExprKind<'hir> {
let lowered_cond = self.with_loop_condition_scope(|t| t.lower_expr(cond)); let lowered_cond = self.with_loop_condition_scope(|t| t.lower_cond(cond));
let new_cond = self.manage_let_cond(lowered_cond);
let then = self.lower_block_expr(body); let then = self.lower_block_expr(body);
let expr_break = self.expr_break(span, AttrVec::new()); let expr_break = self.expr_break(span, AttrVec::new());
let stmt_break = self.stmt_expr(span, expr_break); let stmt_break = self.stmt_expr(span, expr_break);
let else_blk = self.block_all(span, arena_vec![self; stmt_break], None); let else_blk = self.block_all(span, arena_vec![self; stmt_break], None);
let else_expr = self.arena.alloc(self.expr_block(else_blk, AttrVec::new())); let else_expr = self.arena.alloc(self.expr_block(else_blk, AttrVec::new()));
let if_kind = hir::ExprKind::If(new_cond, self.arena.alloc(then), Some(else_expr)); let if_kind = hir::ExprKind::If(lowered_cond, self.arena.alloc(then), Some(else_expr));
let if_expr = self.expr(span, if_kind, AttrVec::new()); let if_expr = self.expr(span, if_kind, AttrVec::new());
let block = self.block_expr(self.arena.alloc(if_expr)); let block = self.block_expr(self.arena.alloc(if_expr));
let span = self.lower_span(span.with_hi(cond.span.hi())); let span = self.lower_span(span.with_hi(cond.span.hi()));
@ -1044,9 +1069,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
if let ExprKind::Path(qself, path) = &expr.kind { if let ExprKind::Path(qself, path) = &expr.kind {
// Does the path resolve to something disallowed in a tuple struct/variant pattern? // Does the path resolve to something disallowed in a tuple struct/variant pattern?
if let Some(partial_res) = self.resolver.get_partial_res(expr.id) { if let Some(partial_res) = self.resolver.get_partial_res(expr.id) {
if partial_res.unresolved_segments() == 0 if let Some(res) = partial_res.full_res() && !res.expected_in_tuple_struct_pat() {
&& !partial_res.base_res().expected_in_tuple_struct_pat()
{
return None; return None;
} }
} }
@ -1066,9 +1089,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
if let ExprKind::Path(qself, path) = &expr.kind { if let ExprKind::Path(qself, path) = &expr.kind {
// Does the path resolve to something disallowed in a unit struct/variant pattern? // Does the path resolve to something disallowed in a unit struct/variant pattern?
if let Some(partial_res) = self.resolver.get_partial_res(expr.id) { if let Some(partial_res) = self.resolver.get_partial_res(expr.id) {
if partial_res.unresolved_segments() == 0 if let Some(res) = partial_res.full_res() && !res.expected_in_unit_struct_pat() {
&& !partial_res.base_res().expected_in_unit_struct_pat()
{
return None; return None;
} }
} }
@ -1609,11 +1630,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
} }
/// Desugar `ExprKind::Yeet` from: `do yeet <expr>` into: /// Desugar `ExprKind::Yeet` from: `do yeet <expr>` into:
/// ```rust /// ```ignore(illustrative)
/// // If there is an enclosing `try {...}`: /// // If there is an enclosing `try {...}`:
/// break 'catch_target FromResidual::from_residual(Yeet(residual)), /// break 'catch_target FromResidual::from_residual(Yeet(residual));
/// // Otherwise: /// // Otherwise:
/// return FromResidual::from_residual(Yeet(residual)), /// return FromResidual::from_residual(Yeet(residual));
/// ``` /// ```
/// But to simplify this, there's a `from_yeet` lang item function which /// But to simplify this, there's a `from_yeet` lang item function which
/// handles the combined `FromResidual::from_residual(Yeet(residual))`. /// handles the combined `FromResidual::from_residual(Yeet(residual))`.

View File

@ -24,7 +24,7 @@ pub(super) struct NodeCollector<'a, 'hir> {
/// The parent of this node /// The parent of this node
parent_node: hir::ItemLocalId, parent_node: hir::ItemLocalId,
owner: LocalDefId, owner: OwnerId,
definitions: &'a definitions::Definitions, definitions: &'a definitions::Definitions,
} }
@ -81,9 +81,9 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?})", current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?})",
self.source_map.span_to_diagnostic_string(span), self.source_map.span_to_diagnostic_string(span),
node, node,
self.definitions.def_path(self.owner).to_string_no_crate_verbose(), self.definitions.def_path(self.owner.def_id).to_string_no_crate_verbose(),
self.owner, self.owner,
self.definitions.def_path(hir_id.owner).to_string_no_crate_verbose(), self.definitions.def_path(hir_id.owner.def_id).to_string_no_crate_verbose(),
hir_id.owner, hir_id.owner,
) )
} }
@ -112,19 +112,19 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
fn visit_nested_item(&mut self, item: ItemId) { fn visit_nested_item(&mut self, item: ItemId) {
debug!("visit_nested_item: {:?}", item); debug!("visit_nested_item: {:?}", item);
self.insert_nested(item.def_id); self.insert_nested(item.owner_id.def_id);
} }
fn visit_nested_trait_item(&mut self, item_id: TraitItemId) { fn visit_nested_trait_item(&mut self, item_id: TraitItemId) {
self.insert_nested(item_id.def_id); self.insert_nested(item_id.owner_id.def_id);
} }
fn visit_nested_impl_item(&mut self, item_id: ImplItemId) { fn visit_nested_impl_item(&mut self, item_id: ImplItemId) {
self.insert_nested(item_id.def_id); self.insert_nested(item_id.owner_id.def_id);
} }
fn visit_nested_foreign_item(&mut self, foreign_id: ForeignItemId) { fn visit_nested_foreign_item(&mut self, foreign_id: ForeignItemId) {
self.insert_nested(foreign_id.def_id); self.insert_nested(foreign_id.owner_id.def_id);
} }
fn visit_nested_body(&mut self, id: BodyId) { fn visit_nested_body(&mut self, id: BodyId) {
@ -143,7 +143,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
fn visit_item(&mut self, i: &'hir Item<'hir>) { fn visit_item(&mut self, i: &'hir Item<'hir>) {
debug_assert_eq!(i.def_id, self.owner); debug_assert_eq!(i.owner_id, self.owner);
self.with_parent(i.hir_id(), |this| { self.with_parent(i.hir_id(), |this| {
if let ItemKind::Struct(ref struct_def, _) = i.kind { if let ItemKind::Struct(ref struct_def, _) = i.kind {
// If this is a tuple or unit-like struct, register the constructor. // If this is a tuple or unit-like struct, register the constructor.
@ -157,7 +157,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
fn visit_foreign_item(&mut self, fi: &'hir ForeignItem<'hir>) { fn visit_foreign_item(&mut self, fi: &'hir ForeignItem<'hir>) {
debug_assert_eq!(fi.def_id, self.owner); debug_assert_eq!(fi.owner_id, self.owner);
self.with_parent(fi.hir_id(), |this| { self.with_parent(fi.hir_id(), |this| {
intravisit::walk_foreign_item(this, fi); intravisit::walk_foreign_item(this, fi);
}); });
@ -176,7 +176,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) { fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) {
debug_assert_eq!(ti.def_id, self.owner); debug_assert_eq!(ti.owner_id, self.owner);
self.with_parent(ti.hir_id(), |this| { self.with_parent(ti.hir_id(), |this| {
intravisit::walk_trait_item(this, ti); intravisit::walk_trait_item(this, ti);
}); });
@ -184,7 +184,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) { fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) {
debug_assert_eq!(ii.def_id, self.owner); debug_assert_eq!(ii.owner_id, self.owner);
self.with_parent(ii.hir_id(), |this| { self.with_parent(ii.hir_id(), |this| {
intravisit::walk_impl_item(this, ii); intravisit::walk_impl_item(this, ii);
}); });

View File

@ -1,4 +1,4 @@
use super::errors::{InvalidAbi, MisplacedRelaxTraitBound}; use super::errors::{InvalidAbi, InvalidAbiSuggestion, MisplacedRelaxTraitBound};
use super::ResolverAstLoweringExt; use super::ResolverAstLoweringExt;
use super::{Arena, AstOwner, ImplTraitContext, ImplTraitPosition}; use super::{Arena, AstOwner, ImplTraitContext, ImplTraitPosition};
use super::{FnDeclKind, LoweringContext, ParamMode}; use super::{FnDeclKind, LoweringContext, ParamMode};
@ -14,9 +14,10 @@ use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
use rustc_hir::PredicateOrigin; use rustc_hir::PredicateOrigin;
use rustc_index::vec::{Idx, IndexVec}; use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::ty::{DefIdTree, ResolverAstLowering, TyCtxt}; use rustc_middle::ty::{DefIdTree, ResolverAstLowering, TyCtxt};
use rustc_span::lev_distance::find_best_match_for_name;
use rustc_span::source_map::DesugaringKind; use rustc_span::source_map::DesugaringKind;
use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::Span; use rustc_span::{Span, Symbol};
use rustc_target::spec::abi; use rustc_target::spec::abi;
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
@ -67,7 +68,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
bodies: Vec::new(), bodies: Vec::new(),
attrs: SortedMap::default(), attrs: SortedMap::default(),
children: FxHashMap::default(), children: FxHashMap::default(),
current_hir_id_owner: CRATE_DEF_ID, current_hir_id_owner: hir::CRATE_OWNER_ID,
item_local_id_counter: hir::ItemLocalId::new(0), item_local_id_counter: hir::ItemLocalId::new(0),
node_id_to_local_id: Default::default(), node_id_to_local_id: Default::default(),
local_id_to_def_id: SortedMap::new(), local_id_to_def_id: SortedMap::new(),
@ -176,7 +177,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
} }
pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> { pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> {
let mut node_ids = smallvec![hir::ItemId { def_id: self.local_def_id(i.id) }]; let mut node_ids =
smallvec![hir::ItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }];
if let ItemKind::Use(ref use_tree) = &i.kind { if let ItemKind::Use(ref use_tree) = &i.kind {
self.lower_item_id_use_tree(use_tree, i.id, &mut node_ids); self.lower_item_id_use_tree(use_tree, i.id, &mut node_ids);
} }
@ -192,7 +194,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
match tree.kind { match tree.kind {
UseTreeKind::Nested(ref nested_vec) => { UseTreeKind::Nested(ref nested_vec) => {
for &(ref nested, id) in nested_vec { for &(ref nested, id) in nested_vec {
vec.push(hir::ItemId { def_id: self.local_def_id(id) }); vec.push(hir::ItemId {
owner_id: hir::OwnerId { def_id: self.local_def_id(id) },
});
self.lower_item_id_use_tree(nested, id, vec); self.lower_item_id_use_tree(nested, id, vec);
} }
} }
@ -201,7 +205,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
for (_, &id) in for (_, &id) in
iter::zip(self.expect_full_res_from_use(base_id).skip(1), &[id1, id2]) iter::zip(self.expect_full_res_from_use(base_id).skip(1), &[id1, id2])
{ {
vec.push(hir::ItemId { def_id: self.local_def_id(id) }); vec.push(hir::ItemId {
owner_id: hir::OwnerId { def_id: self.local_def_id(id) },
});
} }
} }
} }
@ -214,7 +220,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let attrs = self.lower_attrs(hir_id, &i.attrs); let attrs = self.lower_attrs(hir_id, &i.attrs);
let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, vis_span, &i.kind); let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, vis_span, &i.kind);
let item = hir::Item { let item = hir::Item {
def_id: hir_id.expect_owner(), owner_id: hir_id.expect_owner(),
ident: self.lower_ident(ident), ident: self.lower_ident(ident),
kind, kind,
vis_span, vis_span,
@ -539,7 +545,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
let ident = *ident; let ident = *ident;
let mut path = path.clone(); let mut path = path.clone();
for seg in &mut path.segments { for seg in &mut path.segments {
seg.id = self.next_node_id(); // Give the cloned segment the same resolution information
// as the old one (this is needed for stability checking).
let new_id = self.next_node_id();
self.resolver.clone_res(seg.id, new_id);
seg.id = new_id;
} }
let span = path.span; let span = path.span;
@ -552,7 +562,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
} }
let item = hir::Item { let item = hir::Item {
def_id: new_id, owner_id: hir::OwnerId { def_id: new_id },
ident: this.lower_ident(ident), ident: this.lower_ident(ident),
kind, kind,
vis_span, vis_span,
@ -608,7 +618,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
// Give the segments new node-ids since they are being cloned. // Give the segments new node-ids since they are being cloned.
for seg in &mut prefix.segments { for seg in &mut prefix.segments {
seg.id = self.next_node_id(); // Give the cloned segment the same resolution information
// as the old one (this is needed for stability checking).
let new_id = self.next_node_id();
self.resolver.clone_res(seg.id, new_id);
seg.id = new_id;
} }
// Each `use` import is an item and thus are owners of the // Each `use` import is an item and thus are owners of the
@ -626,7 +640,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
} }
let item = hir::Item { let item = hir::Item {
def_id: new_hir_id, owner_id: hir::OwnerId { def_id: new_hir_id },
ident: this.lower_ident(ident), ident: this.lower_ident(ident),
kind, kind,
vis_span, vis_span,
@ -646,10 +660,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> { fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> {
let hir_id = self.lower_node_id(i.id); let hir_id = self.lower_node_id(i.id);
let def_id = hir_id.expect_owner(); let owner_id = hir_id.expect_owner();
self.lower_attrs(hir_id, &i.attrs); self.lower_attrs(hir_id, &i.attrs);
let item = hir::ForeignItem { let item = hir::ForeignItem {
def_id, owner_id,
ident: self.lower_ident(i.ident), ident: self.lower_ident(i.ident),
kind: match i.kind { kind: match i.kind {
ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => { ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => {
@ -688,7 +702,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef { fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef {
hir::ForeignItemRef { hir::ForeignItemRef {
id: hir::ForeignItemId { def_id: self.local_def_id(i.id) }, id: hir::ForeignItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } },
ident: self.lower_ident(i.ident), ident: self.lower_ident(i.ident),
span: self.lower_span(i.span), span: self.lower_span(i.span),
} }
@ -798,7 +812,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
); );
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true) (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true)
} }
AssocItemKind::TyAlias(box TyAlias { AssocItemKind::Type(box TyAlias {
ref generics, ref generics,
where_clauses, where_clauses,
ref bounds, ref bounds,
@ -831,7 +845,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_attrs(hir_id, &i.attrs); self.lower_attrs(hir_id, &i.attrs);
let item = hir::TraitItem { let item = hir::TraitItem {
def_id: trait_item_def_id, owner_id: trait_item_def_id,
ident: self.lower_ident(i.ident), ident: self.lower_ident(i.ident),
generics, generics,
kind, kind,
@ -844,13 +858,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef { fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
let kind = match &i.kind { let kind = match &i.kind {
AssocItemKind::Const(..) => hir::AssocItemKind::Const, AssocItemKind::Const(..) => hir::AssocItemKind::Const,
AssocItemKind::TyAlias(..) => hir::AssocItemKind::Type, AssocItemKind::Type(..) => hir::AssocItemKind::Type,
AssocItemKind::Fn(box Fn { sig, .. }) => { AssocItemKind::Fn(box Fn { sig, .. }) => {
hir::AssocItemKind::Fn { has_self: sig.decl.has_self() } hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
} }
AssocItemKind::MacCall(..) => unimplemented!(), AssocItemKind::MacCall(..) => unimplemented!(),
}; };
let id = hir::TraitItemId { def_id: self.local_def_id(i.id) }; let id = hir::TraitItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } };
hir::TraitItemRef { hir::TraitItemRef {
id, id,
ident: self.lower_ident(i.ident), ident: self.lower_ident(i.ident),
@ -892,7 +906,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
(generics, hir::ImplItemKind::Fn(sig, body_id)) (generics, hir::ImplItemKind::Fn(sig, body_id))
} }
AssocItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => { AssocItemKind::Type(box TyAlias { generics, where_clauses, ty, .. }) => {
let mut generics = generics.clone(); let mut generics = generics.clone();
add_ty_alias_where_clause(&mut generics, *where_clauses, false); add_ty_alias_where_clause(&mut generics, *where_clauses, false);
self.lower_generics( self.lower_generics(
@ -902,11 +916,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|this| match ty { |this| match ty {
None => { None => {
let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err)); let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err));
hir::ImplItemKind::TyAlias(ty) hir::ImplItemKind::Type(ty)
} }
Some(ty) => { Some(ty) => {
let ty = this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy); let ty = this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy);
hir::ImplItemKind::TyAlias(ty) hir::ImplItemKind::Type(ty)
} }
}, },
) )
@ -917,7 +931,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let hir_id = self.lower_node_id(i.id); let hir_id = self.lower_node_id(i.id);
self.lower_attrs(hir_id, &i.attrs); self.lower_attrs(hir_id, &i.attrs);
let item = hir::ImplItem { let item = hir::ImplItem {
def_id: hir_id.expect_owner(), owner_id: hir_id.expect_owner(),
ident: self.lower_ident(i.ident), ident: self.lower_ident(i.ident),
generics, generics,
kind, kind,
@ -930,18 +944,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef { fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
hir::ImplItemRef { hir::ImplItemRef {
id: hir::ImplItemId { def_id: self.local_def_id(i.id) }, id: hir::ImplItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } },
ident: self.lower_ident(i.ident), ident: self.lower_ident(i.ident),
span: self.lower_span(i.span), span: self.lower_span(i.span),
kind: match &i.kind { kind: match &i.kind {
AssocItemKind::Const(..) => hir::AssocItemKind::Const, AssocItemKind::Const(..) => hir::AssocItemKind::Const,
AssocItemKind::TyAlias(..) => hir::AssocItemKind::Type, AssocItemKind::Type(..) => hir::AssocItemKind::Type,
AssocItemKind::Fn(box Fn { sig, .. }) => { AssocItemKind::Fn(box Fn { sig, .. }) => {
hir::AssocItemKind::Fn { has_self: sig.decl.has_self() } hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
} }
AssocItemKind::MacCall(..) => unimplemented!(), AssocItemKind::MacCall(..) => unimplemented!(),
}, },
trait_item_def_id: self.resolver.get_partial_res(i.id).map(|r| r.base_res().def_id()), trait_item_def_id: self
.resolver
.get_partial_res(i.id)
.map(|r| r.expect_full_res().def_id()),
} }
} }
@ -1049,9 +1066,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
asyncness: Async, asyncness: Async,
body: Option<&Block>, body: Option<&Block>,
) -> hir::BodyId { ) -> hir::BodyId {
let closure_id = match asyncness { let (closure_id, body) = match (asyncness, body) {
Async::Yes { closure_id, .. } => closure_id, (Async::Yes { closure_id, .. }, Some(body)) => (closure_id, body),
Async::No => return self.lower_fn_body_block(span, decl, body), _ => return self.lower_fn_body_block(span, decl, body),
}; };
self.lower_body(|this| { self.lower_body(|this| {
@ -1193,16 +1210,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
parameters.push(new_parameter); parameters.push(new_parameter);
} }
let body_span = body.map_or(span, |b| b.span);
let async_expr = this.make_async_expr( let async_expr = this.make_async_expr(
CaptureBy::Value, CaptureBy::Value,
closure_id, closure_id,
None, None,
body_span, body.span,
hir::AsyncGeneratorKind::Fn, hir::AsyncGeneratorKind::Fn,
|this| { |this| {
// Create a block from the user's function body: // Create a block from the user's function body:
let user_body = this.lower_block_expr_opt(body_span, body); let user_body = this.lower_block_expr(body);
// Transform into `drop-temps { <user-body> }`, an expression: // Transform into `drop-temps { <user-body> }`, an expression:
let desugared_span = let desugared_span =
@ -1234,7 +1250,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
( (
this.arena.alloc_from_iter(parameters), this.arena.alloc_from_iter(parameters),
this.expr(body_span, async_expr, AttrVec::new()), this.expr(body.span, async_expr, AttrVec::new()),
) )
}) })
} }
@ -1280,10 +1296,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
} }
fn error_on_invalid_abi(&self, abi: StrLit) { fn error_on_invalid_abi(&self, abi: StrLit) {
let abi_names = abi::enabled_names(self.tcx.features(), abi.span)
.iter()
.map(|s| Symbol::intern(s))
.collect::<Vec<_>>();
let suggested_name = find_best_match_for_name(&abi_names, abi.symbol_unescaped, None);
self.tcx.sess.emit_err(InvalidAbi { self.tcx.sess.emit_err(InvalidAbi {
abi: abi.symbol_unescaped,
span: abi.span, span: abi.span,
abi: abi.symbol, suggestion: suggested_name.map(|suggested_name| InvalidAbiSuggestion {
valid_abis: abi::all_names().join(", "), span: abi.span,
suggestion: format!("\"{suggested_name}\""),
}),
command: "rustc --print=calling-conventions".to_string(),
}); });
} }
@ -1335,9 +1360,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
match self match self
.resolver .resolver
.get_partial_res(bound_pred.bounded_ty.id) .get_partial_res(bound_pred.bounded_ty.id)
.map(|d| (d.base_res(), d.unresolved_segments())) .and_then(|r| r.full_res())
{ {
Some((Res::Def(DefKind::TyParam, def_id), 0)) Some(Res::Def(DefKind::TyParam, def_id))
if bound_pred.bound_generic_params.is_empty() => if bound_pred.bound_generic_params.is_empty() =>
{ {
generics generics
@ -1464,6 +1489,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let bounded_ty = let bounded_ty =
self.ty_path(ty_id, param_span, hir::QPath::Resolved(None, ty_path)); self.ty_path(ty_id, param_span, hir::QPath::Resolved(None, ty_path));
Some(hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { Some(hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
hir_id: self.next_id(),
bounded_ty: self.arena.alloc(bounded_ty), bounded_ty: self.arena.alloc(bounded_ty),
bounds, bounds,
span, span,
@ -1494,6 +1520,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ref bounds, ref bounds,
span, span,
}) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { }) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
hir_id: self.next_id(),
bound_generic_params: self.lower_generic_params(bound_generic_params), bound_generic_params: self.lower_generic_params(bound_generic_params),
bounded_ty: self bounded_ty: self
.lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)), .lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)),

View File

@ -32,7 +32,6 @@
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(let_chains)] #![feature(let_chains)]
#![cfg_attr(bootstrap, feature(let_else))]
#![feature(never_type)] #![feature(never_type)]
#![recursion_limit = "256"] #![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)] #![allow(rustc::potential_query_instability)]
@ -62,8 +61,8 @@ use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
use rustc_hir::definitions::DefPathData; use rustc_hir::definitions::DefPathData;
use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate}; use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate};
use rustc_index::vec::{Idx, IndexVec}; use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::span_bug;
use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_session::parse::feature_err; use rustc_session::parse::feature_err;
use rustc_span::hygiene::MacroKind; use rustc_span::hygiene::MacroKind;
use rustc_span::source_map::DesugaringKind; use rustc_span::source_map::DesugaringKind;
@ -126,7 +125,7 @@ struct LoweringContext<'a, 'hir> {
is_in_trait_impl: bool, is_in_trait_impl: bool,
is_in_dyn_type: bool, is_in_dyn_type: bool,
current_hir_id_owner: LocalDefId, current_hir_id_owner: hir::OwnerId,
item_local_id_counter: hir::ItemLocalId, item_local_id_counter: hir::ItemLocalId,
local_id_to_def_id: SortedMap<ItemLocalId, LocalDefId>, local_id_to_def_id: SortedMap<ItemLocalId, LocalDefId>,
trait_map: FxHashMap<ItemLocalId, Box<[TraitCandidate]>>, trait_map: FxHashMap<ItemLocalId, Box<[TraitCandidate]>>,
@ -161,6 +160,10 @@ trait ResolverAstLoweringExt {
fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>>; fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>>;
fn get_partial_res(&self, id: NodeId) -> Option<PartialRes>; fn get_partial_res(&self, id: NodeId) -> Option<PartialRes>;
fn get_import_res(&self, id: NodeId) -> PerNS<Option<Res<NodeId>>>; fn get_import_res(&self, id: NodeId) -> PerNS<Option<Res<NodeId>>>;
// Clones the resolution (if any) on 'source' and applies it
// to 'target'. Used when desugaring a `UseTreeKind::Nested` to
// multiple `UseTreeKind::Simple`s
fn clone_res(&mut self, source: NodeId, target: NodeId);
fn get_label_res(&self, id: NodeId) -> Option<NodeId>; fn get_label_res(&self, id: NodeId) -> Option<NodeId>;
fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes>; fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes>;
fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>; fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>;
@ -176,12 +179,7 @@ impl ResolverAstLoweringExt for ResolverAstLowering {
return None; return None;
} }
let partial_res = self.partial_res_map.get(&expr.id)?; if let Res::Def(DefKind::Fn, def_id) = self.partial_res_map.get(&expr.id)?.full_res()? {
if partial_res.unresolved_segments() != 0 {
return None;
}
if let Res::Def(DefKind::Fn, def_id) = partial_res.base_res() {
// We only support cross-crate argument rewriting. Uses // We only support cross-crate argument rewriting. Uses
// within the same crate should be updated to use the new // within the same crate should be updated to use the new
// const generics style. // const generics style.
@ -198,6 +196,12 @@ impl ResolverAstLoweringExt for ResolverAstLowering {
None None
} }
fn clone_res(&mut self, source: NodeId, target: NodeId) {
if let Some(res) = self.partial_res_map.get(&source) {
self.partial_res_map.insert(target, *res);
}
}
/// Obtains resolution for a `NodeId` with a single resolution. /// Obtains resolution for a `NodeId` with a single resolution.
fn get_partial_res(&self, id: NodeId) -> Option<PartialRes> { fn get_partial_res(&self, id: NodeId) -> Option<PartialRes> {
self.partial_res_map.get(&id).copied() self.partial_res_map.get(&id).copied()
@ -324,17 +328,20 @@ enum FnDeclKind {
} }
impl FnDeclKind { impl FnDeclKind {
fn impl_trait_return_allowed(&self, tcx: TyCtxt<'_>) -> bool { fn impl_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool {
match self { match self {
FnDeclKind::Fn | FnDeclKind::Inherent => true, FnDeclKind::Fn | FnDeclKind::Inherent => true,
FnDeclKind::Impl if tcx.features().return_position_impl_trait_in_trait => true, FnDeclKind::Impl if tcx.features().return_position_impl_trait_in_trait => true,
FnDeclKind::Trait if tcx.features().return_position_impl_trait_in_trait => true,
_ => false, _ => false,
} }
} }
fn impl_trait_in_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool { fn async_fn_allowed(&self, tcx: TyCtxt<'_>) -> bool {
match self { match self {
FnDeclKind::Trait if tcx.features().return_position_impl_trait_in_trait => true, FnDeclKind::Fn | FnDeclKind::Inherent => true,
FnDeclKind::Impl if tcx.features().async_fn_in_trait => true,
FnDeclKind::Trait if tcx.features().async_fn_in_trait => true,
_ => false, _ => false,
} }
} }
@ -572,7 +579,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let current_node_ids = std::mem::take(&mut self.node_id_to_local_id); let current_node_ids = std::mem::take(&mut self.node_id_to_local_id);
let current_id_to_def_id = std::mem::take(&mut self.local_id_to_def_id); let current_id_to_def_id = std::mem::take(&mut self.local_id_to_def_id);
let current_trait_map = std::mem::take(&mut self.trait_map); let current_trait_map = std::mem::take(&mut self.trait_map);
let current_owner = std::mem::replace(&mut self.current_hir_id_owner, def_id); let current_owner =
std::mem::replace(&mut self.current_hir_id_owner, hir::OwnerId { def_id });
let current_local_counter = let current_local_counter =
std::mem::replace(&mut self.item_local_id_counter, hir::ItemLocalId::new(1)); std::mem::replace(&mut self.item_local_id_counter, hir::ItemLocalId::new(1));
let current_impl_trait_defs = std::mem::take(&mut self.impl_trait_defs); let current_impl_trait_defs = std::mem::take(&mut self.impl_trait_defs);
@ -587,7 +595,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
debug_assert_eq!(_old, None); debug_assert_eq!(_old, None);
let item = f(self); let item = f(self);
debug_assert_eq!(def_id, item.def_id()); debug_assert_eq!(def_id, item.def_id().def_id);
// `f` should have consumed all the elements in these vectors when constructing `item`. // `f` should have consumed all the elements in these vectors when constructing `item`.
debug_assert!(self.impl_trait_defs.is_empty()); debug_assert!(self.impl_trait_defs.is_empty());
debug_assert!(self.impl_trait_bounds.is_empty()); debug_assert!(self.impl_trait_bounds.is_empty());
@ -753,12 +761,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
fn expect_full_res(&mut self, id: NodeId) -> Res<NodeId> { fn expect_full_res(&mut self, id: NodeId) -> Res<NodeId> {
self.resolver.get_partial_res(id).map_or(Res::Err, |pr| { self.resolver.get_partial_res(id).map_or(Res::Err, |pr| pr.expect_full_res())
if pr.unresolved_segments() != 0 {
panic!("path not fully resolved: {:?}", pr);
}
pr.base_res()
})
} }
fn expect_full_res_from_use(&mut self, id: NodeId) -> impl Iterator<Item = Res<NodeId>> { fn expect_full_res_from_use(&mut self, id: NodeId) -> impl Iterator<Item = Res<NodeId>> {
@ -786,7 +789,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
/// Mark a span as relative to the current owning item. /// Mark a span as relative to the current owning item.
fn lower_span(&self, span: Span) -> Span { fn lower_span(&self, span: Span) -> Span {
if self.tcx.sess.opts.unstable_opts.incremental_relative_spans { if self.tcx.sess.opts.unstable_opts.incremental_relative_spans {
span.with_parent(Some(self.current_hir_id_owner)) span.with_parent(Some(self.current_hir_id_owner.def_id))
} else { } else {
// Do not make spans relative when not using incremental compilation. // Do not make spans relative when not using incremental compilation.
span span
@ -812,7 +815,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
LifetimeRes::Fresh { param, .. } => { LifetimeRes::Fresh { param, .. } => {
// Late resolution delegates to us the creation of the `LocalDefId`. // Late resolution delegates to us the creation of the `LocalDefId`.
let _def_id = self.create_def( let _def_id = self.create_def(
self.current_hir_id_owner, self.current_hir_id_owner.def_id,
param, param,
DefPathData::LifetimeNs(kw::UnderscoreLifetime), DefPathData::LifetimeNs(kw::UnderscoreLifetime),
); );
@ -1060,9 +1063,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Desugar `AssocTy: Bounds` into `AssocTy = impl Bounds`. We do this by // Desugar `AssocTy: Bounds` into `AssocTy = impl Bounds`. We do this by
// constructing the HIR for `impl bounds...` and then lowering that. // constructing the HIR for `impl bounds...` and then lowering that.
let parent_def_id = self.current_hir_id_owner;
let impl_trait_node_id = self.next_node_id(); let impl_trait_node_id = self.next_node_id();
self.create_def(parent_def_id, impl_trait_node_id, DefPathData::ImplTrait);
self.with_dyn_type_scope(false, |this| { self.with_dyn_type_scope(false, |this| {
let node_id = this.next_node_id(); let node_id = this.next_node_id();
@ -1140,8 +1141,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// type and value namespaces. If we resolved the path in the value namespace, we // type and value namespaces. If we resolved the path in the value namespace, we
// transform it into a generic const argument. // transform it into a generic const argument.
TyKind::Path(ref qself, ref path) => { TyKind::Path(ref qself, ref path) => {
if let Some(partial_res) = self.resolver.get_partial_res(ty.id) { if let Some(res) = self
let res = partial_res.base_res(); .resolver
.get_partial_res(ty.id)
.and_then(|partial_res| partial_res.full_res())
{
if !res.matches_ns(Namespace::TypeNS) { if !res.matches_ns(Namespace::TypeNS) {
debug!( debug!(
"lower_generic_arg: Lowering type argument as const argument: {:?}", "lower_generic_arg: Lowering type argument as const argument: {:?}",
@ -1154,7 +1158,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let node_id = self.next_node_id(); let node_id = self.next_node_id();
// Add a definition for the in-band const def. // Add a definition for the in-band const def.
self.create_def(parent_def_id, node_id, DefPathData::AnonConst); self.create_def(
parent_def_id.def_id,
node_id,
DefPathData::AnonConst,
);
let span = self.lower_span(ty.span); let span = self.lower_span(ty.span);
let path_expr = Expr { let path_expr = Expr {
@ -1204,8 +1212,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// by `ty_path`. // by `ty_path`.
if qself.is_none() if qself.is_none()
&& let Some(partial_res) = self.resolver.get_partial_res(t.id) && let Some(partial_res) = self.resolver.get_partial_res(t.id)
&& partial_res.unresolved_segments() == 0 && let Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) = partial_res.full_res()
&& let Res::Def(DefKind::Trait | DefKind::TraitAlias, _) = partial_res.base_res()
{ {
let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| { let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {
let poly_trait_ref = this.ast_arena.ptr.alloc(PolyTraitRef { let poly_trait_ref = this.ast_arena.ptr.alloc(PolyTraitRef {
@ -1349,9 +1356,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
def_node_id, def_node_id,
bounds, bounds,
false, false,
&ImplTraitContext::TypeAliasesOpaqueTy, itctx,
), ),
ImplTraitContext::Universal => { ImplTraitContext::Universal => {
self.create_def(
self.current_hir_id_owner.def_id,
def_node_id,
DefPathData::ImplTrait,
);
let span = t.span; let span = t.span;
let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
let (param, bounds, path) = let (param, bounds, path) =
@ -1445,7 +1457,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// frequently opened issues show. // frequently opened issues show.
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None); let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id); let opaque_ty_def_id = match origin {
hir::OpaqueTyOrigin::TyAlias => self.create_def(
self.current_hir_id_owner.def_id,
opaque_ty_node_id,
DefPathData::ImplTrait,
),
hir::OpaqueTyOrigin::FnReturn(fn_def_id) => {
self.create_def(fn_def_id, opaque_ty_node_id, DefPathData::ImplTrait)
}
hir::OpaqueTyOrigin::AsyncFn(..) => bug!("unreachable"),
};
debug!(?opaque_ty_def_id); debug!(?opaque_ty_def_id);
// Contains the new lifetime definitions created for the TAIT (if any). // Contains the new lifetime definitions created for the TAIT (if any).
@ -1551,7 +1573,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
debug!(?lifetimes); debug!(?lifetimes);
// `impl Trait` now just becomes `Foo<'a, 'b, ..>`. // `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes, in_trait) hir::TyKind::OpaqueDef(
hir::ItemId { owner_id: hir::OwnerId { def_id: opaque_ty_def_id } },
lifetimes,
in_trait,
)
} }
/// Registers a new opaque type with the proper `NodeId`s and /// Registers a new opaque type with the proper `NodeId`s and
@ -1567,7 +1593,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Generate an `type Foo = impl Trait;` declaration. // Generate an `type Foo = impl Trait;` declaration.
trace!("registering opaque type with id {:#?}", opaque_ty_id); trace!("registering opaque type with id {:#?}", opaque_ty_id);
let opaque_ty_item = hir::Item { let opaque_ty_item = hir::Item {
def_id: opaque_ty_id, owner_id: hir::OwnerId { def_id: opaque_ty_id },
ident: Ident::empty(), ident: Ident::empty(),
kind: opaque_ty_item_kind, kind: opaque_ty_item_kind,
vis_span: self.lower_span(span.shrink_to_lo()), vis_span: self.lower_span(span.shrink_to_lo()),
@ -1701,62 +1727,38 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
})); }));
let output = if let Some((ret_id, span)) = make_ret_async { let output = if let Some((ret_id, span)) = make_ret_async {
if !kind.async_fn_allowed(self.tcx) {
match kind { match kind {
FnDeclKind::Trait => { FnDeclKind::Trait | FnDeclKind::Impl => {
if !kind.impl_trait_in_trait_allowed(self.tcx) {
self.tcx self.tcx
.sess .sess
.create_feature_err( .create_feature_err(
TraitFnAsync { fn_span, span }, TraitFnAsync { fn_span, span },
sym::return_position_impl_trait_in_trait, sym::async_fn_in_trait,
) )
.emit(); .emit();
} }
self.lower_async_fn_ret_ty(
&decl.output,
fn_node_id.expect("`make_ret_async` but no `fn_def_id`"),
ret_id,
true,
)
}
_ => { _ => {
if !kind.impl_trait_return_allowed(self.tcx) {
if kind == FnDeclKind::Impl {
self.tcx
.sess
.create_feature_err(
TraitFnAsync { fn_span, span },
sym::return_position_impl_trait_in_trait,
)
.emit();
} else {
self.tcx.sess.emit_err(TraitFnAsync { fn_span, span }); self.tcx.sess.emit_err(TraitFnAsync { fn_span, span });
} }
} }
}
self.lower_async_fn_ret_ty( self.lower_async_fn_ret_ty(
&decl.output, &decl.output,
fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), fn_node_id.expect("`make_ret_async` but no `fn_def_id`"),
ret_id, ret_id,
false, matches!(kind, FnDeclKind::Trait),
) )
}
}
} else { } else {
match decl.output { match decl.output {
FnRetTy::Ty(ref ty) => { FnRetTy::Ty(ref ty) => {
let mut context = match fn_node_id { let mut context = match fn_node_id {
Some(fn_node_id) if kind.impl_trait_return_allowed(self.tcx) => { Some(fn_node_id) if kind.impl_trait_allowed(self.tcx) => {
let fn_def_id = self.local_def_id(fn_node_id); let fn_def_id = self.local_def_id(fn_node_id);
ImplTraitContext::ReturnPositionOpaqueTy { ImplTraitContext::ReturnPositionOpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
in_trait: false, in_trait: matches!(kind, FnDeclKind::Trait),
}
}
Some(fn_node_id) if kind.impl_trait_in_trait_allowed(self.tcx) => {
let fn_def_id = self.local_def_id(fn_node_id);
ImplTraitContext::ReturnPositionOpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
in_trait: true,
} }
} }
_ => ImplTraitContext::Disallowed(match kind { _ => ImplTraitContext::Disallowed(match kind {
@ -1950,9 +1952,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let future_bound = this.lower_async_fn_output_type_to_future_bound( let future_bound = this.lower_async_fn_output_type_to_future_bound(
output, output,
span, span,
if in_trait && !this.tcx.features().return_position_impl_trait_in_trait {
ImplTraitContext::Disallowed(ImplTraitPosition::TraitReturn)
} else {
ImplTraitContext::ReturnPositionOpaqueTy { ImplTraitContext::ReturnPositionOpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
in_trait, in_trait,
}
}, },
); );
@ -2038,7 +2044,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// async fn, so the *type parameters* are inherited. It's // async fn, so the *type parameters* are inherited. It's
// only the lifetime parameters that we must supply. // only the lifetime parameters that we must supply.
let opaque_ty_ref = hir::TyKind::OpaqueDef( let opaque_ty_ref = hir::TyKind::OpaqueDef(
hir::ItemId { def_id: opaque_ty_def_id }, hir::ItemId { owner_id: hir::OwnerId { def_id: opaque_ty_def_id } },
generic_args, generic_args,
in_trait, in_trait,
); );

View File

@ -239,7 +239,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
ident: Ident, ident: Ident,
lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>, lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>,
) -> hir::PatKind<'hir> { ) -> hir::PatKind<'hir> {
match self.resolver.get_partial_res(p.id).map(|d| d.base_res()) { match self.resolver.get_partial_res(p.id).map(|d| d.expect_full_res()) {
// `None` can occur in body-less function signatures // `None` can occur in body-less function signatures
res @ (None | Some(Res::Local(_))) => { res @ (None | Some(Res::Local(_))) => {
let canonical_id = match res { let canonical_id = match res {

View File

@ -29,11 +29,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let partial_res = let partial_res =
self.resolver.get_partial_res(id).unwrap_or_else(|| PartialRes::new(Res::Err)); self.resolver.get_partial_res(id).unwrap_or_else(|| PartialRes::new(Res::Err));
let base_res = partial_res.base_res();
let unresolved_segments = partial_res.unresolved_segments();
let path_span_lo = p.span.shrink_to_lo(); let path_span_lo = p.span.shrink_to_lo();
let proj_start = p.segments.len() - partial_res.unresolved_segments(); let proj_start = p.segments.len() - unresolved_segments;
let path = self.arena.alloc(hir::Path { let path = self.arena.alloc(hir::Path {
res: self.lower_res(partial_res.base_res()), res: self.lower_res(base_res),
segments: self.arena.alloc_from_iter(p.segments[..proj_start].iter().enumerate().map( segments: self.arena.alloc_from_iter(p.segments[..proj_start].iter().enumerate().map(
|(i, segment)| { |(i, segment)| {
let param_mode = match (qself_position, param_mode) { let param_mode = match (qself_position, param_mode) {
@ -46,7 +48,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
_ => param_mode, _ => param_mode,
}; };
let parenthesized_generic_args = match partial_res.base_res() { let parenthesized_generic_args = match base_res {
// `a::b::Trait(Args)` // `a::b::Trait(Args)`
Res::Def(DefKind::Trait, _) if i + 1 == proj_start => { Res::Def(DefKind::Trait, _) if i + 1 == proj_start => {
ParenthesizedGenericArgs::Ok ParenthesizedGenericArgs::Ok
@ -83,7 +85,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Simple case, either no projections, or only fully-qualified. // Simple case, either no projections, or only fully-qualified.
// E.g., `std::mem::size_of` or `<I as Iterator>::Item`. // E.g., `std::mem::size_of` or `<I as Iterator>::Item`.
if partial_res.unresolved_segments() == 0 { if unresolved_segments == 0 {
return hir::QPath::Resolved(qself, path); return hir::QPath::Resolved(qself, path);
} }

View File

@ -14,6 +14,7 @@ use rustc_ast::*;
use rustc_ast_pretty::pprust::{self, State}; use rustc_ast_pretty::pprust::{self, State};
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{error_code, fluent, pluralize, struct_span_err, Applicability}; use rustc_errors::{error_code, fluent, pluralize, struct_span_err, Applicability};
use rustc_macros::Subdiagnostic;
use rustc_parse::validate_attr; use rustc_parse::validate_attr;
use rustc_session::lint::builtin::{ use rustc_session::lint::builtin::{
DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY, DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY,
@ -38,6 +39,13 @@ enum SelfSemantic {
No, No,
} }
/// What is the context that prevents using `~const`?
enum DisallowTildeConstContext<'a> {
TraitObject,
ImplTrait,
Fn(FnKind<'a>),
}
struct AstValidator<'a> { struct AstValidator<'a> {
session: &'a Session, session: &'a Session,
@ -56,7 +64,7 @@ struct AstValidator<'a> {
/// e.g., `impl Iterator<Item = impl Debug>`. /// e.g., `impl Iterator<Item = impl Debug>`.
outer_impl_trait: Option<Span>, outer_impl_trait: Option<Span>,
is_tilde_const_allowed: bool, disallow_tilde_const: Option<DisallowTildeConstContext<'a>>,
/// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item` /// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
/// or `Foo::Bar<impl Trait>` /// or `Foo::Bar<impl Trait>`
@ -93,18 +101,26 @@ impl<'a> AstValidator<'a> {
self.is_impl_trait_banned = old; self.is_impl_trait_banned = old;
} }
fn with_tilde_const(&mut self, allowed: bool, f: impl FnOnce(&mut Self)) { fn with_tilde_const(
let old = mem::replace(&mut self.is_tilde_const_allowed, allowed); &mut self,
disallowed: Option<DisallowTildeConstContext<'a>>,
f: impl FnOnce(&mut Self),
) {
let old = mem::replace(&mut self.disallow_tilde_const, disallowed);
f(self); f(self);
self.is_tilde_const_allowed = old; self.disallow_tilde_const = old;
} }
fn with_tilde_const_allowed(&mut self, f: impl FnOnce(&mut Self)) { fn with_tilde_const_allowed(&mut self, f: impl FnOnce(&mut Self)) {
self.with_tilde_const(true, f) self.with_tilde_const(None, f)
} }
fn with_banned_tilde_const(&mut self, f: impl FnOnce(&mut Self)) { fn with_banned_tilde_const(
self.with_tilde_const(false, f) &mut self,
ctx: DisallowTildeConstContext<'a>,
f: impl FnOnce(&mut Self),
) {
self.with_tilde_const(Some(ctx), f)
} }
fn with_let_management( fn with_let_management(
@ -154,7 +170,7 @@ impl<'a> AstValidator<'a> {
DEPRECATED_WHERE_CLAUSE_LOCATION, DEPRECATED_WHERE_CLAUSE_LOCATION,
id, id,
where_clauses.0.1, where_clauses.0.1,
fluent::ast_passes::deprecated_where_clause_location, fluent::ast_passes_deprecated_where_clause_location,
BuiltinLintDiagnostics::DeprecatedWhereclauseLocation( BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(
where_clauses.1.1.shrink_to_hi(), where_clauses.1.1.shrink_to_hi(),
suggestion, suggestion,
@ -172,7 +188,7 @@ impl<'a> AstValidator<'a> {
fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) { fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
let old = mem::replace(&mut self.outer_impl_trait, outer); let old = mem::replace(&mut self.outer_impl_trait, outer);
if outer.is_some() { if outer.is_some() {
self.with_banned_tilde_const(f); self.with_banned_tilde_const(DisallowTildeConstContext::ImplTrait, f);
} else { } else {
f(self); f(self);
} }
@ -197,7 +213,10 @@ impl<'a> AstValidator<'a> {
TyKind::ImplTrait(..) => { TyKind::ImplTrait(..) => {
self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t)) self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t))
} }
TyKind::TraitObject(..) => self.with_banned_tilde_const(|this| visit::walk_ty(this, t)), TyKind::TraitObject(..) => self
.with_banned_tilde_const(DisallowTildeConstContext::TraitObject, |this| {
visit::walk_ty(this, t)
}),
TyKind::Path(ref qself, ref path) => { TyKind::Path(ref qself, ref path) => {
// We allow these: // We allow these:
// - `Option<impl Trait>` // - `Option<impl Trait>`
@ -233,20 +252,6 @@ impl<'a> AstValidator<'a> {
} }
} }
fn visit_struct_field_def(&mut self, field: &'a FieldDef) {
if let Some(ident) = field.ident {
if ident.name == kw::Underscore {
self.visit_vis(&field.vis);
self.visit_ident(ident);
self.visit_ty_common(&field.ty);
self.walk_ty(&field.ty);
walk_list!(self, visit_attribute, &field.attrs);
return;
}
}
self.visit_field_def(field);
}
fn err_handler(&self) -> &rustc_errors::Handler { fn err_handler(&self) -> &rustc_errors::Handler {
&self.session.diagnostic() &self.session.diagnostic()
} }
@ -987,8 +992,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
visit::walk_lifetime(self, lifetime); visit::walk_lifetime(self, lifetime);
} }
fn visit_field_def(&mut self, s: &'a FieldDef) { fn visit_field_def(&mut self, field: &'a FieldDef) {
visit::walk_field_def(self, s) visit::walk_field_def(self, field)
} }
fn visit_item(&mut self, item: &'a Item) { fn visit_item(&mut self, item: &'a Item) {
@ -1176,42 +1181,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.check_mod_file_item_asciionly(item.ident); self.check_mod_file_item_asciionly(item.ident);
} }
} }
ItemKind::Struct(ref vdata, ref generics) => match vdata { ItemKind::Union(ref vdata, ..) => {
// Duplicating the `Visitor` logic allows catching all cases
// of `Anonymous(Struct, Union)` outside of a field struct or union.
//
// Inside `visit_ty` the validator catches every `Anonymous(Struct, Union)` it
// encounters, and only on `ItemKind::Struct` and `ItemKind::Union`
// it uses `visit_ty_common`, which doesn't contain that specific check.
VariantData::Struct(ref fields, ..) => {
self.visit_vis(&item.vis);
self.visit_ident(item.ident);
self.visit_generics(generics);
self.with_banned_assoc_ty_bound(|this| {
walk_list!(this, visit_struct_field_def, fields);
});
walk_list!(self, visit_attribute, &item.attrs);
return;
}
_ => {}
},
ItemKind::Union(ref vdata, ref generics) => {
if vdata.fields().is_empty() { if vdata.fields().is_empty() {
self.err_handler().span_err(item.span, "unions cannot have zero fields"); self.err_handler().span_err(item.span, "unions cannot have zero fields");
} }
match vdata {
VariantData::Struct(ref fields, ..) => {
self.visit_vis(&item.vis);
self.visit_ident(item.ident);
self.visit_generics(generics);
self.with_banned_assoc_ty_bound(|this| {
walk_list!(this, visit_struct_field_def, fields);
});
walk_list!(self, visit_attribute, &item.attrs);
return;
}
_ => {}
}
} }
ItemKind::Const(def, .., None) => { ItemKind::Const(def, .., None) => {
self.check_defaultness(item.span, def); self.check_defaultness(item.span, def);
@ -1411,13 +1384,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
); );
err.emit(); err.emit();
} }
(_, TraitBoundModifier::MaybeConst) => { (_, TraitBoundModifier::MaybeConst) if let Some(reason) = &self.disallow_tilde_const => {
if !self.is_tilde_const_allowed { let mut err = self.err_handler().struct_span_err(bound.span(), "`~const` is not allowed here");
self.err_handler() match reason {
.struct_span_err(bound.span(), "`~const` is not allowed here") DisallowTildeConstContext::TraitObject => err.note("trait objects cannot have `~const` trait bounds"),
.note("only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions") DisallowTildeConstContext::ImplTrait => err.note("`impl Trait`s cannot have `~const` trait bounds"),
.emit(); DisallowTildeConstContext::Fn(FnKind::Closure(..)) => err.note("closures cannot have `~const` trait bounds"),
} DisallowTildeConstContext::Fn(FnKind::Fn(_, ident, ..)) => err.span_note(ident.span, "this function is not `const`, so it cannot have `~const` trait bounds"),
};
err.emit();
} }
(_, TraitBoundModifier::MaybeConstMaybe) => { (_, TraitBoundModifier::MaybeConstMaybe) => {
self.err_handler() self.err_handler()
@ -1524,10 +1499,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
} }
let tilde_const_allowed = let tilde_const_allowed =
matches!(fk.header(), Some(FnHeader { constness: Const::Yes(_), .. })) matches!(fk.header(), Some(FnHeader { constness: ast::Const::Yes(_), .. }))
|| matches!(fk.ctxt(), Some(FnCtxt::Assoc(_))); || matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)));
self.with_tilde_const(tilde_const_allowed, |this| visit::walk_fn(this, fk)); let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk));
self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
} }
fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) { fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
@ -1557,7 +1534,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}); });
} }
} }
AssocItemKind::TyAlias(box TyAlias { AssocItemKind::Type(box TyAlias {
generics, generics,
where_clauses, where_clauses,
where_predicates_split, where_predicates_split,
@ -1596,7 +1573,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
} }
match item.kind { match item.kind {
AssocItemKind::TyAlias(box TyAlias { ref generics, ref bounds, ref ty, .. }) AssocItemKind::Type(box TyAlias { ref generics, ref bounds, ref ty, .. })
if ctxt == AssocCtxt::Trait => if ctxt == AssocCtxt::Trait =>
{ {
self.visit_vis(&item.vis); self.visit_vis(&item.vis);
@ -1771,7 +1748,7 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
in_const_trait_impl: false, in_const_trait_impl: false,
has_proc_macro_decls: false, has_proc_macro_decls: false,
outer_impl_trait: None, outer_impl_trait: None,
is_tilde_const_allowed: false, disallow_tilde_const: None,
is_impl_trait_banned: false, is_impl_trait_banned: false,
is_assoc_ty_bound_banned: false, is_assoc_ty_bound_banned: false,
forbidden_let_reason: Some(ForbiddenLetReason::GenericForbidden), forbidden_let_reason: Some(ForbiddenLetReason::GenericForbidden),
@ -1783,15 +1760,17 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
} }
/// Used to forbid `let` expressions in certain syntactic locations. /// Used to forbid `let` expressions in certain syntactic locations.
#[derive(Clone, Copy)] #[derive(Clone, Copy, Subdiagnostic)]
pub(crate) enum ForbiddenLetReason { pub(crate) enum ForbiddenLetReason {
/// `let` is not valid and the source environment is not important /// `let` is not valid and the source environment is not important
GenericForbidden, GenericForbidden,
/// A let chain with the `||` operator /// A let chain with the `||` operator
NotSupportedOr(Span), #[note(not_supported_or)]
NotSupportedOr(#[primary_span] Span),
/// A let chain with invalid parentheses /// A let chain with invalid parentheses
/// ///
/// For example, `let 1 = 1 && (expr && expr)` is allowed /// For example, `let 1 = 1 && (expr && expr)` is allowed
/// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not /// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not
NotSupportedParentheses(Span), #[note(not_supported_parentheses)]
NotSupportedParentheses(#[primary_span] Span),
} }

View File

@ -1,13 +1,13 @@
//! Errors emitted by ast_passes. //! Errors emitted by ast_passes.
use rustc_errors::{fluent, AddSubdiagnostic, Applicability, Diagnostic}; use rustc_errors::{fluent, AddToDiagnostic, Applicability, Diagnostic, SubdiagnosticMessage};
use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic}; use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::{Span, Symbol}; use rustc_span::{Span, Symbol};
use crate::ast_validation::ForbiddenLetReason; use crate::ast_validation::ForbiddenLetReason;
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(ast_passes::forbidden_let)] #[diag(ast_passes_forbidden_let)]
#[note] #[note]
pub struct ForbiddenLet { pub struct ForbiddenLet {
#[primary_span] #[primary_span]
@ -16,130 +16,116 @@ pub struct ForbiddenLet {
pub(crate) reason: ForbiddenLetReason, pub(crate) reason: ForbiddenLetReason,
} }
impl AddSubdiagnostic for ForbiddenLetReason { #[derive(Diagnostic)]
fn add_to_diagnostic(self, diag: &mut Diagnostic) { #[diag(ast_passes_forbidden_let_stable)]
match self {
Self::GenericForbidden => {}
Self::NotSupportedOr(span) => {
diag.span_note(span, fluent::ast_passes::not_supported_or);
}
Self::NotSupportedParentheses(span) => {
diag.span_note(span, fluent::ast_passes::not_supported_parentheses);
}
}
}
}
#[derive(SessionDiagnostic)]
#[diag(ast_passes::forbidden_let_stable)]
#[note] #[note]
pub struct ForbiddenLetStable { pub struct ForbiddenLetStable {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(ast_passes::forbidden_assoc_constraint)] #[diag(ast_passes_forbidden_assoc_constraint)]
pub struct ForbiddenAssocConstraint { pub struct ForbiddenAssocConstraint {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(ast_passes::keyword_lifetime)] #[diag(ast_passes_keyword_lifetime)]
pub struct KeywordLifetime { pub struct KeywordLifetime {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(ast_passes::invalid_label)] #[diag(ast_passes_invalid_label)]
pub struct InvalidLabel { pub struct InvalidLabel {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
pub name: Symbol, pub name: Symbol,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(ast_passes::invalid_visibility, code = "E0449")] #[diag(ast_passes_invalid_visibility, code = "E0449")]
pub struct InvalidVisibility { pub struct InvalidVisibility {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
#[label(ast_passes::implied)] #[label(implied)]
pub implied: Option<Span>, pub implied: Option<Span>,
#[subdiagnostic] #[subdiagnostic]
pub note: Option<InvalidVisibilityNote>, pub note: Option<InvalidVisibilityNote>,
} }
#[derive(SessionSubdiagnostic)] #[derive(Subdiagnostic)]
pub enum InvalidVisibilityNote { pub enum InvalidVisibilityNote {
#[note(ast_passes::individual_impl_items)] #[note(individual_impl_items)]
IndividualImplItems, IndividualImplItems,
#[note(ast_passes::individual_foreign_items)] #[note(individual_foreign_items)]
IndividualForeignItems, IndividualForeignItems,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(ast_passes::trait_fn_const, code = "E0379")] #[diag(ast_passes_trait_fn_const, code = "E0379")]
pub struct TraitFnConst { pub struct TraitFnConst {
#[primary_span] #[primary_span]
#[label] #[label]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(ast_passes::forbidden_lifetime_bound)] #[diag(ast_passes_forbidden_lifetime_bound)]
pub struct ForbiddenLifetimeBound { pub struct ForbiddenLifetimeBound {
#[primary_span] #[primary_span]
pub spans: Vec<Span>, pub spans: Vec<Span>,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(ast_passes::forbidden_non_lifetime_param)] #[diag(ast_passes_forbidden_non_lifetime_param)]
pub struct ForbiddenNonLifetimeParam { pub struct ForbiddenNonLifetimeParam {
#[primary_span] #[primary_span]
pub spans: Vec<Span>, pub spans: Vec<Span>,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(ast_passes::fn_param_too_many)] #[diag(ast_passes_fn_param_too_many)]
pub struct FnParamTooMany { pub struct FnParamTooMany {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
pub max_num_args: usize, pub max_num_args: usize,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(ast_passes::fn_param_c_var_args_only)] #[diag(ast_passes_fn_param_c_var_args_only)]
pub struct FnParamCVarArgsOnly { pub struct FnParamCVarArgsOnly {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(ast_passes::fn_param_c_var_args_not_last)] #[diag(ast_passes_fn_param_c_var_args_not_last)]
pub struct FnParamCVarArgsNotLast { pub struct FnParamCVarArgsNotLast {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(ast_passes::fn_param_doc_comment)] #[diag(ast_passes_fn_param_doc_comment)]
pub struct FnParamDocComment { pub struct FnParamDocComment {
#[primary_span] #[primary_span]
#[label] #[label]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(ast_passes::fn_param_forbidden_attr)] #[diag(ast_passes_fn_param_forbidden_attr)]
pub struct FnParamForbiddenAttr { pub struct FnParamForbiddenAttr {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(ast_passes::fn_param_forbidden_self)] #[diag(ast_passes_fn_param_forbidden_self)]
#[note] #[note]
pub struct FnParamForbiddenSelf { pub struct FnParamForbiddenSelf {
#[primary_span] #[primary_span]
@ -147,8 +133,8 @@ pub struct FnParamForbiddenSelf {
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(ast_passes::forbidden_default)] #[diag(ast_passes_forbidden_default)]
pub struct ForbiddenDefault { pub struct ForbiddenDefault {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
@ -156,8 +142,8 @@ pub struct ForbiddenDefault {
pub def_span: Span, pub def_span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(ast_passes::assoc_const_without_body)] #[diag(ast_passes_assoc_const_without_body)]
pub struct AssocConstWithoutBody { pub struct AssocConstWithoutBody {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
@ -165,8 +151,8 @@ pub struct AssocConstWithoutBody {
pub replace_span: Span, pub replace_span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(ast_passes::assoc_fn_without_body)] #[diag(ast_passes_assoc_fn_without_body)]
pub struct AssocFnWithoutBody { pub struct AssocFnWithoutBody {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
@ -174,8 +160,8 @@ pub struct AssocFnWithoutBody {
pub replace_span: Span, pub replace_span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(ast_passes::assoc_type_without_body)] #[diag(ast_passes_assoc_type_without_body)]
pub struct AssocTypeWithoutBody { pub struct AssocTypeWithoutBody {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
@ -183,8 +169,8 @@ pub struct AssocTypeWithoutBody {
pub replace_span: Span, pub replace_span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(ast_passes::const_without_body)] #[diag(ast_passes_const_without_body)]
pub struct ConstWithoutBody { pub struct ConstWithoutBody {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
@ -192,8 +178,8 @@ pub struct ConstWithoutBody {
pub replace_span: Span, pub replace_span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(ast_passes::static_without_body)] #[diag(ast_passes_static_without_body)]
pub struct StaticWithoutBody { pub struct StaticWithoutBody {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
@ -201,8 +187,8 @@ pub struct StaticWithoutBody {
pub replace_span: Span, pub replace_span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(ast_passes::ty_alias_without_body)] #[diag(ast_passes_ty_alias_without_body)]
pub struct TyAliasWithoutBody { pub struct TyAliasWithoutBody {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
@ -210,8 +196,8 @@ pub struct TyAliasWithoutBody {
pub replace_span: Span, pub replace_span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(ast_passes::fn_without_body)] #[diag(ast_passes_fn_without_body)]
pub struct FnWithoutBody { pub struct FnWithoutBody {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
@ -227,8 +213,11 @@ pub struct ExternBlockSuggestion {
pub abi: Option<Symbol>, pub abi: Option<Symbol>,
} }
impl AddSubdiagnostic for ExternBlockSuggestion { impl AddToDiagnostic for ExternBlockSuggestion {
fn add_to_diagnostic(self, diag: &mut Diagnostic) { fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
where
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
{
let start_suggestion = if let Some(abi) = self.abi { let start_suggestion = if let Some(abi) = self.abi {
format!("extern \"{}\" {{", abi) format!("extern \"{}\" {{", abi)
} else { } else {
@ -237,7 +226,7 @@ impl AddSubdiagnostic for ExternBlockSuggestion {
let end_suggestion = " }".to_owned(); let end_suggestion = " }".to_owned();
diag.multipart_suggestion( diag.multipart_suggestion(
fluent::ast_passes::extern_block_suggestion, fluent::extern_block_suggestion,
vec![(self.start_span, start_suggestion), (self.end_span, end_suggestion)], vec![(self.start_span, start_suggestion), (self.end_span, end_suggestion)],
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );

View File

@ -1,15 +1,15 @@
use rustc_ast as ast; use rustc_ast as ast;
use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
use rustc_ast::{AssocConstraint, AssocConstraintKind, NodeId}; use rustc_ast::{AssocConstraint, AssocConstraintKind, NodeId};
use rustc_ast::{PatKind, RangeEnd, VariantData}; use rustc_ast::{PatKind, RangeEnd};
use rustc_errors::{struct_span_err, Applicability, StashKey}; use rustc_errors::{struct_span_err, Applicability, StashKey};
use rustc_feature::Features; use rustc_feature::{AttributeGate, BuiltinAttribute, Features, GateIssue, BUILTIN_ATTRIBUTE_MAP};
use rustc_feature::{AttributeGate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; use rustc_session::parse::{feature_err, feature_err_issue, feature_warn};
use rustc_session::parse::{feature_err, feature_warn};
use rustc_session::Session; use rustc_session::Session;
use rustc_span::source_map::Spanned; use rustc_span::source_map::Spanned;
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
use rustc_span::Span; use rustc_span::Span;
use rustc_target::spec::abi;
macro_rules! gate_feature_fn { macro_rules! gate_feature_fn {
($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{ ($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{
@ -84,210 +84,26 @@ impl<'a> PostExpansionVisitor<'a> {
} }
} }
match symbol_unescaped.as_str() { match abi::is_enabled(&self.features, span, symbol_unescaped.as_str()) {
// Stable Ok(()) => (),
"Rust" | "C" | "cdecl" | "stdcall" | "fastcall" | "aapcs" | "win64" | "sysv64" Err(abi::AbiDisabled::Unstable { feature, explain }) => {
| "system" => {} feature_err_issue(
"rust-intrinsic" => { &self.sess.parse_sess,
gate_feature_post!(&self, intrinsics, span, "intrinsics are subject to change"); feature,
}
"platform-intrinsic" => {
gate_feature_post!(
&self,
platform_intrinsics,
span, span,
"platform intrinsics are experimental and possibly buggy" GateIssue::Language,
); explain,
)
.emit();
} }
"vectorcall" => { Err(abi::AbiDisabled::Unrecognized) => {
gate_feature_post!(
&self,
abi_vectorcall,
span,
"vectorcall is experimental and subject to change"
);
}
"thiscall" => {
gate_feature_post!(
&self,
abi_thiscall,
span,
"thiscall is experimental and subject to change"
);
}
"rust-call" => {
gate_feature_post!(
&self,
unboxed_closures,
span,
"rust-call ABI is subject to change"
);
}
"rust-cold" => {
gate_feature_post!(
&self,
rust_cold_cc,
span,
"rust-cold is experimental and subject to change"
);
}
"ptx-kernel" => {
gate_feature_post!(
&self,
abi_ptx,
span,
"PTX ABIs are experimental and subject to change"
);
}
"unadjusted" => {
gate_feature_post!(
&self,
abi_unadjusted,
span,
"unadjusted ABI is an implementation detail and perma-unstable"
);
}
"msp430-interrupt" => {
gate_feature_post!(
&self,
abi_msp430_interrupt,
span,
"msp430-interrupt ABI is experimental and subject to change"
);
}
"x86-interrupt" => {
gate_feature_post!(
&self,
abi_x86_interrupt,
span,
"x86-interrupt ABI is experimental and subject to change"
);
}
"amdgpu-kernel" => {
gate_feature_post!(
&self,
abi_amdgpu_kernel,
span,
"amdgpu-kernel ABI is experimental and subject to change"
);
}
"avr-interrupt" | "avr-non-blocking-interrupt" => {
gate_feature_post!(
&self,
abi_avr_interrupt,
span,
"avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change"
);
}
"efiapi" => {
gate_feature_post!(
&self,
abi_efiapi,
span,
"efiapi ABI is experimental and subject to change"
);
}
"C-cmse-nonsecure-call" => {
gate_feature_post!(
&self,
abi_c_cmse_nonsecure_call,
span,
"C-cmse-nonsecure-call ABI is experimental and subject to change"
);
}
"C-unwind" => {
gate_feature_post!(
&self,
c_unwind,
span,
"C-unwind ABI is experimental and subject to change"
);
}
"stdcall-unwind" => {
gate_feature_post!(
&self,
c_unwind,
span,
"stdcall-unwind ABI is experimental and subject to change"
);
}
"system-unwind" => {
gate_feature_post!(
&self,
c_unwind,
span,
"system-unwind ABI is experimental and subject to change"
);
}
"thiscall-unwind" => {
gate_feature_post!(
&self,
c_unwind,
span,
"thiscall-unwind ABI is experimental and subject to change"
);
}
"cdecl-unwind" => {
gate_feature_post!(
&self,
c_unwind,
span,
"cdecl-unwind ABI is experimental and subject to change"
);
}
"fastcall-unwind" => {
gate_feature_post!(
&self,
c_unwind,
span,
"fastcall-unwind ABI is experimental and subject to change"
);
}
"vectorcall-unwind" => {
gate_feature_post!(
&self,
c_unwind,
span,
"vectorcall-unwind ABI is experimental and subject to change"
);
}
"aapcs-unwind" => {
gate_feature_post!(
&self,
c_unwind,
span,
"aapcs-unwind ABI is experimental and subject to change"
);
}
"win64-unwind" => {
gate_feature_post!(
&self,
c_unwind,
span,
"win64-unwind ABI is experimental and subject to change"
);
}
"sysv64-unwind" => {
gate_feature_post!(
&self,
c_unwind,
span,
"sysv64-unwind ABI is experimental and subject to change"
);
}
"wasm" => {
gate_feature_post!(
&self,
wasm_abi,
span,
"wasm ABI is experimental and subject to change"
);
}
abi => {
if self.sess.opts.pretty.map_or(true, |ppm| ppm.needs_hir()) { if self.sess.opts.pretty.map_or(true, |ppm| ppm.needs_hir()) {
self.sess.parse_sess.span_diagnostic.delay_span_bug( self.sess.parse_sess.span_diagnostic.delay_span_bug(
span, span,
&format!("unrecognized ABI not caught in lowering: {}", abi), &format!(
"unrecognized ABI not caught in lowering: {}",
symbol_unescaped.as_str()
),
); );
} }
} }
@ -300,46 +116,6 @@ impl<'a> PostExpansionVisitor<'a> {
} }
} }
fn maybe_report_invalid_custom_discriminants(&self, variants: &[ast::Variant]) {
let has_fields = variants.iter().any(|variant| match variant.data {
VariantData::Tuple(..) | VariantData::Struct(..) => true,
VariantData::Unit(..) => false,
});
let discriminant_spans = variants
.iter()
.filter(|variant| match variant.data {
VariantData::Tuple(..) | VariantData::Struct(..) => false,
VariantData::Unit(..) => true,
})
.filter_map(|variant| variant.disr_expr.as_ref().map(|c| c.value.span))
.collect::<Vec<_>>();
if !discriminant_spans.is_empty() && has_fields {
let mut err = feature_err(
&self.sess.parse_sess,
sym::arbitrary_enum_discriminant,
discriminant_spans.clone(),
"custom discriminant values are not allowed in enums with tuple or struct variants",
);
for sp in discriminant_spans {
err.span_label(sp, "disallowed custom discriminant");
}
for variant in variants.iter() {
match &variant.data {
VariantData::Struct(..) => {
err.span_label(variant.span, "struct variant defined here");
}
VariantData::Tuple(..) => {
err.span_label(variant.span, "tuple variant defined here");
}
VariantData::Unit(..) => {}
}
}
err.emit();
}
}
/// Feature gate `impl Trait` inside `type Alias = $type_expr;`. /// Feature gate `impl Trait` inside `type Alias = $type_expr;`.
fn check_impl_trait(&self, ty: &ast::Ty) { fn check_impl_trait(&self, ty: &ast::Ty) {
struct ImplTraitVisitor<'a> { struct ImplTraitVisitor<'a> {
@ -457,26 +233,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
} }
} }
ast::ItemKind::Enum(ast::EnumDef { ref variants, .. }, ..) => {
for variant in variants {
match (&variant.data, &variant.disr_expr) {
(ast::VariantData::Unit(..), _) => {}
(_, Some(disr_expr)) => gate_feature_post!(
&self,
arbitrary_enum_discriminant,
disr_expr.value.span,
"discriminants on non-unit variants are experimental"
),
_ => {}
}
}
let has_feature = self.features.arbitrary_enum_discriminant;
if !has_feature && !i.span.allows_unstable(sym::arbitrary_enum_discriminant) {
self.maybe_report_invalid_custom_discriminants(&variants);
}
}
ast::ItemKind::Impl(box ast::Impl { polarity, defaultness, ref of_trait, .. }) => { ast::ItemKind::Impl(box ast::Impl { polarity, defaultness, ref of_trait, .. }) => {
if let ast::ImplPolarity::Negative(span) = polarity { if let ast::ImplPolarity::Negative(span) = polarity {
gate_feature_post!( gate_feature_post!(
@ -645,7 +401,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
if let PatKind::Range(Some(_), None, Spanned { .. }) = inner_pat.kind { if let PatKind::Range(Some(_), None, Spanned { .. }) = inner_pat.kind {
gate_feature_post!( gate_feature_post!(
&self, &self,
half_open_range_patterns, half_open_range_patterns_in_slices,
pat.span, pat.span,
"`X..` patterns in slices are experimental" "`X..` patterns in slices are experimental"
); );
@ -701,7 +457,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) { fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
let is_fn = match i.kind { let is_fn = match i.kind {
ast::AssocItemKind::Fn(_) => true, ast::AssocItemKind::Fn(_) => true,
ast::AssocItemKind::TyAlias(box ast::TyAlias { ref ty, .. }) => { ast::AssocItemKind::Type(box ast::TyAlias { ref ty, .. }) => {
if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) { if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) {
gate_feature_post!( gate_feature_post!(
&self, &self,
@ -773,7 +529,10 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
gate_all!(generators, "yield syntax is experimental"); gate_all!(generators, "yield syntax is experimental");
gate_all!(raw_ref_op, "raw address of syntax is experimental"); gate_all!(raw_ref_op, "raw address of syntax is experimental");
gate_all!(const_trait_impl, "const trait impls are experimental"); gate_all!(const_trait_impl, "const trait impls are experimental");
gate_all!(half_open_range_patterns, "half-open range patterns are unstable"); gate_all!(
half_open_range_patterns_in_slices,
"half-open range patterns in slices are unstable"
);
gate_all!(inline_const, "inline-const is experimental"); gate_all!(inline_const, "inline-const is experimental");
gate_all!(inline_const_pat, "inline-const in pattern position is experimental"); gate_all!(inline_const_pat, "inline-const in pattern position is experimental");
gate_all!(associated_const_equality, "associated const equality is incomplete"); gate_all!(associated_const_equality, "associated const equality is incomplete");

View File

@ -9,7 +9,6 @@
#![feature(if_let_guard)] #![feature(if_let_guard)]
#![feature(iter_is_partitioned)] #![feature(iter_is_partitioned)]
#![feature(let_chains)] #![feature(let_chains)]
#![cfg_attr(bootstrap, feature(let_else))]
#![recursion_limit = "256"] #![recursion_limit = "256"]
#[macro_use] #[macro_use]

View File

@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021" edition = "2021"
[lib] [lib]
doctest = false
[dependencies] [dependencies]
rustc_span = { path = "../rustc_span" } rustc_span = { path = "../rustc_span" }

View File

@ -193,9 +193,13 @@ impl<'a> State<'a> {
self.print_call_post(args) self.print_call_post(args)
} }
fn print_expr_method_call(&mut self, segment: &ast::PathSegment, args: &[P<ast::Expr>]) { fn print_expr_method_call(
let base_args = &args[1..]; &mut self,
self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX); segment: &ast::PathSegment,
receiver: &ast::Expr,
base_args: &[P<ast::Expr>],
) {
self.print_expr_maybe_paren(receiver, parser::PREC_POSTFIX);
self.word("."); self.word(".");
self.print_ident(segment.ident); self.print_ident(segment.ident);
if let Some(ref args) = segment.args { if let Some(ref args) = segment.args {
@ -303,8 +307,8 @@ impl<'a> State<'a> {
ast::ExprKind::Call(ref func, ref args) => { ast::ExprKind::Call(ref func, ref args) => {
self.print_expr_call(func, &args); self.print_expr_call(func, &args);
} }
ast::ExprKind::MethodCall(ref segment, ref args, _) => { ast::ExprKind::MethodCall(ref segment, ref receiver, ref args, _) => {
self.print_expr_method_call(segment, &args); self.print_expr_method_call(segment, &receiver, &args);
} }
ast::ExprKind::Binary(op, ref lhs, ref rhs) => { ast::ExprKind::Binary(op, ref lhs, ref rhs) => {
self.print_expr_binary(op, lhs, rhs); self.print_expr_binary(op, lhs, rhs);

View File

@ -516,7 +516,7 @@ impl<'a> State<'a> {
ast::AssocItemKind::Const(def, ty, body) => { ast::AssocItemKind::Const(def, ty, body) => {
self.print_item_const(ident, None, ty, body.as_deref(), vis, *def); self.print_item_const(ident, None, ty, body.as_deref(), vis, *def);
} }
ast::AssocItemKind::TyAlias(box ast::TyAlias { ast::AssocItemKind::Type(box ast::TyAlias {
defaultness, defaultness,
generics, generics,
where_clauses, where_clauses,

View File

@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021" edition = "2021"
[lib] [lib]
doctest = false
[dependencies] [dependencies]
rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_ast_pretty = { path = "../rustc_ast_pretty" }

View File

@ -5,7 +5,6 @@
//! to this crate. //! to this crate.
#![feature(let_chains)] #![feature(let_chains)]
#![cfg_attr(bootstrap, feature(let_else))]
#![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)] #![deny(rustc::diagnostic_outside_of_impl)]

View File

@ -2,23 +2,22 @@ use std::num::IntErrorKind;
use rustc_ast as ast; use rustc_ast as ast;
use rustc_errors::{ use rustc_errors::{
error_code, fluent, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler, error_code, fluent, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic,
}; };
use rustc_macros::SessionDiagnostic; use rustc_macros::Diagnostic;
use rustc_session::SessionDiagnostic;
use rustc_span::{Span, Symbol}; use rustc_span::{Span, Symbol};
use crate::UnsupportedLiteralReason; use crate::UnsupportedLiteralReason;
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::expected_one_cfg_pattern, code = "E0536")] #[diag(attr_expected_one_cfg_pattern, code = "E0536")]
pub(crate) struct ExpectedOneCfgPattern { pub(crate) struct ExpectedOneCfgPattern {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::invalid_predicate, code = "E0537")] #[diag(attr_invalid_predicate, code = "E0537")]
pub(crate) struct InvalidPredicate { pub(crate) struct InvalidPredicate {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
@ -26,8 +25,8 @@ pub(crate) struct InvalidPredicate {
pub predicate: String, pub predicate: String,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::multiple_item, code = "E0538")] #[diag(attr_multiple_item, code = "E0538")]
pub(crate) struct MultipleItem { pub(crate) struct MultipleItem {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
@ -35,8 +34,8 @@ pub(crate) struct MultipleItem {
pub item: String, pub item: String,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::incorrect_meta_item, code = "E0539")] #[diag(attr_incorrect_meta_item, code = "E0539")]
pub(crate) struct IncorrectMetaItem { pub(crate) struct IncorrectMetaItem {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
@ -50,44 +49,44 @@ pub(crate) struct UnknownMetaItem<'a> {
} }
// Manual implementation to be able to format `expected` items correctly. // Manual implementation to be able to format `expected` items correctly.
impl<'a> SessionDiagnostic<'a> for UnknownMetaItem<'_> { impl<'a> IntoDiagnostic<'a> for UnknownMetaItem<'_> {
fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> { fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
let expected = self.expected.iter().map(|name| format!("`{}`", name)).collect::<Vec<_>>(); let expected = self.expected.iter().map(|name| format!("`{}`", name)).collect::<Vec<_>>();
let mut diag = handler.struct_span_err_with_code( let mut diag = handler.struct_span_err_with_code(
self.span, self.span,
fluent::attr::unknown_meta_item, fluent::attr_unknown_meta_item,
error_code!(E0541), error_code!(E0541),
); );
diag.set_arg("item", self.item); diag.set_arg("item", self.item);
diag.set_arg("expected", expected.join(", ")); diag.set_arg("expected", expected.join(", "));
diag.span_label(self.span, fluent::attr::label); diag.span_label(self.span, fluent::label);
diag diag
} }
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::missing_since, code = "E0542")] #[diag(attr_missing_since, code = "E0542")]
pub(crate) struct MissingSince { pub(crate) struct MissingSince {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::missing_note, code = "E0543")] #[diag(attr_missing_note, code = "E0543")]
pub(crate) struct MissingNote { pub(crate) struct MissingNote {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::multiple_stability_levels, code = "E0544")] #[diag(attr_multiple_stability_levels, code = "E0544")]
pub(crate) struct MultipleStabilityLevels { pub(crate) struct MultipleStabilityLevels {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::invalid_issue_string, code = "E0545")] #[diag(attr_invalid_issue_string, code = "E0545")]
pub(crate) struct InvalidIssueString { pub(crate) struct InvalidIssueString {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
@ -98,33 +97,33 @@ pub(crate) struct InvalidIssueString {
// The error kinds of `IntErrorKind` are duplicated here in order to allow the messages to be // The error kinds of `IntErrorKind` are duplicated here in order to allow the messages to be
// translatable. // translatable.
#[derive(SessionSubdiagnostic)] #[derive(Subdiagnostic)]
pub(crate) enum InvalidIssueStringCause { pub(crate) enum InvalidIssueStringCause {
#[label(attr::must_not_be_zero)] #[label(must_not_be_zero)]
MustNotBeZero { MustNotBeZero {
#[primary_span] #[primary_span]
span: Span, span: Span,
}, },
#[label(attr::empty)] #[label(empty)]
Empty { Empty {
#[primary_span] #[primary_span]
span: Span, span: Span,
}, },
#[label(attr::invalid_digit)] #[label(invalid_digit)]
InvalidDigit { InvalidDigit {
#[primary_span] #[primary_span]
span: Span, span: Span,
}, },
#[label(attr::pos_overflow)] #[label(pos_overflow)]
PosOverflow { PosOverflow {
#[primary_span] #[primary_span]
span: Span, span: Span,
}, },
#[label(attr::neg_overflow)] #[label(neg_overflow)]
NegOverflow { NegOverflow {
#[primary_span] #[primary_span]
span: Span, span: Span,
@ -144,22 +143,22 @@ impl InvalidIssueStringCause {
} }
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::missing_feature, code = "E0546")] #[diag(attr_missing_feature, code = "E0546")]
pub(crate) struct MissingFeature { pub(crate) struct MissingFeature {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::non_ident_feature, code = "E0546")] #[diag(attr_non_ident_feature, code = "E0546")]
pub(crate) struct NonIdentFeature { pub(crate) struct NonIdentFeature {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::missing_issue, code = "E0547")] #[diag(attr_missing_issue, code = "E0547")]
pub(crate) struct MissingIssue { pub(crate) struct MissingIssue {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
@ -167,8 +166,8 @@ pub(crate) struct MissingIssue {
// FIXME: This diagnostic is identical to `IncorrectMetaItem`, barring the error code. Consider // FIXME: This diagnostic is identical to `IncorrectMetaItem`, barring the error code. Consider
// changing this to `IncorrectMetaItem`. See #51489. // changing this to `IncorrectMetaItem`. See #51489.
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::incorrect_meta_item, code = "E0551")] #[diag(attr_incorrect_meta_item, code = "E0551")]
pub(crate) struct IncorrectMetaItem2 { pub(crate) struct IncorrectMetaItem2 {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
@ -176,15 +175,15 @@ pub(crate) struct IncorrectMetaItem2 {
// FIXME: Why is this the same error code as `InvalidReprHintNoParen` and `InvalidReprHintNoValue`? // FIXME: Why is this the same error code as `InvalidReprHintNoParen` and `InvalidReprHintNoValue`?
// It is more similar to `IncorrectReprFormatGeneric`. // It is more similar to `IncorrectReprFormatGeneric`.
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::incorrect_repr_format_packed_one_or_zero_arg, code = "E0552")] #[diag(attr_incorrect_repr_format_packed_one_or_zero_arg, code = "E0552")]
pub(crate) struct IncorrectReprFormatPackedOneOrZeroArg { pub(crate) struct IncorrectReprFormatPackedOneOrZeroArg {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::invalid_repr_hint_no_paren, code = "E0552")] #[diag(attr_invalid_repr_hint_no_paren, code = "E0552")]
pub(crate) struct InvalidReprHintNoParen { pub(crate) struct InvalidReprHintNoParen {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
@ -192,8 +191,8 @@ pub(crate) struct InvalidReprHintNoParen {
pub name: String, pub name: String,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::invalid_repr_hint_no_value, code = "E0552")] #[diag(attr_invalid_repr_hint_no_value, code = "E0552")]
pub(crate) struct InvalidReprHintNoValue { pub(crate) struct InvalidReprHintNoValue {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
@ -209,18 +208,18 @@ pub(crate) struct UnsupportedLiteral {
pub start_point_span: Span, pub start_point_span: Span,
} }
impl<'a> SessionDiagnostic<'a> for UnsupportedLiteral { impl<'a> IntoDiagnostic<'a> for UnsupportedLiteral {
fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> { fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
let mut diag = handler.struct_span_err_with_code( let mut diag = handler.struct_span_err_with_code(
self.span, self.span,
match self.reason { match self.reason {
UnsupportedLiteralReason::Generic => fluent::attr::unsupported_literal_generic, UnsupportedLiteralReason::Generic => fluent::attr_unsupported_literal_generic,
UnsupportedLiteralReason::CfgString => fluent::attr::unsupported_literal_cfg_string, UnsupportedLiteralReason::CfgString => fluent::attr_unsupported_literal_cfg_string,
UnsupportedLiteralReason::DeprecatedString => { UnsupportedLiteralReason::DeprecatedString => {
fluent::attr::unsupported_literal_deprecated_string fluent::attr_unsupported_literal_deprecated_string
} }
UnsupportedLiteralReason::DeprecatedKvPair => { UnsupportedLiteralReason::DeprecatedKvPair => {
fluent::attr::unsupported_literal_deprecated_kv_pair fluent::attr_unsupported_literal_deprecated_kv_pair
} }
}, },
error_code!(E0565), error_code!(E0565),
@ -228,7 +227,7 @@ impl<'a> SessionDiagnostic<'a> for UnsupportedLiteral {
if self.is_bytestr { if self.is_bytestr {
diag.span_suggestion( diag.span_suggestion(
self.start_point_span, self.start_point_span,
fluent::attr::unsupported_literal_suggestion, fluent::attr_unsupported_literal_suggestion,
"", "",
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );
@ -237,16 +236,16 @@ impl<'a> SessionDiagnostic<'a> for UnsupportedLiteral {
} }
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::invalid_repr_align_need_arg, code = "E0589")] #[diag(attr_invalid_repr_align_need_arg, code = "E0589")]
pub(crate) struct InvalidReprAlignNeedArg { pub(crate) struct InvalidReprAlignNeedArg {
#[primary_span] #[primary_span]
#[suggestion(code = "align(...)", applicability = "has-placeholders")] #[suggestion(code = "align(...)", applicability = "has-placeholders")]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::invalid_repr_generic, code = "E0589")] #[diag(attr_invalid_repr_generic, code = "E0589")]
pub(crate) struct InvalidReprGeneric<'a> { pub(crate) struct InvalidReprGeneric<'a> {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
@ -255,15 +254,15 @@ pub(crate) struct InvalidReprGeneric<'a> {
pub error_part: &'a str, pub error_part: &'a str,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::incorrect_repr_format_align_one_arg, code = "E0693")] #[diag(attr_incorrect_repr_format_align_one_arg, code = "E0693")]
pub(crate) struct IncorrectReprFormatAlignOneArg { pub(crate) struct IncorrectReprFormatAlignOneArg {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::incorrect_repr_format_generic, code = "E0693")] #[diag(attr_incorrect_repr_format_generic, code = "E0693")]
pub(crate) struct IncorrectReprFormatGeneric<'a> { pub(crate) struct IncorrectReprFormatGeneric<'a> {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
@ -274,9 +273,9 @@ pub(crate) struct IncorrectReprFormatGeneric<'a> {
pub cause: Option<IncorrectReprFormatGenericCause<'a>>, pub cause: Option<IncorrectReprFormatGenericCause<'a>>,
} }
#[derive(SessionSubdiagnostic)] #[derive(Subdiagnostic)]
pub(crate) enum IncorrectReprFormatGenericCause<'a> { pub(crate) enum IncorrectReprFormatGenericCause<'a> {
#[suggestion(attr::suggestion, code = "{name}({int})", applicability = "machine-applicable")] #[suggestion(suggestion, code = "{name}({int})", applicability = "machine-applicable")]
Int { Int {
#[primary_span] #[primary_span]
span: Span, span: Span,
@ -288,11 +287,7 @@ pub(crate) enum IncorrectReprFormatGenericCause<'a> {
int: u128, int: u128,
}, },
#[suggestion( #[suggestion(suggestion, code = "{name}({symbol})", applicability = "machine-applicable")]
attr::suggestion,
code = "{name}({symbol})",
applicability = "machine-applicable"
)]
Symbol { Symbol {
#[primary_span] #[primary_span]
span: Span, span: Span,
@ -317,29 +312,29 @@ impl<'a> IncorrectReprFormatGenericCause<'a> {
} }
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::rustc_promotable_pairing, code = "E0717")] #[diag(attr_rustc_promotable_pairing, code = "E0717")]
pub(crate) struct RustcPromotablePairing { pub(crate) struct RustcPromotablePairing {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::rustc_allowed_unstable_pairing, code = "E0789")] #[diag(attr_rustc_allowed_unstable_pairing, code = "E0789")]
pub(crate) struct RustcAllowedUnstablePairing { pub(crate) struct RustcAllowedUnstablePairing {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::cfg_predicate_identifier)] #[diag(attr_cfg_predicate_identifier)]
pub(crate) struct CfgPredicateIdentifier { pub(crate) struct CfgPredicateIdentifier {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::deprecated_item_suggestion)] #[diag(attr_deprecated_item_suggestion)]
pub(crate) struct DeprecatedItemSuggestion { pub(crate) struct DeprecatedItemSuggestion {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
@ -351,22 +346,22 @@ pub(crate) struct DeprecatedItemSuggestion {
pub details: (), pub details: (),
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::expected_single_version_literal)] #[diag(attr_expected_single_version_literal)]
pub(crate) struct ExpectedSingleVersionLiteral { pub(crate) struct ExpectedSingleVersionLiteral {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::expected_version_literal)] #[diag(attr_expected_version_literal)]
pub(crate) struct ExpectedVersionLiteral { pub(crate) struct ExpectedVersionLiteral {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::expects_feature_list)] #[diag(attr_expects_feature_list)]
pub(crate) struct ExpectsFeatureList { pub(crate) struct ExpectsFeatureList {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
@ -374,8 +369,8 @@ pub(crate) struct ExpectsFeatureList {
pub name: String, pub name: String,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::expects_features)] #[diag(attr_expects_features)]
pub(crate) struct ExpectsFeatures { pub(crate) struct ExpectsFeatures {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
@ -383,15 +378,15 @@ pub(crate) struct ExpectsFeatures {
pub name: String, pub name: String,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::soft_no_args)] #[diag(attr_soft_no_args)]
pub(crate) struct SoftNoArgs { pub(crate) struct SoftNoArgs {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(attr::unknown_version_literal)] #[diag(attr_unknown_version_literal)]
pub(crate) struct UnknownVersionLiteral { pub(crate) struct UnknownVersionLiteral {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,

View File

@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021" edition = "2021"
[lib] [lib]
doctest = false
[dependencies] [dependencies]
either = "1.5.0" either = "1.5.0"

View File

@ -14,8 +14,8 @@ use crate::{
places_conflict, region_infer::values::LivenessValues, places_conflict, region_infer::values::LivenessValues,
}; };
pub(super) fn generate_constraints<'cx, 'tcx>( pub(super) fn generate_constraints<'tcx>(
infcx: &InferCtxt<'cx, 'tcx>, infcx: &InferCtxt<'tcx>,
liveness_constraints: &mut LivenessValues<RegionVid>, liveness_constraints: &mut LivenessValues<RegionVid>,
all_facts: &mut Option<AllFacts>, all_facts: &mut Option<AllFacts>,
location_table: &LocationTable, location_table: &LocationTable,
@ -37,8 +37,8 @@ pub(super) fn generate_constraints<'cx, 'tcx>(
} }
/// 'cg = the duration of the constraint generation process itself. /// 'cg = the duration of the constraint generation process itself.
struct ConstraintGeneration<'cg, 'cx, 'tcx> { struct ConstraintGeneration<'cg, 'tcx> {
infcx: &'cg InferCtxt<'cx, 'tcx>, infcx: &'cg InferCtxt<'tcx>,
all_facts: &'cg mut Option<AllFacts>, all_facts: &'cg mut Option<AllFacts>,
location_table: &'cg LocationTable, location_table: &'cg LocationTable,
liveness_constraints: &'cg mut LivenessValues<RegionVid>, liveness_constraints: &'cg mut LivenessValues<RegionVid>,
@ -46,7 +46,7 @@ struct ConstraintGeneration<'cg, 'cx, 'tcx> {
body: &'cg Body<'tcx>, body: &'cg Body<'tcx>,
} }
impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> { impl<'cg, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'tcx> {
fn visit_basic_block_data(&mut self, bb: BasicBlock, data: &BasicBlockData<'tcx>) { fn visit_basic_block_data(&mut self, bb: BasicBlock, data: &BasicBlockData<'tcx>) {
self.super_basic_block_data(bb, data); self.super_basic_block_data(bb, data);
} }
@ -156,7 +156,7 @@ impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> {
} }
} }
impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> { impl<'cx, 'tcx> ConstraintGeneration<'cx, 'tcx> {
/// Some variable with type `live_ty` is "regular live" at /// Some variable with type `live_ty` is "regular live" at
/// `location` -- i.e., it may be used later. This means that all /// `location` -- i.e., it may be used later. This means that all
/// regions appearing in the type `live_ty` must be live at /// regions appearing in the type `live_ty` must be live at

View File

@ -31,9 +31,8 @@ pub fn get_body_with_borrowck_facts<'tcx>(
def: ty::WithOptConstParam<LocalDefId>, def: ty::WithOptConstParam<LocalDefId>,
) -> BodyWithBorrowckFacts<'tcx> { ) -> BodyWithBorrowckFacts<'tcx> {
let (input_body, promoted) = tcx.mir_promoted(def); let (input_body, promoted) = tcx.mir_promoted(def);
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def.did)).enter(|infcx| { let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def.did)).build();
let input_body: &Body<'_> = &input_body.borrow(); let input_body: &Body<'_> = &input_body.borrow();
let promoted: &IndexVec<_, _> = &promoted.borrow(); let promoted: &IndexVec<_, _> = &promoted.borrow();
*super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap() *super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap()
})
} }

View File

@ -56,7 +56,7 @@ impl<'tcx> UniverseInfo<'tcx> {
) { ) {
match self.0 { match self.0 {
UniverseInfoInner::RelateTys { expected, found } => { UniverseInfoInner::RelateTys { expected, found } => {
let err = mbcx.infcx.report_mismatched_types( let err = mbcx.infcx.err_ctxt().report_mismatched_types(
&cause, &cause,
expected, expected,
found, found,
@ -238,20 +238,11 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
placeholder_region: ty::Region<'tcx>, placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>, error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
mbcx.infcx.tcx.infer_ctxt().enter_with_canonical( let (ref infcx, key, _) =
cause.span, mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
&self.canonical_query,
|ref infcx, key, _| {
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx); let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
type_op_prove_predicate_with_cause(infcx, &mut *fulfill_cx, key, cause); type_op_prove_predicate_with_cause(infcx, &mut *fulfill_cx, key, cause);
try_extract_error_from_fulfill_cx( try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
fulfill_cx,
infcx,
placeholder_region,
error_region,
)
},
)
} }
} }
@ -288,10 +279,8 @@ where
placeholder_region: ty::Region<'tcx>, placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>, error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
mbcx.infcx.tcx.infer_ctxt().enter_with_canonical( let (ref infcx, key, _) =
cause.span, mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
&self.canonical_query,
|ref infcx, key, _| {
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx); let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
let mut selcx = SelectionContext::new(infcx); let mut selcx = SelectionContext::new(infcx);
@ -303,22 +292,11 @@ where
// to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` test. Check // to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` test. Check
// after #85499 lands to see if its fixes have erased this difference. // after #85499 lands to see if its fixes have erased this difference.
let (param_env, value) = key.into_parts(); let (param_env, value) = key.into_parts();
let Normalized { value: _, obligations } = rustc_trait_selection::traits::normalize( let Normalized { value: _, obligations } =
&mut selcx, rustc_trait_selection::traits::normalize(&mut selcx, param_env, cause, value.value);
param_env,
cause,
value.value,
);
fulfill_cx.register_predicate_obligations(infcx, obligations); fulfill_cx.register_predicate_obligations(infcx, obligations);
try_extract_error_from_fulfill_cx( try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
fulfill_cx,
infcx,
placeholder_region,
error_region,
)
},
)
} }
} }
@ -349,21 +327,11 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
placeholder_region: ty::Region<'tcx>, placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>, error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
mbcx.infcx.tcx.infer_ctxt().enter_with_canonical( let (ref infcx, key, _) =
cause.span, mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
&self.canonical_query,
|ref infcx, key, _| {
let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx); let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
type_op_ascribe_user_type_with_span(infcx, &mut *fulfill_cx, key, Some(cause.span)) type_op_ascribe_user_type_with_span(infcx, &mut *fulfill_cx, key, Some(cause.span)).ok()?;
.ok()?; try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
try_extract_error_from_fulfill_cx(
fulfill_cx,
infcx,
placeholder_region,
error_region,
)
},
)
} }
} }
@ -407,7 +375,7 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
#[instrument(skip(fulfill_cx, infcx), level = "debug")] #[instrument(skip(fulfill_cx, infcx), level = "debug")]
fn try_extract_error_from_fulfill_cx<'tcx>( fn try_extract_error_from_fulfill_cx<'tcx>(
mut fulfill_cx: Box<dyn TraitEngine<'tcx> + 'tcx>, mut fulfill_cx: Box<dyn TraitEngine<'tcx> + 'tcx>,
infcx: &InferCtxt<'_, 'tcx>, infcx: &InferCtxt<'tcx>,
placeholder_region: ty::Region<'tcx>, placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>, error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
@ -427,7 +395,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
} }
fn try_extract_error_from_region_constraints<'tcx>( fn try_extract_error_from_region_constraints<'tcx>(
infcx: &InferCtxt<'_, 'tcx>, infcx: &InferCtxt<'tcx>,
placeholder_region: ty::Region<'tcx>, placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>, error_region: Option<ty::Region<'tcx>>,
region_constraints: &RegionConstraintData<'tcx>, region_constraints: &RegionConstraintData<'tcx>,
@ -449,10 +417,8 @@ fn try_extract_error_from_region_constraints<'tcx>(
})?; })?;
debug!(?sub_region, "cause = {:#?}", cause); debug!(?sub_region, "cause = {:#?}", cause);
let nice_error = match (error_region, *sub_region) { let error = match (error_region, *sub_region) {
(Some(error_region), ty::ReVar(vid)) => NiceRegionError::new( (Some(error_region), ty::ReVar(vid)) => RegionResolutionError::SubSupConflict(
infcx,
RegionResolutionError::SubSupConflict(
vid, vid,
region_var_origin(vid), region_var_origin(vid),
cause.clone(), cause.clone(),
@ -461,30 +427,28 @@ fn try_extract_error_from_region_constraints<'tcx>(
placeholder_region, placeholder_region,
vec![], vec![],
), ),
), (Some(error_region), _) => {
(Some(error_region), _) => NiceRegionError::new( RegionResolutionError::ConcreteFailure(cause.clone(), error_region, placeholder_region)
infcx, }
RegionResolutionError::ConcreteFailure(cause.clone(), error_region, placeholder_region),
),
// Note universe here is wrong... // Note universe here is wrong...
(None, ty::ReVar(vid)) => NiceRegionError::new( (None, ty::ReVar(vid)) => RegionResolutionError::UpperBoundUniverseConflict(
infcx,
RegionResolutionError::UpperBoundUniverseConflict(
vid, vid,
region_var_origin(vid), region_var_origin(vid),
universe_of_region(vid), universe_of_region(vid),
cause.clone(), cause.clone(),
placeholder_region, placeholder_region,
), ),
), (None, _) => {
(None, _) => NiceRegionError::new( RegionResolutionError::ConcreteFailure(cause.clone(), sub_region, placeholder_region)
infcx, }
RegionResolutionError::ConcreteFailure(cause.clone(), sub_region, placeholder_region),
),
}; };
nice_error.try_report_from_nll().or_else(|| { NiceRegionError::new(&infcx.err_ctxt(), error).try_report_from_nll().or_else(|| {
if let SubregionOrigin::Subtype(trace) = cause { if let SubregionOrigin::Subtype(trace) = cause {
Some(infcx.report_and_explain_type_error(*trace, TypeError::RegionsPlaceholderMismatch)) Some(
infcx
.err_ctxt()
.report_and_explain_type_error(*trace, TypeError::RegionsPlaceholderMismatch),
)
} else { } else {
None None
} }

View File

@ -16,7 +16,7 @@ use rustc_middle::mir::{
FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef, FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
}; };
use rustc_middle::ty::{self, subst::Subst, suggest_constraining_type_params, PredicateKind, Ty}; use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty};
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex}; use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
use rustc_span::def_id::LocalDefId; use rustc_span::def_id::LocalDefId;
use rustc_span::hygiene::DesugaringKind; use rustc_span::hygiene::DesugaringKind;
@ -198,7 +198,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
move_span, move_span,
move_spans, move_spans,
*moved_place, *moved_place,
Some(used_place),
partially_str, partially_str,
loop_message, loop_message,
move_msg, move_msg,
@ -369,6 +368,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let mut visitor = ConditionVisitor { spans: &spans, name: &name, errors: vec![] }; let mut visitor = ConditionVisitor { spans: &spans, name: &name, errors: vec![] };
visitor.visit_body(&body); visitor.visit_body(&body);
let mut show_assign_sugg = false;
let isnt_initialized = if let InitializationRequiringAction::PartialAssignment let isnt_initialized = if let InitializationRequiringAction::PartialAssignment
| InitializationRequiringAction::Assignment = desired_action | InitializationRequiringAction::Assignment = desired_action
{ {
@ -396,6 +396,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
.count() .count()
== 0 == 0
{ {
show_assign_sugg = true;
"isn't initialized" "isn't initialized"
} else { } else {
"is possibly-uninitialized" "is possibly-uninitialized"
@ -446,10 +447,84 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} }
} }
} }
err.span_label(decl_span, "binding declared here but left uninitialized"); err.span_label(decl_span, "binding declared here but left uninitialized");
if show_assign_sugg {
struct LetVisitor {
decl_span: Span,
sugg_span: Option<Span>,
}
impl<'v> Visitor<'v> for LetVisitor {
fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
if self.sugg_span.is_some() {
return;
}
if let hir::StmtKind::Local(hir::Local {
span, ty, init: None, ..
}) = &ex.kind && span.contains(self.decl_span) {
self.sugg_span = ty.map_or(Some(self.decl_span), |ty| Some(ty.span));
}
hir::intravisit::walk_stmt(self, ex);
}
}
let mut visitor = LetVisitor { decl_span, sugg_span: None };
visitor.visit_body(&body);
if let Some(span) = visitor.sugg_span {
self.suggest_assign_value(&mut err, moved_place, span);
}
}
err err
} }
fn suggest_assign_value(
&self,
err: &mut Diagnostic,
moved_place: PlaceRef<'tcx>,
sugg_span: Span,
) {
let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
debug!("ty: {:?}, kind: {:?}", ty, ty.kind());
let tcx = self.infcx.tcx;
let implements_default = |ty, param_env| {
let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
return false;
};
// Regions are already solved, so we must use a fresh InferCtxt,
// but the type has region variables, so erase those.
tcx.infer_ctxt()
.build()
.type_implements_trait(
default_trait,
tcx.erase_regions(ty),
ty::List::empty(),
param_env,
)
.must_apply_modulo_regions()
};
let assign_value = match ty.kind() {
ty::Bool => "false",
ty::Float(_) => "0.0",
ty::Int(_) | ty::Uint(_) => "0",
ty::Never | ty::Error(_) => "",
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Vec) => "vec![]",
ty::Adt(_, _) if implements_default(ty, self.param_env) => "Default::default()",
_ => "todo!()",
};
if !assign_value.is_empty() {
err.span_suggestion_verbose(
sugg_span.shrink_to_hi(),
format!("consider assigning a value"),
format!(" = {}", assign_value),
Applicability::MaybeIncorrect,
);
}
}
fn suggest_borrow_fn_like( fn suggest_borrow_fn_like(
&self, &self,
err: &mut Diagnostic, err: &mut Diagnostic,
@ -537,7 +612,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
.and_then(|def_id| tcx.hir().get_generics(def_id)) .and_then(|def_id| tcx.hir().get_generics(def_id))
else { return; }; else { return; };
// Try to find predicates on *generic params* that would allow copying `ty` // Try to find predicates on *generic params* that would allow copying `ty`
let predicates: Result<Vec<_>, _> = tcx.infer_ctxt().enter(|infcx| { let infcx = tcx.infer_ctxt().build();
let mut fulfill_cx = <dyn rustc_infer::traits::TraitEngine<'_>>::new(infcx.tcx); let mut fulfill_cx = <dyn rustc_infer::traits::TraitEngine<'_>>::new(infcx.tcx);
let copy_did = infcx.tcx.lang_items().copy_trait().unwrap(); let copy_did = infcx.tcx.lang_items().copy_trait().unwrap();
@ -558,7 +633,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let errors = fulfill_cx.select_all_or_error(&infcx); let errors = fulfill_cx.select_all_or_error(&infcx);
// Only emit suggestion if all required predicates are on generic // Only emit suggestion if all required predicates are on generic
errors let predicates: Result<Vec<_>, _> = errors
.into_iter() .into_iter()
.map(|err| match err.obligation.predicate.kind().skip_binder() { .map(|err| match err.obligation.predicate.kind().skip_binder() {
PredicateKind::Trait(predicate) => match predicate.self_ty().kind() { PredicateKind::Trait(predicate) => match predicate.self_ty().kind() {
@ -570,8 +645,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}, },
_ => Err(()), _ => Err(()),
}) })
.collect() .collect();
});
if let Ok(predicates) = predicates { if let Ok(predicates) = predicates {
suggest_constraining_type_params( suggest_constraining_type_params(
@ -2146,7 +2220,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} }
StorageDeadOrDrop::Destructor(_) => kind, StorageDeadOrDrop::Destructor(_) => kind,
}, },
ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => { ProjectionElem::OpaqueCast { .. }
| ProjectionElem::Field(..)
| ProjectionElem::Downcast(..) => {
match place_ty.ty.kind() { match place_ty.ty.kind() {
ty::Adt(def, _) if def.has_dtor(tcx) => { ty::Adt(def, _) if def.has_dtor(tcx) => {
// Report the outermost adt with a destructor // Report the outermost adt with a destructor

View File

@ -1,8 +1,5 @@
//! Print diagnostics to explain why values are borrowed. //! Print diagnostics to explain why values are borrowed.
use std::collections::VecDeque;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{Applicability, Diagnostic}; use rustc_errors::{Applicability, Diagnostic};
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
use rustc_infer::infer::NllRegionVariableOrigin; use rustc_infer::infer::NllRegionVariableOrigin;
@ -359,19 +356,37 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let borrow_region_vid = borrow.region; let borrow_region_vid = borrow.region;
debug!(?borrow_region_vid); debug!(?borrow_region_vid);
let region_sub = self.regioncx.find_sub_region_live_at(borrow_region_vid, location); let mut region_sub = self.regioncx.find_sub_region_live_at(borrow_region_vid, location);
debug!(?region_sub); debug!(?region_sub);
match find_use::find(body, regioncx, tcx, region_sub, location) { let mut use_location = location;
let mut use_in_later_iteration_of_loop = false;
if region_sub == borrow_region_vid {
// When `region_sub` is the same as `borrow_region_vid` (the location where the borrow is
// issued is the same location that invalidates the reference), this is likely a loop iteration
// - in this case, try using the loop terminator location in `find_sub_region_live_at`.
if let Some(loop_terminator_location) =
regioncx.find_loop_terminator_location(borrow.region, body)
{
region_sub = self
.regioncx
.find_sub_region_live_at(borrow_region_vid, loop_terminator_location);
debug!("explain_why_borrow_contains_point: region_sub in loop={:?}", region_sub);
use_location = loop_terminator_location;
use_in_later_iteration_of_loop = true;
}
}
match find_use::find(body, regioncx, tcx, region_sub, use_location) {
Some(Cause::LiveVar(local, location)) => { Some(Cause::LiveVar(local, location)) => {
let span = body.source_info(location).span; let span = body.source_info(location).span;
let spans = self let spans = self
.move_spans(Place::from(local).as_ref(), location) .move_spans(Place::from(local).as_ref(), location)
.or_else(|| self.borrow_spans(span, location)); .or_else(|| self.borrow_spans(span, location));
let borrow_location = location; if use_in_later_iteration_of_loop {
if self.is_use_in_later_iteration_of_loop(borrow_location, location) { let later_use = self.later_use_kind(borrow, spans, use_location);
let later_use = self.later_use_kind(borrow, spans, location);
BorrowExplanation::UsedLaterInLoop(later_use.0, later_use.1, later_use.2) BorrowExplanation::UsedLaterInLoop(later_use.0, later_use.1, later_use.2)
} else { } else {
// Check if the location represents a `FakeRead`, and adapt the error // Check if the location represents a `FakeRead`, and adapt the error
@ -425,131 +440,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} }
} }
/// true if `borrow_location` can reach `use_location` by going through a loop and
/// `use_location` is also inside of that loop
fn is_use_in_later_iteration_of_loop(
&self,
borrow_location: Location,
use_location: Location,
) -> bool {
let back_edge = self.reach_through_backedge(borrow_location, use_location);
back_edge.map_or(false, |back_edge| self.can_reach_head_of_loop(use_location, back_edge))
}
/// Returns the outmost back edge if `from` location can reach `to` location passing through
/// that back edge
fn reach_through_backedge(&self, from: Location, to: Location) -> Option<Location> {
let mut visited_locations = FxHashSet::default();
let mut pending_locations = VecDeque::new();
visited_locations.insert(from);
pending_locations.push_back(from);
debug!("reach_through_backedge: from={:?} to={:?}", from, to,);
let mut outmost_back_edge = None;
while let Some(location) = pending_locations.pop_front() {
debug!(
"reach_through_backedge: location={:?} outmost_back_edge={:?}
pending_locations={:?} visited_locations={:?}",
location, outmost_back_edge, pending_locations, visited_locations
);
if location == to && outmost_back_edge.is_some() {
// We've managed to reach the use location
debug!("reach_through_backedge: found!");
return outmost_back_edge;
}
let block = &self.body.basic_blocks[location.block];
if location.statement_index < block.statements.len() {
let successor = location.successor_within_block();
if visited_locations.insert(successor) {
pending_locations.push_back(successor);
}
} else {
pending_locations.extend(
block
.terminator()
.successors()
.map(|bb| Location { statement_index: 0, block: bb })
.filter(|s| visited_locations.insert(*s))
.map(|s| {
if self.is_back_edge(location, s) {
match outmost_back_edge {
None => {
outmost_back_edge = Some(location);
}
Some(back_edge)
if location.dominates(back_edge, &self.dominators) =>
{
outmost_back_edge = Some(location);
}
Some(_) => {}
}
}
s
}),
);
}
}
None
}
/// true if `from` location can reach `loop_head` location and `loop_head` dominates all the
/// intermediate nodes
fn can_reach_head_of_loop(&self, from: Location, loop_head: Location) -> bool {
self.find_loop_head_dfs(from, loop_head, &mut FxHashSet::default())
}
fn find_loop_head_dfs(
&self,
from: Location,
loop_head: Location,
visited_locations: &mut FxHashSet<Location>,
) -> bool {
visited_locations.insert(from);
if from == loop_head {
return true;
}
if loop_head.dominates(from, &self.dominators) {
let block = &self.body.basic_blocks[from.block];
if from.statement_index < block.statements.len() {
let successor = from.successor_within_block();
if !visited_locations.contains(&successor)
&& self.find_loop_head_dfs(successor, loop_head, visited_locations)
{
return true;
}
} else {
for bb in block.terminator().successors() {
let successor = Location { statement_index: 0, block: bb };
if !visited_locations.contains(&successor)
&& self.find_loop_head_dfs(successor, loop_head, visited_locations)
{
return true;
}
}
}
}
false
}
/// True if an edge `source -> target` is a backedge -- in other words, if the target
/// dominates the source.
fn is_back_edge(&self, source: Location, target: Location) -> bool {
target.dominates(source, &self.dominators)
}
/// Determine how the borrow was later used. /// Determine how the borrow was later used.
/// First span returned points to the location of the conflicting use /// First span returned points to the location of the conflicting use
/// Second span if `Some` is returned in the case of closures and points /// Second span if `Some` is returned in the case of closures and points

View File

@ -237,6 +237,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} }
ProjectionElem::Downcast(..) if opt.including_downcast => return None, ProjectionElem::Downcast(..) if opt.including_downcast => return None,
ProjectionElem::Downcast(..) => (), ProjectionElem::Downcast(..) => (),
ProjectionElem::OpaqueCast(..) => (),
ProjectionElem::Field(field, _ty) => { ProjectionElem::Field(field, _ty) => {
// FIXME(project-rfc_2229#36): print capture precisely here. // FIXME(project-rfc_2229#36): print capture precisely here.
if let Some(field) = self.is_upvar_field_projection(PlaceRef { if let Some(field) = self.is_upvar_field_projection(PlaceRef {
@ -317,6 +318,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
PlaceRef { local, projection: proj_base }.ty(self.body, self.infcx.tcx) PlaceRef { local, projection: proj_base }.ty(self.body, self.infcx.tcx)
} }
ProjectionElem::Downcast(..) => place.ty(self.body, self.infcx.tcx), ProjectionElem::Downcast(..) => place.ty(self.body, self.infcx.tcx),
ProjectionElem::OpaqueCast(ty) => PlaceTy::from_ty(*ty),
ProjectionElem::Field(_, field_type) => PlaceTy::from_ty(*field_type), ProjectionElem::Field(_, field_type) => PlaceTy::from_ty(*field_type),
}, },
}; };
@ -970,7 +972,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
move_span: Span, move_span: Span,
move_spans: UseSpans<'tcx>, move_spans: UseSpans<'tcx>,
moved_place: Place<'tcx>, moved_place: Place<'tcx>,
used_place: Option<PlaceRef<'tcx>>,
partially_str: &str, partially_str: &str,
loop_message: &str, loop_message: &str,
move_msg: &str, move_msg: &str,
@ -1024,7 +1025,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring { if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring {
let ty = moved_place.ty(self.body, self.infcx.tcx).ty; let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
let suggest = match self.infcx.tcx.get_diagnostic_item(sym::IntoIterator) { let suggest = match self.infcx.tcx.get_diagnostic_item(sym::IntoIterator) {
Some(def_id) => self.infcx.tcx.infer_ctxt().enter(|infcx| { Some(def_id) => {
let infcx = self.infcx.tcx.infer_ctxt().build();
type_known_to_meet_bound_modulo_regions( type_known_to_meet_bound_modulo_regions(
&infcx, &infcx,
self.param_env, self.param_env,
@ -1035,7 +1037,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
def_id, def_id,
DUMMY_SP, DUMMY_SP,
) )
}), }
_ => false, _ => false,
}; };
if suggest { if suggest {
@ -1058,9 +1060,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
place_name, partially_str, loop_message place_name, partially_str, loop_message
), ),
); );
// If we have a `&mut` ref, we need to reborrow. // If the moved place was a `&mut` ref, then we can
if let Some(ty::Ref(_, _, hir::Mutability::Mut)) = used_place // suggest to reborrow it where it was moved, so it
.map(|used_place| used_place.ty(self.body, self.infcx.tcx).ty.kind()) // will still be valid by the time we get to the usage.
if let ty::Ref(_, _, hir::Mutability::Mut) =
moved_place.ty(self.body, self.infcx.tcx).ty.kind()
{ {
// If we are in a loop this will be suggested later. // If we are in a loop this will be suggested later.
if !is_loop_move { if !is_loop_move {

View File

@ -401,7 +401,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}; };
if let Some(use_spans) = use_spans { if let Some(use_spans) = use_spans {
self.explain_captures( self.explain_captures(
&mut err, span, span, use_spans, move_place, None, "", "", "", false, true, &mut err, span, span, use_spans, move_place, "", "", "", false, true,
); );
} }
err err

View File

@ -169,6 +169,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
.., ..,
ProjectionElem::Index(_) ProjectionElem::Index(_)
| ProjectionElem::ConstantIndex { .. } | ProjectionElem::ConstantIndex { .. }
| ProjectionElem::OpaqueCast { .. }
| ProjectionElem::Subslice { .. } | ProjectionElem::Subslice { .. }
| ProjectionElem::Downcast(..), | ProjectionElem::Downcast(..),
], ],
@ -931,7 +932,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let opt_suggestions = self let opt_suggestions = self
.infcx .infcx
.tcx .tcx
.typeck(path_segment.hir_id.owner) .typeck(path_segment.hir_id.owner.def_id)
.type_dependent_def_id(*hir_id) .type_dependent_def_id(*hir_id)
.and_then(|def_id| self.infcx.tcx.impl_of_method(def_id)) .and_then(|def_id| self.infcx.tcx.impl_of_method(def_id))
.map(|def_id| self.infcx.tcx.associated_items(def_id)) .map(|def_id| self.infcx.tcx.associated_items(def_id))
@ -1031,7 +1032,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if look_at_return && hir.get_return_block(closure_id).is_some() { if look_at_return && hir.get_return_block(closure_id).is_some() {
// ...otherwise we are probably in the tail expression of the function, point at the // ...otherwise we are probably in the tail expression of the function, point at the
// return type. // return type.
match hir.get_by_def_id(hir.get_parent_item(fn_call_id)) { match hir.get_by_def_id(hir.get_parent_item(fn_call_id).def_id) {
hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(sig, ..), .. }) hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(sig, ..), .. })
| hir::Node::TraitItem(hir::TraitItem { | hir::Node::TraitItem(hir::TraitItem {
ident, ident,

View File

@ -186,7 +186,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if let Some(lower_bound_region) = lower_bound_region { if let Some(lower_bound_region) = lower_bound_region {
let generic_ty = type_test.generic_kind.to_ty(self.infcx.tcx); let generic_ty = type_test.generic_kind.to_ty(self.infcx.tcx);
let origin = RelateParamBound(type_test_span, generic_ty, None); let origin = RelateParamBound(type_test_span, generic_ty, None);
self.buffer_error(self.infcx.construct_generic_bound_failure( self.buffer_error(self.infcx.err_ctxt().construct_generic_bound_failure(
self.body.source.def_id().expect_local(), self.body.source.def_id().expect_local(),
type_test_span, type_test_span,
Some(origin), Some(origin),
@ -281,7 +281,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let tcx = self.infcx.tcx; let tcx = self.infcx.tcx;
match tcx.hir().get_if_local(def_id) { match tcx.hir().get_if_local(def_id) {
Some(Node::ImplItem(impl_item)) => { Some(Node::ImplItem(impl_item)) => {
match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id())) { match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id()).def_id)
{
Some(Node::Item(Item { Some(Node::Item(Item {
kind: ItemKind::Impl(hir::Impl { self_ty, .. }), kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
.. ..
@ -291,7 +292,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
} }
Some(Node::TraitItem(trait_item)) => { Some(Node::TraitItem(trait_item)) => {
let trait_did = tcx.hir().get_parent_item(trait_item.hir_id()); let trait_did = tcx.hir().get_parent_item(trait_item.hir_id());
match tcx.hir().find_by_def_id(trait_did) { match tcx.hir().find_by_def_id(trait_did.def_id) {
Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => { Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => {
// The method being called is defined in the `trait`, but the `'static` // The method being called is defined in the `trait`, but the `'static`
// obligation comes from the `impl`. Find that `impl` so that we can point // obligation comes from the `impl`. Find that `impl` so that we can point
@ -340,7 +341,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
/// Report an error because the universal region `fr` was required to outlive /// Report an error because the universal region `fr` was required to outlive
/// `outlived_fr` but it is not known to do so. For example: /// `outlived_fr` but it is not known to do so. For example:
/// ///
/// ```compile_fail,E0312 /// ```compile_fail
/// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x } /// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
/// ``` /// ```
/// ///
@ -364,7 +365,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
// Check if we can use one of the "nice region errors". // Check if we can use one of the "nice region errors".
if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) { if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
let nice = NiceRegionError::new_from_span(self.infcx, cause.span, o, f); let infer_err = self.infcx.err_ctxt();
let nice = NiceRegionError::new_from_span(&infer_err, cause.span, o, f);
if let Some(diag) = nice.try_report_from_nll() { if let Some(diag) = nice.try_report_from_nll() {
self.buffer_error(diag); self.buffer_error(diag);
return; return;

View File

@ -251,7 +251,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
.or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(fr)) .or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(fr))
.or_else(|| self.give_name_if_anonymous_region_appears_in_output(fr)) .or_else(|| self.give_name_if_anonymous_region_appears_in_output(fr))
.or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(fr)) .or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(fr))
.or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr)); .or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr))
.or_else(|| self.give_name_if_anonymous_region_appears_in_arg_position_impl_trait(fr));
if let Some(ref value) = value { if let Some(ref value) = value {
self.region_names.try_borrow_mut().unwrap().insert(fr, value.clone()); self.region_names.try_borrow_mut().unwrap().insert(fr, value.clone());
@ -707,7 +708,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
hir::AsyncGeneratorKind::Block => " of async block", hir::AsyncGeneratorKind::Block => " of async block",
hir::AsyncGeneratorKind::Closure => " of async closure", hir::AsyncGeneratorKind::Closure => " of async closure",
hir::AsyncGeneratorKind::Fn => { hir::AsyncGeneratorKind::Fn => {
let parent_item = hir.get_by_def_id(hir.get_parent_item(mir_hir_id)); let parent_item =
hir.get_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
let output = &parent_item let output = &parent_item
.fn_decl() .fn_decl()
.expect("generator lowered from async fn should be in fn") .expect("generator lowered from async fn should be in fn")
@ -863,20 +865,13 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
}; };
let tcx = self.infcx.tcx; let tcx = self.infcx.tcx;
let body_parent_did = tcx.opt_parent(self.mir_def_id().to_def_id())?; let region_parent = tcx.parent(region.def_id);
if tcx.parent(region.def_id) != body_parent_did if tcx.def_kind(region_parent) != DefKind::Impl {
|| tcx.def_kind(body_parent_did) != DefKind::Impl
{
return None; return None;
} }
let mut found = false; let found = tcx
tcx.fold_regions(tcx.type_of(body_parent_did), |r: ty::Region<'tcx>, _| { .any_free_region_meets(&tcx.type_of(region_parent), |r| *r == ty::ReEarlyBound(region));
if *r == ty::ReEarlyBound(region) {
found = true;
}
r
});
Some(RegionName { Some(RegionName {
name: self.synthesize_region_name(), name: self.synthesize_region_name(),
@ -889,4 +884,92 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
), ),
}) })
} }
fn give_name_if_anonymous_region_appears_in_arg_position_impl_trait(
&self,
fr: RegionVid,
) -> Option<RegionName> {
let ty::ReEarlyBound(region) = *self.to_error_region(fr)? else {
return None;
};
if region.has_name() {
return None;
};
let predicates = self
.infcx
.tcx
.predicates_of(self.body.source.def_id())
.instantiate_identity(self.infcx.tcx)
.predicates;
if let Some(upvar_index) = self
.regioncx
.universal_regions()
.defining_ty
.upvar_tys()
.position(|ty| self.any_param_predicate_mentions(&predicates, ty, region))
{
let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(
self.infcx.tcx,
&self.upvars,
upvar_index,
);
let region_name = self.synthesize_region_name();
Some(RegionName {
name: region_name,
source: RegionNameSource::AnonRegionFromUpvar(upvar_span, upvar_name),
})
} else if let Some(arg_index) = self
.regioncx
.universal_regions()
.unnormalized_input_tys
.iter()
.position(|ty| self.any_param_predicate_mentions(&predicates, *ty, region))
{
let (arg_name, arg_span) = self.regioncx.get_argument_name_and_span_for_region(
self.body,
&self.local_names,
arg_index,
);
let region_name = self.synthesize_region_name();
Some(RegionName {
name: region_name,
source: RegionNameSource::AnonRegionFromArgument(
RegionNameHighlight::CannotMatchHirTy(arg_span, arg_name?.to_string()),
),
})
} else {
None
}
}
fn any_param_predicate_mentions(
&self,
predicates: &[ty::Predicate<'tcx>],
ty: Ty<'tcx>,
region: ty::EarlyBoundRegion,
) -> bool {
let tcx = self.infcx.tcx;
ty.walk().any(|arg| {
if let ty::GenericArgKind::Type(ty) = arg.unpack()
&& let ty::Param(_) = ty.kind()
{
predicates.iter().any(|pred| {
match pred.kind().skip_binder() {
ty::PredicateKind::Trait(data) if data.self_ty() == ty => {}
ty::PredicateKind::Projection(data) if data.projection_ty.self_ty() == ty => {}
_ => return false,
}
tcx.any_free_region_meets(pred, |r| {
*r == ty::ReEarlyBound(region)
})
})
} else {
false
}
})
}
} }

View File

@ -3,7 +3,6 @@
#![allow(rustc::potential_query_instability)] #![allow(rustc::potential_query_instability)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(let_chains)] #![feature(let_chains)]
#![cfg_attr(bootstrap, feature(let_else))]
#![feature(min_specialization)] #![feature(min_specialization)]
#![feature(never_type)] #![feature(never_type)]
#![feature(rustc_attrs)] #![feature(rustc_attrs)]
@ -132,14 +131,11 @@ fn mir_borrowck<'tcx>(
debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id())); debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id()));
let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner; let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner;
let opt_closure_req = tcx let infcx =
.infer_ctxt() tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)).build();
.with_opaque_type_inference(DefiningAnchor::Bind(hir_owner))
.enter(|infcx| {
let input_body: &Body<'_> = &input_body.borrow(); let input_body: &Body<'_> = &input_body.borrow();
let promoted: &IndexVec<_, _> = &promoted.borrow(); let promoted: &IndexVec<_, _> = &promoted.borrow();
do_mir_borrowck(&infcx, input_body, promoted, false).0 let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, false).0;
});
debug!("mir_borrowck done"); debug!("mir_borrowck done");
tcx.arena.alloc(opt_closure_req) tcx.arena.alloc(opt_closure_req)
@ -151,8 +147,8 @@ fn mir_borrowck<'tcx>(
/// region ids on which the borrow checking was performed together with Polonius /// region ids on which the borrow checking was performed together with Polonius
/// facts. /// facts.
#[instrument(skip(infcx, input_body, input_promoted), fields(id=?input_body.source.with_opt_param().as_local().unwrap()), level = "debug")] #[instrument(skip(infcx, input_body, input_promoted), fields(id=?input_body.source.with_opt_param().as_local().unwrap()), level = "debug")]
fn do_mir_borrowck<'a, 'tcx>( fn do_mir_borrowck<'tcx>(
infcx: &InferCtxt<'a, 'tcx>, infcx: &InferCtxt<'tcx>,
input_body: &Body<'tcx>, input_body: &Body<'tcx>,
input_promoted: &IndexVec<Promoted, Body<'tcx>>, input_promoted: &IndexVec<Promoted, Body<'tcx>>,
return_body_with_facts: bool, return_body_with_facts: bool,
@ -475,7 +471,7 @@ pub struct BodyWithBorrowckFacts<'tcx> {
} }
struct MirBorrowckCtxt<'cx, 'tcx> { struct MirBorrowckCtxt<'cx, 'tcx> {
infcx: &'cx InferCtxt<'cx, 'tcx>, infcx: &'cx InferCtxt<'tcx>,
param_env: ParamEnv<'tcx>, param_env: ParamEnv<'tcx>,
body: &'cx Body<'tcx>, body: &'cx Body<'tcx>,
move_data: &'cx MoveData<'tcx>, move_data: &'cx MoveData<'tcx>,
@ -1781,6 +1777,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
for (place_base, elem) in place.iter_projections().rev() { for (place_base, elem) in place.iter_projections().rev() {
match elem { match elem {
ProjectionElem::Index(_/*operand*/) | ProjectionElem::Index(_/*operand*/) |
ProjectionElem::OpaqueCast(_) |
ProjectionElem::ConstantIndex { .. } | ProjectionElem::ConstantIndex { .. } |
// assigning to P[i] requires P to be valid. // assigning to P[i] requires P to be valid.
ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) => ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) =>
@ -2172,6 +2169,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
| ProjectionElem::Index(..) | ProjectionElem::Index(..)
| ProjectionElem::ConstantIndex { .. } | ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Subslice { .. } | ProjectionElem::Subslice { .. }
| ProjectionElem::OpaqueCast { .. }
| ProjectionElem::Downcast(..) => { | ProjectionElem::Downcast(..) => {
let upvar_field_projection = self.is_upvar_field_projection(place); let upvar_field_projection = self.is_upvar_field_projection(place);
if let Some(field) = upvar_field_projection { if let Some(field) = upvar_field_projection {

View File

@ -55,8 +55,8 @@ pub(crate) struct NllOutput<'tcx> {
/// regions (e.g., region parameters) declared on the function. That set will need to be given to /// regions (e.g., region parameters) declared on the function. That set will need to be given to
/// `compute_regions`. /// `compute_regions`.
#[instrument(skip(infcx, param_env, body, promoted), level = "debug")] #[instrument(skip(infcx, param_env, body, promoted), level = "debug")]
pub(crate) fn replace_regions_in_mir<'cx, 'tcx>( pub(crate) fn replace_regions_in_mir<'tcx>(
infcx: &InferCtxt<'cx, 'tcx>, infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
body: &mut Body<'tcx>, body: &mut Body<'tcx>,
promoted: &mut IndexVec<Promoted, Body<'tcx>>, promoted: &mut IndexVec<Promoted, Body<'tcx>>,
@ -155,7 +155,7 @@ fn populate_polonius_move_facts(
/// ///
/// This may result in errors being reported. /// This may result in errors being reported.
pub(crate) fn compute_regions<'cx, 'tcx>( pub(crate) fn compute_regions<'cx, 'tcx>(
infcx: &InferCtxt<'cx, 'tcx>, infcx: &InferCtxt<'tcx>,
universal_regions: UniversalRegions<'tcx>, universal_regions: UniversalRegions<'tcx>,
body: &Body<'tcx>, body: &Body<'tcx>,
promoted: &IndexVec<Promoted, Body<'tcx>>, promoted: &IndexVec<Promoted, Body<'tcx>>,
@ -318,8 +318,8 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
} }
} }
pub(super) fn dump_mir_results<'a, 'tcx>( pub(super) fn dump_mir_results<'tcx>(
infcx: &InferCtxt<'a, 'tcx>, infcx: &InferCtxt<'tcx>,
body: &Body<'tcx>, body: &Body<'tcx>,
regioncx: &RegionInferenceContext<'tcx>, regioncx: &RegionInferenceContext<'tcx>,
closure_region_requirements: &Option<ClosureRegionRequirements<'_>>, closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
@ -368,8 +368,8 @@ pub(super) fn dump_mir_results<'a, 'tcx>(
}; };
} }
pub(super) fn dump_annotation<'a, 'tcx>( pub(super) fn dump_annotation<'tcx>(
infcx: &InferCtxt<'a, 'tcx>, infcx: &InferCtxt<'tcx>,
body: &Body<'tcx>, body: &Body<'tcx>,
regioncx: &RegionInferenceContext<'tcx>, regioncx: &RegionInferenceContext<'tcx>,
closure_region_requirements: &Option<ClosureRegionRequirements<'_>>, closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,

View File

@ -250,6 +250,7 @@ fn place_components_conflict<'tcx>(
| (ProjectionElem::Index { .. }, _, _) | (ProjectionElem::Index { .. }, _, _)
| (ProjectionElem::ConstantIndex { .. }, _, _) | (ProjectionElem::ConstantIndex { .. }, _, _)
| (ProjectionElem::Subslice { .. }, _, _) | (ProjectionElem::Subslice { .. }, _, _)
| (ProjectionElem::OpaqueCast { .. }, _, _)
| (ProjectionElem::Downcast { .. }, _, _) => { | (ProjectionElem::Downcast { .. }, _, _) => {
// Recursive case. This can still be disjoint on a // Recursive case. This can still be disjoint on a
// further iteration if this a shallow access and // further iteration if this a shallow access and
@ -317,6 +318,17 @@ fn place_projection_conflict<'tcx>(
debug!("place_element_conflict: DISJOINT-OR-EQ-DEREF"); debug!("place_element_conflict: DISJOINT-OR-EQ-DEREF");
Overlap::EqualOrDisjoint Overlap::EqualOrDisjoint
} }
(ProjectionElem::OpaqueCast(v1), ProjectionElem::OpaqueCast(v2)) => {
if v1 == v2 {
// same type - recur.
debug!("place_element_conflict: DISJOINT-OR-EQ-OPAQUE");
Overlap::EqualOrDisjoint
} else {
// Different types. Disjoint!
debug!("place_element_conflict: DISJOINT-OPAQUE");
Overlap::Disjoint
}
}
(ProjectionElem::Field(f1, _), ProjectionElem::Field(f2, _)) => { (ProjectionElem::Field(f1, _), ProjectionElem::Field(f2, _)) => {
if f1 == f2 { if f1 == f2 {
// same field (e.g., `a.y` vs. `a.y`) - recur. // same field (e.g., `a.y` vs. `a.y`) - recur.
@ -520,6 +532,7 @@ fn place_projection_conflict<'tcx>(
| ProjectionElem::Field(..) | ProjectionElem::Field(..)
| ProjectionElem::Index(..) | ProjectionElem::Index(..)
| ProjectionElem::ConstantIndex { .. } | ProjectionElem::ConstantIndex { .. }
| ProjectionElem::OpaqueCast { .. }
| ProjectionElem::Subslice { .. } | ProjectionElem::Subslice { .. }
| ProjectionElem::Downcast(..), | ProjectionElem::Downcast(..),
_, _,

View File

@ -81,6 +81,7 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
} }
ProjectionElem::Downcast(..) ProjectionElem::Downcast(..)
| ProjectionElem::Subslice { .. } | ProjectionElem::Subslice { .. }
| ProjectionElem::OpaqueCast { .. }
| ProjectionElem::ConstantIndex { .. } | ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Index(_) => { | ProjectionElem::Index(_) => {
cursor = cursor_base; cursor = cursor_base;

View File

@ -15,7 +15,7 @@ use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound,
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin}; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
use rustc_middle::mir::{ use rustc_middle::mir::{
Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements, Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
ConstraintCategory, Local, Location, ReturnConstraint, ConstraintCategory, Local, Location, ReturnConstraint, TerminatorKind,
}; };
use rustc_middle::traits::ObligationCause; use rustc_middle::traits::ObligationCause;
use rustc_middle::traits::ObligationCauseCode; use rustc_middle::traits::ObligationCauseCode;
@ -565,7 +565,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
#[instrument(skip(self, infcx, body, polonius_output), level = "debug")] #[instrument(skip(self, infcx, body, polonius_output), level = "debug")]
pub(super) fn solve( pub(super) fn solve(
&mut self, &mut self,
infcx: &InferCtxt<'_, 'tcx>, infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>, body: &Body<'tcx>,
polonius_output: Option<Rc<PoloniusOutput>>, polonius_output: Option<Rc<PoloniusOutput>>,
@ -835,7 +835,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// 'a`. See `TypeTest` for more details. /// 'a`. See `TypeTest` for more details.
fn check_type_tests( fn check_type_tests(
&self, &self,
infcx: &InferCtxt<'_, 'tcx>, infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>, body: &Body<'tcx>,
mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>, mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
@ -923,7 +923,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
#[instrument(level = "debug", skip(self, infcx, propagated_outlives_requirements))] #[instrument(level = "debug", skip(self, infcx, propagated_outlives_requirements))]
fn try_promote_type_test( fn try_promote_type_test(
&self, &self,
infcx: &InferCtxt<'_, 'tcx>, infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>, body: &Body<'tcx>,
type_test: &TypeTest<'tcx>, type_test: &TypeTest<'tcx>,
@ -1036,7 +1036,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
#[instrument(level = "debug", skip(self, infcx))] #[instrument(level = "debug", skip(self, infcx))]
fn try_promote_type_test_subject( fn try_promote_type_test_subject(
&self, &self,
infcx: &InferCtxt<'_, 'tcx>, infcx: &InferCtxt<'tcx>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
) -> Option<ClosureOutlivesSubject<'tcx>> { ) -> Option<ClosureOutlivesSubject<'tcx>> {
let tcx = infcx.tcx; let tcx = infcx.tcx;
@ -1212,7 +1212,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// `point`. /// `point`.
fn eval_verify_bound( fn eval_verify_bound(
&self, &self,
infcx: &InferCtxt<'_, 'tcx>, infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>, body: &Body<'tcx>,
generic_ty: Ty<'tcx>, generic_ty: Ty<'tcx>,
@ -1262,7 +1262,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
fn eval_if_eq( fn eval_if_eq(
&self, &self,
infcx: &InferCtxt<'_, 'tcx>, infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
generic_ty: Ty<'tcx>, generic_ty: Ty<'tcx>,
lower_bound: RegionVid, lower_bound: RegionVid,
@ -1398,7 +1398,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// whether any of the constraints were too strong. In particular, /// whether any of the constraints were too strong. In particular,
/// we want to check for a case where a universally quantified /// we want to check for a case where a universally quantified
/// region exceeded its bounds. Consider: /// region exceeded its bounds. Consider:
/// ```compile_fail,E0312 /// ```compile_fail
/// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x } /// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
/// ``` /// ```
/// In this case, returning `x` requires `&'a u32 <: &'b u32` /// In this case, returning `x` requires `&'a u32 <: &'b u32`
@ -1451,7 +1451,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// <https://smallcultfollowing.com/babysteps/blog/2019/01/17/polonius-and-region-errors/> /// <https://smallcultfollowing.com/babysteps/blog/2019/01/17/polonius-and-region-errors/>
/// ///
/// In the canonical example /// In the canonical example
/// ```compile_fail,E0312 /// ```compile_fail
/// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x } /// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
/// ``` /// ```
/// returning `x` requires `&'a u32 <: &'b u32` and hence we establish (transitively) a /// returning `x` requires `&'a u32 <: &'b u32` and hence we establish (transitively) a
@ -1718,7 +1718,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
fn check_member_constraints( fn check_member_constraints(
&self, &self,
infcx: &InferCtxt<'_, 'tcx>, infcx: &InferCtxt<'tcx>,
errors_buffer: &mut RegionErrors<'tcx>, errors_buffer: &mut RegionErrors<'tcx>,
) { ) {
let member_constraints = self.member_constraints.clone(); let member_constraints = self.member_constraints.clone();
@ -2236,6 +2236,27 @@ impl<'tcx> RegionInferenceContext<'tcx> {
pub(crate) fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { pub(crate) fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
self.universe_causes[&universe].clone() self.universe_causes[&universe].clone()
} }
/// Tries to find the terminator of the loop in which the region 'r' resides.
/// Returns the location of the terminator if found.
pub(crate) fn find_loop_terminator_location(
&self,
r: RegionVid,
body: &Body<'_>,
) -> Option<Location> {
let scc = self.constraint_sccs.scc(r.to_region_vid());
let locations = self.scc_values.locations_outlived_by(scc);
for location in locations {
let bb = &body[location.block];
if let Some(terminator) = &bb.terminator {
// terminator of a loop should be TerminatorKind::FalseUnwind
if let TerminatorKind::FalseUnwind { .. } = terminator.kind {
return Some(location);
}
}
}
None
}
} }
impl<'tcx> RegionDefinition<'tcx> { impl<'tcx> RegionDefinition<'tcx> {

View File

@ -2,22 +2,18 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::vec_map::VecMap; use rustc_data_structures::vec_map::VecMap;
use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::LocalDefId;
use rustc_hir::OpaqueTyOrigin; use rustc_hir::OpaqueTyOrigin;
use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
use rustc_infer::infer::TyCtxtInferExt as _; use rustc_infer::infer::TyCtxtInferExt as _;
use rustc_infer::infer::{DefiningAnchor, InferCtxt}; use rustc_infer::infer::{DefiningAnchor, InferCtxt};
use rustc_infer::traits::{Obligation, ObligationCause, TraitEngine}; use rustc_infer::traits::{Obligation, ObligationCause, TraitEngine};
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts};
use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::visit::TypeVisitable;
use rustc_middle::ty::{ use rustc_middle::ty::{
self, OpaqueHiddenType, OpaqueTypeKey, ToPredicate, Ty, TyCtxt, TypeFoldable, self, OpaqueHiddenType, OpaqueTypeKey, ToPredicate, Ty, TyCtxt, TypeFoldable,
}; };
use rustc_span::Span; use rustc_span::Span;
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
use rustc_trait_selection::traits::TraitEngineExt as _; use rustc_trait_selection::traits::TraitEngineExt as _;
use crate::session_diagnostics::ConstNotUsedTraitAlias;
use super::RegionInferenceContext; use super::RegionInferenceContext;
impl<'tcx> RegionInferenceContext<'tcx> { impl<'tcx> RegionInferenceContext<'tcx> {
@ -63,7 +59,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
#[instrument(level = "debug", skip(self, infcx), ret)] #[instrument(level = "debug", skip(self, infcx), ret)]
pub(crate) fn infer_opaque_types( pub(crate) fn infer_opaque_types(
&self, &self,
infcx: &InferCtxt<'_, 'tcx>, infcx: &InferCtxt<'tcx>,
opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>, opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>,
) -> VecMap<LocalDefId, OpaqueHiddenType<'tcx>> { ) -> VecMap<LocalDefId, OpaqueHiddenType<'tcx>> {
let mut result: VecMap<LocalDefId, OpaqueHiddenType<'tcx>> = VecMap::new(); let mut result: VecMap<LocalDefId, OpaqueHiddenType<'tcx>> = VecMap::new();
@ -194,7 +190,7 @@ pub trait InferCtxtExt<'tcx> {
) -> Ty<'tcx>; ) -> Ty<'tcx>;
} }
impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
/// Given the fully resolved, instantiated type for an opaque /// Given the fully resolved, instantiated type for an opaque
/// type, i.e., the value of an inference variable like C1 or C2 /// type, i.e., the value of an inference variable like C1 or C2
/// (*), computes the "definition type" for an opaque type /// (*), computes the "definition type" for an opaque type
@ -229,31 +225,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
return self.tcx.ty_error(); return self.tcx.ty_error();
} }
let OpaqueTypeKey { def_id, substs } = opaque_type_key; let definition_ty = instantiated_ty
.remap_generic_params_to_declaration_params(opaque_type_key, self.tcx, false, origin)
// Use substs to build up a reverse map from regions to their .ty;
// identity mappings. This is necessary because of `impl
// Trait` lifetimes are computed by replacing existing
// lifetimes with 'static and remapping only those used in the
// `impl Trait` return type, resulting in the parameters
// shifting.
let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id.to_def_id());
debug!(?id_substs);
let map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>> =
substs.iter().enumerate().map(|(index, subst)| (subst, id_substs[index])).collect();
debug!("map = {:#?}", map);
// Convert the type from the function into a type valid outside
// the function, by replacing invalid regions with 'static,
// after producing an error for each of them.
let definition_ty = instantiated_ty.ty.fold_with(&mut ReverseMapper::new(
self.tcx,
opaque_type_key,
map,
instantiated_ty.ty,
instantiated_ty.span,
));
debug!(?definition_ty);
if !check_opaque_type_parameter_valid( if !check_opaque_type_parameter_valid(
self.tcx, self.tcx,
@ -266,32 +240,34 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// Only check this for TAIT. RPIT already supports `src/test/ui/impl-trait/nested-return-type2.rs` // Only check this for TAIT. RPIT already supports `src/test/ui/impl-trait/nested-return-type2.rs`
// on stable and we'd break that. // on stable and we'd break that.
if let OpaqueTyOrigin::TyAlias = origin { let OpaqueTyOrigin::TyAlias = origin else {
return definition_ty;
};
let def_id = opaque_type_key.def_id;
// This logic duplicates most of `check_opaque_meets_bounds`. // This logic duplicates most of `check_opaque_meets_bounds`.
// FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely. // FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely.
let param_env = self.tcx.param_env(def_id); let param_env = self.tcx.param_env(def_id);
let body_id = self.tcx.local_def_id_to_hir_id(def_id); let body_id = self.tcx.local_def_id_to_hir_id(def_id);
// HACK This bubble is required for this tests to pass: // HACK This bubble is required for this tests to pass:
// type-alias-impl-trait/issue-67844-nested-opaque.rs // type-alias-impl-trait/issue-67844-nested-opaque.rs
self.tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).enter( let infcx =
move |infcx| { self.tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build();
// Require the hidden type to be well-formed with only the generics of the opaque type. // Require the hidden type to be well-formed with only the generics of the opaque type.
// Defining use functions may have more bounds than the opaque type, which is ok, as long as the // Defining use functions may have more bounds than the opaque type, which is ok, as long as the
// hidden type is well formed even without those bounds. // hidden type is well formed even without those bounds.
let predicate = let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into()))
ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into()))
.to_predicate(infcx.tcx); .to_predicate(infcx.tcx);
let mut fulfillment_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx); let mut fulfillment_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx);
let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id.to_def_id());
// Require that the hidden type actually fulfills all the bounds of the opaque type, even without // Require that the hidden type actually fulfills all the bounds of the opaque type, even without
// the bounds that the function supplies. // the bounds that the function supplies.
match infcx.register_hidden_type( let opaque_ty = self.tcx.mk_opaque(def_id.to_def_id(), id_substs);
OpaqueTypeKey { def_id, substs: id_substs }, match infcx
ObligationCause::misc(instantiated_ty.span, body_id), .at(&ObligationCause::misc(instantiated_ty.span, body_id), param_env)
param_env, .eq(opaque_ty, definition_ty)
definition_ty, {
origin,
) {
Ok(infer_ok) => { Ok(infer_ok) => {
for obligation in infer_ok.obligations { for obligation in infer_ok.obligations {
fulfillment_cx.register_predicate_obligation(&infcx, obligation); fulfillment_cx.register_predicate_obligation(&infcx, obligation);
@ -299,9 +275,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
} }
Err(err) => { Err(err) => {
infcx infcx
.err_ctxt()
.report_mismatched_types( .report_mismatched_types(
&ObligationCause::misc(instantiated_ty.span, body_id), &ObligationCause::misc(instantiated_ty.span, body_id),
self.tcx.mk_opaque(def_id.to_def_id(), id_substs), opaque_ty,
definition_ty, definition_ty,
err, err,
) )
@ -325,14 +302,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
if errors.is_empty() { if errors.is_empty() {
definition_ty definition_ty
} else { } else {
infcx.report_fulfillment_errors(&errors, None, false); infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
self.tcx.ty_error() self.tcx.ty_error()
} }
},
)
} else {
definition_ty
}
} }
} }
@ -427,221 +399,3 @@ fn check_opaque_type_parameter_valid(
} }
true true
} }
struct ReverseMapper<'tcx> {
tcx: TyCtxt<'tcx>,
key: ty::OpaqueTypeKey<'tcx>,
map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
do_not_error: bool,
/// initially `Some`, set to `None` once error has been reported
hidden_ty: Option<Ty<'tcx>>,
/// Span of function being checked.
span: Span,
}
impl<'tcx> ReverseMapper<'tcx> {
fn new(
tcx: TyCtxt<'tcx>,
key: ty::OpaqueTypeKey<'tcx>,
map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
hidden_ty: Ty<'tcx>,
span: Span,
) -> Self {
Self { tcx, key, map, do_not_error: false, hidden_ty: Some(hidden_ty), span }
}
fn fold_kind_no_missing_regions_error(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
assert!(!self.do_not_error);
self.do_not_error = true;
let kind = kind.fold_with(self);
self.do_not_error = false;
kind
}
fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
assert!(!self.do_not_error);
kind.fold_with(self)
}
}
impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
#[instrument(skip(self), level = "debug")]
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match *r {
// Ignore bound regions and `'static` regions that appear in the
// type, we only need to remap regions that reference lifetimes
// from the function declaration.
// This would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
ty::ReLateBound(..) | ty::ReStatic => return r,
// If regions have been erased (by writeback), don't try to unerase
// them.
ty::ReErased => return r,
// The regions that we expect from borrow checking.
ty::ReEarlyBound(_) | ty::ReFree(_) => {}
ty::RePlaceholder(_) | ty::ReVar(_) => {
// All of the regions in the type should either have been
// erased by writeback, or mapped back to named regions by
// borrow checking.
bug!("unexpected region kind in opaque type: {:?}", r);
}
}
let generics = self.tcx().generics_of(self.key.def_id);
match self.map.get(&r.into()).map(|k| k.unpack()) {
Some(GenericArgKind::Lifetime(r1)) => r1,
Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
None if self.do_not_error => self.tcx.lifetimes.re_static,
None if generics.parent.is_some() => {
if let Some(hidden_ty) = self.hidden_ty.take() {
unexpected_hidden_region_diagnostic(
self.tcx,
self.tcx.def_span(self.key.def_id),
hidden_ty,
r,
self.key,
)
.emit();
}
self.tcx.lifetimes.re_static
}
None => {
self.tcx
.sess
.struct_span_err(self.span, "non-defining opaque type use in defining scope")
.span_label(
self.span,
format!(
"lifetime `{}` is part of concrete type but not used in \
parameter list of the `impl Trait` type alias",
r
),
)
.emit();
self.tcx().lifetimes.re_static
}
}
}
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
match *ty.kind() {
ty::Closure(def_id, substs) => {
// I am a horrible monster and I pray for death. When
// we encounter a closure here, it is always a closure
// from within the function that we are currently
// type-checking -- one that is now being encapsulated
// in an opaque type. Ideally, we would
// go through the types/lifetimes that it references
// and treat them just like we would any other type,
// which means we would error out if we find any
// reference to a type/region that is not in the
// "reverse map".
//
// **However,** in the case of closures, there is a
// somewhat subtle (read: hacky) consideration. The
// problem is that our closure types currently include
// all the lifetime parameters declared on the
// enclosing function, even if they are unused by the
// closure itself. We can't readily filter them out,
// so here we replace those values with `'empty`. This
// can't really make a difference to the rest of the
// compiler; those regions are ignored for the
// outlives relation, and hence don't affect trait
// selection or auto traits, and they are erased
// during codegen.
let generics = self.tcx.generics_of(def_id);
let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| {
if index < generics.parent_count {
// Accommodate missing regions in the parent kinds...
self.fold_kind_no_missing_regions_error(kind)
} else {
// ...but not elsewhere.
self.fold_kind_normally(kind)
}
}));
self.tcx.mk_closure(def_id, substs)
}
ty::Generator(def_id, substs, movability) => {
let generics = self.tcx.generics_of(def_id);
let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| {
if index < generics.parent_count {
// Accommodate missing regions in the parent kinds...
self.fold_kind_no_missing_regions_error(kind)
} else {
// ...but not elsewhere.
self.fold_kind_normally(kind)
}
}));
self.tcx.mk_generator(def_id, substs, movability)
}
ty::Param(param) => {
// Look it up in the substitution list.
match self.map.get(&ty.into()).map(|k| k.unpack()) {
// Found it in the substitution list; replace with the parameter from the
// opaque type.
Some(GenericArgKind::Type(t1)) => t1,
Some(u) => panic!("type mapped to unexpected kind: {:?}", u),
None => {
debug!(?param, ?self.map);
self.tcx
.sess
.struct_span_err(
self.span,
&format!(
"type parameter `{}` is part of concrete type but not \
used in parameter list for the `impl Trait` type alias",
ty
),
)
.emit();
self.tcx().ty_error()
}
}
}
_ => ty.super_fold_with(self),
}
}
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
trace!("checking const {:?}", ct);
// Find a const parameter
match ct.kind() {
ty::ConstKind::Param(..) => {
// Look it up in the substitution list.
match self.map.get(&ct.into()).map(|k| k.unpack()) {
// Found it in the substitution list, replace with the parameter from the
// opaque type.
Some(GenericArgKind::Const(c1)) => c1,
Some(u) => panic!("const mapped to unexpected kind: {:?}", u),
None => {
self.tcx.sess.emit_err(ConstNotUsedTraitAlias {
ct: ct.to_string(),
span: self.span,
});
self.tcx().const_error(ct.ty())
}
}
}
_ => ct,
}
}
}

View File

@ -1,8 +1,8 @@
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin}; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
use rustc_middle::mir::visit::{MutVisitor, TyContext}; use rustc_middle::mir::visit::{MutVisitor, TyContext};
use rustc_middle::mir::Constant;
use rustc_middle::mir::{Body, Location, Promoted}; use rustc_middle::mir::{Body, Location, Promoted};
use rustc_middle::mir::{Constant, ConstantKind};
use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
@ -10,7 +10,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
/// inference variables, returning the number of variables created. /// inference variables, returning the number of variables created.
#[instrument(skip(infcx, body, promoted), level = "debug")] #[instrument(skip(infcx, body, promoted), level = "debug")]
pub fn renumber_mir<'tcx>( pub fn renumber_mir<'tcx>(
infcx: &InferCtxt<'_, 'tcx>, infcx: &InferCtxt<'tcx>,
body: &mut Body<'tcx>, body: &mut Body<'tcx>,
promoted: &mut IndexVec<Promoted, Body<'tcx>>, promoted: &mut IndexVec<Promoted, Body<'tcx>>,
) { ) {
@ -28,7 +28,7 @@ pub fn renumber_mir<'tcx>(
/// Replaces all regions appearing in `value` with fresh inference /// Replaces all regions appearing in `value` with fresh inference
/// variables. /// variables.
#[instrument(skip(infcx), level = "debug")] #[instrument(skip(infcx), level = "debug")]
pub fn renumber_regions<'tcx, T>(infcx: &InferCtxt<'_, 'tcx>, value: T) -> T pub fn renumber_regions<'tcx, T>(infcx: &InferCtxt<'tcx>, value: T) -> T
where where
T: TypeFoldable<'tcx>, T: TypeFoldable<'tcx>,
{ {
@ -38,23 +38,8 @@ where
}) })
} }
// FIXME(valtrees): This function is necessary because `fold_regions`
// panics for mir constants in the visitor.
//
// Once `visit_mir_constant` is removed we can also remove this function
// and just use `renumber_regions`.
fn renumber_regions_in_mir_constant<'tcx>(
infcx: &InferCtxt<'_, 'tcx>,
value: ConstantKind<'tcx>,
) -> ConstantKind<'tcx> {
infcx.tcx.super_fold_regions(value, |_region, _depth| {
let origin = NllRegionVariableOrigin::Existential { from_forall: false };
infcx.next_nll_region_var(origin)
})
}
struct NllVisitor<'a, 'tcx> { struct NllVisitor<'a, 'tcx> {
infcx: &'a InferCtxt<'a, 'tcx>, infcx: &'a InferCtxt<'tcx>,
} }
impl<'a, 'tcx> NllVisitor<'a, 'tcx> { impl<'a, 'tcx> NllVisitor<'a, 'tcx> {
@ -64,13 +49,6 @@ impl<'a, 'tcx> NllVisitor<'a, 'tcx> {
{ {
renumber_regions(self.infcx, value) renumber_regions(self.infcx, value)
} }
fn renumber_regions_in_mir_constant(
&mut self,
value: ConstantKind<'tcx>,
) -> ConstantKind<'tcx> {
renumber_regions_in_mir_constant(self.infcx, value)
}
} }
impl<'a, 'tcx> MutVisitor<'tcx> for NllVisitor<'a, 'tcx> { impl<'a, 'tcx> MutVisitor<'tcx> for NllVisitor<'a, 'tcx> {
@ -103,7 +81,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NllVisitor<'a, 'tcx> {
#[instrument(skip(self), level = "debug")] #[instrument(skip(self), level = "debug")]
fn visit_constant(&mut self, constant: &mut Constant<'tcx>, _location: Location) { fn visit_constant(&mut self, constant: &mut Constant<'tcx>, _location: Location) {
let literal = constant.literal; let literal = constant.literal;
constant.literal = self.renumber_regions_in_mir_constant(literal); constant.literal = self.renumber_regions(literal);
debug!("constant: {:#?}", constant); debug!("constant: {:#?}", constant);
} }
} }

View File

@ -1,12 +1,12 @@
use rustc_errors::{IntoDiagnosticArg, MultiSpan}; use rustc_errors::{IntoDiagnosticArg, MultiSpan};
use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::Ty; use rustc_middle::ty::Ty;
use rustc_span::Span; use rustc_span::Span;
use crate::diagnostics::RegionName; use crate::diagnostics::RegionName;
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(borrowck::move_unsized, code = "E0161")] #[diag(borrowck_move_unsized, code = "E0161")]
pub(crate) struct MoveUnsized<'tcx> { pub(crate) struct MoveUnsized<'tcx> {
pub ty: Ty<'tcx>, pub ty: Ty<'tcx>,
#[primary_span] #[primary_span]
@ -14,8 +14,8 @@ pub(crate) struct MoveUnsized<'tcx> {
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(borrowck::higher_ranked_lifetime_error)] #[diag(borrowck_higher_ranked_lifetime_error)]
pub(crate) struct HigherRankedLifetimeError { pub(crate) struct HigherRankedLifetimeError {
#[subdiagnostic] #[subdiagnostic]
pub cause: Option<HigherRankedErrorCause>, pub cause: Option<HigherRankedErrorCause>,
@ -23,23 +23,23 @@ pub(crate) struct HigherRankedLifetimeError {
pub span: Span, pub span: Span,
} }
#[derive(SessionSubdiagnostic)] #[derive(Subdiagnostic)]
pub(crate) enum HigherRankedErrorCause { pub(crate) enum HigherRankedErrorCause {
#[note(borrowck::could_not_prove)] #[note(borrowck_could_not_prove)]
CouldNotProve { predicate: String }, CouldNotProve { predicate: String },
#[note(borrowck::could_not_normalize)] #[note(borrowck_could_not_normalize)]
CouldNotNormalize { value: String }, CouldNotNormalize { value: String },
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(borrowck::higher_ranked_subtype_error)] #[diag(borrowck_higher_ranked_subtype_error)]
pub(crate) struct HigherRankedSubtypeError { pub(crate) struct HigherRankedSubtypeError {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(borrowck::generic_does_not_live_long_enough)] #[diag(borrowck_generic_does_not_live_long_enough)]
pub(crate) struct GenericDoesNotLiveLongEnough { pub(crate) struct GenericDoesNotLiveLongEnough {
pub kind: String, pub kind: String,
#[primary_span] #[primary_span]
@ -47,24 +47,15 @@ pub(crate) struct GenericDoesNotLiveLongEnough {
} }
#[derive(LintDiagnostic)] #[derive(LintDiagnostic)]
#[diag(borrowck::var_does_not_need_mut)] #[diag(borrowck_var_does_not_need_mut)]
pub(crate) struct VarNeedNotMut { pub(crate) struct VarNeedNotMut {
#[suggestion_short(applicability = "machine-applicable", code = "")] #[suggestion_short(applicability = "machine-applicable", code = "")]
pub span: Span, pub span: Span,
} }
#[derive(Diagnostic)]
#[derive(SessionDiagnostic)] #[diag(borrowck_var_cannot_escape_closure)]
#[diag(borrowck::const_not_used_in_type_alias)]
pub(crate) struct ConstNotUsedTraitAlias {
pub ct: String,
#[primary_span]
pub span: Span,
}
#[derive(SessionDiagnostic)]
#[diag(borrowck::var_cannot_escape_closure)]
#[note] #[note]
#[note(borrowck::cannot_escape)] #[note(cannot_escape)]
pub(crate) struct FnMutError { pub(crate) struct FnMutError {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
@ -72,54 +63,54 @@ pub(crate) struct FnMutError {
pub ty_err: FnMutReturnTypeErr, pub ty_err: FnMutReturnTypeErr,
} }
#[derive(SessionSubdiagnostic)] #[derive(Subdiagnostic)]
pub(crate) enum VarHereDenote { pub(crate) enum VarHereDenote {
#[label(borrowck::var_here_captured)] #[label(borrowck_var_here_captured)]
Captured { Captured {
#[primary_span] #[primary_span]
span: Span, span: Span,
}, },
#[label(borrowck::var_here_defined)] #[label(borrowck_var_here_defined)]
Defined { Defined {
#[primary_span] #[primary_span]
span: Span, span: Span,
}, },
#[label(borrowck::closure_inferred_mut)] #[label(borrowck_closure_inferred_mut)]
FnMutInferred { FnMutInferred {
#[primary_span] #[primary_span]
span: Span, span: Span,
}, },
} }
#[derive(SessionSubdiagnostic)] #[derive(Subdiagnostic)]
pub(crate) enum FnMutReturnTypeErr { pub(crate) enum FnMutReturnTypeErr {
#[label(borrowck::returned_closure_escaped)] #[label(borrowck_returned_closure_escaped)]
ReturnClosure { ReturnClosure {
#[primary_span] #[primary_span]
span: Span, span: Span,
}, },
#[label(borrowck::returned_async_block_escaped)] #[label(borrowck_returned_async_block_escaped)]
ReturnAsyncBlock { ReturnAsyncBlock {
#[primary_span] #[primary_span]
span: Span, span: Span,
}, },
#[label(borrowck::returned_ref_escaped)] #[label(borrowck_returned_ref_escaped)]
ReturnRef { ReturnRef {
#[primary_span] #[primary_span]
span: Span, span: Span,
}, },
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(borrowck::lifetime_constraints_error)] #[diag(borrowck_lifetime_constraints_error)]
pub(crate) struct LifetimeOutliveErr { pub(crate) struct LifetimeOutliveErr {
#[primary_span] #[primary_span]
pub span: Span, pub span: Span,
} }
#[derive(SessionSubdiagnostic)] #[derive(Subdiagnostic)]
pub(crate) enum LifetimeReturnCategoryErr<'a> { pub(crate) enum LifetimeReturnCategoryErr<'a> {
#[label(borrowck::returned_lifetime_wrong)] #[label(borrowck_returned_lifetime_wrong)]
WrongReturn { WrongReturn {
#[primary_span] #[primary_span]
span: Span, span: Span,
@ -127,7 +118,7 @@ pub(crate) enum LifetimeReturnCategoryErr<'a> {
outlived_fr_name: RegionName, outlived_fr_name: RegionName,
fr_name: &'a RegionName, fr_name: &'a RegionName,
}, },
#[label(borrowck::returned_lifetime_short)] #[label(borrowck_returned_lifetime_short)]
ShortReturn { ShortReturn {
#[primary_span] #[primary_span]
span: Span, span: Span,
@ -149,9 +140,9 @@ impl IntoDiagnosticArg for RegionName {
} }
} }
#[derive(SessionSubdiagnostic)] #[derive(Subdiagnostic)]
pub(crate) enum RequireStaticErr { pub(crate) enum RequireStaticErr {
#[note(borrowck::used_impl_require_static)] #[note(borrowck_used_impl_require_static)]
UsedImpl { UsedImpl {
#[primary_span] #[primary_span]
multi_span: MultiSpan, multi_span: MultiSpan,

View File

@ -52,11 +52,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
Some(error_info) => error_info.to_universe_info(old_universe), Some(error_info) => error_info.to_universe_info(old_universe),
None => UniverseInfo::other(), None => UniverseInfo::other(),
}; };
for u in old_universe..universe { for u in (old_universe + 1)..=universe {
self.borrowck_context self.borrowck_context.constraints.universe_causes.insert(u, universe_info.clone());
.constraints
.universe_causes
.insert(u + 1, universe_info.clone());
} }
} }
@ -71,15 +68,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
where where
T: TypeFoldable<'tcx>, T: TypeFoldable<'tcx>,
{ {
let old_universe = self.infcx.universe();
let (instantiated, _) = let (instantiated, _) =
self.infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical); self.infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
for u in 0..canonical.max_universe.as_u32() { for u in (old_universe + 1)..=self.infcx.universe() {
let info = UniverseInfo::other(); self.borrowck_context.constraints.universe_causes.insert(u, UniverseInfo::other());
self.borrowck_context
.constraints
.universe_causes
.insert(ty::UniverseIndex::from_u32(u), info);
} }
instantiated instantiated

View File

@ -19,7 +19,7 @@ use crate::{
}; };
pub(crate) struct ConstraintConversion<'a, 'tcx> { pub(crate) struct ConstraintConversion<'a, 'tcx> {
infcx: &'a InferCtxt<'a, 'tcx>, infcx: &'a InferCtxt<'tcx>,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
universal_regions: &'a UniversalRegions<'tcx>, universal_regions: &'a UniversalRegions<'tcx>,
/// Each RBP `GK: 'a` is assumed to be true. These encode /// Each RBP `GK: 'a` is assumed to be true. These encode
@ -43,7 +43,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
pub(crate) fn new( pub(crate) fn new(
infcx: &'a InferCtxt<'a, 'tcx>, infcx: &'a InferCtxt<'tcx>,
universal_regions: &'a UniversalRegions<'tcx>, universal_regions: &'a UniversalRegions<'tcx>,
region_bound_pairs: &'a RegionBoundPairs<'tcx>, region_bound_pairs: &'a RegionBoundPairs<'tcx>,
implicit_region_bound: ty::Region<'tcx>, implicit_region_bound: ty::Region<'tcx>,

View File

@ -8,7 +8,6 @@ use rustc_infer::infer::InferCtxt;
use rustc_middle::mir::ConstraintCategory; use rustc_middle::mir::ConstraintCategory;
use rustc_middle::traits::query::OutlivesBound; use rustc_middle::traits::query::OutlivesBound;
use rustc_middle::ty::{self, RegionVid, Ty}; use rustc_middle::ty::{self, RegionVid, Ty};
use rustc_span::DUMMY_SP;
use rustc_trait_selection::traits::query::type_op::{self, TypeOp}; use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
use std::rc::Rc; use std::rc::Rc;
use type_op::TypeOpOutput; use type_op::TypeOpOutput;
@ -48,7 +47,7 @@ pub(crate) struct CreateResult<'tcx> {
} }
pub(crate) fn create<'tcx>( pub(crate) fn create<'tcx>(
infcx: &InferCtxt<'_, 'tcx>, infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
implicit_region_bound: ty::Region<'tcx>, implicit_region_bound: ty::Region<'tcx>,
universal_regions: &Rc<UniversalRegions<'tcx>>, universal_regions: &Rc<UniversalRegions<'tcx>>,
@ -197,7 +196,7 @@ impl UniversalRegionRelations<'_> {
} }
struct UniversalRegionRelationsBuilder<'this, 'tcx> { struct UniversalRegionRelationsBuilder<'this, 'tcx> {
infcx: &'this InferCtxt<'this, 'tcx>, infcx: &'this InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
universal_regions: Rc<UniversalRegions<'tcx>>, universal_regions: Rc<UniversalRegions<'tcx>>,
implicit_region_bound: ty::Region<'tcx>, implicit_region_bound: ty::Region<'tcx>,
@ -219,6 +218,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
} }
pub(crate) fn create(mut self) -> CreateResult<'tcx> { pub(crate) fn create(mut self) -> CreateResult<'tcx> {
let span = self.infcx.tcx.def_span(self.universal_regions.defining_ty.def_id());
let unnormalized_input_output_tys = self let unnormalized_input_output_tys = self
.universal_regions .universal_regions
.unnormalized_input_tys .unnormalized_input_tys
@ -250,7 +250,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
self.infcx self.infcx
.tcx .tcx
.sess .sess
.delay_span_bug(DUMMY_SP, &format!("failed to normalize {:?}", ty)); .delay_span_bug(span, &format!("failed to normalize {:?}", ty));
TypeOpOutput { TypeOpOutput {
output: self.infcx.tcx.ty_error(), output: self.infcx.tcx.ty_error(),
constraints: None, constraints: None,
@ -301,8 +301,8 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
&self.region_bound_pairs, &self.region_bound_pairs,
self.implicit_region_bound, self.implicit_region_bound,
self.param_env, self.param_env,
Locations::All(DUMMY_SP), Locations::All(span),
DUMMY_SP, span,
ConstraintCategory::Internal, ConstraintCategory::Internal,
&mut self.constraints, &mut self.constraints,
) )
@ -362,6 +362,11 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
self.region_bound_pairs self.region_bound_pairs
.insert(ty::OutlivesPredicate(GenericKind::Projection(projection_b), r_a)); .insert(ty::OutlivesPredicate(GenericKind::Projection(projection_b), r_a));
} }
OutlivesBound::RegionSubOpaque(r_a, def_id, substs) => {
self.region_bound_pairs
.insert(ty::OutlivesPredicate(GenericKind::Opaque(def_id, substs), r_a));
}
} }
} }
} }

View File

@ -7,16 +7,11 @@
//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and //! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
//! contain revealed `impl Trait` values). //! contain revealed `impl Trait` values).
use crate::type_check::constraint_conversion::ConstraintConversion;
use rustc_index::vec::Idx; use rustc_index::vec::Idx;
use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_middle::mir::*; use rustc_middle::mir::*;
use rustc_middle::ty::Ty; use rustc_middle::ty::Ty;
use rustc_span::Span; use rustc_span::Span;
use rustc_span::DUMMY_SP;
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
use rustc_trait_selection::traits::query::Fallible;
use type_op::TypeOpOutput;
use crate::universal_regions::UniversalRegions; use crate::universal_regions::UniversalRegions;
@ -185,7 +180,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
} }
#[instrument(skip(self, span), level = "debug")] #[instrument(skip(self), level = "debug")]
fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) { fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) {
if let Err(_) = if let Err(_) =
self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation) self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
@ -194,13 +189,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd // `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd
// like to normalize *before* inserting into `local_decls`, but // like to normalize *before* inserting into `local_decls`, but
// doing so ends up causing some other trouble. // doing so ends up causing some other trouble.
let b = match self.normalize_and_add_constraints(b) { let b = self.normalize(b, Locations::All(span));
Ok(n) => n,
Err(_) => {
debug!("equate_inputs_and_outputs: NoSolution");
b
}
};
// Note: if we have to introduce new placeholders during normalization above, then we won't have // Note: if we have to introduce new placeholders during normalization above, then we won't have
// added those universes to the universe info, which we would want in `relate_tys`. // added those universes to the universe info, which we would want in `relate_tys`.
@ -218,28 +207,4 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
} }
} }
pub(crate) fn normalize_and_add_constraints(&mut self, t: Ty<'tcx>) -> Fallible<Ty<'tcx>> {
let TypeOpOutput { output: norm_ty, constraints, .. } =
self.param_env.and(type_op::normalize::Normalize::new(t)).fully_perform(self.infcx)?;
debug!("{:?} normalized to {:?}", t, norm_ty);
for data in constraints {
ConstraintConversion::new(
self.infcx,
&self.borrowck_context.universal_regions,
&self.region_bound_pairs,
self.implicit_region_bound,
self.param_env,
Locations::All(DUMMY_SP),
DUMMY_SP,
ConstraintCategory::Internal,
&mut self.borrowck_context.constraints,
)
.convert_all(&*data);
}
Ok(norm_ty)
}
} }

View File

@ -123,7 +123,7 @@ mod relate_tys;
/// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis /// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis
/// - `elements` -- MIR region map /// - `elements` -- MIR region map
pub(crate) fn type_check<'mir, 'tcx>( pub(crate) fn type_check<'mir, 'tcx>(
infcx: &InferCtxt<'_, 'tcx>, infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>, body: &Body<'tcx>,
promoted: &IndexVec<Promoted, Body<'tcx>>, promoted: &IndexVec<Promoted, Body<'tcx>>,
@ -138,8 +138,6 @@ pub(crate) fn type_check<'mir, 'tcx>(
use_polonius: bool, use_polonius: bool,
) -> MirTypeckResults<'tcx> { ) -> MirTypeckResults<'tcx> {
let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body)); let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
let mut universe_causes = FxHashMap::default();
universe_causes.insert(ty::UniverseIndex::from_u32(0), UniverseInfo::other());
let mut constraints = MirTypeckRegionConstraints { let mut constraints = MirTypeckRegionConstraints {
placeholder_indices: PlaceholderIndices::default(), placeholder_indices: PlaceholderIndices::default(),
placeholder_index_to_region: IndexVec::default(), placeholder_index_to_region: IndexVec::default(),
@ -148,7 +146,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
member_constraints: MemberConstraintSet::default(), member_constraints: MemberConstraintSet::default(),
closure_bounds_mapping: Default::default(), closure_bounds_mapping: Default::default(),
type_tests: Vec::default(), type_tests: Vec::default(),
universe_causes, universe_causes: FxHashMap::default(),
}; };
let CreateResult { let CreateResult {
@ -165,9 +163,8 @@ pub(crate) fn type_check<'mir, 'tcx>(
debug!(?normalized_inputs_and_output); debug!(?normalized_inputs_and_output);
for u in ty::UniverseIndex::ROOT..infcx.universe() { for u in ty::UniverseIndex::ROOT..=infcx.universe() {
let info = UniverseInfo::other(); constraints.universe_causes.insert(u, UniverseInfo::other());
constraints.universe_causes.insert(u, info);
} }
let mut borrowck_context = BorrowCheckContext { let mut borrowck_context = BorrowCheckContext {
@ -236,7 +233,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
.unwrap(); .unwrap();
let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type); let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind()); trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind());
if hidden_type.has_infer_types_or_consts() { if hidden_type.has_non_region_infer() {
infcx.tcx.sess.delay_span_bug( infcx.tcx.sess.delay_span_bug(
decl.hidden_type.span, decl.hidden_type.span,
&format!("could not resolve {:#?}", hidden_type.ty.kind()), &format!("could not resolve {:#?}", hidden_type.ty.kind()),
@ -428,12 +425,18 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
} }
if let ty::FnDef(def_id, substs) = *constant.literal.ty().kind() { if let ty::FnDef(def_id, substs) = *constant.literal.ty().kind() {
// const_trait_impl: use a non-const param env when checking that a FnDef type is well formed.
// this is because the well-formedness of the function does not need to be proved to have `const`
// impls for trait bounds.
let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs); let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
let prev = self.cx.param_env;
self.cx.param_env = prev.without_const();
self.cx.normalize_and_prove_instantiated_predicates( self.cx.normalize_and_prove_instantiated_predicates(
def_id, def_id,
instantiated_predicates, instantiated_predicates,
locations, locations,
); );
self.cx.param_env = prev;
} }
} }
} }
@ -581,6 +584,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
// modify their locations. // modify their locations.
let all_facts = &mut None; let all_facts = &mut None;
let mut constraints = Default::default(); let mut constraints = Default::default();
let mut type_tests = Default::default();
let mut closure_bounds = Default::default(); let mut closure_bounds = Default::default();
let mut liveness_constraints = let mut liveness_constraints =
LivenessValues::new(Rc::new(RegionValueElements::new(&promoted_body))); LivenessValues::new(Rc::new(RegionValueElements::new(&promoted_body)));
@ -592,6 +596,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
&mut this.cx.borrowck_context.constraints.outlives_constraints, &mut this.cx.borrowck_context.constraints.outlives_constraints,
&mut constraints, &mut constraints,
); );
mem::swap(&mut this.cx.borrowck_context.constraints.type_tests, &mut type_tests);
mem::swap( mem::swap(
&mut this.cx.borrowck_context.constraints.closure_bounds_mapping, &mut this.cx.borrowck_context.constraints.closure_bounds_mapping,
&mut closure_bounds, &mut closure_bounds,
@ -616,6 +621,13 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
swap_constraints(self); swap_constraints(self);
let locations = location.to_locations(); let locations = location.to_locations();
// Use location of promoted const in collected constraints
for type_test in type_tests.iter() {
let mut type_test = type_test.clone();
type_test.locations = locations;
self.cx.borrowck_context.constraints.type_tests.push(type_test)
}
for constraint in constraints.outlives().iter() { for constraint in constraints.outlives().iter() {
let mut constraint = constraint.clone(); let mut constraint = constraint.clone();
constraint.locations = locations; constraint.locations = locations;
@ -764,6 +776,19 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
} }
PlaceTy::from_ty(fty) PlaceTy::from_ty(fty)
} }
ProjectionElem::OpaqueCast(ty) => {
let ty = self.sanitize_type(place, ty);
let ty = self.cx.normalize(ty, location);
self.cx
.eq_types(
base.ty,
ty,
location.to_locations(),
ConstraintCategory::TypeAnnotation,
)
.unwrap();
PlaceTy::from_ty(ty)
}
} }
} }
@ -857,7 +882,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
/// way, it accrues region constraints -- these can later be used by /// way, it accrues region constraints -- these can later be used by
/// NLL region checking. /// NLL region checking.
struct TypeChecker<'a, 'tcx> { struct TypeChecker<'a, 'tcx> {
infcx: &'a InferCtxt<'a, 'tcx>, infcx: &'a InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
last_span: Span, last_span: Span,
body: &'a Body<'tcx>, body: &'a Body<'tcx>,
@ -927,7 +952,7 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> {
impl<'tcx> MirTypeckRegionConstraints<'tcx> { impl<'tcx> MirTypeckRegionConstraints<'tcx> {
fn placeholder_region( fn placeholder_region(
&mut self, &mut self,
infcx: &InferCtxt<'_, 'tcx>, infcx: &InferCtxt<'tcx>,
placeholder: ty::PlaceholderRegion, placeholder: ty::PlaceholderRegion,
) -> ty::Region<'tcx> { ) -> ty::Region<'tcx> {
let placeholder_index = self.placeholder_indices.insert(placeholder); let placeholder_index = self.placeholder_indices.insert(placeholder);
@ -1011,7 +1036,7 @@ impl Locations {
impl<'a, 'tcx> TypeChecker<'a, 'tcx> { impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
fn new( fn new(
infcx: &'a InferCtxt<'a, 'tcx>, infcx: &'a InferCtxt<'tcx>,
body: &'a Body<'tcx>, body: &'a Body<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
region_bound_pairs: &'a RegionBoundPairs<'tcx>, region_bound_pairs: &'a RegionBoundPairs<'tcx>,
@ -1170,10 +1195,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
tcx, tcx,
self.param_env, self.param_env,
proj, proj,
|this, field, ()| { |this, field, _| {
let ty = this.field_ty(tcx, field); let ty = this.field_ty(tcx, field);
self.normalize(ty, locations) self.normalize(ty, locations)
}, },
|_, _| unreachable!(),
); );
curr_projected_ty = projected_ty; curr_projected_ty = projected_ty;
} }
@ -1604,7 +1630,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let op_arg_ty = self.normalize(op_arg_ty, term_location); let op_arg_ty = self.normalize(op_arg_ty, term_location);
let category = if from_hir_call { let category = if from_hir_call {
ConstraintCategory::CallArgument(func_ty) ConstraintCategory::CallArgument(self.infcx.tcx.erase_regions(func_ty))
} else { } else {
ConstraintCategory::Boring ConstraintCategory::Boring
}; };
@ -1757,7 +1783,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// `Sized` bound in no way depends on precise regions, so this // `Sized` bound in no way depends on precise regions, so this
// shouldn't affect `is_sized`. // shouldn't affect `is_sized`.
let erased_ty = tcx.erase_regions(ty); let erased_ty = tcx.erase_regions(ty);
if !erased_ty.is_sized(tcx.at(span), self.param_env) { if !erased_ty.is_sized(tcx, self.param_env) {
// in current MIR construction, all non-control-flow rvalue // in current MIR construction, all non-control-flow rvalue
// expressions evaluate through `as_temp` or `into` a return // expressions evaluate through `as_temp` or `into` a return
// slot or local, so to find all unsized rvalues it is enough // slot or local, so to find all unsized rvalues it is enough
@ -2189,25 +2215,104 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
} }
} }
CastKind::IntToInt => {
CastKind::Misc => {
let ty_from = op.ty(body, tcx); let ty_from = op.ty(body, tcx);
let cast_ty_from = CastTy::from_ty(ty_from); let cast_ty_from = CastTy::from_ty(ty_from);
let cast_ty_to = CastTy::from_ty(*ty); let cast_ty_to = CastTy::from_ty(*ty);
// Misc casts are either between floats and ints, or one ptr type to another.
match (cast_ty_from, cast_ty_to) { match (cast_ty_from, cast_ty_to) {
( (Some(CastTy::Int(_)), Some(CastTy::Int(_))) => (),
Some(CastTy::Int(_) | CastTy::Float),
Some(CastTy::Int(_) | CastTy::Float),
)
| (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Ptr(_))) => (),
_ => { _ => {
span_mirbug!( span_mirbug!(
self, self,
rvalue, rvalue,
"Invalid Misc cast {:?} -> {:?}", "Invalid IntToInt cast {:?} -> {:?}",
ty_from, ty_from,
ty, ty
)
}
}
}
CastKind::IntToFloat => {
let ty_from = op.ty(body, tcx);
let cast_ty_from = CastTy::from_ty(ty_from);
let cast_ty_to = CastTy::from_ty(*ty);
match (cast_ty_from, cast_ty_to) {
(Some(CastTy::Int(_)), Some(CastTy::Float)) => (),
_ => {
span_mirbug!(
self,
rvalue,
"Invalid IntToFloat cast {:?} -> {:?}",
ty_from,
ty
)
}
}
}
CastKind::FloatToInt => {
let ty_from = op.ty(body, tcx);
let cast_ty_from = CastTy::from_ty(ty_from);
let cast_ty_to = CastTy::from_ty(*ty);
match (cast_ty_from, cast_ty_to) {
(Some(CastTy::Float), Some(CastTy::Int(_))) => (),
_ => {
span_mirbug!(
self,
rvalue,
"Invalid FloatToInt cast {:?} -> {:?}",
ty_from,
ty
)
}
}
}
CastKind::FloatToFloat => {
let ty_from = op.ty(body, tcx);
let cast_ty_from = CastTy::from_ty(ty_from);
let cast_ty_to = CastTy::from_ty(*ty);
match (cast_ty_from, cast_ty_to) {
(Some(CastTy::Float), Some(CastTy::Float)) => (),
_ => {
span_mirbug!(
self,
rvalue,
"Invalid FloatToFloat cast {:?} -> {:?}",
ty_from,
ty
)
}
}
}
CastKind::FnPtrToPtr => {
let ty_from = op.ty(body, tcx);
let cast_ty_from = CastTy::from_ty(ty_from);
let cast_ty_to = CastTy::from_ty(*ty);
match (cast_ty_from, cast_ty_to) {
(Some(CastTy::FnPtr), Some(CastTy::Ptr(_))) => (),
_ => {
span_mirbug!(
self,
rvalue,
"Invalid FnPtrToPtr cast {:?} -> {:?}",
ty_from,
ty
)
}
}
}
CastKind::PtrToPtr => {
let ty_from = op.ty(body, tcx);
let cast_ty_from = CastTy::from_ty(ty_from);
let cast_ty_to = CastTy::from_ty(*ty);
match (cast_ty_from, cast_ty_to) {
(Some(CastTy::Ptr(_)), Some(CastTy::Ptr(_))) => (),
_ => {
span_mirbug!(
self,
rvalue,
"Invalid PtrToPtr cast {:?} -> {:?}",
ty_from,
ty
) )
} }
} }
@ -2503,6 +2608,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
ProjectionElem::Field(..) ProjectionElem::Field(..)
| ProjectionElem::Downcast(..) | ProjectionElem::Downcast(..)
| ProjectionElem::OpaqueCast(..)
| ProjectionElem::Index(..) | ProjectionElem::Index(..)
| ProjectionElem::ConstantIndex { .. } | ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Subslice { .. } => { | ProjectionElem::Subslice { .. } => {
@ -2723,7 +2829,7 @@ impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> {
/// constraints in our `InferCtxt` /// constraints in our `InferCtxt`
type ErrorInfo = InstantiateOpaqueType<'tcx>; type ErrorInfo = InstantiateOpaqueType<'tcx>;
fn fully_perform(mut self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> { fn fully_perform(mut self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
let (mut output, region_constraints) = scrape_region_constraints(infcx, || { let (mut output, region_constraints) = scrape_region_constraints(infcx, || {
Ok(InferOk { value: (), obligations: self.obligations.clone() }) Ok(InferOk { value: (), obligations: self.obligations.clone() })
})?; })?;

View File

@ -1,6 +1,6 @@
use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate}; use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate};
use rustc_infer::infer::NllRegionVariableOrigin; use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_infer::traits::ObligationCause; use rustc_infer::traits::PredicateObligations;
use rustc_middle::mir::ConstraintCategory; use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::error::TypeError; use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::relate::TypeRelation;
@ -155,27 +155,16 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
true true
} }
fn register_opaque_type( fn register_opaque_type_obligations(
&mut self, &mut self,
a: Ty<'tcx>, obligations: PredicateObligations<'tcx>,
b: Ty<'tcx>,
a_is_expected: bool,
) -> Result<(), TypeError<'tcx>> { ) -> Result<(), TypeError<'tcx>> {
let param_env = self.param_env();
let span = self.span();
let def_id = self.type_checker.body.source.def_id().expect_local();
let body_id = self.type_checker.tcx().hir().local_def_id_to_hir_id(def_id);
let cause = ObligationCause::misc(span, body_id);
self.type_checker self.type_checker
.fully_perform_op( .fully_perform_op(
self.locations, self.locations,
self.category, self.category,
InstantiateOpaqueType { InstantiateOpaqueType {
obligations: self obligations,
.type_checker
.infcx
.handle_opaque_type(a, b, a_is_expected, &cause, param_env)?
.obligations,
// These fields are filled in during execution of the operation // These fields are filled in during execution of the operation
base_universe: None, base_universe: None,
region_constraints: None, region_constraints: None,

View File

@ -22,8 +22,8 @@ use rustc_hir::{BodyOwnerKind, HirId};
use rustc_index::vec::{Idx, IndexVec}; use rustc_index::vec::{Idx, IndexVec};
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin}; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt}; use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt};
use rustc_middle::ty::{InternalSubsts, SubstsRef};
use std::iter; use std::iter;
use crate::nll::ToRegionVid; use crate::nll::ToRegionVid;
@ -219,7 +219,7 @@ impl<'tcx> UniversalRegions<'tcx> {
/// signature. This will also compute the relationships that are /// signature. This will also compute the relationships that are
/// known between those regions. /// known between those regions.
pub fn new( pub fn new(
infcx: &InferCtxt<'_, 'tcx>, infcx: &InferCtxt<'tcx>,
mir_def: ty::WithOptConstParam<LocalDefId>, mir_def: ty::WithOptConstParam<LocalDefId>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
) -> Self { ) -> Self {
@ -382,7 +382,7 @@ impl<'tcx> UniversalRegions<'tcx> {
} }
struct UniversalRegionsBuilder<'cx, 'tcx> { struct UniversalRegionsBuilder<'cx, 'tcx> {
infcx: &'cx InferCtxt<'cx, 'tcx>, infcx: &'cx InferCtxt<'tcx>,
mir_def: ty::WithOptConstParam<LocalDefId>, mir_def: ty::WithOptConstParam<LocalDefId>,
mir_hir_id: HirId, mir_hir_id: HirId,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
@ -414,7 +414,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
let typeck_root_def_id = self.infcx.tcx.typeck_root_def_id(self.mir_def.did.to_def_id()); let typeck_root_def_id = self.infcx.tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
// If this is is a 'root' body (not a closure/generator/inline const), then // If this is a 'root' body (not a closure/generator/inline const), then
// there are no extern regions, so the local regions start at the same // there are no extern regions, so the local regions start at the same
// position as the (empty) sub-list of extern regions // position as the (empty) sub-list of extern regions
let first_local_index = if self.mir_def.did.to_def_id() == typeck_root_def_id { let first_local_index = if self.mir_def.did.to_def_id() == typeck_root_def_id {
@ -699,7 +699,7 @@ trait InferCtxtExt<'tcx> {
); );
} }
impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
fn replace_free_regions_with_nll_infer_vars<T>( fn replace_free_regions_with_nll_infer_vars<T>(
&self, &self,
origin: NllRegionVariableOrigin, origin: NllRegionVariableOrigin,

View File

@ -58,6 +58,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
/// Builds the whole `assert!` expression. For example, `let elem = 1; assert!(elem == 1);` expands to: /// Builds the whole `assert!` expression. For example, `let elem = 1; assert!(elem == 1);` expands to:
/// ///
/// ```rust /// ```rust
/// #![feature(generic_assert_internals)]
/// let elem = 1; /// let elem = 1;
/// { /// {
/// #[allow(unused_imports)] /// #[allow(unused_imports)]
@ -70,7 +71,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
/// __local_bind0 /// __local_bind0
/// } == 1 /// } == 1
/// ) { /// ) {
/// panic!("Assertion failed: elem == 1\nWith captures:\n elem = {}", __capture0) /// panic!("Assertion failed: elem == 1\nWith captures:\n elem = {:?}", __capture0)
/// } /// }
/// } /// }
/// ``` /// ```
@ -241,8 +242,8 @@ impl<'cx, 'a> Context<'cx, 'a> {
self.manage_cond_expr(prefix); self.manage_cond_expr(prefix);
self.manage_cond_expr(suffix); self.manage_cond_expr(suffix);
} }
ExprKind::MethodCall(_, ref mut local_exprs, _) => { ExprKind::MethodCall(_, _,ref mut local_exprs, _) => {
for local_expr in local_exprs.iter_mut().skip(1) { for local_expr in local_exprs.iter_mut() {
self.manage_cond_expr(local_expr); self.manage_cond_expr(local_expr);
} }
} }
@ -378,14 +379,12 @@ impl<'cx, 'a> Context<'cx, 'a> {
id: DUMMY_NODE_ID, id: DUMMY_NODE_ID,
ident: Ident::new(sym::try_capture, self.span), ident: Ident::new(sym::try_capture, self.span),
}, },
vec![
expr_paren(self.cx, self.span, self.cx.expr_addr_of(self.span, wrapper)), expr_paren(self.cx, self.span, self.cx.expr_addr_of(self.span, wrapper)),
expr_addr_of_mut( vec![expr_addr_of_mut(
self.cx, self.cx,
self.span, self.span,
self.cx.expr_path(Path::from_ident(capture)), self.cx.expr_path(Path::from_ident(capture)),
), )],
],
self.span, self.span,
)) ))
.add_trailing_semicolon(); .add_trailing_semicolon();
@ -443,10 +442,11 @@ fn expr_addr_of_mut(cx: &ExtCtxt<'_>, sp: Span, e: P<Expr>) -> P<Expr> {
fn expr_method_call( fn expr_method_call(
cx: &ExtCtxt<'_>, cx: &ExtCtxt<'_>,
path: PathSegment, path: PathSegment,
receiver: P<Expr>,
args: Vec<P<Expr>>, args: Vec<P<Expr>>,
span: Span, span: Span,
) -> P<Expr> { ) -> P<Expr> {
cx.expr(span, ExprKind::MethodCall(path, args, span)) cx.expr(span, ExprKind::MethodCall(path, receiver, args, span))
} }
fn expr_paren(cx: &ExtCtxt<'_>, sp: Span, e: P<Expr>) -> P<Expr> { fn expr_paren(cx: &ExtCtxt<'_>, sp: Span, e: P<Expr>) -> P<Expr> {

View File

@ -8,7 +8,7 @@ use rustc_ast::tokenstream::TokenStream;
use rustc_attr as attr; use rustc_attr as attr;
use rustc_errors::PResult; use rustc_errors::PResult;
use rustc_expand::base::{self, *}; use rustc_expand::base::{self, *};
use rustc_macros::SessionDiagnostic; use rustc_macros::Diagnostic;
use rustc_span::Span; use rustc_span::Span;
pub fn expand_cfg( pub fn expand_cfg(
@ -35,16 +35,16 @@ pub fn expand_cfg(
} }
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(builtin_macros::requires_cfg_pattern)] #[diag(builtin_macros_requires_cfg_pattern)]
struct RequiresCfgPattern { struct RequiresCfgPattern {
#[primary_span] #[primary_span]
#[label] #[label]
span: Span, span: Span,
} }
#[derive(SessionDiagnostic)] #[derive(Diagnostic)]
#[diag(builtin_macros::expected_one_cfg_pattern)] #[diag(builtin_macros_expected_one_cfg_pattern)]
struct OneCfgPattern { struct OneCfgPattern {
#[primary_span] #[primary_span]
span: Span, span: Span,

View File

@ -7,6 +7,7 @@ use rustc_ast::visit::Visitor;
use rustc_ast::NodeId; use rustc_ast::NodeId;
use rustc_ast::{mut_visit, visit}; use rustc_ast::{mut_visit, visit};
use rustc_ast::{Attribute, HasAttrs, HasTokens}; use rustc_ast::{Attribute, HasAttrs, HasTokens};
use rustc_errors::PResult;
use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_expand::config::StripUnconfigured; use rustc_expand::config::StripUnconfigured;
use rustc_expand::configure; use rustc_expand::configure;
@ -144,30 +145,31 @@ impl CfgEval<'_, '_> {
// the location of `#[cfg]` and `#[cfg_attr]` in the token stream. The tokenization // the location of `#[cfg]` and `#[cfg_attr]` in the token stream. The tokenization
// process is lossless, so this process is invisible to proc-macros. // process is lossless, so this process is invisible to proc-macros.
let parse_annotatable_with: fn(&mut Parser<'_>) -> _ = match annotatable { let parse_annotatable_with: for<'a> fn(&mut Parser<'a>) -> PResult<'a, _> =
match annotatable {
Annotatable::Item(_) => { Annotatable::Item(_) => {
|parser| Annotatable::Item(parser.parse_item(ForceCollect::Yes).unwrap().unwrap()) |parser| Ok(Annotatable::Item(parser.parse_item(ForceCollect::Yes)?.unwrap()))
} }
Annotatable::TraitItem(_) => |parser| { Annotatable::TraitItem(_) => |parser| {
Annotatable::TraitItem( Ok(Annotatable::TraitItem(
parser.parse_trait_item(ForceCollect::Yes).unwrap().unwrap().unwrap(), parser.parse_trait_item(ForceCollect::Yes)?.unwrap().unwrap(),
) ))
}, },
Annotatable::ImplItem(_) => |parser| { Annotatable::ImplItem(_) => |parser| {
Annotatable::ImplItem( Ok(Annotatable::ImplItem(
parser.parse_impl_item(ForceCollect::Yes).unwrap().unwrap().unwrap(), parser.parse_impl_item(ForceCollect::Yes)?.unwrap().unwrap(),
) ))
}, },
Annotatable::ForeignItem(_) => |parser| { Annotatable::ForeignItem(_) => |parser| {
Annotatable::ForeignItem( Ok(Annotatable::ForeignItem(
parser.parse_foreign_item(ForceCollect::Yes).unwrap().unwrap().unwrap(), parser.parse_foreign_item(ForceCollect::Yes)?.unwrap().unwrap(),
) ))
}, },
Annotatable::Stmt(_) => |parser| { Annotatable::Stmt(_) => |parser| {
Annotatable::Stmt(P(parser.parse_stmt(ForceCollect::Yes).unwrap().unwrap())) Ok(Annotatable::Stmt(P(parser.parse_stmt(ForceCollect::Yes)?.unwrap())))
}, },
Annotatable::Expr(_) => { Annotatable::Expr(_) => {
|parser| Annotatable::Expr(parser.parse_expr_force_collect().unwrap()) |parser| Ok(Annotatable::Expr(parser.parse_expr_force_collect()?))
} }
_ => unreachable!(), _ => unreachable!(),
}; };
@ -193,7 +195,13 @@ impl CfgEval<'_, '_> {
let mut parser = let mut parser =
rustc_parse::stream_to_parser(&self.cfg.sess.parse_sess, orig_tokens, None); rustc_parse::stream_to_parser(&self.cfg.sess.parse_sess, orig_tokens, None);
parser.capture_cfg = true; parser.capture_cfg = true;
annotatable = parse_annotatable_with(&mut parser); match parse_annotatable_with(&mut parser) {
Ok(a) => annotatable = a,
Err(mut err) => {
err.emit();
return Some(annotatable);
}
}
// Now that we have our re-parsed `AttrTokenStream`, recursively configuring // Now that we have our re-parsed `AttrTokenStream`, recursively configuring
// our attribute target will correctly the tokens as well. // our attribute target will correctly the tokens as well.
@ -202,8 +210,15 @@ impl CfgEval<'_, '_> {
} }
impl MutVisitor for CfgEval<'_, '_> { impl MutVisitor for CfgEval<'_, '_> {
#[instrument(level = "trace", skip(self))]
fn visit_expr(&mut self, expr: &mut P<ast::Expr>) { fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
self.cfg.configure_expr(expr); self.cfg.configure_expr(expr, false);
mut_visit::noop_visit_expr(expr, self);
}
#[instrument(level = "trace", skip(self))]
fn visit_method_receiver_expr(&mut self, expr: &mut P<ast::Expr>) {
self.cfg.configure_expr(expr, true);
mut_visit::noop_visit_expr(expr, self); mut_visit::noop_visit_expr(expr, self);
} }

View File

@ -16,6 +16,7 @@ pub fn expand_deriving_copy(
let trait_def = TraitDef { let trait_def = TraitDef {
span, span,
path: path_std!(marker::Copy), path: path_std!(marker::Copy),
skip_path_as_bound: false,
additional_bounds: Vec::new(), additional_bounds: Vec::new(),
generics: Bounds::empty(), generics: Bounds::empty(),
supports_unions: true, supports_unions: true,

View File

@ -72,6 +72,7 @@ pub fn expand_deriving_clone(
let trait_def = TraitDef { let trait_def = TraitDef {
span, span,
path: path_std!(clone::Clone), path: path_std!(clone::Clone),
skip_path_as_bound: false,
additional_bounds: bounds, additional_bounds: bounds,
generics: Bounds::empty(), generics: Bounds::empty(),
supports_unions: true, supports_unions: true,

View File

@ -25,6 +25,7 @@ pub fn expand_deriving_eq(
let trait_def = TraitDef { let trait_def = TraitDef {
span, span,
path: path_std!(cmp::Eq), path: path_std!(cmp::Eq),
skip_path_as_bound: false,
additional_bounds: Vec::new(), additional_bounds: Vec::new(),
generics: Bounds::empty(), generics: Bounds::empty(),
supports_unions: true, supports_unions: true,

View File

@ -19,6 +19,7 @@ pub fn expand_deriving_ord(
let trait_def = TraitDef { let trait_def = TraitDef {
span, span,
path: path_std!(cmp::Ord), path: path_std!(cmp::Ord),
skip_path_as_bound: false,
additional_bounds: Vec::new(), additional_bounds: Vec::new(),
generics: Bounds::empty(), generics: Bounds::empty(),
supports_unions: false, supports_unions: false,

View File

@ -83,6 +83,7 @@ pub fn expand_deriving_partial_eq(
let trait_def = TraitDef { let trait_def = TraitDef {
span, span,
path: path_std!(cmp::PartialEq), path: path_std!(cmp::PartialEq),
skip_path_as_bound: false,
additional_bounds: Vec::new(), additional_bounds: Vec::new(),
generics: Bounds::empty(), generics: Bounds::empty(),
supports_unions: false, supports_unions: false,

View File

@ -37,6 +37,7 @@ pub fn expand_deriving_partial_ord(
let trait_def = TraitDef { let trait_def = TraitDef {
span, span,
path: path_std!(cmp::PartialOrd), path: path_std!(cmp::PartialOrd),
skip_path_as_bound: false,
additional_bounds: vec![], additional_bounds: vec![],
generics: Bounds::empty(), generics: Bounds::empty(),
supports_unions: false, supports_unions: false,

View File

@ -20,6 +20,7 @@ pub fn expand_deriving_debug(
let trait_def = TraitDef { let trait_def = TraitDef {
span, span,
path: path_std!(fmt::Debug), path: path_std!(fmt::Debug),
skip_path_as_bound: false,
additional_bounds: Vec::new(), additional_bounds: Vec::new(),
generics: Bounds::empty(), generics: Bounds::empty(),
supports_unions: false, supports_unions: false,

View File

@ -23,6 +23,7 @@ pub fn expand_deriving_rustc_decodable(
let trait_def = TraitDef { let trait_def = TraitDef {
span, span,
path: Path::new_(vec![krate, sym::Decodable], vec![], PathKind::Global), path: Path::new_(vec![krate, sym::Decodable], vec![], PathKind::Global),
skip_path_as_bound: false,
additional_bounds: Vec::new(), additional_bounds: Vec::new(),
generics: Bounds::empty(), generics: Bounds::empty(),
supports_unions: false, supports_unions: false,

View File

@ -24,6 +24,7 @@ pub fn expand_deriving_default(
let trait_def = TraitDef { let trait_def = TraitDef {
span, span,
path: Path::new(vec![kw::Default, sym::Default]), path: Path::new(vec![kw::Default, sym::Default]),
skip_path_as_bound: has_a_default_variant(item),
additional_bounds: Vec::new(), additional_bounds: Vec::new(),
generics: Bounds::empty(), generics: Bounds::empty(),
supports_unions: false, supports_unions: false,
@ -262,3 +263,22 @@ impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, '
} }
} }
} }
fn has_a_default_variant(item: &Annotatable) -> bool {
struct HasDefaultAttrOnVariant {
found: bool,
}
impl<'ast> rustc_ast::visit::Visitor<'ast> for HasDefaultAttrOnVariant {
fn visit_variant(&mut self, v: &'ast rustc_ast::Variant) {
if v.attrs.iter().any(|attr| attr.has_name(kw::Default)) {
self.found = true;
}
// no need to subrecurse.
}
}
let mut visitor = HasDefaultAttrOnVariant { found: false };
item.visit_with(&mut visitor);
visitor.found
}

View File

@ -107,6 +107,7 @@ pub fn expand_deriving_rustc_encodable(
let trait_def = TraitDef { let trait_def = TraitDef {
span, span,
path: Path::new_(vec![krate, sym::Encodable], vec![], PathKind::Global), path: Path::new_(vec![krate, sym::Encodable], vec![], PathKind::Global),
skip_path_as_bound: false,
additional_bounds: Vec::new(), additional_bounds: Vec::new(),
generics: Bounds::empty(), generics: Bounds::empty(),
supports_unions: false, supports_unions: false,

View File

@ -174,6 +174,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span; use rustc_span::Span;
use std::cell::RefCell; use std::cell::RefCell;
use std::iter; use std::iter;
use std::ops::Not;
use std::vec; use std::vec;
use thin_vec::thin_vec; use thin_vec::thin_vec;
use ty::{Bounds, Path, Ref, Self_, Ty}; use ty::{Bounds, Path, Ref, Self_, Ty};
@ -187,6 +188,9 @@ pub struct TraitDef<'a> {
/// Path of the trait, including any type parameters /// Path of the trait, including any type parameters
pub path: Path, pub path: Path,
/// Whether to skip adding the current trait as a bound to the type parameters of the type.
pub skip_path_as_bound: bool,
/// Additional bounds required of any type parameters of the type, /// Additional bounds required of any type parameters of the type,
/// other than the current trait /// other than the current trait
pub additional_bounds: Vec<Ty>, pub additional_bounds: Vec<Ty>,
@ -562,7 +566,7 @@ impl<'a> TraitDef<'a> {
tokens: None, tokens: None,
}, },
attrs: ast::AttrVec::new(), attrs: ast::AttrVec::new(),
kind: ast::AssocItemKind::TyAlias(Box::new(ast::TyAlias { kind: ast::AssocItemKind::Type(Box::new(ast::TyAlias {
defaultness: ast::Defaultness::Final, defaultness: ast::Defaultness::Final,
generics: Generics::default(), generics: Generics::default(),
where_clauses: ( where_clauses: (
@ -596,7 +600,7 @@ impl<'a> TraitDef<'a> {
cx.trait_bound(p.to_path(cx, self.span, type_ident, generics)) cx.trait_bound(p.to_path(cx, self.span, type_ident, generics))
}).chain( }).chain(
// require the current trait // require the current trait
iter::once(cx.trait_bound(trait_path.clone())) self.skip_path_as_bound.not().then(|| cx.trait_bound(trait_path.clone()))
).chain( ).chain(
// also add in any bounds from the declaration // also add in any bounds from the declaration
param.bounds.iter().cloned() param.bounds.iter().cloned()
@ -1110,6 +1114,11 @@ impl<'a> MethodDef<'a> {
/// ``` /// ```
/// is equivalent to: /// is equivalent to:
/// ``` /// ```
/// #![feature(core_intrinsics)]
/// enum A {
/// A1,
/// A2(i32)
/// }
/// impl ::core::cmp::PartialEq for A { /// impl ::core::cmp::PartialEq for A {
/// #[inline] /// #[inline]
/// fn eq(&self, other: &A) -> bool { /// fn eq(&self, other: &A) -> bool {

View File

@ -22,6 +22,7 @@ pub fn expand_deriving_hash(
let hash_trait_def = TraitDef { let hash_trait_def = TraitDef {
span, span,
path, path,
skip_path_as_bound: false,
additional_bounds: Vec::new(), additional_bounds: Vec::new(),
generics: Bounds::empty(), generics: Bounds::empty(),
supports_unions: false, supports_unions: false,

View File

@ -131,6 +131,8 @@ fn inject_impl_of_structural_trait(
// Create generics param list for where clauses and impl headers // Create generics param list for where clauses and impl headers
let mut generics = generics.clone(); let mut generics = generics.clone();
let ctxt = span.ctxt();
// Create the type of `self`. // Create the type of `self`.
// //
// in addition, remove defaults from generic params (impls cannot have them). // in addition, remove defaults from generic params (impls cannot have them).
@ -138,16 +140,18 @@ fn inject_impl_of_structural_trait(
.params .params
.iter_mut() .iter_mut()
.map(|param| match &mut param.kind { .map(|param| match &mut param.kind {
ast::GenericParamKind::Lifetime => { ast::GenericParamKind::Lifetime => ast::GenericArg::Lifetime(
ast::GenericArg::Lifetime(cx.lifetime(span, param.ident)) cx.lifetime(param.ident.span.with_ctxt(ctxt), param.ident),
} ),
ast::GenericParamKind::Type { default } => { ast::GenericParamKind::Type { default } => {
*default = None; *default = None;
ast::GenericArg::Type(cx.ty_ident(span, param.ident)) ast::GenericArg::Type(cx.ty_ident(param.ident.span.with_ctxt(ctxt), param.ident))
} }
ast::GenericParamKind::Const { ty: _, kw_span: _, default } => { ast::GenericParamKind::Const { ty: _, kw_span: _, default } => {
*default = None; *default = None;
ast::GenericArg::Const(cx.const_ident(span, param.ident)) ast::GenericArg::Const(
cx.const_ident(param.ident.span.with_ctxt(ctxt), param.ident),
)
} }
}) })
.collect(); .collect();
@ -174,6 +178,8 @@ fn inject_impl_of_structural_trait(
}) })
.cloned(), .cloned(),
); );
// Mark as `automatically_derived` to avoid some silly lints.
attrs.push(cx.attribute(cx.meta_word(span, sym::automatically_derived)));
let newitem = cx.item( let newitem = cx.item(
span, span,

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,240 @@
use rustc_ast::ptr::P;
use rustc_ast::Expr;
use rustc_data_structures::fx::FxHashMap;
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::Span;
// Definitions:
//
// format_args!("hello {abc:.xyz$}!!", abc="world");
// └──────────────────────────────────────────────┘
// FormatArgs
//
// format_args!("hello {abc:.xyz$}!!", abc="world");
// └─────────┘
// argument
//
// format_args!("hello {abc:.xyz$}!!", abc="world");
// └───────────────────┘
// template
//
// format_args!("hello {abc:.xyz$}!!", abc="world");
// └────┘└─────────┘└┘
// pieces
//
// format_args!("hello {abc:.xyz$}!!", abc="world");
// └────┘ └┘
// literal pieces
//
// format_args!("hello {abc:.xyz$}!!", abc="world");
// └─────────┘
// placeholder
//
// format_args!("hello {abc:.xyz$}!!", abc="world");
// └─┘ └─┘
// positions (could be names, numbers, empty, or `*`)
/// (Parsed) format args.
///
/// Basically the "AST" for a complete `format_args!()`.
///
/// E.g., `format_args!("hello {name}");`.
#[derive(Clone, Debug)]
pub struct FormatArgs {
pub span: Span,
pub template: Vec<FormatArgsPiece>,
pub arguments: FormatArguments,
}
/// A piece of a format template string.
///
/// E.g. "hello" or "{name}".
#[derive(Clone, Debug)]
pub enum FormatArgsPiece {
Literal(Symbol),
Placeholder(FormatPlaceholder),
}
/// The arguments to format_args!().
///
/// E.g. `1, 2, name="ferris", n=3`,
/// but also implicit captured arguments like `x` in `format_args!("{x}")`.
#[derive(Clone, Debug)]
pub struct FormatArguments {
arguments: Vec<FormatArgument>,
num_unnamed_args: usize,
num_explicit_args: usize,
names: FxHashMap<Symbol, usize>,
}
impl FormatArguments {
pub fn new() -> Self {
Self {
arguments: Vec::new(),
names: FxHashMap::default(),
num_unnamed_args: 0,
num_explicit_args: 0,
}
}
pub fn add(&mut self, arg: FormatArgument) -> usize {
let index = self.arguments.len();
if let Some(name) = arg.kind.ident() {
self.names.insert(name.name, index);
} else if self.names.is_empty() {
// Only count the unnamed args before the first named arg.
// (Any later ones are errors.)
self.num_unnamed_args += 1;
}
if !matches!(arg.kind, FormatArgumentKind::Captured(..)) {
// This is an explicit argument.
// Make sure that all arguments so far are explcit.
assert_eq!(
self.num_explicit_args,
self.arguments.len(),
"captured arguments must be added last"
);
self.num_explicit_args += 1;
}
self.arguments.push(arg);
index
}
pub fn by_name(&self, name: Symbol) -> Option<(usize, &FormatArgument)> {
let i = *self.names.get(&name)?;
Some((i, &self.arguments[i]))
}
pub fn by_index(&self, i: usize) -> Option<&FormatArgument> {
(i < self.num_explicit_args).then(|| &self.arguments[i])
}
pub fn unnamed_args(&self) -> &[FormatArgument] {
&self.arguments[..self.num_unnamed_args]
}
pub fn named_args(&self) -> &[FormatArgument] {
&self.arguments[self.num_unnamed_args..self.num_explicit_args]
}
pub fn explicit_args(&self) -> &[FormatArgument] {
&self.arguments[..self.num_explicit_args]
}
pub fn into_vec(self) -> Vec<FormatArgument> {
self.arguments
}
}
#[derive(Clone, Debug)]
pub struct FormatArgument {
pub kind: FormatArgumentKind,
pub expr: P<Expr>,
}
#[derive(Clone, Debug)]
pub enum FormatArgumentKind {
/// `format_args(…, arg)`
Normal,
/// `format_args(…, arg = 1)`
Named(Ident),
/// `format_args("… {arg} …")`
Captured(Ident),
}
impl FormatArgumentKind {
pub fn ident(&self) -> Option<Ident> {
match self {
&Self::Normal => None,
&Self::Named(id) => Some(id),
&Self::Captured(id) => Some(id),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct FormatPlaceholder {
/// Index into [`FormatArgs::arguments`].
pub argument: FormatArgPosition,
/// The span inside the format string for the full `{…}` placeholder.
pub span: Option<Span>,
/// `{}`, `{:?}`, or `{:x}`, etc.
pub format_trait: FormatTrait,
/// `{}` or `{:.5}` or `{:-^20}`, etc.
pub format_options: FormatOptions,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct FormatArgPosition {
/// Which argument this position refers to (Ok),
/// or would've referred to if it existed (Err).
pub index: Result<usize, usize>,
/// What kind of position this is. See [`FormatArgPositionKind`].
pub kind: FormatArgPositionKind,
/// The span of the name or number.
pub span: Option<Span>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum FormatArgPositionKind {
/// `{}` or `{:.*}`
Implicit,
/// `{1}` or `{:1$}` or `{:.1$}`
Number,
/// `{a}` or `{:a$}` or `{:.a$}`
Named,
}
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub enum FormatTrait {
/// `{}`
Display,
/// `{:?}`
Debug,
/// `{:e}`
LowerExp,
/// `{:E}`
UpperExp,
/// `{:o}`
Octal,
/// `{:p}`
Pointer,
/// `{:b}`
Binary,
/// `{:x}`
LowerHex,
/// `{:X}`
UpperHex,
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct FormatOptions {
/// The width. E.g. `{:5}` or `{:width$}`.
pub width: Option<FormatCount>,
/// The precision. E.g. `{:.5}` or `{:.precision$}`.
pub precision: Option<FormatCount>,
/// The alignment. E.g. `{:>}` or `{:<}` or `{:^}`.
pub alignment: Option<FormatAlignment>,
/// The fill character. E.g. the `.` in `{:.>10}`.
pub fill: Option<char>,
/// The `+`, `-`, `0`, `#`, `x?` and `X?` flags.
pub flags: u32,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum FormatAlignment {
/// `{:<}`
Left,
/// `{:>}`
Right,
/// `{:^}`
Center,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum FormatCount {
/// `{:5}` or `{:.5}`
Literal(usize),
/// `{:.*}`, `{:.5$}`, or `{:a$}`, etc.
Argument(FormatArgPosition),
}

View File

@ -0,0 +1,353 @@
use super::*;
use rustc_ast as ast;
use rustc_ast::visit::{self, Visitor};
use rustc_ast::{BlockCheckMode, UnsafeSource};
use rustc_data_structures::fx::FxIndexSet;
use rustc_span::{sym, symbol::kw};
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
enum ArgumentType {
Format(FormatTrait),
Usize,
}
fn make_argument(ecx: &ExtCtxt<'_>, sp: Span, arg: P<ast::Expr>, ty: ArgumentType) -> P<ast::Expr> {
// Generate:
// ::core::fmt::ArgumentV1::new_…(arg)
use ArgumentType::*;
use FormatTrait::*;
ecx.expr_call_global(
sp,
ecx.std_path(&[
sym::fmt,
sym::ArgumentV1,
match ty {
Format(Display) => sym::new_display,
Format(Debug) => sym::new_debug,
Format(LowerExp) => sym::new_lower_exp,
Format(UpperExp) => sym::new_upper_exp,
Format(Octal) => sym::new_octal,
Format(Pointer) => sym::new_pointer,
Format(Binary) => sym::new_binary,
Format(LowerHex) => sym::new_lower_hex,
Format(UpperHex) => sym::new_upper_hex,
Usize => sym::from_usize,
},
]),
vec![arg],
)
}
fn make_count(
ecx: &ExtCtxt<'_>,
sp: Span,
count: &Option<FormatCount>,
argmap: &mut FxIndexSet<(usize, ArgumentType)>,
) -> P<ast::Expr> {
// Generate:
// ::core::fmt::rt::v1::Count::…(…)
match count {
Some(FormatCount::Literal(n)) => ecx.expr_call_global(
sp,
ecx.std_path(&[sym::fmt, sym::rt, sym::v1, sym::Count, sym::Is]),
vec![ecx.expr_usize(sp, *n)],
),
Some(FormatCount::Argument(arg)) => {
if let Ok(arg_index) = arg.index {
let (i, _) = argmap.insert_full((arg_index, ArgumentType::Usize));
ecx.expr_call_global(
sp,
ecx.std_path(&[sym::fmt, sym::rt, sym::v1, sym::Count, sym::Param]),
vec![ecx.expr_usize(sp, i)],
)
} else {
DummyResult::raw_expr(sp, true)
}
}
None => ecx.expr_path(ecx.path_global(
sp,
ecx.std_path(&[sym::fmt, sym::rt, sym::v1, sym::Count, sym::Implied]),
)),
}
}
fn make_format_spec(
ecx: &ExtCtxt<'_>,
sp: Span,
placeholder: &FormatPlaceholder,
argmap: &mut FxIndexSet<(usize, ArgumentType)>,
) -> P<ast::Expr> {
// Generate:
// ::core::fmt::rt::v1::Argument {
// position: 0usize,
// format: ::core::fmt::rt::v1::FormatSpec {
// fill: ' ',
// align: ::core::fmt::rt::v1::Alignment::Unknown,
// flags: 0u32,
// precision: ::core::fmt::rt::v1::Count::Implied,
// width: ::core::fmt::rt::v1::Count::Implied,
// },
// }
let position = match placeholder.argument.index {
Ok(arg_index) => {
let (i, _) =
argmap.insert_full((arg_index, ArgumentType::Format(placeholder.format_trait)));
ecx.expr_usize(sp, i)
}
Err(_) => DummyResult::raw_expr(sp, true),
};
let fill = ecx.expr_char(sp, placeholder.format_options.fill.unwrap_or(' '));
let align = ecx.expr_path(ecx.path_global(
sp,
ecx.std_path(&[
sym::fmt,
sym::rt,
sym::v1,
sym::Alignment,
match placeholder.format_options.alignment {
Some(FormatAlignment::Left) => sym::Left,
Some(FormatAlignment::Right) => sym::Right,
Some(FormatAlignment::Center) => sym::Center,
None => sym::Unknown,
},
]),
));
let flags = ecx.expr_u32(sp, placeholder.format_options.flags);
let prec = make_count(ecx, sp, &placeholder.format_options.precision, argmap);
let width = make_count(ecx, sp, &placeholder.format_options.width, argmap);
ecx.expr_struct(
sp,
ecx.path_global(sp, ecx.std_path(&[sym::fmt, sym::rt, sym::v1, sym::Argument])),
vec![
ecx.field_imm(sp, Ident::new(sym::position, sp), position),
ecx.field_imm(
sp,
Ident::new(sym::format, sp),
ecx.expr_struct(
sp,
ecx.path_global(
sp,
ecx.std_path(&[sym::fmt, sym::rt, sym::v1, sym::FormatSpec]),
),
vec![
ecx.field_imm(sp, Ident::new(sym::fill, sp), fill),
ecx.field_imm(sp, Ident::new(sym::align, sp), align),
ecx.field_imm(sp, Ident::new(sym::flags, sp), flags),
ecx.field_imm(sp, Ident::new(sym::precision, sp), prec),
ecx.field_imm(sp, Ident::new(sym::width, sp), width),
],
),
),
],
)
}
pub fn expand_parsed_format_args(ecx: &mut ExtCtxt<'_>, fmt: FormatArgs) -> P<ast::Expr> {
let macsp = ecx.with_def_site_ctxt(ecx.call_site());
let lit_pieces = ecx.expr_array_ref(
fmt.span,
fmt.template
.iter()
.enumerate()
.filter_map(|(i, piece)| match piece {
&FormatArgsPiece::Literal(s) => Some(ecx.expr_str(fmt.span, s)),
&FormatArgsPiece::Placeholder(_) => {
// Inject empty string before placeholders when not already preceded by a literal piece.
if i == 0 || matches!(fmt.template[i - 1], FormatArgsPiece::Placeholder(_)) {
Some(ecx.expr_str(fmt.span, kw::Empty))
} else {
None
}
}
})
.collect(),
);
// Whether we'll use the `Arguments::new_v1_formatted` form (true),
// or the `Arguments::new_v1` form (false).
let mut use_format_options = false;
// Create a list of all _unique_ (argument, format trait) combinations.
// E.g. "{0} {0:x} {0} {1}" -> [(0, Display), (0, LowerHex), (1, Display)]
let mut argmap = FxIndexSet::default();
for piece in &fmt.template {
let FormatArgsPiece::Placeholder(placeholder) = piece else { continue };
if placeholder.format_options != Default::default() {
// Can't use basic form if there's any formatting options.
use_format_options = true;
}
if let Ok(index) = placeholder.argument.index {
if !argmap.insert((index, ArgumentType::Format(placeholder.format_trait))) {
// Duplicate (argument, format trait) combination,
// which we'll only put once in the args array.
use_format_options = true;
}
}
}
let format_options = use_format_options.then(|| {
// Generate:
// &[format_spec_0, format_spec_1, format_spec_2]
ecx.expr_array_ref(
macsp,
fmt.template
.iter()
.filter_map(|piece| {
let FormatArgsPiece::Placeholder(placeholder) = piece else { return None };
Some(make_format_spec(ecx, macsp, placeholder, &mut argmap))
})
.collect(),
)
});
let arguments = fmt.arguments.into_vec();
// If the args array contains exactly all the original arguments once,
// in order, we can use a simple array instead of a `match` construction.
// However, if there's a yield point in any argument except the first one,
// we don't do this, because an ArgumentV1 cannot be kept across yield points.
let use_simple_array = argmap.len() == arguments.len()
&& argmap.iter().enumerate().all(|(i, &(j, _))| i == j)
&& arguments.iter().skip(1).all(|arg| !may_contain_yield_point(&arg.expr));
let args = if use_simple_array {
// Generate:
// &[
// ::core::fmt::ArgumentV1::new_display(&arg0),
// ::core::fmt::ArgumentV1::new_lower_hex(&arg1),
// ::core::fmt::ArgumentV1::new_debug(&arg2),
// ]
ecx.expr_array_ref(
macsp,
arguments
.into_iter()
.zip(argmap)
.map(|(arg, (_, ty))| {
let sp = arg.expr.span.with_ctxt(macsp.ctxt());
make_argument(ecx, sp, ecx.expr_addr_of(sp, arg.expr), ty)
})
.collect(),
)
} else {
// Generate:
// match (&arg0, &arg1, &arg2) {
// args => &[
// ::core::fmt::ArgumentV1::new_display(args.0),
// ::core::fmt::ArgumentV1::new_lower_hex(args.1),
// ::core::fmt::ArgumentV1::new_debug(args.0),
// ]
// }
let args_ident = Ident::new(sym::args, macsp);
let args = argmap
.iter()
.map(|&(arg_index, ty)| {
if let Some(arg) = arguments.get(arg_index) {
let sp = arg.expr.span.with_ctxt(macsp.ctxt());
make_argument(
ecx,
sp,
ecx.expr_field(
sp,
ecx.expr_ident(macsp, args_ident),
Ident::new(sym::integer(arg_index), macsp),
),
ty,
)
} else {
DummyResult::raw_expr(macsp, true)
}
})
.collect();
ecx.expr_addr_of(
macsp,
ecx.expr_match(
macsp,
ecx.expr_tuple(
macsp,
arguments
.into_iter()
.map(|arg| {
ecx.expr_addr_of(arg.expr.span.with_ctxt(macsp.ctxt()), arg.expr)
})
.collect(),
),
vec![ecx.arm(macsp, ecx.pat_ident(macsp, args_ident), ecx.expr_array(macsp, args))],
),
)
};
if let Some(format_options) = format_options {
// Generate:
// ::core::fmt::Arguments::new_v1_formatted(
// lit_pieces,
// args,
// format_options,
// unsafe { ::core::fmt::UnsafeArg::new() }
// )
ecx.expr_call_global(
macsp,
ecx.std_path(&[sym::fmt, sym::Arguments, sym::new_v1_formatted]),
vec![
lit_pieces,
args,
format_options,
ecx.expr_block(P(ast::Block {
stmts: vec![ecx.stmt_expr(ecx.expr_call_global(
macsp,
ecx.std_path(&[sym::fmt, sym::UnsafeArg, sym::new]),
Vec::new(),
))],
id: ast::DUMMY_NODE_ID,
rules: BlockCheckMode::Unsafe(UnsafeSource::CompilerGenerated),
span: macsp,
tokens: None,
could_be_bare_literal: false,
})),
],
)
} else {
// Generate:
// ::core::fmt::Arguments::new_v1(
// lit_pieces,
// args,
// )
ecx.expr_call_global(
macsp,
ecx.std_path(&[sym::fmt, sym::Arguments, sym::new_v1]),
vec![lit_pieces, args],
)
}
}
fn may_contain_yield_point(e: &ast::Expr) -> bool {
struct MayContainYieldPoint(bool);
impl Visitor<'_> for MayContainYieldPoint {
fn visit_expr(&mut self, e: &ast::Expr) {
if let ast::ExprKind::Await(_) | ast::ExprKind::Yield(_) = e.kind {
self.0 = true;
} else {
visit::walk_expr(self, e);
}
}
fn visit_mac_call(&mut self, _: &ast::MacCall) {
self.0 = true;
}
fn visit_attribute(&mut self, _: &ast::Attribute) {
// Conservatively assume this may be a proc macro attribute in
// expression position.
self.0 = true;
}
fn visit_item(&mut self, _: &ast::Item) {
// Do not recurse into nested items.
}
}
let mut visitor = MayContainYieldPoint(false);
visitor.visit_expr(e);
visitor.0
}

View File

@ -7,9 +7,9 @@
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(decl_macro)] #![feature(decl_macro)]
#![feature(if_let_guard)] #![feature(if_let_guard)]
#![feature(is_some_and)]
#![feature(is_sorted)] #![feature(is_sorted)]
#![feature(let_chains)] #![feature(let_chains)]
#![cfg_attr(bootstrap, feature(let_else))]
#![feature(proc_macro_internals)] #![feature(proc_macro_internals)]
#![feature(proc_macro_quote)] #![feature(proc_macro_quote)]
#![recursion_limit = "256"] #![recursion_limit = "256"]

View File

@ -36,13 +36,22 @@ pub fn expand_test_case(
let sp = ecx.with_def_site_ctxt(attr_sp); let sp = ecx.with_def_site_ctxt(attr_sp);
let mut item = anno_item.expect_item(); let mut item = anno_item.expect_item();
item = item.map(|mut item| { item = item.map(|mut item| {
let test_path_symbol = Symbol::intern(&item_path(
// skip the name of the root module
&ecx.current_expansion.module.mod_path[1..],
&item.ident,
));
item.vis = ast::Visibility { item.vis = ast::Visibility {
span: item.vis.span, span: item.vis.span,
kind: ast::VisibilityKind::Public, kind: ast::VisibilityKind::Public,
tokens: None, tokens: None,
}; };
item.ident.span = item.ident.span.with_ctxt(sp.ctxt()); item.ident.span = item.ident.span.with_ctxt(sp.ctxt());
item.attrs.push(ecx.attribute(ecx.meta_word(sp, sym::rustc_test_marker))); item.attrs.push(ecx.attribute(attr::mk_name_value_item_str(
Ident::new(sym::rustc_test_marker, sp),
test_path_symbol,
sp,
)));
item item
}); });
@ -115,7 +124,7 @@ pub fn expand_test_or_bench(
// reworked in the future to not need it, it'd be nice. // reworked in the future to not need it, it'd be nice.
_ => diag.struct_span_err(attr_sp, msg).forget_guarantee(), _ => diag.struct_span_err(attr_sp, msg).forget_guarantee(),
}; };
err.span_label(attr_sp, "the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions") err.span_label(attr_sp, "the `#[test]` macro causes a function to be run on a test and has no effect on non-functions")
.span_label(item.span, format!("expected a non-associated function, found {} {}", item.kind.article(), item.kind.descr())) .span_label(item.span, format!("expected a non-associated function, found {} {}", item.kind.article(), item.kind.descr()))
.span_suggestion(attr_sp, "replace with conditional compilation to make the item only exist when tests are being run", "#[cfg(test)]", Applicability::MaybeIncorrect) .span_suggestion(attr_sp, "replace with conditional compilation to make the item only exist when tests are being run", "#[cfg(test)]", Applicability::MaybeIncorrect)
.emit(); .emit();
@ -215,6 +224,12 @@ pub fn expand_test_or_bench(
) )
}; };
let test_path_symbol = Symbol::intern(&item_path(
// skip the name of the root module
&cx.current_expansion.module.mod_path[1..],
&item.ident,
));
let mut test_const = cx.item( let mut test_const = cx.item(
sp, sp,
Ident::new(item.ident.name, sp), Ident::new(item.ident.name, sp),
@ -224,9 +239,14 @@ pub fn expand_test_or_bench(
Ident::new(sym::cfg, attr_sp), Ident::new(sym::cfg, attr_sp),
vec![attr::mk_nested_word_item(Ident::new(sym::test, attr_sp))], vec![attr::mk_nested_word_item(Ident::new(sym::test, attr_sp))],
)), )),
// #[rustc_test_marker] // #[rustc_test_marker = "test_case_sort_key"]
cx.attribute(cx.meta_word(attr_sp, sym::rustc_test_marker)), cx.attribute(attr::mk_name_value_item_str(
], Ident::new(sym::rustc_test_marker, attr_sp),
test_path_symbol,
attr_sp,
)),
]
.into(),
// const $ident: test::TestDescAndFn = // const $ident: test::TestDescAndFn =
ast::ItemKind::Const( ast::ItemKind::Const(
ast::Defaultness::Final, ast::Defaultness::Final,
@ -250,14 +270,7 @@ pub fn expand_test_or_bench(
cx.expr_call( cx.expr_call(
sp, sp,
cx.expr_path(test_path("StaticTestName")), cx.expr_path(test_path("StaticTestName")),
vec![cx.expr_str( vec![cx.expr_str(sp, test_path_symbol)],
sp,
Symbol::intern(&item_path(
// skip the name of the root module
&cx.current_expansion.module.mod_path[1..],
&item.ident,
)),
)],
), ),
), ),
// ignore: true | false // ignore: true | false

View File

@ -18,9 +18,11 @@ use thin_vec::thin_vec;
use std::{iter, mem}; use std::{iter, mem};
#[derive(Clone)]
struct Test { struct Test {
span: Span, span: Span,
ident: Ident, ident: Ident,
name: Symbol,
} }
struct TestCtxt<'a> { struct TestCtxt<'a> {
@ -120,10 +122,10 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
fn flat_map_item(&mut self, i: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> { fn flat_map_item(&mut self, i: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
let mut item = i.into_inner(); let mut item = i.into_inner();
if is_test_case(&self.cx.ext_cx.sess, &item) { if let Some(name) = get_test_name(&self.cx.ext_cx.sess, &item) {
debug!("this is a test item"); debug!("this is a test item");
let test = Test { span: item.span, ident: item.ident }; let test = Test { span: item.span, ident: item.ident, name };
self.tests.push(test); self.tests.push(test);
} }
@ -357,9 +359,12 @@ fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> P<ast::Expr> {
debug!("building test vector from {} tests", cx.test_cases.len()); debug!("building test vector from {} tests", cx.test_cases.len());
let ecx = &cx.ext_cx; let ecx = &cx.ext_cx;
let mut tests = cx.test_cases.clone();
tests.sort_by(|a, b| a.name.as_str().cmp(&b.name.as_str()));
ecx.expr_array_ref( ecx.expr_array_ref(
sp, sp,
cx.test_cases tests
.iter() .iter()
.map(|test| { .map(|test| {
ecx.expr_addr_of(test.span, ecx.expr_path(ecx.path(test.span, vec![test.ident]))) ecx.expr_addr_of(test.span, ecx.expr_path(ecx.path(test.span, vec![test.ident])))
@ -368,8 +373,8 @@ fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> P<ast::Expr> {
) )
} }
fn is_test_case(sess: &Session, i: &ast::Item) -> bool { fn get_test_name(sess: &Session, i: &ast::Item) -> Option<Symbol> {
sess.contains_name(&i.attrs, sym::rustc_test_marker) sess.first_attr_value_str_by_name(&i.attrs, sym::rustc_test_marker)
} }
fn get_test_runner( fn get_test_runner(

View File

@ -29,7 +29,11 @@ jobs:
matrix: matrix:
include: include:
- os: ubuntu-latest - os: ubuntu-latest
env:
TARGET_TRIPLE: x86_64-unknown-linux-gnu
- os: macos-latest - os: macos-latest
env:
TARGET_TRIPLE: x86_64-apple-darwin
# cross-compile from Linux to Windows using mingw # cross-compile from Linux to Windows using mingw
- os: ubuntu-latest - os: ubuntu-latest
env: env:
@ -112,7 +116,7 @@ jobs:
if: matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu' if: matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu'
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v2
with: with:
name: cg_clif-${{ runner.os }} name: cg_clif-${{ matrix.env.TARGET_TRIPLE }}
path: cg_clif.tar.xz path: cg_clif.tar.xz
- name: Upload prebuilt cg_clif (cross compile) - name: Upload prebuilt cg_clif (cross compile)
@ -122,56 +126,89 @@ jobs:
name: cg_clif-${{ runner.os }}-cross-x86_64-mingw name: cg_clif-${{ runner.os }}-cross-x86_64-mingw
path: cg_clif.tar.xz path: cg_clif.tar.xz
build_windows: windows:
runs-on: windows-latest runs-on: ${{ matrix.os }}
timeout-minutes: 60 timeout-minutes: 60
strategy:
fail-fast: false
matrix:
include:
# Native Windows build with MSVC
- os: windows-latest
env:
TARGET_TRIPLE: x86_64-pc-windows-msvc
# cross-compile from Windows to Windows MinGW
- os: windows-latest
env:
TARGET_TRIPLE: x86_64-pc-windows-gnu
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
#- name: Cache cargo installed crates - name: Cache cargo installed crates
# uses: actions/cache@v2 uses: actions/cache@v2
# with: with:
# path: ~/.cargo/bin path: ~/.cargo/bin
# key: ${{ runner.os }}-cargo-installed-crates key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-installed-crates
#- name: Cache cargo registry and index - name: Cache cargo registry and index
# uses: actions/cache@v2 uses: actions/cache@v2
# with: with:
# path: | path: |
# ~/.cargo/registry ~/.cargo/registry
# ~/.cargo/git ~/.cargo/git
# key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }} key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
#- name: Cache cargo target dir - name: Cache cargo target dir
# uses: actions/cache@v2 uses: actions/cache@v2
# with: with:
# path: target path: target
# key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
- name: Set MinGW as the default toolchain
if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
run: rustup set default-host x86_64-pc-windows-gnu
- name: Prepare dependencies - name: Prepare dependencies
run: | run: |
git config --global user.email "user@example.com" git config --global user.email "user@example.com"
git config --global user.name "User" git config --global user.name "User"
git config --global core.autocrlf false git config --global core.autocrlf false
rustup set default-host x86_64-pc-windows-gnu
rustc y.rs -o y.exe -g rustc y.rs -o y.exe -g
./y.exe prepare ./y.exe prepare
- name: Build without unstable features
env:
TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }}
# This is the config rust-lang/rust uses for builds
run: ./y.rs build --no-unstable-features
- name: Build - name: Build
#name: Test run: ./y.rs build --sysroot none
- name: Test
run: | run: |
# Enable backtraces for easier debugging # Enable backtraces for easier debugging
#$Env:RUST_BACKTRACE=1 $Env:RUST_BACKTRACE=1
# Reduce amount of benchmark runs as they are slow # Reduce amount of benchmark runs as they are slow
#$Env:COMPILE_RUNS=2 $Env:COMPILE_RUNS=2
#$Env:RUN_RUNS=2 $Env:RUN_RUNS=2
# Enable extra checks # Enable extra checks
#$Env:CG_CLIF_ENABLE_VERIFIER=1 $Env:CG_CLIF_ENABLE_VERIFIER=1
./y.exe build # WIP Disable some tests
# This fails due to some weird argument handling by hyperfine, not an actual regression
# more of a build system issue
(Get-Content config.txt) -replace '(bench.simple-raytracer)', '# $1' | Out-File config.txt
# This fails with a different output than expected
(Get-Content config.txt) -replace '(test.regex-shootout-regex-dna)', '# $1' | Out-File config.txt
./y.exe test
- name: Package prebuilt cg_clif - name: Package prebuilt cg_clif
# don't use compression as xzip isn't supported by tar on windows and bzip2 hangs # don't use compression as xzip isn't supported by tar on windows and bzip2 hangs
@ -180,5 +217,5 @@ jobs:
- name: Upload prebuilt cg_clif - name: Upload prebuilt cg_clif
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v2
with: with:
name: cg_clif-${{ runner.os }} name: cg_clif-${{ matrix.env.TARGET_TRIPLE }}
path: cg_clif.tar path: cg_clif.tar

View File

@ -7,7 +7,7 @@
"rust-analyzer.cargo.features": ["unstable-features"], "rust-analyzer.cargo.features": ["unstable-features"],
"rust-analyzer.linkedProjects": [ "rust-analyzer.linkedProjects": [
"./Cargo.toml", "./Cargo.toml",
//"./build_sysroot/sysroot_src/src/libstd/Cargo.toml", //"./build_sysroot/sysroot_src/library/std/Cargo.toml",
{ {
"roots": [ "roots": [
"./example/mini_core.rs", "./example/mini_core.rs",
@ -36,10 +36,10 @@
] ]
}, },
{ {
"roots": ["./scripts/filter_profile.rs"], "roots": ["./example/std_example.rs"],
"crates": [ "crates": [
{ {
"root_module": "./scripts/filter_profile.rs", "root_module": "./example/std_example.rs",
"edition": "2018", "edition": "2018",
"deps": [{ "crate": 1, "name": "std" }], "deps": [{ "crate": 1, "name": "std" }],
"cfg": [], "cfg": [],

View File

@ -24,6 +24,12 @@ name = "ar"
version = "0.8.0" version = "0.8.0"
source = "git+https://github.com/bjorn3/rust-ar.git?branch=do_not_remove_cg_clif_ranlib#de9ab0e56bf3a208381d342aa5b60f9ff2891648" source = "git+https://github.com/bjorn3/rust-ar.git?branch=do_not_remove_cg_clif_ranlib#de9ab0e56bf3a208381d342aa5b60f9ff2891648"
[[package]]
name = "arrayvec"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.1.0" version = "1.1.0"
@ -36,6 +42,12 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bumpalo"
version = "3.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
version = "1.4.3" version = "1.4.3"
@ -50,19 +62,21 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "cranelift-bforest" name = "cranelift-bforest"
version = "0.87.0" version = "0.88.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93945adbccc8d731503d3038814a51e8317497c9e205411820348132fa01a358" checksum = "44409ccf2d0f663920cab563d2b79fcd6b2e9a2bcc6e929fef76c8f82ad6c17a"
dependencies = [ dependencies = [
"cranelift-entity", "cranelift-entity",
] ]
[[package]] [[package]]
name = "cranelift-codegen" name = "cranelift-codegen"
version = "0.87.0" version = "0.88.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b482acc9d0d0d1ad3288a90a8150ee648be3dce8dc8c8669ff026f72debdc31" checksum = "98de2018ad96eb97f621f7d6b900a0cc661aec8d02ea4a50e56ecb48e5a2fcaf"
dependencies = [ dependencies = [
"arrayvec",
"bumpalo",
"cranelift-bforest", "cranelift-bforest",
"cranelift-codegen-meta", "cranelift-codegen-meta",
"cranelift-codegen-shared", "cranelift-codegen-shared",
@ -77,30 +91,30 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-codegen-meta" name = "cranelift-codegen-meta"
version = "0.87.0" version = "0.88.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9ec188d71e663192ef9048f204e410a7283b609942efc9fcc77da6d496edbb8" checksum = "5287ce36e6c4758fbaf298bd1a8697ad97a4f2375a3d1b61142ea538db4877e5"
dependencies = [ dependencies = [
"cranelift-codegen-shared", "cranelift-codegen-shared",
] ]
[[package]] [[package]]
name = "cranelift-codegen-shared" name = "cranelift-codegen-shared"
version = "0.87.0" version = "0.88.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ad794b1b1c2c7bd9f7b76cfe0f084eaf7753e55d56191c3f7d89e8fa4978b99" checksum = "2855c24219e2f08827f3f4ffb2da92e134ae8d8ecc185b11ec8f9878cf5f588e"
[[package]] [[package]]
name = "cranelift-entity" name = "cranelift-entity"
version = "0.87.0" version = "0.88.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "342da0d5056f4119d3c311c4aab2460ceb6ee6e127bb395b76dd2279a09ea7a5" checksum = "0b65673279d75d34bf11af9660ae2dbd1c22e6d28f163f5c72f4e1dc56d56103"
[[package]] [[package]]
name = "cranelift-frontend" name = "cranelift-frontend"
version = "0.87.0" version = "0.88.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfff792f775b07d4d9cfe9f1c767ce755c6cbadda1bbd6db18a1c75ff9f7376a" checksum = "3ed2b3d7a4751163f6c4a349205ab1b7d9c00eecf19dcea48592ef1f7688eefc"
dependencies = [ dependencies = [
"cranelift-codegen", "cranelift-codegen",
"log", "log",
@ -110,15 +124,15 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-isle" name = "cranelift-isle"
version = "0.87.0" version = "0.88.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d51089478849f2ac8ef60a8a2d5346c8d4abfec0e45ac5b24530ef9f9499e1e" checksum = "3be64cecea9d90105fc6a2ba2d003e98c867c1d6c4c86cc878f97ad9fb916293"
[[package]] [[package]]
name = "cranelift-jit" name = "cranelift-jit"
version = "0.87.0" version = "0.88.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "095936e41720f86004b4c57ce88e6a13af28646bb3a6fb4afbebd5ae90c50029" checksum = "f98ed42a70a0c9c388e34ec9477f57fc7300f541b1e5136a0e2ea02b1fac6015"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cranelift-codegen", "cranelift-codegen",
@ -134,9 +148,9 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-module" name = "cranelift-module"
version = "0.87.0" version = "0.88.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "704a1aea4723d97eafe0fb7af110f6f6868b1ac95f5380bbc9adb2a3b8cf97e8" checksum = "d658ac7f156708bfccb647216cc8b9387469f50d352ba4ad80150541e4ae2d49"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cranelift-codegen", "cranelift-codegen",
@ -144,9 +158,9 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-native" name = "cranelift-native"
version = "0.87.0" version = "0.88.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "885debe62f2078638d6585f54c9f05f5c2008f22ce5a2a9100ada785fc065dbd" checksum = "c4a03a6ac1b063e416ca4b93f6247978c991475e8271465340caa6f92f3c16a4"
dependencies = [ dependencies = [
"cranelift-codegen", "cranelift-codegen",
"libc", "libc",
@ -155,9 +169,9 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-object" name = "cranelift-object"
version = "0.87.0" version = "0.88.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aac1310cf1081ae8eca916c92cd163b977c77cab6e831fa812273c26ff921816" checksum = "eef0b4119b645b870a43a036d76c0ada3a076b1f82e8b8487659304c8b09049b"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cranelift-codegen", "cranelift-codegen",
@ -232,9 +246,9 @@ checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b"
[[package]] [[package]]
name = "libloading" name = "libloading"
version = "0.6.7" version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"winapi", "winapi",

View File

@ -8,19 +8,19 @@ crate-type = ["dylib"]
[dependencies] [dependencies]
# These have to be in sync with each other # These have to be in sync with each other
cranelift-codegen = { version = "0.87.0", features = ["unwind", "all-arch"] } cranelift-codegen = { version = "0.88.1", features = ["unwind", "all-arch"] }
cranelift-frontend = "0.87.0" cranelift-frontend = "0.88.1"
cranelift-module = "0.87.0" cranelift-module = "0.88.1"
cranelift-native = "0.87.0" cranelift-native = "0.88.1"
cranelift-jit = { version = "0.87.0", optional = true } cranelift-jit = { version = "0.88.1", optional = true }
cranelift-object = "0.87.0" cranelift-object = "0.88.1"
target-lexicon = "0.12.0" target-lexicon = "0.12.0"
gimli = { version = "0.26.0", default-features = false, features = ["write"]} gimli = { version = "0.26.0", default-features = false, features = ["write"]}
object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "do_not_remove_cg_clif_ranlib" } ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "do_not_remove_cg_clif_ranlib" }
indexmap = "1.9.1" indexmap = "1.9.1"
libloading = { version = "0.6.0", optional = true } libloading = { version = "0.7.3", optional = true }
once_cell = "1.10.0" once_cell = "1.10.0"
smallvec = "1.8.1" smallvec = "1.8.1"

View File

@ -55,10 +55,20 @@ dependencies = [
] ]
[[package]] [[package]]
name = "compiler_builtins" name = "cfg-if"
version = "0.1.79" version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f873ce2bd3550b0b565f878b3d04ea8253f4259dc3d20223af2e1ba86f5ecca" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-core",
]
[[package]]
name = "compiler_builtins"
version = "0.1.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18cd7635fea7bb481ea543b392789844c1ad581299da70184c7175ce3af76603"
dependencies = [ dependencies = [
"rustc-std-workspace-core", "rustc-std-workspace-core",
] ]
@ -123,9 +133,9 @@ dependencies = [
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.2.5" version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "897cd85af6387be149f55acf168e41be176a02de7872403aaab184afc2f327e6" checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [ dependencies = [
"compiler_builtins", "compiler_builtins",
"libc", "libc",
@ -135,9 +145,9 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.132" version = "0.2.135"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
dependencies = [ dependencies = [
"rustc-std-workspace-core", "rustc-std-workspace-core",
] ]
@ -182,7 +192,7 @@ name = "panic_abort"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"alloc", "alloc",
"cfg-if", "cfg-if 0.1.10",
"compiler_builtins", "compiler_builtins",
"core", "core",
"libc", "libc",
@ -193,7 +203,7 @@ name = "panic_unwind"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"alloc", "alloc",
"cfg-if", "cfg-if 0.1.10",
"compiler_builtins", "compiler_builtins",
"core", "core",
"libc", "libc",
@ -245,7 +255,7 @@ version = "0.0.0"
dependencies = [ dependencies = [
"addr2line", "addr2line",
"alloc", "alloc",
"cfg-if", "cfg-if 1.0.0",
"compiler_builtins", "compiler_builtins",
"core", "core",
"dlmalloc", "dlmalloc",
@ -267,7 +277,7 @@ dependencies = [
name = "std_detect" name = "std_detect"
version = "0.1.5" version = "0.1.5"
dependencies = [ dependencies = [
"cfg-if", "cfg-if 1.0.0",
"compiler_builtins", "compiler_builtins",
"libc", "libc",
"rustc-std-workspace-alloc", "rustc-std-workspace-alloc",
@ -289,7 +299,7 @@ dependencies = [
name = "test" name = "test"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"cfg-if", "cfg-if 0.1.10",
"core", "core",
"getopts", "getopts",
"libc", "libc",
@ -301,9 +311,9 @@ dependencies = [
[[package]] [[package]]
name = "unicode-width" name = "unicode-width"
version = "0.1.9" version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
dependencies = [ dependencies = [
"compiler_builtins", "compiler_builtins",
"rustc-std-workspace-core", "rustc-std-workspace-core",
@ -315,7 +325,7 @@ name = "unwind"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"cc", "cc",
"cfg-if", "cfg-if 0.1.10",
"compiler_builtins", "compiler_builtins",
"core", "core",
"libc", "libc",

View File

@ -0,0 +1,52 @@
use std::env;
use std::path::Path;
use super::build_sysroot;
use super::config;
use super::prepare;
use super::utils::{cargo_command, spawn_and_wait};
use super::SysrootKind;
pub(crate) fn run(
channel: &str,
sysroot_kind: SysrootKind,
target_dir: &Path,
cg_clif_dylib: &Path,
host_triple: &str,
target_triple: &str,
) {
if !config::get_bool("testsuite.abi-cafe") {
eprintln!("[SKIP] abi-cafe");
return;
}
if host_triple != target_triple {
eprintln!("[SKIP] abi-cafe (cross-compilation not supported)");
return;
}
eprintln!("Building sysroot for abi-cafe");
build_sysroot::build_sysroot(
channel,
sysroot_kind,
target_dir,
cg_clif_dylib,
host_triple,
target_triple,
);
eprintln!("Running abi-cafe");
let abi_cafe_path = prepare::ABI_CAFE.source_dir();
env::set_current_dir(abi_cafe_path.clone()).unwrap();
let pairs = ["rustc_calls_cgclif", "cgclif_calls_rustc", "cgclif_calls_cc", "cc_calls_cgclif"];
let mut cmd = cargo_command("cargo", "run", Some(target_triple), &abi_cafe_path);
cmd.arg("--");
cmd.arg("--pairs");
cmd.args(pairs);
cmd.arg("--add-rustc-codegen-backend");
cmd.arg(format!("cgclif:{}", cg_clif_dylib.display()));
spawn_and_wait(cmd);
}

View File

@ -1,60 +0,0 @@
use super::build_sysroot;
use super::config;
use super::utils::spawn_and_wait;
use build_system::SysrootKind;
use std::env;
use std::path::Path;
use std::process::Command;
pub(crate) fn run(
channel: &str,
sysroot_kind: SysrootKind,
target_dir: &Path,
cg_clif_build_dir: &Path,
host_triple: &str,
target_triple: &str,
) {
if !config::get_bool("testsuite.abi-checker") {
eprintln!("[SKIP] abi-checker");
return;
}
if host_triple != target_triple {
eprintln!("[SKIP] abi-checker (cross-compilation not supported)");
return;
}
eprintln!("Building sysroot for abi-checker");
build_sysroot::build_sysroot(
channel,
sysroot_kind,
target_dir,
cg_clif_build_dir,
host_triple,
target_triple,
);
eprintln!("Running abi-checker");
let mut abi_checker_path = env::current_dir().unwrap();
abi_checker_path.push("abi-checker");
env::set_current_dir(abi_checker_path.clone()).unwrap();
let build_dir = abi_checker_path.parent().unwrap().join("build");
let cg_clif_dylib_path = build_dir.join(if cfg!(windows) { "bin" } else { "lib" }).join(
env::consts::DLL_PREFIX.to_string() + "rustc_codegen_cranelift" + env::consts::DLL_SUFFIX,
);
let pairs = ["rustc_calls_cgclif", "cgclif_calls_rustc", "cgclif_calls_cc", "cc_calls_cgclif"];
let mut cmd = Command::new("cargo");
cmd.arg("run");
cmd.arg("--target");
cmd.arg(target_triple);
cmd.arg("--");
cmd.arg("--pairs");
cmd.args(pairs);
cmd.arg("--add-rustc-codegen-backend");
cmd.arg(format!("cgclif:{}", cg_clif_dylib_path.display()));
spawn_and_wait(cmd);
}

View File

@ -1,16 +1,16 @@
use std::env; use std::env;
use std::path::{Path, PathBuf}; use std::path::PathBuf;
use std::process::Command;
use super::utils::is_ci; use super::rustc_info::get_file_name;
use super::utils::{cargo_command, is_ci};
pub(crate) fn build_backend( pub(crate) fn build_backend(
channel: &str, channel: &str,
host_triple: &str, host_triple: &str,
use_unstable_features: bool, use_unstable_features: bool,
) -> PathBuf { ) -> PathBuf {
let mut cmd = Command::new("cargo"); let source_dir = std::env::current_dir().unwrap();
cmd.arg("build").arg("--target").arg(host_triple); let mut cmd = cargo_command("cargo", "build", Some(host_triple), &source_dir);
cmd.env("CARGO_BUILD_INCREMENTAL", "true"); // Force incr comp even in release mode cmd.env("CARGO_BUILD_INCREMENTAL", "true"); // Force incr comp even in release mode
@ -41,5 +41,9 @@ pub(crate) fn build_backend(
eprintln!("[BUILD] rustc_codegen_cranelift"); eprintln!("[BUILD] rustc_codegen_cranelift");
super::utils::spawn_and_wait(cmd); super::utils::spawn_and_wait(cmd);
Path::new("target").join(host_triple).join(channel) source_dir
.join("target")
.join(host_triple)
.join(channel)
.join(get_file_name("rustc_codegen_cranelift", "dylib"))
} }

View File

@ -3,14 +3,14 @@ use std::path::{Path, PathBuf};
use std::process::{self, Command}; use std::process::{self, Command};
use super::rustc_info::{get_file_name, get_rustc_version, get_wrapper_file_name}; use super::rustc_info::{get_file_name, get_rustc_version, get_wrapper_file_name};
use super::utils::{spawn_and_wait, try_hard_link}; use super::utils::{cargo_command, spawn_and_wait, try_hard_link};
use super::SysrootKind; use super::SysrootKind;
pub(crate) fn build_sysroot( pub(crate) fn build_sysroot(
channel: &str, channel: &str,
sysroot_kind: SysrootKind, sysroot_kind: SysrootKind,
target_dir: &Path, target_dir: &Path,
cg_clif_build_dir: &Path, cg_clif_dylib_src: &Path,
host_triple: &str, host_triple: &str,
target_triple: &str, target_triple: &str,
) { ) {
@ -23,7 +23,6 @@ pub(crate) fn build_sysroot(
fs::create_dir_all(target_dir.join("lib")).unwrap(); fs::create_dir_all(target_dir.join("lib")).unwrap();
// Copy the backend // Copy the backend
let cg_clif_dylib = get_file_name("rustc_codegen_cranelift", "dylib");
let cg_clif_dylib_path = target_dir let cg_clif_dylib_path = target_dir
.join(if cfg!(windows) { .join(if cfg!(windows) {
// Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the // Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the
@ -32,8 +31,8 @@ pub(crate) fn build_sysroot(
} else { } else {
"lib" "lib"
}) })
.join(&cg_clif_dylib); .join(get_file_name("rustc_codegen_cranelift", "dylib"));
try_hard_link(cg_clif_build_dir.join(cg_clif_dylib), &cg_clif_dylib_path); try_hard_link(cg_clif_dylib_src, &cg_clif_dylib_path);
// Build and copy rustc and cargo wrappers // Build and copy rustc and cargo wrappers
for wrapper in ["rustc-clif", "cargo-clif"] { for wrapper in ["rustc-clif", "cargo-clif"] {
@ -186,10 +185,10 @@ fn build_clif_sysroot_for_triple(
} }
// Build sysroot // Build sysroot
let mut build_cmd = Command::new("cargo"); let mut build_cmd = cargo_command("cargo", "build", Some(triple), Path::new("build_sysroot"));
build_cmd.arg("build").arg("--target").arg(triple).current_dir("build_sysroot");
let mut rustflags = "-Zforce-unstable-if-unmarked -Cpanic=abort".to_string(); let mut rustflags = "-Zforce-unstable-if-unmarked -Cpanic=abort".to_string();
rustflags.push_str(&format!(" -Zcodegen-backend={}", cg_clif_dylib_path.to_str().unwrap())); rustflags.push_str(&format!(" -Zcodegen-backend={}", cg_clif_dylib_path.to_str().unwrap()));
rustflags.push_str(&format!(" --sysroot={}", target_dir.to_str().unwrap()));
if channel == "release" { if channel == "release" {
build_cmd.arg("--release"); build_cmd.arg("--release");
rustflags.push_str(" -Zmir-opt-level=3"); rustflags.push_str(" -Zmir-opt-level=3");

View File

@ -1,4 +1,5 @@
use std::{fs, process}; use std::fs;
use std::process;
fn load_config_file() -> Vec<(String, Option<String>)> { fn load_config_file() -> Vec<(String, Option<String>)> {
fs::read_to_string("config.txt") fs::read_to_string("config.txt")

View File

@ -4,7 +4,7 @@ use std::process;
use self::utils::is_ci; use self::utils::is_ci;
mod abi_checker; mod abi_cafe;
mod build_backend; mod build_backend;
mod build_sysroot; mod build_sysroot;
mod config; mod config;
@ -122,32 +122,23 @@ pub fn main() {
host_triple.clone() host_triple.clone()
}; };
if target_triple.ends_with("-msvc") { let cg_clif_dylib = build_backend::build_backend(channel, &host_triple, use_unstable_features);
eprintln!("The MSVC toolchain is not yet supported by rustc_codegen_cranelift.");
eprintln!("Switch to the MinGW toolchain for Windows support.");
eprintln!("Hint: You can use `rustup set default-host x86_64-pc-windows-gnu` to");
eprintln!("set the global default target to MinGW");
process::exit(1);
}
let cg_clif_build_dir =
build_backend::build_backend(channel, &host_triple, use_unstable_features);
match command { match command {
Command::Test => { Command::Test => {
tests::run_tests( tests::run_tests(
channel, channel,
sysroot_kind, sysroot_kind,
&target_dir, &target_dir,
&cg_clif_build_dir, &cg_clif_dylib,
&host_triple, &host_triple,
&target_triple, &target_triple,
); );
abi_checker::run( abi_cafe::run(
channel, channel,
sysroot_kind, sysroot_kind,
&target_dir, &target_dir,
&cg_clif_build_dir, &cg_clif_dylib,
&host_triple, &host_triple,
&target_triple, &target_triple,
); );
@ -157,7 +148,7 @@ pub fn main() {
channel, channel,
sysroot_kind, sysroot_kind,
&target_dir, &target_dir,
&cg_clif_build_dir, &cg_clif_dylib,
&host_triple, &host_triple,
&target_triple, &target_triple,
); );

View File

@ -1,64 +1,63 @@
use std::env; use std::env;
use std::ffi::OsStr; use std::ffi::OsStr;
use std::ffi::OsString;
use std::fs; use std::fs;
use std::path::Path; use std::path::{Path, PathBuf};
use std::process::Command; use std::process::Command;
use super::rustc_info::{get_file_name, get_rustc_path, get_rustc_version}; use super::rustc_info::{get_file_name, get_rustc_path, get_rustc_version};
use super::utils::{copy_dir_recursively, spawn_and_wait}; use super::utils::{cargo_command, copy_dir_recursively, spawn_and_wait};
pub(crate) fn prepare() { pub(crate) const ABI_CAFE: GitRepo =
prepare_sysroot(); GitRepo::github("Gankra", "abi-cafe", "4c6dc8c9c687e2b3a760ff2176ce236872b37212", "abi-cafe");
eprintln!("[INSTALL] hyperfine"); pub(crate) const RAND: GitRepo =
Command::new("cargo").arg("install").arg("hyperfine").spawn().unwrap().wait().unwrap(); GitRepo::github("rust-random", "rand", "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", "rand");
clone_repo_shallow_github( pub(crate) const REGEX: GitRepo =
"abi-checker", GitRepo::github("rust-lang", "regex", "341f207c1071f7290e3f228c710817c280c8dca1", "regex");
"Gankra",
"abi-checker",
"a2232d45f202846f5c02203c9f27355360f9a2ff",
);
apply_patches("abi-checker", Path::new("abi-checker"));
clone_repo_shallow_github( pub(crate) const PORTABLE_SIMD: GitRepo = GitRepo::github(
"rand",
"rust-random",
"rand",
"0f933f9c7176e53b2a3c7952ded484e1783f0bf1",
);
apply_patches("rand", Path::new("rand"));
clone_repo_shallow_github(
"regex",
"rust-lang",
"regex",
"341f207c1071f7290e3f228c710817c280c8dca1",
);
clone_repo_shallow_github(
"portable-simd",
"rust-lang", "rust-lang",
"portable-simd", "portable-simd",
"b8d6b6844602f80af79cd96401339ec594d472d8", "d5cd4a8112d958bd3a252327e0d069a6363249bd",
); "portable-simd",
apply_patches("portable-simd", Path::new("portable-simd")); );
clone_repo_shallow_github( pub(crate) const SIMPLE_RAYTRACER: GitRepo = GitRepo::github(
"simple-raytracer",
"ebobby", "ebobby",
"simple-raytracer", "simple-raytracer",
"804a7a21b9e673a482797aa289a18ed480e4d813", "804a7a21b9e673a482797aa289a18ed480e4d813",
); "<none>",
);
pub(crate) fn prepare() {
if Path::new("download").exists() {
std::fs::remove_dir_all(Path::new("download")).unwrap();
}
std::fs::create_dir_all(Path::new("download")).unwrap();
prepare_sysroot();
// FIXME maybe install this only locally?
eprintln!("[INSTALL] hyperfine");
Command::new("cargo").arg("install").arg("hyperfine").spawn().unwrap().wait().unwrap();
ABI_CAFE.fetch();
RAND.fetch();
REGEX.fetch();
PORTABLE_SIMD.fetch();
SIMPLE_RAYTRACER.fetch();
eprintln!("[LLVM BUILD] simple-raytracer"); eprintln!("[LLVM BUILD] simple-raytracer");
let mut build_cmd = Command::new("cargo"); let build_cmd = cargo_command("cargo", "build", None, &SIMPLE_RAYTRACER.source_dir());
build_cmd.arg("build").env_remove("CARGO_TARGET_DIR").current_dir("simple-raytracer");
spawn_and_wait(build_cmd); spawn_and_wait(build_cmd);
fs::copy( fs::copy(
Path::new("simple-raytracer/target/debug").join(get_file_name("main", "bin")), SIMPLE_RAYTRACER
Path::new("simple-raytracer").join(get_file_name("raytracer_cg_llvm", "bin")), .source_dir()
.join("target")
.join("debug")
.join(get_file_name("main", "bin")),
SIMPLE_RAYTRACER.source_dir().join(get_file_name("raytracer_cg_llvm", "bin")),
) )
.unwrap(); .unwrap();
} }
@ -90,38 +89,78 @@ fn prepare_sysroot() {
apply_patches("sysroot", &sysroot_src); apply_patches("sysroot", &sysroot_src);
} }
pub(crate) struct GitRepo {
url: GitRepoUrl,
rev: &'static str,
patch_name: &'static str,
}
enum GitRepoUrl {
Github { user: &'static str, repo: &'static str },
}
impl GitRepo {
const fn github(
user: &'static str,
repo: &'static str,
rev: &'static str,
patch_name: &'static str,
) -> GitRepo {
GitRepo { url: GitRepoUrl::Github { user, repo }, rev, patch_name }
}
pub(crate) fn source_dir(&self) -> PathBuf {
match self.url {
GitRepoUrl::Github { user: _, repo } => {
std::env::current_dir().unwrap().join("download").join(repo)
}
}
}
fn fetch(&self) {
match self.url {
GitRepoUrl::Github { user, repo } => {
clone_repo_shallow_github(&self.source_dir(), user, repo, self.rev);
}
}
apply_patches(self.patch_name, &self.source_dir());
}
}
#[allow(dead_code)] #[allow(dead_code)]
fn clone_repo(target_dir: &str, repo: &str, rev: &str) { fn clone_repo(download_dir: &Path, repo: &str, rev: &str) {
eprintln!("[CLONE] {}", repo); eprintln!("[CLONE] {}", repo);
// Ignore exit code as the repo may already have been checked out // Ignore exit code as the repo may already have been checked out
Command::new("git").arg("clone").arg(repo).arg(target_dir).spawn().unwrap().wait().unwrap(); Command::new("git").arg("clone").arg(repo).arg(&download_dir).spawn().unwrap().wait().unwrap();
let mut clean_cmd = Command::new("git"); let mut clean_cmd = Command::new("git");
clean_cmd.arg("checkout").arg("--").arg(".").current_dir(target_dir); clean_cmd.arg("checkout").arg("--").arg(".").current_dir(&download_dir);
spawn_and_wait(clean_cmd); spawn_and_wait(clean_cmd);
let mut checkout_cmd = Command::new("git"); let mut checkout_cmd = Command::new("git");
checkout_cmd.arg("checkout").arg("-q").arg(rev).current_dir(target_dir); checkout_cmd.arg("checkout").arg("-q").arg(rev).current_dir(download_dir);
spawn_and_wait(checkout_cmd); spawn_and_wait(checkout_cmd);
} }
fn clone_repo_shallow_github(target_dir: &str, username: &str, repo: &str, rev: &str) { fn clone_repo_shallow_github(download_dir: &Path, user: &str, repo: &str, rev: &str) {
if cfg!(windows) { if cfg!(windows) {
// Older windows doesn't have tar or curl by default. Fall back to using git. // Older windows doesn't have tar or curl by default. Fall back to using git.
clone_repo(target_dir, &format!("https://github.com/{}/{}.git", username, repo), rev); clone_repo(download_dir, &format!("https://github.com/{}/{}.git", user, repo), rev);
return; return;
} }
let archive_url = format!("https://github.com/{}/{}/archive/{}.tar.gz", username, repo, rev); let downloads_dir = std::env::current_dir().unwrap().join("download");
let archive_file = format!("{}.tar.gz", rev);
let archive_dir = format!("{}-{}", repo, rev);
eprintln!("[DOWNLOAD] {}/{} from {}", username, repo, archive_url); let archive_url = format!("https://github.com/{}/{}/archive/{}.tar.gz", user, repo, rev);
let archive_file = downloads_dir.join(format!("{}.tar.gz", rev));
let archive_dir = downloads_dir.join(format!("{}-{}", repo, rev));
eprintln!("[DOWNLOAD] {}/{} from {}", user, repo, archive_url);
// Remove previous results if they exists // Remove previous results if they exists
let _ = std::fs::remove_file(&archive_file); let _ = std::fs::remove_file(&archive_file);
let _ = std::fs::remove_dir_all(&archive_dir); let _ = std::fs::remove_dir_all(&archive_dir);
let _ = std::fs::remove_dir_all(target_dir); let _ = std::fs::remove_dir_all(&download_dir);
// Download zip archive // Download zip archive
let mut download_cmd = Command::new("curl"); let mut download_cmd = Command::new("curl");
@ -130,13 +169,13 @@ fn clone_repo_shallow_github(target_dir: &str, username: &str, repo: &str, rev:
// Unpack tar archive // Unpack tar archive
let mut unpack_cmd = Command::new("tar"); let mut unpack_cmd = Command::new("tar");
unpack_cmd.arg("xf").arg(&archive_file); unpack_cmd.arg("xf").arg(&archive_file).current_dir(downloads_dir);
spawn_and_wait(unpack_cmd); spawn_and_wait(unpack_cmd);
// Rename unpacked dir to the expected name // Rename unpacked dir to the expected name
std::fs::rename(archive_dir, target_dir).unwrap(); std::fs::rename(archive_dir, &download_dir).unwrap();
init_git_repo(Path::new(target_dir)); init_git_repo(&download_dir);
// Cleanup // Cleanup
std::fs::remove_file(archive_file).unwrap(); std::fs::remove_file(archive_file).unwrap();
@ -156,14 +195,20 @@ fn init_git_repo(repo_dir: &Path) {
spawn_and_wait(git_commit_cmd); spawn_and_wait(git_commit_cmd);
} }
fn get_patches(crate_name: &str) -> Vec<OsString> { fn get_patches(source_dir: &Path, crate_name: &str) -> Vec<PathBuf> {
let mut patches: Vec<_> = fs::read_dir("patches") let mut patches: Vec<_> = fs::read_dir(source_dir.join("patches"))
.unwrap() .unwrap()
.map(|entry| entry.unwrap().path()) .map(|entry| entry.unwrap().path())
.filter(|path| path.extension() == Some(OsStr::new("patch"))) .filter(|path| path.extension() == Some(OsStr::new("patch")))
.map(|path| path.file_name().unwrap().to_owned()) .filter(|path| {
.filter(|file_name| { path.file_name()
file_name.to_str().unwrap().split_once("-").unwrap().1.starts_with(crate_name) .unwrap()
.to_str()
.unwrap()
.split_once("-")
.unwrap()
.1
.starts_with(crate_name)
}) })
.collect(); .collect();
patches.sort(); patches.sort();
@ -171,11 +216,18 @@ fn get_patches(crate_name: &str) -> Vec<OsString> {
} }
fn apply_patches(crate_name: &str, target_dir: &Path) { fn apply_patches(crate_name: &str, target_dir: &Path) {
for patch in get_patches(crate_name) { if crate_name == "<none>" {
eprintln!("[PATCH] {:?} <- {:?}", target_dir.file_name().unwrap(), patch); return;
let patch_arg = env::current_dir().unwrap().join("patches").join(patch); }
for patch in get_patches(&std::env::current_dir().unwrap(), crate_name) {
eprintln!(
"[PATCH] {:?} <- {:?}",
target_dir.file_name().unwrap(),
patch.file_name().unwrap()
);
let mut apply_patch_cmd = Command::new("git"); let mut apply_patch_cmd = Command::new("git");
apply_patch_cmd.arg("am").arg(patch_arg).arg("-q").current_dir(target_dir); apply_patch_cmd.arg("am").arg(patch).arg("-q").current_dir(target_dir);
spawn_and_wait(apply_patch_cmd); spawn_and_wait(apply_patch_cmd);
} }
} }

View File

@ -65,7 +65,7 @@ pub(crate) fn get_file_name(crate_name: &str, crate_type: &str) -> String {
} }
/// Similar to `get_file_name`, but converts any dashes (`-`) in the `crate_name` to /// Similar to `get_file_name`, but converts any dashes (`-`) in the `crate_name` to
/// underscores (`_`). This is specially made for the the rustc and cargo wrappers /// underscores (`_`). This is specially made for the rustc and cargo wrappers
/// which have a dash in the name, and that is not allowed in a crate name. /// which have a dash in the name, and that is not allowed in a crate name.
pub(crate) fn get_wrapper_file_name(crate_name: &str, crate_type: &str) -> String { pub(crate) fn get_wrapper_file_name(crate_name: &str, crate_type: &str) -> String {
let crate_name = crate_name.replace('-', "_"); let crate_name = crate_name.replace('-', "_");

View File

@ -1,7 +1,8 @@
use super::build_sysroot; use super::build_sysroot;
use super::config; use super::config;
use super::prepare;
use super::rustc_info::get_wrapper_file_name; use super::rustc_info::get_wrapper_file_name;
use super::utils::{spawn_and_wait, spawn_and_wait_with_input}; use super::utils::{cargo_command, hyperfine_command, spawn_and_wait, spawn_and_wait_with_input};
use build_system::SysrootKind; use build_system::SysrootKind;
use std::env; use std::env;
use std::ffi::OsStr; use std::ffi::OsStr;
@ -217,103 +218,95 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
TestCase::new("test.rust-random/rand", &|runner| { TestCase::new("test.rust-random/rand", &|runner| {
runner.in_dir(["rand"], |runner| { runner.in_dir(prepare::RAND.source_dir(), |runner| {
runner.run_cargo(["clean"]); runner.run_cargo("clean", []);
if runner.host_triple == runner.target_triple { if runner.host_triple == runner.target_triple {
eprintln!("[TEST] rust-random/rand"); eprintln!("[TEST] rust-random/rand");
runner.run_cargo(["test", "--workspace"]); runner.run_cargo("test", ["--workspace"]);
} else { } else {
eprintln!("[AOT] rust-random/rand"); eprintln!("[AOT] rust-random/rand");
runner.run_cargo([ runner.run_cargo("build", ["--workspace", "--tests"]);
"build",
"--workspace",
"--target",
&runner.target_triple,
"--tests",
]);
} }
}); });
}), }),
TestCase::new("bench.simple-raytracer", &|runner| { TestCase::new("bench.simple-raytracer", &|runner| {
runner.in_dir(["simple-raytracer"], |runner| { runner.in_dir(prepare::SIMPLE_RAYTRACER.source_dir(), |runner| {
let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string()); let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string()).parse().unwrap();
if runner.host_triple == runner.target_triple { if runner.host_triple == runner.target_triple {
eprintln!("[BENCH COMPILE] ebobby/simple-raytracer"); eprintln!("[BENCH COMPILE] ebobby/simple-raytracer");
let mut bench_compile = Command::new("hyperfine"); let prepare = runner.cargo_command("clean", []);
bench_compile.arg("--runs");
bench_compile.arg(&run_runs);
bench_compile.arg("--warmup");
bench_compile.arg("1");
bench_compile.arg("--prepare");
bench_compile.arg(format!("{:?}", runner.cargo_command(["clean"])));
if cfg!(windows) { let llvm_build_cmd = cargo_command("cargo", "build", None, Path::new("."));
bench_compile.arg("cmd /C \"set RUSTFLAGS= && cargo build\"");
} else { let cargo_clif = runner
bench_compile.arg("RUSTFLAGS='' cargo build"); .root_dir
} .clone()
.join("build")
.join(get_wrapper_file_name("cargo-clif", "bin"));
let clif_build_cmd = cargo_command(cargo_clif, "build", None, Path::new("."));
let bench_compile =
hyperfine_command(1, run_runs, Some(prepare), llvm_build_cmd, clif_build_cmd);
bench_compile.arg(format!("{:?}", runner.cargo_command(["build"])));
spawn_and_wait(bench_compile); spawn_and_wait(bench_compile);
eprintln!("[BENCH RUN] ebobby/simple-raytracer"); eprintln!("[BENCH RUN] ebobby/simple-raytracer");
fs::copy(PathBuf::from("./target/debug/main"), PathBuf::from("raytracer_cg_clif")) fs::copy(PathBuf::from("./target/debug/main"), PathBuf::from("raytracer_cg_clif"))
.unwrap(); .unwrap();
let mut bench_run = Command::new("hyperfine"); let bench_run = hyperfine_command(
bench_run.arg("--runs"); 0,
bench_run.arg(&run_runs); run_runs,
bench_run.arg(PathBuf::from("./raytracer_cg_llvm")); None,
bench_run.arg(PathBuf::from("./raytracer_cg_clif")); Command::new("./raytracer_cg_llvm"),
Command::new("./raytracer_cg_clif"),
);
spawn_and_wait(bench_run); spawn_and_wait(bench_run);
} else { } else {
runner.run_cargo(["clean"]); runner.run_cargo("clean", []);
eprintln!("[BENCH COMPILE] ebobby/simple-raytracer (skipped)"); eprintln!("[BENCH COMPILE] ebobby/simple-raytracer (skipped)");
eprintln!("[COMPILE] ebobby/simple-raytracer"); eprintln!("[COMPILE] ebobby/simple-raytracer");
runner.run_cargo(["build", "--target", &runner.target_triple]); runner.run_cargo("build", []);
eprintln!("[BENCH RUN] ebobby/simple-raytracer (skipped)"); eprintln!("[BENCH RUN] ebobby/simple-raytracer (skipped)");
} }
}); });
}), }),
TestCase::new("test.libcore", &|runner| { TestCase::new("test.libcore", &|runner| {
runner.in_dir(["build_sysroot", "sysroot_src", "library", "core", "tests"], |runner| { runner.in_dir(
runner.run_cargo(["clean"]); std::env::current_dir()
.unwrap()
.join("build_sysroot")
.join("sysroot_src")
.join("library")
.join("core")
.join("tests"),
|runner| {
runner.run_cargo("clean", []);
if runner.host_triple == runner.target_triple { if runner.host_triple == runner.target_triple {
runner.run_cargo(["test"]); runner.run_cargo("test", []);
} else { } else {
eprintln!("Cross-Compiling: Not running tests"); eprintln!("Cross-Compiling: Not running tests");
runner.run_cargo(["build", "--target", &runner.target_triple, "--tests"]); runner.run_cargo("build", ["--tests"]);
} }
}); },
);
}), }),
TestCase::new("test.regex-shootout-regex-dna", &|runner| { TestCase::new("test.regex-shootout-regex-dna", &|runner| {
runner.in_dir(["regex"], |runner| { runner.in_dir(prepare::REGEX.source_dir(), |runner| {
runner.run_cargo(["clean"]); runner.run_cargo("clean", []);
// newer aho_corasick versions throw a deprecation warning // newer aho_corasick versions throw a deprecation warning
let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags); let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags);
let mut build_cmd = runner.cargo_command([ let mut build_cmd = runner.cargo_command("build", ["--example", "shootout-regex-dna"]);
"build",
"--example",
"shootout-regex-dna",
"--target",
&runner.target_triple,
]);
build_cmd.env("RUSTFLAGS", lint_rust_flags.clone()); build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
spawn_and_wait(build_cmd); spawn_and_wait(build_cmd);
if runner.host_triple == runner.target_triple { if runner.host_triple == runner.target_triple {
let mut run_cmd = runner.cargo_command([ let mut run_cmd = runner.cargo_command("run", ["--example", "shootout-regex-dna"]);
"run",
"--example",
"shootout-regex-dna",
"--target",
&runner.target_triple,
]);
run_cmd.env("RUSTFLAGS", lint_rust_flags); run_cmd.env("RUSTFLAGS", lint_rust_flags);
let input = let input =
@ -353,15 +346,16 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
}); });
}), }),
TestCase::new("test.regex", &|runner| { TestCase::new("test.regex", &|runner| {
runner.in_dir(["regex"], |runner| { runner.in_dir(prepare::REGEX.source_dir(), |runner| {
runner.run_cargo(["clean"]); runner.run_cargo("clean", []);
// newer aho_corasick versions throw a deprecation warning // newer aho_corasick versions throw a deprecation warning
let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags); let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags);
if runner.host_triple == runner.target_triple { if runner.host_triple == runner.target_triple {
let mut run_cmd = runner.cargo_command([ let mut run_cmd = runner.cargo_command(
"test", "test",
[
"--tests", "--tests",
"--", "--",
"--exclude-should-panic", "--exclude-should-panic",
@ -369,25 +363,26 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
"1", "1",
"-Zunstable-options", "-Zunstable-options",
"-q", "-q",
]); ],
);
run_cmd.env("RUSTFLAGS", lint_rust_flags); run_cmd.env("RUSTFLAGS", lint_rust_flags);
spawn_and_wait(run_cmd); spawn_and_wait(run_cmd);
} else { } else {
eprintln!("Cross-Compiling: Not running tests"); eprintln!("Cross-Compiling: Not running tests");
let mut build_cmd = let mut build_cmd =
runner.cargo_command(["build", "--tests", "--target", &runner.target_triple]); runner.cargo_command("build", ["--tests", "--target", &runner.target_triple]);
build_cmd.env("RUSTFLAGS", lint_rust_flags.clone()); build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
spawn_and_wait(build_cmd); spawn_and_wait(build_cmd);
} }
}); });
}), }),
TestCase::new("test.portable-simd", &|runner| { TestCase::new("test.portable-simd", &|runner| {
runner.in_dir(["portable-simd"], |runner| { runner.in_dir(prepare::PORTABLE_SIMD.source_dir(), |runner| {
runner.run_cargo(["clean"]); runner.run_cargo("clean", []);
runner.run_cargo(["build", "--all-targets", "--target", &runner.target_triple]); runner.run_cargo("build", ["--all-targets", "--target", &runner.target_triple]);
if runner.host_triple == runner.target_triple { if runner.host_triple == runner.target_triple {
runner.run_cargo(["test", "-q"]); runner.run_cargo("test", ["-q"]);
} }
}); });
}), }),
@ -397,7 +392,7 @@ pub(crate) fn run_tests(
channel: &str, channel: &str,
sysroot_kind: SysrootKind, sysroot_kind: SysrootKind,
target_dir: &Path, target_dir: &Path,
cg_clif_build_dir: &Path, cg_clif_dylib: &Path,
host_triple: &str, host_triple: &str,
target_triple: &str, target_triple: &str,
) { ) {
@ -408,7 +403,7 @@ pub(crate) fn run_tests(
channel, channel,
SysrootKind::None, SysrootKind::None,
&target_dir, &target_dir,
cg_clif_build_dir, cg_clif_dylib,
&host_triple, &host_triple,
&target_triple, &target_triple,
); );
@ -427,7 +422,7 @@ pub(crate) fn run_tests(
channel, channel,
sysroot_kind, sysroot_kind,
&target_dir, &target_dir,
cg_clif_build_dir, cg_clif_dylib,
&host_triple, &host_triple,
&target_triple, &target_triple,
); );
@ -521,16 +516,8 @@ impl TestRunner {
} }
} }
fn in_dir<'a, I, F>(&self, dir: I, callback: F) fn in_dir(&self, new: impl AsRef<Path>, callback: impl FnOnce(&TestRunner)) {
where
I: IntoIterator<Item = &'a str>,
F: FnOnce(&TestRunner),
{
let current = env::current_dir().unwrap(); let current = env::current_dir().unwrap();
let mut new = current.clone();
for d in dir {
new.push(d);
}
env::set_current_dir(new).unwrap(); env::set_current_dir(new).unwrap();
callback(self); callback(self);
@ -595,25 +582,29 @@ impl TestRunner {
spawn_and_wait(cmd); spawn_and_wait(cmd);
} }
fn cargo_command<I, S>(&self, args: I) -> Command fn cargo_command<'a, I>(&self, subcommand: &str, args: I) -> Command
where where
I: IntoIterator<Item = S>, I: IntoIterator<Item = &'a str>,
S: AsRef<OsStr>,
{ {
let mut cargo_clif = self.root_dir.clone(); let mut cargo_clif = self.root_dir.clone();
cargo_clif.push("build"); cargo_clif.push("build");
cargo_clif.push(get_wrapper_file_name("cargo-clif", "bin")); cargo_clif.push(get_wrapper_file_name("cargo-clif", "bin"));
let mut cmd = Command::new(cargo_clif); let mut cmd = cargo_command(
cargo_clif,
subcommand,
if subcommand == "clean" { None } else { Some(&self.target_triple) },
Path::new("."),
);
cmd.args(args); cmd.args(args);
cmd.env("RUSTFLAGS", &self.rust_flags); cmd.env("RUSTFLAGS", &self.rust_flags);
cmd cmd
} }
fn run_cargo<'a, I>(&self, args: I) fn run_cargo<'a, I>(&self, subcommand: &str, args: I)
where where
I: IntoIterator<Item = &'a str>, I: IntoIterator<Item = &'a str>,
{ {
spawn_and_wait(self.cargo_command(args)); spawn_and_wait(self.cargo_command(subcommand, args));
} }
} }

View File

@ -4,6 +4,52 @@ use std::io::Write;
use std::path::Path; use std::path::Path;
use std::process::{self, Command, Stdio}; use std::process::{self, Command, Stdio};
pub(crate) fn cargo_command(
cargo: impl AsRef<Path>,
subcommand: &str,
triple: Option<&str>,
source_dir: &Path,
) -> Command {
let mut cmd = Command::new(cargo.as_ref());
cmd.arg(subcommand)
.arg("--manifest-path")
.arg(source_dir.join("Cargo.toml"))
.arg("--target-dir")
.arg(source_dir.join("target"));
if let Some(triple) = triple {
cmd.arg("--target").arg(triple);
}
cmd
}
pub(crate) fn hyperfine_command(
warmup: u64,
runs: u64,
prepare: Option<Command>,
a: Command,
b: Command,
) -> Command {
let mut bench = Command::new("hyperfine");
if warmup != 0 {
bench.arg("--warmup").arg(warmup.to_string());
}
if runs != 0 {
bench.arg("--runs").arg(runs.to_string());
}
if let Some(prepare) = prepare {
bench.arg("--prepare").arg(format!("{:?}", prepare));
}
bench.arg(format!("{:?}", a)).arg(format!("{:?}", b));
bench
}
#[track_caller] #[track_caller]
pub(crate) fn try_hard_link(src: impl AsRef<Path>, dst: impl AsRef<Path>) { pub(crate) fn try_hard_link(src: impl AsRef<Path>, dst: impl AsRef<Path>) {
let src = src.as_ref(); let src = src.as_ref();

View File

@ -3,4 +3,8 @@ set -e
rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version} rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version}
rm -rf target/ build/ perf.data{,.old} y.bin rm -rf target/ build/ perf.data{,.old} y.bin
rm -rf rand/ regex/ simple-raytracer/ portable-simd/ abi-checker/ rm -rf download/
# Kept for now in case someone updates their checkout of cg_clif before running clean_all.sh
# FIXME remove at some point in the future
rm -rf rand/ regex/ simple-raytracer/ portable-simd/ abi-checker/ abi-cafe/

View File

@ -49,4 +49,4 @@ test.regex-shootout-regex-dna
test.regex test.regex
test.portable-simd test.portable-simd
testsuite.abi-checker testsuite.abi-cafe

View File

@ -5,7 +5,6 @@
// Test that we can handle unsized types with an extern type tail part. // Test that we can handle unsized types with an extern type tail part.
// Regression test for issue #91827. // Regression test for issue #91827.
#![feature(const_ptr_offset_from)]
#![feature(extern_types)] #![feature(extern_types)]
use std::ptr::addr_of; use std::ptr::addr_of;

View File

@ -559,16 +559,22 @@ pub union MaybeUninit<T> {
pub mod intrinsics { pub mod intrinsics {
extern "rust-intrinsic" { extern "rust-intrinsic" {
#[rustc_safe_intrinsic]
pub fn abort() -> !; pub fn abort() -> !;
#[rustc_safe_intrinsic]
pub fn size_of<T>() -> usize; pub fn size_of<T>() -> usize;
pub fn size_of_val<T: ?::Sized>(val: *const T) -> usize; pub fn size_of_val<T: ?::Sized>(val: *const T) -> usize;
#[rustc_safe_intrinsic]
pub fn min_align_of<T>() -> usize; pub fn min_align_of<T>() -> usize;
pub fn min_align_of_val<T: ?::Sized>(val: *const T) -> usize; pub fn min_align_of_val<T: ?::Sized>(val: *const T) -> usize;
pub fn copy<T>(src: *const T, dst: *mut T, count: usize); pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
pub fn transmute<T, U>(e: T) -> U; pub fn transmute<T, U>(e: T) -> U;
pub fn ctlz_nonzero<T>(x: T) -> T; pub fn ctlz_nonzero<T>(x: T) -> T;
#[rustc_safe_intrinsic]
pub fn needs_drop<T: ?::Sized>() -> bool; pub fn needs_drop<T: ?::Sized>() -> bool;
#[rustc_safe_intrinsic]
pub fn bitreverse<T>(x: T) -> T; pub fn bitreverse<T>(x: T) -> T;
#[rustc_safe_intrinsic]
pub fn bswap<T>(x: T) -> T; pub fn bswap<T>(x: T) -> T;
pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize); pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
} }

View File

@ -93,6 +93,7 @@ fn start<T: Termination + 'static>(
main: fn() -> T, main: fn() -> T,
argc: isize, argc: isize,
argv: *const *const u8, argv: *const *const u8,
_sigpipe: u8,
) -> isize { ) -> isize {
if argc == 3 { if argc == 3 {
unsafe { puts(*argv as *const i8); } unsafe { puts(*argv as *const i8); }

View File

@ -1,4 +1,4 @@
#![feature(core_intrinsics, generators, generator_trait, is_sorted, bench_black_box)] #![feature(core_intrinsics, generators, generator_trait, is_sorted)]
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
use std::arch::x86_64::*; use std::arch::x86_64::*;

View File

@ -0,0 +1,29 @@
From 2b15fee2bb5fd14e34c7e17e44d99cb34f4c555d Mon Sep 17 00:00:00 2001
From: Afonso Bordado <afonsobordado@az8.co>
Date: Tue, 27 Sep 2022 07:55:17 +0100
Subject: [PATCH] Disable some test on x86_64-pc-windows-gnu
---
src/report.rs | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/report.rs b/src/report.rs
index eeec614..f582867 100644
--- a/src/report.rs
+++ b/src/report.rs
@@ -48,6 +48,12 @@ pub fn get_test_rules(test: &TestKey, caller: &dyn AbiImpl, callee: &dyn AbiImpl
//
// THIS AREA RESERVED FOR VENDORS TO APPLY PATCHES
+ // x86_64-pc-windows-gnu has some broken i128 tests that aren't disabled by default
+ if cfg!(all(target_os = "windows", target_env = "gnu")) && test.test_name == "ui128" {
+ result.run = Link;
+ result.check = Pass(Link);
+ }
+
// END OF VENDOR RESERVED AREA
//
//
--
2.30.1.windows.1

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