Auto merge of #17732 - lnicola:sync-from-rust, r=lnicola
minor: sync from downstream
This commit is contained in:
commit
48fb66be7a
2388 changed files with 43150 additions and 25108 deletions
10
.github/workflows/dependencies.yml
vendored
10
.github/workflows/dependencies.yml
vendored
|
|
@ -64,11 +64,17 @@ jobs:
|
|||
- name: cargo update
|
||||
# Remove first line that always just says "Updating crates.io index"
|
||||
run: cargo update 2>&1 | sed '/crates.io index/d' | tee -a cargo_update.log
|
||||
- name: cargo update rustbook
|
||||
run: |
|
||||
echo -e "\nrustbook dependencies:" >> cargo_update.log
|
||||
cargo update --manifest-path src/tools/rustbook 2>&1 | sed '/crates.io index/d' | tee -a cargo_update.log
|
||||
- name: upload Cargo.lock artifact for use in PR
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Cargo-lock
|
||||
path: Cargo.lock
|
||||
path: |
|
||||
Cargo.lock
|
||||
src/tools/rustbook/Cargo.lock
|
||||
retention-days: 1
|
||||
- name: upload cargo-update log artifact for use in PR
|
||||
uses: actions/upload-artifact@v4
|
||||
|
|
@ -113,7 +119,7 @@ jobs:
|
|||
git config user.name github-actions
|
||||
git config user.email github-actions@github.com
|
||||
git switch --force-create cargo_update
|
||||
git add ./Cargo.lock
|
||||
git add ./Cargo.lock ./src/tools/rustbook/Cargo.lock
|
||||
git commit --no-verify --file=commit.txt
|
||||
|
||||
- name: push
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -50,7 +50,6 @@ build/
|
|||
/target
|
||||
/src/bootstrap/target
|
||||
/src/tools/x/target
|
||||
/inc-fat/
|
||||
# Created by default with `src/ci/docker/run.sh`
|
||||
/obj/
|
||||
/rustc-ice*
|
||||
|
|
|
|||
2
.mailmap
2
.mailmap
|
|
@ -435,7 +435,7 @@ Nick Platt <platt.nicholas@gmail.com>
|
|||
Niclas Schwarzlose <15schnic@gmail.com>
|
||||
Nicolas Abram <abramlujan@gmail.com>
|
||||
Nicole Mazzuca <npmazzuca@gmail.com>
|
||||
Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> nils <48135649+Nilstrieb@users.noreply.github.com>
|
||||
Noratrieb <48135649+Noratrieb@users.noreply.github.com> <48135649+Nilstrieb@users.noreply.github.com>
|
||||
Nif Ward <nif.ward@gmail.com>
|
||||
Nika Layzell <nika@thelayzells.com> <michael@thelayzells.com>
|
||||
NODA Kai <nodakai@gmail.com>
|
||||
|
|
|
|||
124
.reuse/dep5
124
.reuse/dep5
|
|
@ -1,124 +0,0 @@
|
|||
# WARNING: this metadata is currently incomplete, do not rely on it yet.
|
||||
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
|
||||
# Note that we're explicitly listing the individual files at the root of the
|
||||
# repository rather than just having `Files: *`. This is explicitly done to
|
||||
# help downstream forks of the Rust compiler: this way, the files they add
|
||||
# won't be automatically marked as authored by the Rust project.
|
||||
Files: compiler/*
|
||||
library/*
|
||||
tests/*
|
||||
src/*
|
||||
.github/*
|
||||
Cargo.lock
|
||||
Cargo.toml
|
||||
CODE_OF_CONDUCT.md
|
||||
config.example.toml
|
||||
configure
|
||||
CONTRIBUTING.md
|
||||
COPYRIGHT
|
||||
INSTALL.md
|
||||
LICENSE-APACHE
|
||||
LICENSE-MIT
|
||||
README.md
|
||||
RELEASES.md
|
||||
rustfmt.toml
|
||||
rust-bors.toml
|
||||
triagebot.toml
|
||||
x
|
||||
x.ps1
|
||||
x.py
|
||||
.clang-format
|
||||
.editorconfig
|
||||
.git-blame-ignore-revs
|
||||
.gitattributes
|
||||
.gitignore
|
||||
.gitmodules
|
||||
.mailmap
|
||||
.ignore
|
||||
Copyright: The Rust Project Developers (see https://thanks.rust-lang.org)
|
||||
License: MIT or Apache-2.0
|
||||
|
||||
Files: compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp
|
||||
Copyright: 2003-2019 University of Illinois at Urbana-Champaign.
|
||||
The Rust Project Developers (see https://thanks.rust-lang.org)
|
||||
License: Apache-2.0 WITH LLVM-exception AND (Apache-2.0 OR MIT)
|
||||
|
||||
Files: library/core/src/unicode/unicode_data.rs
|
||||
Copyright: 1991-2022 Unicode, Inc. All rights reserved.
|
||||
License: Unicode-DFS-2016
|
||||
|
||||
Files: library/std/src/sync/mpmc/*
|
||||
Copyright: 2019 The Crossbeam Project Developers
|
||||
The Rust Project Developers (see https://thanks.rust-lang.org)
|
||||
License: MIT OR Apache-2.0
|
||||
|
||||
Files: library/std/src/sys/sync/mutex/fuchsia.rs
|
||||
Copyright: 2016 The Fuchsia Authors
|
||||
The Rust Project Developers (see https://thanks.rust-lang.org)
|
||||
License: BSD-2-Clause AND (MIT OR Apache-2.0)
|
||||
|
||||
Files: src/test/rustdoc/auxiliary/enum-primitive.rs
|
||||
Copyright: 2015 Anders Kaseorg <andersk@mit.edu>
|
||||
License: MIT
|
||||
|
||||
Files: src/librustdoc/html/static/fonts/FiraSans*
|
||||
Copyright: 2014, Mozilla Foundation
|
||||
2014, Telefonica S.A.
|
||||
License: OFL-1.1
|
||||
|
||||
Files: src/librustdoc/html/static/fonts/NanumBarun*
|
||||
Copyright: 2010 NAVER Corporation
|
||||
License: OFL-1.1
|
||||
|
||||
Files: src/librustdoc/html/static/fonts/SourceCodePro*
|
||||
src/librustdoc/html/static/fonts/SourceSerif4*
|
||||
Copyright: 2010, 2012, 2014-2023, Adobe Systems Incorporated
|
||||
License: OFL-1.1
|
||||
|
||||
Files: src/librustdoc/html/static/css/normalize.css
|
||||
Copyright: Nicolas Gallagher and Jonathan Neal
|
||||
License: MIT
|
||||
|
||||
Files: src/librustdoc/html/static/css/rustdoc.css
|
||||
Copyright: 2016 Ike Ku, Jessica Stokes and Leon Guan
|
||||
The Rust Project Developers (see https://thanks.rust-lang.org)
|
||||
License: MIT OR Apache-2.0
|
||||
|
||||
Files: src/doc/rustc-dev-guide/mermaid.min.js
|
||||
Copyright: 2014-2021 Knut Sveidqvist
|
||||
License: MIT
|
||||
|
||||
Files: library/backtrace/*
|
||||
Copyright: 2014 Alex Crichton
|
||||
The Rust Project Developers (see https://thanks.rust-lang.org)
|
||||
License: MIT OR Apache-2.0
|
||||
|
||||
Files: src/doc/embedded-book/*
|
||||
Copyright: Rust on Embedded Devices Working Group
|
||||
The Rust Project Developers (see https://thanks.rust-lang.org)
|
||||
License: MIT OR Apache-2.0 OR CC-BY-SA-4.0
|
||||
|
||||
Files: src/doc/rust-by-example/*
|
||||
Copyright: 2014 Jorge Aparicio
|
||||
The Rust Project Developers (see https://thanks.rust-lang.org)
|
||||
License: MIT OR Apache-2.0
|
||||
|
||||
# Reuse cannot process the LLVM source tree, and so the copyrights for the LLVM
|
||||
# submodule are written out here manually. The collect-licence-metadata tool
|
||||
# has a specific exception coded within it to ignore ./src/llvm-project so
|
||||
# any time LLVM is updated, please revisit this section. The copyrights are
|
||||
# taken from the relevant LLVM sub-folders: llvm, lld, lldb, compiler-rt and libunwind.
|
||||
#
|
||||
# The git hash for the CREDITS.TXT file is taken from the current git submodule
|
||||
# commit for ./src/llvm-project.
|
||||
#
|
||||
# The copyright years were compiled by looking at all the relevant
|
||||
# ./src/llvm-project/*/LICENSE.txt files
|
||||
|
||||
Files: src/llvm-project/*
|
||||
Copyright: 2003-2019 by the contributors listed in [CREDITS.TXT](https://github.com/rust-lang/llvm-project/blob/7738295178045041669876bf32b0543ec8319a5c/llvm/CREDITS.TXT)
|
||||
2010 Apple Inc
|
||||
2003-2019 University of Illinois at Urbana-Champaign.
|
||||
License: NCSA AND Apache-2.0 WITH LLVM-exception
|
||||
677
Cargo.lock
677
Cargo.lock
File diff suppressed because it is too large
Load diff
18
Cargo.toml
18
Cargo.toml
|
|
@ -4,6 +4,7 @@ members = [
|
|||
"compiler/rustc",
|
||||
"library/std",
|
||||
"library/sysroot",
|
||||
"src/etc/test-float-parse",
|
||||
"src/rustdoc-json-types",
|
||||
"src/tools/build_helper",
|
||||
"src/tools/cargotest",
|
||||
|
|
@ -15,7 +16,6 @@ members = [
|
|||
"src/tools/linkchecker",
|
||||
"src/tools/lint-docs",
|
||||
"src/tools/miropt-test-tools",
|
||||
"src/tools/rustbook",
|
||||
"src/tools/unstable-book-gen",
|
||||
"src/tools/tidy",
|
||||
"src/tools/tier-check",
|
||||
|
|
@ -45,6 +45,7 @@ members = [
|
|||
"src/tools/opt-dist",
|
||||
"src/tools/coverage-dump",
|
||||
"src/tools/rustc-perf-wrapper",
|
||||
"src/tools/wasm-component-ld",
|
||||
]
|
||||
|
||||
exclude = [
|
||||
|
|
@ -104,6 +105,21 @@ rustc-demangle.debug = 0
|
|||
[profile.release.package.lld-wrapper]
|
||||
debug = 0
|
||||
strip = true
|
||||
[profile.release.package.wasm-component-ld-wrapper]
|
||||
debug = 0
|
||||
strip = true
|
||||
|
||||
# Bigint libraries are slow without optimization, speed up testing
|
||||
[profile.dev.package.test-float-parse]
|
||||
opt-level = 3
|
||||
|
||||
# Speed up the binary as much as possible
|
||||
[profile.release.package.test-float-parse]
|
||||
opt-level = 3
|
||||
codegen-units = 1
|
||||
# FIXME: LTO cannot be enabled for binaries in a workspace
|
||||
# <https://github.com/rust-lang/cargo/issues/9330>
|
||||
# lto = true
|
||||
|
||||
[patch.crates-io]
|
||||
# See comments in `library/rustc-std-workspace-core/README.md` for what's going on
|
||||
|
|
|
|||
|
|
@ -1,319 +0,0 @@
|
|||
Creative Commons Legal Code
|
||||
|
||||
Attribution 3.0 Unported
|
||||
|
||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
||||
LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN
|
||||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
||||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
||||
REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR
|
||||
DAMAGES RESULTING FROM ITS USE.
|
||||
|
||||
License
|
||||
|
||||
THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
|
||||
COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
|
||||
COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
|
||||
AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
|
||||
|
||||
BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE
|
||||
TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY
|
||||
BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS
|
||||
CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
|
||||
CONDITIONS.
|
||||
|
||||
1. Definitions
|
||||
|
||||
a. "Adaptation" means a work based upon the Work, or upon the Work and
|
||||
other pre-existing works, such as a translation, adaptation,
|
||||
derivative work, arrangement of music or other alterations of a
|
||||
literary or artistic work, or phonogram or performance and includes
|
||||
cinematographic adaptations or any other form in which the Work may be
|
||||
recast, transformed, or adapted including in any form recognizably
|
||||
derived from the original, except that a work that constitutes a
|
||||
Collection will not be considered an Adaptation for the purpose of
|
||||
this License. For the avoidance of doubt, where the Work is a musical
|
||||
work, performance or phonogram, the synchronization of the Work in
|
||||
timed-relation with a moving image ("synching") will be considered an
|
||||
Adaptation for the purpose of this License.
|
||||
b. "Collection" means a collection of literary or artistic works, such as
|
||||
encyclopedias and anthologies, or performances, phonograms or
|
||||
broadcasts, or other works or subject matter other than works listed
|
||||
in Section 1(f) below, which, by reason of the selection and
|
||||
arrangement of their contents, constitute intellectual creations, in
|
||||
which the Work is included in its entirety in unmodified form along
|
||||
with one or more other contributions, each constituting separate and
|
||||
independent works in themselves, which together are assembled into a
|
||||
collective whole. A work that constitutes a Collection will not be
|
||||
considered an Adaptation (as defined above) for the purposes of this
|
||||
License.
|
||||
c. "Distribute" means to make available to the public the original and
|
||||
copies of the Work or Adaptation, as appropriate, through sale or
|
||||
other transfer of ownership.
|
||||
d. "Licensor" means the individual, individuals, entity or entities that
|
||||
offer(s) the Work under the terms of this License.
|
||||
e. "Original Author" means, in the case of a literary or artistic work,
|
||||
the individual, individuals, entity or entities who created the Work
|
||||
or if no individual or entity can be identified, the publisher; and in
|
||||
addition (i) in the case of a performance the actors, singers,
|
||||
musicians, dancers, and other persons who act, sing, deliver, declaim,
|
||||
play in, interpret or otherwise perform literary or artistic works or
|
||||
expressions of folklore; (ii) in the case of a phonogram the producer
|
||||
being the person or legal entity who first fixes the sounds of a
|
||||
performance or other sounds; and, (iii) in the case of broadcasts, the
|
||||
organization that transmits the broadcast.
|
||||
f. "Work" means the literary and/or artistic work offered under the terms
|
||||
of this License including without limitation any production in the
|
||||
literary, scientific and artistic domain, whatever may be the mode or
|
||||
form of its expression including digital form, such as a book,
|
||||
pamphlet and other writing; a lecture, address, sermon or other work
|
||||
of the same nature; a dramatic or dramatico-musical work; a
|
||||
choreographic work or entertainment in dumb show; a musical
|
||||
composition with or without words; a cinematographic work to which are
|
||||
assimilated works expressed by a process analogous to cinematography;
|
||||
a work of drawing, painting, architecture, sculpture, engraving or
|
||||
lithography; a photographic work to which are assimilated works
|
||||
expressed by a process analogous to photography; a work of applied
|
||||
art; an illustration, map, plan, sketch or three-dimensional work
|
||||
relative to geography, topography, architecture or science; a
|
||||
performance; a broadcast; a phonogram; a compilation of data to the
|
||||
extent it is protected as a copyrightable work; or a work performed by
|
||||
a variety or circus performer to the extent it is not otherwise
|
||||
considered a literary or artistic work.
|
||||
g. "You" means an individual or entity exercising rights under this
|
||||
License who has not previously violated the terms of this License with
|
||||
respect to the Work, or who has received express permission from the
|
||||
Licensor to exercise rights under this License despite a previous
|
||||
violation.
|
||||
h. "Publicly Perform" means to perform public recitations of the Work and
|
||||
to communicate to the public those public recitations, by any means or
|
||||
process, including by wire or wireless means or public digital
|
||||
performances; to make available to the public Works in such a way that
|
||||
members of the public may access these Works from a place and at a
|
||||
place individually chosen by them; to perform the Work to the public
|
||||
by any means or process and the communication to the public of the
|
||||
performances of the Work, including by public digital performance; to
|
||||
broadcast and rebroadcast the Work by any means including signs,
|
||||
sounds or images.
|
||||
i. "Reproduce" means to make copies of the Work by any means including
|
||||
without limitation by sound or visual recordings and the right of
|
||||
fixation and reproducing fixations of the Work, including storage of a
|
||||
protected performance or phonogram in digital form or other electronic
|
||||
medium.
|
||||
|
||||
2. Fair Dealing Rights. Nothing in this License is intended to reduce,
|
||||
limit, or restrict any uses free from copyright or rights arising from
|
||||
limitations or exceptions that are provided for in connection with the
|
||||
copyright protection under copyright law or other applicable laws.
|
||||
|
||||
3. License Grant. Subject to the terms and conditions of this License,
|
||||
Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
|
||||
perpetual (for the duration of the applicable copyright) license to
|
||||
exercise the rights in the Work as stated below:
|
||||
|
||||
a. to Reproduce the Work, to incorporate the Work into one or more
|
||||
Collections, and to Reproduce the Work as incorporated in the
|
||||
Collections;
|
||||
b. to create and Reproduce Adaptations provided that any such Adaptation,
|
||||
including any translation in any medium, takes reasonable steps to
|
||||
clearly label, demarcate or otherwise identify that changes were made
|
||||
to the original Work. For example, a translation could be marked "The
|
||||
original work was translated from English to Spanish," or a
|
||||
modification could indicate "The original work has been modified.";
|
||||
c. to Distribute and Publicly Perform the Work including as incorporated
|
||||
in Collections; and,
|
||||
d. to Distribute and Publicly Perform Adaptations.
|
||||
e. For the avoidance of doubt:
|
||||
|
||||
i. Non-waivable Compulsory License Schemes. In those jurisdictions in
|
||||
which the right to collect royalties through any statutory or
|
||||
compulsory licensing scheme cannot be waived, the Licensor
|
||||
reserves the exclusive right to collect such royalties for any
|
||||
exercise by You of the rights granted under this License;
|
||||
ii. Waivable Compulsory License Schemes. In those jurisdictions in
|
||||
which the right to collect royalties through any statutory or
|
||||
compulsory licensing scheme can be waived, the Licensor waives the
|
||||
exclusive right to collect such royalties for any exercise by You
|
||||
of the rights granted under this License; and,
|
||||
iii. Voluntary License Schemes. The Licensor waives the right to
|
||||
collect royalties, whether individually or, in the event that the
|
||||
Licensor is a member of a collecting society that administers
|
||||
voluntary licensing schemes, via that society, from any exercise
|
||||
by You of the rights granted under this License.
|
||||
|
||||
The above rights may be exercised in all media and formats whether now
|
||||
known or hereafter devised. The above rights include the right to make
|
||||
such modifications as are technically necessary to exercise the rights in
|
||||
other media and formats. Subject to Section 8(f), all rights not expressly
|
||||
granted by Licensor are hereby reserved.
|
||||
|
||||
4. Restrictions. The license granted in Section 3 above is expressly made
|
||||
subject to and limited by the following restrictions:
|
||||
|
||||
a. You may Distribute or Publicly Perform the Work only under the terms
|
||||
of this License. You must include a copy of, or the Uniform Resource
|
||||
Identifier (URI) for, this License with every copy of the Work You
|
||||
Distribute or Publicly Perform. You may not offer or impose any terms
|
||||
on the Work that restrict the terms of this License or the ability of
|
||||
the recipient of the Work to exercise the rights granted to that
|
||||
recipient under the terms of the License. You may not sublicense the
|
||||
Work. You must keep intact all notices that refer to this License and
|
||||
to the disclaimer of warranties with every copy of the Work You
|
||||
Distribute or Publicly Perform. When You Distribute or Publicly
|
||||
Perform the Work, You may not impose any effective technological
|
||||
measures on the Work that restrict the ability of a recipient of the
|
||||
Work from You to exercise the rights granted to that recipient under
|
||||
the terms of the License. This Section 4(a) applies to the Work as
|
||||
incorporated in a Collection, but this does not require the Collection
|
||||
apart from the Work itself to be made subject to the terms of this
|
||||
License. If You create a Collection, upon notice from any Licensor You
|
||||
must, to the extent practicable, remove from the Collection any credit
|
||||
as required by Section 4(b), as requested. If You create an
|
||||
Adaptation, upon notice from any Licensor You must, to the extent
|
||||
practicable, remove from the Adaptation any credit as required by
|
||||
Section 4(b), as requested.
|
||||
b. If You Distribute, or Publicly Perform the Work or any Adaptations or
|
||||
Collections, You must, unless a request has been made pursuant to
|
||||
Section 4(a), keep intact all copyright notices for the Work and
|
||||
provide, reasonable to the medium or means You are utilizing: (i) the
|
||||
name of the Original Author (or pseudonym, if applicable) if supplied,
|
||||
and/or if the Original Author and/or Licensor designate another party
|
||||
or parties (e.g., a sponsor institute, publishing entity, journal) for
|
||||
attribution ("Attribution Parties") in Licensor's copyright notice,
|
||||
terms of service or by other reasonable means, the name of such party
|
||||
or parties; (ii) the title of the Work if supplied; (iii) to the
|
||||
extent reasonably practicable, the URI, if any, that Licensor
|
||||
specifies to be associated with the Work, unless such URI does not
|
||||
refer to the copyright notice or licensing information for the Work;
|
||||
and (iv) , consistent with Section 3(b), in the case of an Adaptation,
|
||||
a credit identifying the use of the Work in the Adaptation (e.g.,
|
||||
"French translation of the Work by Original Author," or "Screenplay
|
||||
based on original Work by Original Author"). The credit required by
|
||||
this Section 4 (b) may be implemented in any reasonable manner;
|
||||
provided, however, that in the case of a Adaptation or Collection, at
|
||||
a minimum such credit will appear, if a credit for all contributing
|
||||
authors of the Adaptation or Collection appears, then as part of these
|
||||
credits and in a manner at least as prominent as the credits for the
|
||||
other contributing authors. For the avoidance of doubt, You may only
|
||||
use the credit required by this Section for the purpose of attribution
|
||||
in the manner set out above and, by exercising Your rights under this
|
||||
License, You may not implicitly or explicitly assert or imply any
|
||||
connection with, sponsorship or endorsement by the Original Author,
|
||||
Licensor and/or Attribution Parties, as appropriate, of You or Your
|
||||
use of the Work, without the separate, express prior written
|
||||
permission of the Original Author, Licensor and/or Attribution
|
||||
Parties.
|
||||
c. Except as otherwise agreed in writing by the Licensor or as may be
|
||||
otherwise permitted by applicable law, if You Reproduce, Distribute or
|
||||
Publicly Perform the Work either by itself or as part of any
|
||||
Adaptations or Collections, You must not distort, mutilate, modify or
|
||||
take other derogatory action in relation to the Work which would be
|
||||
prejudicial to the Original Author's honor or reputation. Licensor
|
||||
agrees that in those jurisdictions (e.g. Japan), in which any exercise
|
||||
of the right granted in Section 3(b) of this License (the right to
|
||||
make Adaptations) would be deemed to be a distortion, mutilation,
|
||||
modification or other derogatory action prejudicial to the Original
|
||||
Author's honor and reputation, the Licensor will waive or not assert,
|
||||
as appropriate, this Section, to the fullest extent permitted by the
|
||||
applicable national law, to enable You to reasonably exercise Your
|
||||
right under Section 3(b) of this License (right to make Adaptations)
|
||||
but not otherwise.
|
||||
|
||||
5. Representations, Warranties and Disclaimer
|
||||
|
||||
UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR
|
||||
OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
|
||||
KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
|
||||
INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
|
||||
LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS,
|
||||
WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION
|
||||
OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
|
||||
|
||||
6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE
|
||||
LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR
|
||||
ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES
|
||||
ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS
|
||||
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
7. Termination
|
||||
|
||||
a. This License and the rights granted hereunder will terminate
|
||||
automatically upon any breach by You of the terms of this License.
|
||||
Individuals or entities who have received Adaptations or Collections
|
||||
from You under this License, however, will not have their licenses
|
||||
terminated provided such individuals or entities remain in full
|
||||
compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
|
||||
survive any termination of this License.
|
||||
b. Subject to the above terms and conditions, the license granted here is
|
||||
perpetual (for the duration of the applicable copyright in the Work).
|
||||
Notwithstanding the above, Licensor reserves the right to release the
|
||||
Work under different license terms or to stop distributing the Work at
|
||||
any time; provided, however that any such election will not serve to
|
||||
withdraw this License (or any other license that has been, or is
|
||||
required to be, granted under the terms of this License), and this
|
||||
License will continue in full force and effect unless terminated as
|
||||
stated above.
|
||||
|
||||
8. Miscellaneous
|
||||
|
||||
a. Each time You Distribute or Publicly Perform the Work or a Collection,
|
||||
the Licensor offers to the recipient a license to the Work on the same
|
||||
terms and conditions as the license granted to You under this License.
|
||||
b. Each time You Distribute or Publicly Perform an Adaptation, Licensor
|
||||
offers to the recipient a license to the original Work on the same
|
||||
terms and conditions as the license granted to You under this License.
|
||||
c. If any provision of this License is invalid or unenforceable under
|
||||
applicable law, it shall not affect the validity or enforceability of
|
||||
the remainder of the terms of this License, and without further action
|
||||
by the parties to this agreement, such provision shall be reformed to
|
||||
the minimum extent necessary to make such provision valid and
|
||||
enforceable.
|
||||
d. No term or provision of this License shall be deemed waived and no
|
||||
breach consented to unless such waiver or consent shall be in writing
|
||||
and signed by the party to be charged with such waiver or consent.
|
||||
e. This License constitutes the entire agreement between the parties with
|
||||
respect to the Work licensed here. There are no understandings,
|
||||
agreements or representations with respect to the Work not specified
|
||||
here. Licensor shall not be bound by any additional provisions that
|
||||
may appear in any communication from You. This License may not be
|
||||
modified without the mutual written agreement of the Licensor and You.
|
||||
f. The rights granted under, and the subject matter referenced, in this
|
||||
License were drafted utilizing the terminology of the Berne Convention
|
||||
for the Protection of Literary and Artistic Works (as amended on
|
||||
September 28, 1979), the Rome Convention of 1961, the WIPO Copyright
|
||||
Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996
|
||||
and the Universal Copyright Convention (as revised on July 24, 1971).
|
||||
These rights and subject matter take effect in the relevant
|
||||
jurisdiction in which the License terms are sought to be enforced
|
||||
according to the corresponding provisions of the implementation of
|
||||
those treaty provisions in the applicable national law. If the
|
||||
standard suite of rights granted under applicable copyright law
|
||||
includes additional rights not granted under this License, such
|
||||
additional rights are deemed to be included in the License; this
|
||||
License is not intended to restrict the license of any rights under
|
||||
applicable law.
|
||||
|
||||
|
||||
Creative Commons Notice
|
||||
|
||||
Creative Commons is not a party to this License, and makes no warranty
|
||||
whatsoever in connection with the Work. Creative Commons will not be
|
||||
liable to You or any party on any legal theory for any damages
|
||||
whatsoever, including without limitation any general, special,
|
||||
incidental or consequential damages arising in connection to this
|
||||
license. Notwithstanding the foregoing two (2) sentences, if Creative
|
||||
Commons has expressly identified itself as the Licensor hereunder, it
|
||||
shall have all rights and obligations of Licensor.
|
||||
|
||||
Except for the limited purpose of indicating to the public that the
|
||||
Work is licensed under the CCPL, Creative Commons does not authorize
|
||||
the use by either party of the trademark "Creative Commons" or any
|
||||
related trademark or logo of Creative Commons without the prior
|
||||
written consent of Creative Commons. Any permitted use will be in
|
||||
compliance with Creative Commons' then-current trademark usage
|
||||
guidelines, as may be published on its website or otherwise made
|
||||
available upon request from time to time. For the avoidance of doubt,
|
||||
this trademark restriction does not form part of this License.
|
||||
|
||||
Creative Commons may be contacted at https://creativecommons.org/.
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
Creative Commons Legal Code
|
||||
|
||||
CC0 1.0 Universal
|
||||
|
||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
||||
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
||||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
||||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
||||
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
||||
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
||||
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
||||
HEREUNDER.
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator
|
||||
and subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for
|
||||
the purpose of contributing to a commons of creative, cultural and
|
||||
scientific works ("Commons") that the public can reliably and without fear
|
||||
of later claims of infringement build upon, modify, incorporate in other
|
||||
works, reuse and redistribute as freely as possible in any form whatsoever
|
||||
and for any purposes, including without limitation commercial purposes.
|
||||
These owners may contribute to the Commons to promote the ideal of a free
|
||||
culture and the further production of creative, cultural and scientific
|
||||
works, or to gain reputation or greater distribution for their Work in
|
||||
part through the use and efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any
|
||||
expectation of additional consideration or compensation, the person
|
||||
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
||||
is an owner of Copyright and Related Rights in the Work, voluntarily
|
||||
elects to apply CC0 to the Work and publicly distribute the Work under its
|
||||
terms, with knowledge of his or her Copyright and Related Rights in the
|
||||
Work and the meaning and intended legal effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not
|
||||
limited to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display,
|
||||
communicate, and translate a Work;
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
iii. publicity and privacy rights pertaining to a person's image or
|
||||
likeness depicted in a Work;
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data
|
||||
in a Work;
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation
|
||||
thereof, including any amended or successor version of such
|
||||
directive); and
|
||||
vii. other similar, equivalent or corresponding rights throughout the
|
||||
world based on applicable law or treaty, and any national
|
||||
implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention
|
||||
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
||||
irrevocably and unconditionally waives, abandons, and surrenders all of
|
||||
Affirmer's Copyright and Related Rights and associated claims and causes
|
||||
of action, whether now known or unknown (including existing as well as
|
||||
future claims and causes of action), in the Work (i) in all territories
|
||||
worldwide, (ii) for the maximum duration provided by applicable law or
|
||||
treaty (including future time extensions), (iii) in any current or future
|
||||
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
||||
including without limitation commercial, advertising or promotional
|
||||
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
||||
member of the public at large and to the detriment of Affirmer's heirs and
|
||||
successors, fully intending that such Waiver shall not be subject to
|
||||
revocation, rescission, cancellation, termination, or any other legal or
|
||||
equitable action to disrupt the quiet enjoyment of the Work by the public
|
||||
as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason
|
||||
be judged legally invalid or ineffective under applicable law, then the
|
||||
Waiver shall be preserved to the maximum extent permitted taking into
|
||||
account Affirmer's express Statement of Purpose. In addition, to the
|
||||
extent the Waiver is so judged Affirmer hereby grants to each affected
|
||||
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
||||
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
||||
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
||||
maximum duration provided by applicable law or treaty (including future
|
||||
time extensions), (iii) in any current or future medium and for any number
|
||||
of copies, and (iv) for any purpose whatsoever, including without
|
||||
limitation commercial, advertising or promotional purposes (the
|
||||
"License"). The License shall be deemed effective as of the date CC0 was
|
||||
applied by Affirmer to the Work. Should any part of the License for any
|
||||
reason be judged legally invalid or ineffective under applicable law, such
|
||||
partial invalidity or ineffectiveness shall not invalidate the remainder
|
||||
of the License, and in such case Affirmer hereby affirms that he or she
|
||||
will not (i) exercise any of his or her remaining Copyright and Related
|
||||
Rights in the Work or (ii) assert any associated claims and causes of
|
||||
action with respect to the Work, in either case contrary to Affirmer's
|
||||
express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
b. Affirmer offers the Work as-is and makes no representations or
|
||||
warranties of any kind concerning the Work, express, implied,
|
||||
statutory or otherwise, including without limitation warranties of
|
||||
title, merchantability, fitness for a particular purpose, non
|
||||
infringement, or the absence of latent or other defects, accuracy, or
|
||||
the present or absence of errors, whether or not discoverable, all to
|
||||
the greatest extent permissible under applicable law.
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without
|
||||
limitation any person's Copyright and Related Rights in the Work.
|
||||
Further, Affirmer disclaims responsibility for obtaining any necessary
|
||||
consents, permissions or other rights required for any use of the
|
||||
Work.
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to
|
||||
this CC0 or use of the Work.
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
Version 1.80 (2024-07-25)
|
||||
Version 1.80.0 (2024-07-25)
|
||||
==========================
|
||||
|
||||
<a id="1.80-Language"></a>
|
||||
|
|
|
|||
170
REUSE.toml
Normal file
170
REUSE.toml
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
version = 1
|
||||
|
||||
# Reuse annotations file.
|
||||
#
|
||||
# This file controls how reuse-tool finds copyright and license notices within
|
||||
# source files. As the tool has a habit of picking up random uses of the word
|
||||
# 'Copyright' within source code, and because it will complain that other files
|
||||
# do not contain any specific copyright and license notifications, we usually
|
||||
# just set a blanket license and copyright notice for a whole sub-tree at a
|
||||
# time.
|
||||
#
|
||||
# See https://reuse.software and https://github.com/fsfe/reuse-tool for more
|
||||
# details. We currently use reuse-tool version 4.0.3.
|
||||
|
||||
[[annotations]]
|
||||
path = [
|
||||
"compiler/**",
|
||||
"library/**",
|
||||
"tests/**",
|
||||
"src/**",
|
||||
".github/**",
|
||||
"Cargo.lock",
|
||||
"Cargo.toml",
|
||||
"CODE_OF_CONDUCT.md",
|
||||
"config.example.toml",
|
||||
"configure",
|
||||
"CONTRIBUTING.md",
|
||||
"COPYRIGHT",
|
||||
"INSTALL.md",
|
||||
"LICENSE-APACHE",
|
||||
"LICENSE-MIT",
|
||||
"README.md",
|
||||
"RELEASES.md",
|
||||
"REUSE.toml",
|
||||
"rustfmt.toml",
|
||||
"rust-bors.toml",
|
||||
"triagebot.toml",
|
||||
"x",
|
||||
"x.ps1",
|
||||
"x.py",
|
||||
".clang-format",
|
||||
".editorconfig",
|
||||
".git-blame-ignore-revs",
|
||||
".gitattributes",
|
||||
".gitignore",
|
||||
".gitmodules",
|
||||
".mailmap",
|
||||
".ignore",
|
||||
]
|
||||
precedence = "override"
|
||||
SPDX-FileCopyrightText = "The Rust Project Developers (see https://thanks.rust-lang.org)"
|
||||
SPDX-License-Identifier = "MIT or Apache-2.0"
|
||||
|
||||
[[annotations]]
|
||||
path = "compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp"
|
||||
precedence = "override"
|
||||
SPDX-FileCopyrightText = [
|
||||
"2003-2019 University of Illinois at Urbana-Champaign.",
|
||||
"The Rust Project Developers (see https://thanks.rust-lang.org)",
|
||||
]
|
||||
SPDX-License-Identifier = "Apache-2.0 WITH LLVM-exception AND (Apache-2.0 OR MIT)"
|
||||
|
||||
[[annotations]]
|
||||
path = "library/core/src/unicode/unicode_data.rs"
|
||||
precedence = "override"
|
||||
SPDX-FileCopyrightText = "1991-2022 Unicode, Inc. All rights reserved."
|
||||
SPDX-License-Identifier = "Unicode-DFS-2016"
|
||||
|
||||
[[annotations]]
|
||||
path = "library/std/src/sync/mpmc/**"
|
||||
precedence = "override"
|
||||
SPDX-FileCopyrightText = [
|
||||
"2019 The Crossbeam Project Developers",
|
||||
"The Rust Project Developers (see https://thanks.rust-lang.org)",
|
||||
]
|
||||
SPDX-License-Identifier = "MIT OR Apache-2.0"
|
||||
|
||||
[[annotations]]
|
||||
path = "library/std/src/sys/sync/mutex/fuchsia.rs"
|
||||
precedence = "override"
|
||||
SPDX-FileCopyrightText = [
|
||||
"2016 The Fuchsia Authors",
|
||||
"The Rust Project Developers (see https://thanks.rust-lang.org)",
|
||||
]
|
||||
SPDX-License-Identifier = "BSD-2-Clause AND (MIT OR Apache-2.0)"
|
||||
|
||||
[[annotations]]
|
||||
path = "src/test/rustdoc/auxiliary/enum-primitive.rs"
|
||||
precedence = "override"
|
||||
SPDX-FileCopyrightText = "2015 Anders Kaseorg <andersk@mit.edu>"
|
||||
SPDX-License-Identifier = "MIT"
|
||||
|
||||
[[annotations]]
|
||||
path = "src/librustdoc/html/static/fonts/FiraSans**"
|
||||
precedence = "override"
|
||||
SPDX-FileCopyrightText = ["2014, Mozilla Foundation", "2014, Telefonica S.A."]
|
||||
SPDX-License-Identifier = "OFL-1.1"
|
||||
|
||||
[[annotations]]
|
||||
path = "src/librustdoc/html/static/fonts/NanumBarun**"
|
||||
precedence = "override"
|
||||
SPDX-FileCopyrightText = "2010 NAVER Corporation"
|
||||
SPDX-License-Identifier = "OFL-1.1"
|
||||
|
||||
[[annotations]]
|
||||
path = [
|
||||
"src/librustdoc/html/static/fonts/SourceCodePro**",
|
||||
"src/librustdoc/html/static/fonts/SourceSerif4**",
|
||||
]
|
||||
precedence = "override"
|
||||
SPDX-FileCopyrightText = "2010, 2012, 2014-2023, Adobe Systems Incorporated"
|
||||
SPDX-License-Identifier = "OFL-1.1"
|
||||
|
||||
[[annotations]]
|
||||
path = "src/librustdoc/html/static/css/normalize.css"
|
||||
precedence = "override"
|
||||
SPDX-FileCopyrightText = "Nicolas Gallagher and Jonathan Neal"
|
||||
SPDX-License-Identifier = "MIT"
|
||||
|
||||
[[annotations]]
|
||||
path = "src/librustdoc/html/static/css/rustdoc.css"
|
||||
precedence = "override"
|
||||
SPDX-FileCopyrightText = [
|
||||
"2016 Ike Ku, Jessica Stokes and Leon Guan",
|
||||
"The Rust Project Developers (see https://thanks.rust-lang.org)",
|
||||
]
|
||||
SPDX-License-Identifier = "MIT OR Apache-2.0"
|
||||
|
||||
[[annotations]]
|
||||
path = "src/doc/rustc-dev-guide/mermaid.min.js"
|
||||
precedence = "override"
|
||||
SPDX-FileCopyrightText = "2014-2021 Knut Sveidqvist"
|
||||
SPDX-License-Identifier = "MIT"
|
||||
|
||||
[[annotations]]
|
||||
path = "library/backtrace/**"
|
||||
precedence = "override"
|
||||
SPDX-FileCopyrightText = [
|
||||
"2014 Alex Crichton",
|
||||
"The Rust Project Developers (see https://thanks.rust-lang.org)",
|
||||
]
|
||||
SPDX-License-Identifier = "MIT OR Apache-2.0"
|
||||
|
||||
[[annotations]]
|
||||
path = "src/doc/embedded-book/**"
|
||||
precedence = "override"
|
||||
SPDX-FileCopyrightText = [
|
||||
"Rust on Embedded Devices Working Group",
|
||||
"The Rust Project Developers (see https://thanks.rust-lang.org)",
|
||||
]
|
||||
SPDX-License-Identifier = "MIT OR Apache-2.0 OR CC-BY-SA-4.0"
|
||||
|
||||
[[annotations]]
|
||||
path = "src/doc/rust-by-example/**"
|
||||
precedence = "override"
|
||||
SPDX-FileCopyrightText = [
|
||||
"2014 Jorge Aparicio",
|
||||
"The Rust Project Developers (see https://thanks.rust-lang.org)",
|
||||
]
|
||||
SPDX-License-Identifier = "MIT OR Apache-2.0"
|
||||
|
||||
[[annotations]]
|
||||
path = "src/llvm-project/**"
|
||||
precedence = "override"
|
||||
SPDX-FileCopyrightText = [
|
||||
"2003-2019 by the contributors listed in [CREDITS.TXT](https://github.com/rust-lang/llvm-project/blob/7738295178045041669876bf32b0543ec8319a5c/llvm/CREDITS.TXT)",
|
||||
"2010 Apple Inc",
|
||||
"2003-2019 University of Illinois at Urbana-Champaign.",
|
||||
]
|
||||
SPDX-License-Identifier = "NCSA AND Apache-2.0 WITH LLVM-exception"
|
||||
|
|
@ -27,7 +27,7 @@ features = ['unprefixed_malloc_on_supported_platforms']
|
|||
|
||||
[features]
|
||||
# tidy-alphabetical-start
|
||||
jemalloc = ['jemalloc-sys']
|
||||
jemalloc = ['dep:jemalloc-sys']
|
||||
llvm = ['rustc_driver_impl/llvm']
|
||||
max_level_info = ['rustc_driver_impl/max_level_info']
|
||||
rustc_use_parallel_compiler = ['rustc_driver_impl/rustc_use_parallel_compiler']
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
fn main() {
|
||||
// See the comment at the top of this file for an explanation of this.
|
||||
#[cfg(feature = "jemalloc-sys")]
|
||||
#[cfg(feature = "jemalloc")]
|
||||
{
|
||||
use std::os::raw::{c_int, c_void};
|
||||
|
||||
|
|
|
|||
|
|
@ -21,10 +21,10 @@ default = ["nightly", "randomize"]
|
|||
# rust-analyzer depends on this crate and we therefore require it to built on a stable toolchain
|
||||
# without depending on rustc_data_structures, rustc_macros and rustc_serialize
|
||||
nightly = [
|
||||
"rustc_data_structures",
|
||||
"dep:rustc_data_structures",
|
||||
"dep:rustc_macros",
|
||||
"dep:rustc_serialize",
|
||||
"rustc_index/nightly",
|
||||
"rustc_macros",
|
||||
"rustc_serialize",
|
||||
]
|
||||
randomize = ["rand", "rand_xoshiro", "nightly"]
|
||||
randomize = ["dep:rand", "dep:rand_xoshiro", "nightly"]
|
||||
# tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -627,7 +627,7 @@ impl Step for Size {
|
|||
|
||||
#[inline]
|
||||
unsafe fn forward_unchecked(start: Self, count: usize) -> Self {
|
||||
Self::from_bytes(u64::forward_unchecked(start.bytes(), count))
|
||||
Self::from_bytes(unsafe { u64::forward_unchecked(start.bytes(), count) })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -642,7 +642,7 @@ impl Step for Size {
|
|||
|
||||
#[inline]
|
||||
unsafe fn backward_unchecked(start: Self, count: usize) -> Self {
|
||||
Self::from_bytes(u64::backward_unchecked(start.bytes(), count))
|
||||
Self::from_bytes(unsafe { u64::backward_unchecked(start.bytes(), count) })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ use rustc_macros::{Decodable, Encodable, HashStable_Generic};
|
|||
use rustc_span::source_map::{respan, Spanned};
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
|
||||
use std::borrow::Cow;
|
||||
use std::cmp;
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
|
|
@ -2264,6 +2265,47 @@ bitflags::bitflags! {
|
|||
}
|
||||
}
|
||||
|
||||
impl InlineAsmOptions {
|
||||
pub const COUNT: usize = Self::all().bits().count_ones() as usize;
|
||||
|
||||
pub const GLOBAL_OPTIONS: Self = Self::ATT_SYNTAX.union(Self::RAW);
|
||||
pub const NAKED_OPTIONS: Self = Self::ATT_SYNTAX.union(Self::RAW).union(Self::NORETURN);
|
||||
|
||||
pub fn human_readable_names(&self) -> Vec<&'static str> {
|
||||
let mut options = vec![];
|
||||
|
||||
if self.contains(InlineAsmOptions::PURE) {
|
||||
options.push("pure");
|
||||
}
|
||||
if self.contains(InlineAsmOptions::NOMEM) {
|
||||
options.push("nomem");
|
||||
}
|
||||
if self.contains(InlineAsmOptions::READONLY) {
|
||||
options.push("readonly");
|
||||
}
|
||||
if self.contains(InlineAsmOptions::PRESERVES_FLAGS) {
|
||||
options.push("preserves_flags");
|
||||
}
|
||||
if self.contains(InlineAsmOptions::NORETURN) {
|
||||
options.push("noreturn");
|
||||
}
|
||||
if self.contains(InlineAsmOptions::NOSTACK) {
|
||||
options.push("nostack");
|
||||
}
|
||||
if self.contains(InlineAsmOptions::ATT_SYNTAX) {
|
||||
options.push("att_syntax");
|
||||
}
|
||||
if self.contains(InlineAsmOptions::RAW) {
|
||||
options.push("raw");
|
||||
}
|
||||
if self.contains(InlineAsmOptions::MAY_UNWIND) {
|
||||
options.push("may_unwind");
|
||||
}
|
||||
|
||||
options
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for InlineAsmOptions {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
bitflags::parser::to_writer(self, f)
|
||||
|
|
@ -2272,7 +2314,7 @@ impl std::fmt::Debug for InlineAsmOptions {
|
|||
|
||||
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Hash, HashStable_Generic)]
|
||||
pub enum InlineAsmTemplatePiece {
|
||||
String(String),
|
||||
String(Cow<'static, str>),
|
||||
Placeholder { operand_idx: usize, modifier: Option<char>, span: Span },
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -699,8 +699,7 @@ impl Token {
|
|||
false
|
||||
}
|
||||
|
||||
/// Would `maybe_whole_expr` in `parser.rs` return `Ok(..)`?
|
||||
/// That is, is this a pre-parsed expression dropped into the token stream
|
||||
/// Is this a pre-parsed expression dropped into the token stream
|
||||
/// (which happens while parsing the result of macro expansion)?
|
||||
pub fn is_whole_expr(&self) -> bool {
|
||||
if let Interpolated(nt) = &self.kind
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ rustc_span = { path = "../rustc_span", optional = true }
|
|||
[features]
|
||||
default = ["nightly"]
|
||||
nightly = [
|
||||
"rustc_serialize",
|
||||
"rustc_data_structures",
|
||||
"rustc_macros",
|
||||
"rustc_span",
|
||||
"dep:rustc_serialize",
|
||||
"dep:rustc_data_structures",
|
||||
"dep:rustc_macros",
|
||||
"dep:rustc_span",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
.emit();
|
||||
}
|
||||
hir::InlineAsmOperand::Const {
|
||||
anon_const: self.lower_anon_const(anon_const),
|
||||
anon_const: self.lower_anon_const_to_anon_const(anon_const),
|
||||
}
|
||||
}
|
||||
InlineAsmOperand::Sym { sym } => {
|
||||
|
|
@ -222,18 +222,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
};
|
||||
|
||||
// Wrap the expression in an AnonConst.
|
||||
let parent_def_id = self.current_hir_id_owner;
|
||||
let parent_def_id = self.current_def_id_parent;
|
||||
let node_id = self.next_node_id();
|
||||
self.create_def(
|
||||
parent_def_id.def_id,
|
||||
node_id,
|
||||
kw::Empty,
|
||||
DefKind::AnonConst,
|
||||
*op_sp,
|
||||
);
|
||||
// HACK(min_generic_const_args): see lower_anon_const
|
||||
if !expr.is_potential_trivial_const_arg() {
|
||||
self.create_def(
|
||||
parent_def_id,
|
||||
node_id,
|
||||
kw::Empty,
|
||||
DefKind::AnonConst,
|
||||
*op_sp,
|
||||
);
|
||||
}
|
||||
let anon_const = AnonConst { id: node_id, value: P(expr) };
|
||||
hir::InlineAsmOperand::SymFn {
|
||||
anon_const: self.lower_anon_const(&anon_const),
|
||||
anon_const: self.lower_anon_const_to_anon_const(&anon_const),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
use crate::{ImplTraitPosition, ResolverAstLoweringExt};
|
||||
|
||||
use super::{ImplTraitContext, LoweringContext, ParamMode};
|
||||
use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
|
||||
|
||||
use ast::visit::Visitor;
|
||||
use hir::def::{DefKind, PartialRes, Res};
|
||||
|
|
@ -259,8 +259,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
self_param_id: pat_node_id,
|
||||
};
|
||||
self_resolver.visit_block(block);
|
||||
let block = this.lower_block(block, false);
|
||||
this.mk_expr(hir::ExprKind::Block(block, None), block.span)
|
||||
this.lower_target_expr(&block)
|
||||
} else {
|
||||
let pat_hir_id = this.lower_node_id(pat_node_id);
|
||||
this.generate_arg(pat_hir_id, span)
|
||||
|
|
@ -273,26 +272,81 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
})
|
||||
}
|
||||
|
||||
// Generates fully qualified call for the resulting body.
|
||||
// FIXME(fn_delegation): Alternatives for target expression lowering:
|
||||
// https://github.com/rust-lang/rfcs/pull/3530#issuecomment-2197170600.
|
||||
fn lower_target_expr(&mut self, block: &Block) -> hir::Expr<'hir> {
|
||||
if block.stmts.len() == 1
|
||||
&& let StmtKind::Expr(expr) = &block.stmts[0].kind
|
||||
{
|
||||
return self.lower_expr_mut(expr);
|
||||
}
|
||||
|
||||
let block = self.lower_block(block, false);
|
||||
self.mk_expr(hir::ExprKind::Block(block, None), block.span)
|
||||
}
|
||||
|
||||
// Generates expression for the resulting body. If possible, `MethodCall` is used
|
||||
// to allow autoref/autoderef for target expression. For example in:
|
||||
//
|
||||
// trait Trait : Sized {
|
||||
// fn by_value(self) -> i32 { 1 }
|
||||
// fn by_mut_ref(&mut self) -> i32 { 2 }
|
||||
// fn by_ref(&self) -> i32 { 3 }
|
||||
// }
|
||||
//
|
||||
// struct NewType(SomeType);
|
||||
// impl Trait for NewType {
|
||||
// reuse Trait::* { self.0 }
|
||||
// }
|
||||
//
|
||||
// `self.0` will automatically coerce.
|
||||
fn finalize_body_lowering(
|
||||
&mut self,
|
||||
delegation: &Delegation,
|
||||
args: Vec<hir::Expr<'hir>>,
|
||||
span: Span,
|
||||
) -> hir::Expr<'hir> {
|
||||
let path = self.lower_qpath(
|
||||
delegation.id,
|
||||
&delegation.qself,
|
||||
&delegation.path,
|
||||
ParamMode::Optional,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
None,
|
||||
);
|
||||
|
||||
let args = self.arena.alloc_from_iter(args);
|
||||
let path_expr = self.arena.alloc(self.mk_expr(hir::ExprKind::Path(path), span));
|
||||
let call = self.arena.alloc(self.mk_expr(hir::ExprKind::Call(path_expr, args), span));
|
||||
|
||||
let has_generic_args =
|
||||
delegation.path.segments.iter().rev().skip(1).any(|segment| segment.args.is_some());
|
||||
|
||||
let call = if self
|
||||
.get_resolution_id(delegation.id, span)
|
||||
.and_then(|def_id| Ok(self.has_self(def_id, span)))
|
||||
.unwrap_or_default()
|
||||
&& delegation.qself.is_none()
|
||||
&& !has_generic_args
|
||||
{
|
||||
let ast_segment = delegation.path.segments.last().unwrap();
|
||||
let segment = self.lower_path_segment(
|
||||
delegation.path.span,
|
||||
ast_segment,
|
||||
ParamMode::Optional,
|
||||
ParenthesizedGenericArgs::Err,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
None,
|
||||
);
|
||||
let segment = self.arena.alloc(segment);
|
||||
|
||||
self.arena.alloc(hir::Expr {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::ExprKind::MethodCall(segment, &args[0], &args[1..], span),
|
||||
span,
|
||||
})
|
||||
} else {
|
||||
let path = self.lower_qpath(
|
||||
delegation.id,
|
||||
&delegation.qself,
|
||||
&delegation.path,
|
||||
ParamMode::Optional,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
None,
|
||||
);
|
||||
|
||||
let callee_path = self.arena.alloc(self.mk_expr(hir::ExprKind::Path(path), span));
|
||||
self.arena.alloc(self.mk_expr(hir::ExprKind::Call(callee_path, args), span))
|
||||
};
|
||||
let block = self.arena.alloc(hir::Block {
|
||||
stmts: &[],
|
||||
expr: Some(call),
|
||||
|
|
|
|||
|
|
@ -75,10 +75,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let kind = match &e.kind {
|
||||
ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
|
||||
ExprKind::ConstBlock(c) => {
|
||||
let c = self.with_new_scopes(c.value.span, |this| hir::ConstBlock {
|
||||
def_id: this.local_def_id(c.id),
|
||||
hir_id: this.lower_node_id(c.id),
|
||||
body: this.lower_const_body(c.value.span, Some(&c.value)),
|
||||
let c = self.with_new_scopes(c.value.span, |this| {
|
||||
let def_id = this.local_def_id(c.id);
|
||||
hir::ConstBlock {
|
||||
def_id,
|
||||
hir_id: this.lower_node_id(c.id),
|
||||
body: this.with_def_id_parent(def_id, |this| {
|
||||
this.lower_const_body(c.value.span, Some(&c.value))
|
||||
}),
|
||||
}
|
||||
});
|
||||
hir::ExprKind::ConstBlock(c)
|
||||
}
|
||||
|
|
@ -377,17 +382,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let mut generic_args = ThinVec::new();
|
||||
for (idx, arg) in args.into_iter().enumerate() {
|
||||
if legacy_args_idx.contains(&idx) {
|
||||
let parent_def_id = self.current_hir_id_owner;
|
||||
let parent_def_id = self.current_def_id_parent;
|
||||
let node_id = self.next_node_id();
|
||||
|
||||
// Add a definition for the in-band const def.
|
||||
self.create_def(
|
||||
parent_def_id.def_id,
|
||||
node_id,
|
||||
kw::Empty,
|
||||
DefKind::AnonConst,
|
||||
f.span,
|
||||
);
|
||||
// HACK(min_generic_const_args): see lower_anon_const
|
||||
if !arg.is_potential_trivial_const_arg() {
|
||||
// Add a definition for the in-band const def.
|
||||
self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span);
|
||||
}
|
||||
|
||||
let anon_const = AnonConst { id: node_id, value: arg };
|
||||
generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const)));
|
||||
|
|
@ -622,6 +624,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
coroutine_source: hir::CoroutineSource,
|
||||
body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
|
||||
) -> hir::ExprKind<'hir> {
|
||||
let closure_def_id = self.local_def_id(closure_node_id);
|
||||
let coroutine_kind = hir::CoroutineKind::Desugared(desugaring_kind, coroutine_source);
|
||||
|
||||
// The `async` desugaring takes a resume argument and maintains a `task_context`,
|
||||
|
|
@ -672,22 +675,24 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
lifetime_elision_allowed: false,
|
||||
});
|
||||
|
||||
let body = self.lower_body(move |this| {
|
||||
this.coroutine_kind = Some(coroutine_kind);
|
||||
let body = self.with_def_id_parent(closure_def_id, move |this| {
|
||||
this.lower_body(move |this| {
|
||||
this.coroutine_kind = Some(coroutine_kind);
|
||||
|
||||
let old_ctx = this.task_context;
|
||||
if task_context.is_some() {
|
||||
this.task_context = task_context;
|
||||
}
|
||||
let res = body(this);
|
||||
this.task_context = old_ctx;
|
||||
let old_ctx = this.task_context;
|
||||
if task_context.is_some() {
|
||||
this.task_context = task_context;
|
||||
}
|
||||
let res = body(this);
|
||||
this.task_context = old_ctx;
|
||||
|
||||
(params, res)
|
||||
(params, res)
|
||||
})
|
||||
});
|
||||
|
||||
// `static |<_task_context?>| -> <return_ty> { <body> }`:
|
||||
hir::ExprKind::Closure(self.arena.alloc(hir::Closure {
|
||||
def_id: self.local_def_id(closure_node_id),
|
||||
def_id: closure_def_id,
|
||||
binder: hir::ClosureBinder::Default,
|
||||
capture_clause,
|
||||
bound_generic_params: &[],
|
||||
|
|
@ -966,27 +971,30 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
fn_decl_span: Span,
|
||||
fn_arg_span: Span,
|
||||
) -> hir::ExprKind<'hir> {
|
||||
let closure_def_id = self.local_def_id(closure_id);
|
||||
let (binder_clause, generic_params) = self.lower_closure_binder(binder);
|
||||
|
||||
let (body_id, closure_kind) = self.with_new_scopes(fn_decl_span, move |this| {
|
||||
let mut coroutine_kind = if this
|
||||
.attrs
|
||||
.get(&closure_hir_id.local_id)
|
||||
.is_some_and(|attrs| attrs.iter().any(|attr| attr.has_name(sym::coroutine)))
|
||||
{
|
||||
Some(hir::CoroutineKind::Coroutine(Movability::Movable))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let body_id = this.lower_fn_body(decl, |this| {
|
||||
this.coroutine_kind = coroutine_kind;
|
||||
let e = this.lower_expr_mut(body);
|
||||
coroutine_kind = this.coroutine_kind;
|
||||
e
|
||||
});
|
||||
let coroutine_option =
|
||||
this.closure_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability);
|
||||
(body_id, coroutine_option)
|
||||
this.with_def_id_parent(closure_def_id, move |this| {
|
||||
let mut coroutine_kind = if this
|
||||
.attrs
|
||||
.get(&closure_hir_id.local_id)
|
||||
.is_some_and(|attrs| attrs.iter().any(|attr| attr.has_name(sym::coroutine)))
|
||||
{
|
||||
Some(hir::CoroutineKind::Coroutine(Movability::Movable))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let body_id = this.lower_fn_body(decl, |this| {
|
||||
this.coroutine_kind = coroutine_kind;
|
||||
let e = this.lower_expr_mut(body);
|
||||
coroutine_kind = this.coroutine_kind;
|
||||
e
|
||||
});
|
||||
let coroutine_option =
|
||||
this.closure_movability_for_fn(decl, fn_decl_span, coroutine_kind, movability);
|
||||
(body_id, coroutine_option)
|
||||
})
|
||||
});
|
||||
|
||||
let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
|
||||
|
|
@ -994,7 +1002,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let fn_decl = self.lower_fn_decl(decl, closure_id, fn_decl_span, FnDeclKind::Closure, None);
|
||||
|
||||
let c = self.arena.alloc(hir::Closure {
|
||||
def_id: self.local_def_id(closure_id),
|
||||
def_id: closure_def_id,
|
||||
binder: binder_clause,
|
||||
capture_clause,
|
||||
bound_generic_params,
|
||||
|
|
@ -1066,6 +1074,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
fn_decl_span: Span,
|
||||
fn_arg_span: Span,
|
||||
) -> hir::ExprKind<'hir> {
|
||||
let closure_def_id = self.local_def_id(closure_id);
|
||||
let (binder_clause, generic_params) = self.lower_closure_binder(binder);
|
||||
|
||||
assert_matches!(
|
||||
|
|
@ -1075,27 +1084,29 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
);
|
||||
|
||||
let body = self.with_new_scopes(fn_decl_span, |this| {
|
||||
let inner_decl =
|
||||
FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
|
||||
this.with_def_id_parent(closure_def_id, |this| {
|
||||
let inner_decl =
|
||||
FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
|
||||
|
||||
// Transform `async |x: u8| -> X { ... }` into
|
||||
// `|x: u8| || -> X { ... }`.
|
||||
let body_id = this.lower_body(|this| {
|
||||
let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
|
||||
&inner_decl,
|
||||
|this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
|
||||
fn_decl_span,
|
||||
body.span,
|
||||
coroutine_kind,
|
||||
hir::CoroutineSource::Closure,
|
||||
);
|
||||
// Transform `async |x: u8| -> X { ... }` into
|
||||
// `|x: u8| || -> X { ... }`.
|
||||
let body_id = this.lower_body(|this| {
|
||||
let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
|
||||
&inner_decl,
|
||||
|this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
|
||||
fn_decl_span,
|
||||
body.span,
|
||||
coroutine_kind,
|
||||
hir::CoroutineSource::Closure,
|
||||
);
|
||||
|
||||
let hir_id = this.lower_node_id(coroutine_kind.closure_id());
|
||||
this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id);
|
||||
let hir_id = this.lower_node_id(coroutine_kind.closure_id());
|
||||
this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id);
|
||||
|
||||
(parameters, expr)
|
||||
});
|
||||
body_id
|
||||
(parameters, expr)
|
||||
});
|
||||
body_id
|
||||
})
|
||||
});
|
||||
|
||||
let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
|
||||
|
|
@ -1106,7 +1117,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
self.lower_fn_decl(&decl, closure_id, fn_decl_span, FnDeclKind::Closure, None);
|
||||
|
||||
let c = self.arena.alloc(hir::Closure {
|
||||
def_id: self.local_def_id(closure_id),
|
||||
def_id: closure_def_id,
|
||||
binder: binder_clause,
|
||||
capture_clause,
|
||||
bound_generic_params,
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
|||
intravisit::walk_generic_param(self, param);
|
||||
}
|
||||
|
||||
fn visit_const_param_default(&mut self, param: HirId, ct: &'hir AnonConst) {
|
||||
fn visit_const_param_default(&mut self, param: HirId, ct: &'hir ConstArg<'hir>) {
|
||||
self.with_parent(param, |this| {
|
||||
intravisit::walk_const_param_default(this, ct);
|
||||
})
|
||||
|
|
@ -229,6 +229,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
|||
}
|
||||
|
||||
fn visit_anon_const(&mut self, constant: &'hir AnonConst) {
|
||||
// FIXME: use real span?
|
||||
self.insert(DUMMY_SP, constant.hir_id, Node::AnonConst(constant));
|
||||
|
||||
self.with_parent(constant.hir_id, |this| {
|
||||
|
|
@ -244,6 +245,15 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
|||
});
|
||||
}
|
||||
|
||||
fn visit_const_arg(&mut self, const_arg: &'hir ConstArg<'hir>) {
|
||||
// FIXME: use real span?
|
||||
self.insert(DUMMY_SP, const_arg.hir_id, Node::ConstArg(const_arg));
|
||||
|
||||
self.with_parent(const_arg.hir_id, |this| {
|
||||
intravisit::walk_const_arg(this, const_arg);
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, expr: &'hir Expr<'hir>) {
|
||||
self.insert(expr.span, expr.hir_id, Node::Expr(expr));
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,10 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
|||
|
||||
for (def_id, info) in lctx.children {
|
||||
let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
|
||||
debug_assert!(matches!(owner, hir::MaybeOwner::Phantom));
|
||||
debug_assert!(
|
||||
matches!(owner, hir::MaybeOwner::Phantom),
|
||||
"duplicate copy of {def_id:?} in lctx.children"
|
||||
);
|
||||
*owner = info;
|
||||
}
|
||||
}
|
||||
|
|
@ -169,7 +172,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
id: NodeId,
|
||||
hir_id: hir::HirId,
|
||||
ident: &mut Ident,
|
||||
attrs: Option<&'hir [Attribute]>,
|
||||
attrs: &'hir [Attribute],
|
||||
vis_span: Span,
|
||||
i: &ItemKind,
|
||||
) -> hir::ItemKind<'hir> {
|
||||
|
|
@ -485,7 +488,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
id: NodeId,
|
||||
vis_span: Span,
|
||||
ident: &mut Ident,
|
||||
attrs: Option<&'hir [Attribute]>,
|
||||
attrs: &'hir [Attribute],
|
||||
) -> hir::ItemKind<'hir> {
|
||||
let path = &tree.prefix;
|
||||
let segments = prefix.segments.iter().chain(path.segments.iter()).cloned().collect();
|
||||
|
|
@ -563,7 +566,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
// `ItemLocalId` and the new owner. (See `lower_node_id`)
|
||||
let kind =
|
||||
this.lower_use_tree(use_tree, &prefix, id, vis_span, &mut ident, attrs);
|
||||
if let Some(attrs) = attrs {
|
||||
if !attrs.is_empty() {
|
||||
this.attrs.insert(hir::ItemLocalId::ZERO, attrs);
|
||||
}
|
||||
|
||||
|
|
@ -713,7 +716,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
hir_id,
|
||||
def_id: self.local_def_id(v.id),
|
||||
data: self.lower_variant_data(hir_id, &v.data),
|
||||
disr_expr: v.disr_expr.as_ref().map(|e| self.lower_anon_const(e)),
|
||||
disr_expr: v.disr_expr.as_ref().map(|e| self.lower_anon_const_to_anon_const(e)),
|
||||
ident: self.lower_ident(v.ident),
|
||||
span: self.lower_span(v.span),
|
||||
}
|
||||
|
|
@ -1522,8 +1525,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
continue;
|
||||
}
|
||||
let is_param = *is_param.get_or_insert_with(compute_is_param);
|
||||
if !is_param {
|
||||
self.dcx().emit_err(MisplacedRelaxTraitBound { span: bound.span() });
|
||||
if !is_param && !self.tcx.features().more_maybe_bounds {
|
||||
self.tcx
|
||||
.sess
|
||||
.create_feature_err(
|
||||
MisplacedRelaxTraitBound { span: bound.span() },
|
||||
sym::more_maybe_bounds,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1601,7 +1610,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|
||||
if let Some((span, hir_id, def_id)) = host_param_parts {
|
||||
let const_node_id = self.next_node_id();
|
||||
let anon_const =
|
||||
let anon_const_did =
|
||||
self.create_def(def_id, const_node_id, kw::Empty, DefKind::AnonConst, span);
|
||||
|
||||
let const_id = self.next_id();
|
||||
|
|
@ -1609,7 +1618,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let bool_id = self.next_id();
|
||||
|
||||
self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
|
||||
self.children.push((anon_const, hir::MaybeOwner::NonOwner(const_id)));
|
||||
self.children.push((anon_const_did, hir::MaybeOwner::NonOwner(const_id)));
|
||||
|
||||
let const_body = self.lower_body(|this| {
|
||||
(
|
||||
|
|
@ -1624,6 +1633,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
)
|
||||
});
|
||||
|
||||
let default_ac = self.arena.alloc(hir::AnonConst {
|
||||
def_id: anon_const_did,
|
||||
hir_id: const_id,
|
||||
body: const_body,
|
||||
span,
|
||||
});
|
||||
let default_ct = self.arena.alloc(hir::ConstArg {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::ConstArgKind::Anon(default_ac),
|
||||
is_desugared_from_effects: false,
|
||||
});
|
||||
let param = hir::GenericParam {
|
||||
def_id,
|
||||
hir_id,
|
||||
|
|
@ -1648,12 +1668,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
)),
|
||||
)),
|
||||
// FIXME(effects) we might not need a default.
|
||||
default: Some(self.arena.alloc(hir::AnonConst {
|
||||
def_id: anon_const,
|
||||
hir_id: const_id,
|
||||
body: const_body,
|
||||
span,
|
||||
})),
|
||||
default: Some(default_ct),
|
||||
is_host_effect: true,
|
||||
synthetic: true,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -120,6 +120,18 @@ struct LoweringContext<'a, 'hir> {
|
|||
is_in_dyn_type: bool,
|
||||
|
||||
current_hir_id_owner: hir::OwnerId,
|
||||
/// Why do we need this in addition to [`Self::current_hir_id_owner`]?
|
||||
///
|
||||
/// Currently (as of June 2024), anonymous constants are not HIR owners; however,
|
||||
/// they do get their own DefIds. Some of these DefIds have to be created during
|
||||
/// AST lowering, rather than def collection, because we can't tell until after
|
||||
/// name resolution whether an anonymous constant will end up instead being a
|
||||
/// [`hir::ConstArgKind::Path`]. However, to compute which generics are
|
||||
/// available to an anonymous constant nested inside another, we need to make
|
||||
/// sure that the parent is recorded as the parent anon const, not the enclosing
|
||||
/// item. So we need to track parent defs differently from HIR owners, since they
|
||||
/// will be finer-grained in the case of anon consts.
|
||||
current_def_id_parent: LocalDefId,
|
||||
item_local_id_counter: hir::ItemLocalId,
|
||||
trait_map: ItemLocalMap<Box<[TraitCandidate]>>,
|
||||
|
||||
|
|
@ -162,6 +174,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
attrs: SortedMap::default(),
|
||||
children: Vec::default(),
|
||||
current_hir_id_owner: hir::CRATE_OWNER_ID,
|
||||
current_def_id_parent: CRATE_DEF_ID,
|
||||
item_local_id_counter: hir::ItemLocalId::ZERO,
|
||||
node_id_to_local_id: Default::default(),
|
||||
trait_map: Default::default(),
|
||||
|
|
@ -592,7 +605,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
let _old = self.node_id_to_local_id.insert(owner, hir::ItemLocalId::ZERO);
|
||||
debug_assert_eq!(_old, None);
|
||||
|
||||
let item = f(self);
|
||||
let item = self.with_def_id_parent(def_id, f);
|
||||
debug_assert_eq!(def_id, item.def_id().def_id);
|
||||
// `f` should have consumed all the elements in these vectors when constructing `item`.
|
||||
debug_assert!(self.impl_trait_defs.is_empty());
|
||||
|
|
@ -612,6 +625,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
self.children.push((def_id, hir::MaybeOwner::Owner(info)));
|
||||
}
|
||||
|
||||
fn with_def_id_parent<T>(&mut self, parent: LocalDefId, f: impl FnOnce(&mut Self) -> T) -> T {
|
||||
let current_def_id_parent = std::mem::replace(&mut self.current_def_id_parent, parent);
|
||||
let result = f(self);
|
||||
self.current_def_id_parent = current_def_id_parent;
|
||||
result
|
||||
}
|
||||
|
||||
/// Installs the remapping `remap` in scope while `f` is being executed.
|
||||
/// This causes references to the `LocalDefId` keys to be changed to
|
||||
/// refer to the values instead.
|
||||
|
|
@ -806,7 +826,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
LifetimeRes::Fresh { param, kind, .. } => {
|
||||
// Late resolution delegates to us the creation of the `LocalDefId`.
|
||||
let _def_id = self.create_def(
|
||||
self.current_hir_id_owner.def_id,
|
||||
self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent?
|
||||
param,
|
||||
kw::UnderscoreLifetime,
|
||||
DefKind::LifetimeParam,
|
||||
|
|
@ -893,15 +913,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
ret
|
||||
}
|
||||
|
||||
fn lower_attrs(&mut self, id: HirId, attrs: &[Attribute]) -> Option<&'hir [Attribute]> {
|
||||
fn lower_attrs(&mut self, id: HirId, attrs: &[Attribute]) -> &'hir [Attribute] {
|
||||
if attrs.is_empty() {
|
||||
None
|
||||
&[]
|
||||
} else {
|
||||
debug_assert_eq!(id.owner, self.current_hir_id_owner);
|
||||
let ret = self.arena.alloc_from_iter(attrs.iter().map(|a| self.lower_attr(a)));
|
||||
debug_assert!(!ret.is_empty());
|
||||
self.attrs.insert(id.local_id, ret);
|
||||
Some(ret)
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1044,7 +1064,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
AssocItemConstraintKind::Equality { term } => {
|
||||
let term = match term {
|
||||
Term::Ty(ty) => self.lower_ty(ty, itctx).into(),
|
||||
Term::Const(c) => self.lower_anon_const(c).into(),
|
||||
Term::Const(c) => self.lower_anon_const_to_const_arg(c).into(),
|
||||
};
|
||||
hir::AssocItemConstraintKind::Equality { term }
|
||||
}
|
||||
|
|
@ -1150,42 +1170,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
ty,
|
||||
);
|
||||
|
||||
// Construct an AnonConst where the expr is the "ty"'s path.
|
||||
|
||||
let parent_def_id = self.current_hir_id_owner;
|
||||
let node_id = self.next_node_id();
|
||||
let span = self.lower_span(ty.span);
|
||||
|
||||
// Add a definition for the in-band const def.
|
||||
let def_id = self.create_def(
|
||||
parent_def_id.def_id,
|
||||
node_id,
|
||||
kw::Empty,
|
||||
DefKind::AnonConst,
|
||||
span,
|
||||
);
|
||||
|
||||
let path_expr = Expr {
|
||||
id: ty.id,
|
||||
kind: ExprKind::Path(None, path.clone()),
|
||||
span,
|
||||
attrs: AttrVec::new(),
|
||||
tokens: None,
|
||||
};
|
||||
|
||||
let ct = self.with_new_scopes(span, |this| {
|
||||
self.arena.alloc(hir::AnonConst {
|
||||
def_id,
|
||||
hir_id: this.lower_node_id(node_id),
|
||||
body: this
|
||||
.lower_const_body(path_expr.span, Some(&path_expr)),
|
||||
span,
|
||||
})
|
||||
});
|
||||
return GenericArg::Const(ConstArg {
|
||||
value: ct,
|
||||
is_desugared_from_effects: false,
|
||||
});
|
||||
let ct =
|
||||
self.lower_const_path_to_const_arg(path, res, ty.id, ty.span);
|
||||
return GenericArg::Const(ct);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1193,10 +1180,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
GenericArg::Type(self.lower_ty(ty, itctx))
|
||||
}
|
||||
ast::GenericArg::Const(ct) => GenericArg::Const(ConstArg {
|
||||
value: self.lower_anon_const(ct),
|
||||
is_desugared_from_effects: false,
|
||||
}),
|
||||
ast::GenericArg::Const(ct) => GenericArg::Const(self.lower_anon_const_to_const_arg(ct)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1232,6 +1216,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
itctx,
|
||||
TraitBoundModifiers::NONE,
|
||||
);
|
||||
let bound = (bound, hir::TraitBoundModifier::None);
|
||||
let bounds = this.arena.alloc_from_iter([bound]);
|
||||
let lifetime_bound = this.elided_dyn_bound(t.span);
|
||||
(bounds, lifetime_bound)
|
||||
|
|
@ -1355,7 +1340,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
TyKind::Array(ty, length) => {
|
||||
hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_array_length(length))
|
||||
}
|
||||
TyKind::Typeof(expr) => hir::TyKind::Typeof(self.lower_anon_const(expr)),
|
||||
TyKind::Typeof(expr) => hir::TyKind::Typeof(self.lower_anon_const_to_anon_const(expr)),
|
||||
TyKind::TraitObject(bounds, kind) => {
|
||||
let mut lifetime_bound = None;
|
||||
let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {
|
||||
|
|
@ -1364,21 +1349,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
// We can safely ignore constness here since AST validation
|
||||
// takes care of rejecting invalid modifier combinations and
|
||||
// const trait bounds in trait object types.
|
||||
GenericBound::Trait(ty, modifiers) => match modifiers.polarity {
|
||||
BoundPolarity::Positive | BoundPolarity::Negative(_) => {
|
||||
Some(this.lower_poly_trait_ref(
|
||||
ty,
|
||||
itctx,
|
||||
// Still, don't pass along the constness here; we don't want to
|
||||
// synthesize any host effect args, it'd only cause problems.
|
||||
TraitBoundModifiers {
|
||||
constness: BoundConstness::Never,
|
||||
..*modifiers
|
||||
},
|
||||
))
|
||||
}
|
||||
BoundPolarity::Maybe(_) => None,
|
||||
},
|
||||
GenericBound::Trait(ty, modifiers) => {
|
||||
// Still, don't pass along the constness here; we don't want to
|
||||
// synthesize any host effect args, it'd only cause problems.
|
||||
let modifiers = TraitBoundModifiers {
|
||||
constness: BoundConstness::Never,
|
||||
..*modifiers
|
||||
};
|
||||
let trait_ref = this.lower_poly_trait_ref(ty, itctx, modifiers);
|
||||
let polarity = this.lower_trait_bound_modifiers(modifiers);
|
||||
Some((trait_ref, polarity))
|
||||
}
|
||||
GenericBound::Outlives(lifetime) => {
|
||||
if lifetime_bound.is_none() {
|
||||
lifetime_bound = Some(this.lower_lifetime(lifetime));
|
||||
|
|
@ -1429,7 +1410,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
);
|
||||
|
||||
self.create_def(
|
||||
self.current_hir_id_owner.def_id,
|
||||
self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent?
|
||||
*def_node_id,
|
||||
ident.name,
|
||||
DefKind::TyParam,
|
||||
|
|
@ -1637,7 +1618,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>],
|
||||
) -> hir::TyKind<'hir> {
|
||||
let opaque_ty_def_id = self.create_def(
|
||||
self.current_hir_id_owner.def_id,
|
||||
self.current_hir_id_owner.def_id, // FIXME: should this use self.current_def_id_parent?
|
||||
opaque_ty_node_id,
|
||||
kw::Empty,
|
||||
DefKind::OpaqueTy,
|
||||
|
|
@ -2222,7 +2203,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
false
|
||||
}
|
||||
})
|
||||
.map(|def| self.lower_anon_const(def));
|
||||
.map(|def| self.lower_anon_const_to_const_arg(def));
|
||||
|
||||
(
|
||||
hir::ParamName::Plain(self.lower_ident(param.ident)),
|
||||
|
|
@ -2360,19 +2341,153 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
"using `_` for array lengths is unstable",
|
||||
)
|
||||
.stash(c.value.span, StashKey::UnderscoreForArrayLengths);
|
||||
hir::ArrayLen::Body(self.lower_anon_const(c))
|
||||
hir::ArrayLen::Body(self.lower_anon_const_to_const_arg(c))
|
||||
}
|
||||
}
|
||||
_ => hir::ArrayLen::Body(self.lower_anon_const(c)),
|
||||
_ => hir::ArrayLen::Body(self.lower_anon_const_to_const_arg(c)),
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst {
|
||||
self.arena.alloc(self.with_new_scopes(c.value.span, |this| hir::AnonConst {
|
||||
def_id: this.local_def_id(c.id),
|
||||
hir_id: this.lower_node_id(c.id),
|
||||
body: this.lower_const_body(c.value.span, Some(&c.value)),
|
||||
span: this.lower_span(c.value.span),
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn lower_const_path_to_const_arg(
|
||||
&mut self,
|
||||
path: &Path,
|
||||
res: Res<NodeId>,
|
||||
ty_id: NodeId,
|
||||
span: Span,
|
||||
) -> &'hir hir::ConstArg<'hir> {
|
||||
let ct_kind = match res {
|
||||
Res::Def(DefKind::ConstParam, _) => {
|
||||
let qpath = self.lower_qpath(
|
||||
ty_id,
|
||||
&None,
|
||||
path,
|
||||
ParamMode::Optional,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
None,
|
||||
);
|
||||
hir::ConstArgKind::Path(qpath)
|
||||
}
|
||||
_ => {
|
||||
// Construct an AnonConst where the expr is the "ty"'s path.
|
||||
|
||||
let parent_def_id = self.current_def_id_parent;
|
||||
let node_id = self.next_node_id();
|
||||
let span = self.lower_span(span);
|
||||
|
||||
// Add a definition for the in-band const def.
|
||||
let def_id =
|
||||
self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, span);
|
||||
let hir_id = self.lower_node_id(node_id);
|
||||
|
||||
let path_expr = Expr {
|
||||
id: ty_id,
|
||||
kind: ExprKind::Path(None, path.clone()),
|
||||
span,
|
||||
attrs: AttrVec::new(),
|
||||
tokens: None,
|
||||
};
|
||||
|
||||
let ct = self.with_new_scopes(span, |this| {
|
||||
self.arena.alloc(hir::AnonConst {
|
||||
def_id,
|
||||
hir_id,
|
||||
body: this.with_def_id_parent(def_id, |this| {
|
||||
this.lower_const_body(path_expr.span, Some(&path_expr))
|
||||
}),
|
||||
span,
|
||||
})
|
||||
});
|
||||
hir::ConstArgKind::Anon(ct)
|
||||
}
|
||||
};
|
||||
|
||||
self.arena.alloc(hir::ConstArg {
|
||||
hir_id: self.next_id(),
|
||||
kind: ct_kind,
|
||||
is_desugared_from_effects: false,
|
||||
})
|
||||
}
|
||||
|
||||
/// See [`hir::ConstArg`] for when to use this function vs
|
||||
/// [`Self::lower_anon_const_to_anon_const`].
|
||||
fn lower_anon_const_to_const_arg(&mut self, anon: &AnonConst) -> &'hir hir::ConstArg<'hir> {
|
||||
self.arena.alloc(self.lower_anon_const_to_const_arg_direct(anon))
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn lower_anon_const_to_const_arg_direct(&mut self, anon: &AnonConst) -> hir::ConstArg<'hir> {
|
||||
// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
|
||||
// currently have to be wrapped in curly brackets, so it's necessary to special-case.
|
||||
let expr = if let ExprKind::Block(block, _) = &anon.value.kind
|
||||
&& let [stmt] = block.stmts.as_slice()
|
||||
&& let StmtKind::Expr(expr) = &stmt.kind
|
||||
&& let ExprKind::Path(..) = &expr.kind
|
||||
{
|
||||
expr
|
||||
} else {
|
||||
&anon.value
|
||||
};
|
||||
let maybe_res =
|
||||
self.resolver.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res());
|
||||
debug!("res={:?}", maybe_res);
|
||||
// FIXME(min_generic_const_args): for now we only lower params to ConstArgKind::Path
|
||||
if let Some(res) = maybe_res
|
||||
&& let Res::Def(DefKind::ConstParam, _) = res
|
||||
&& let ExprKind::Path(qself, path) = &expr.kind
|
||||
{
|
||||
let qpath = self.lower_qpath(
|
||||
expr.id,
|
||||
qself,
|
||||
path,
|
||||
ParamMode::Optional,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
None,
|
||||
);
|
||||
|
||||
return ConstArg {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::ConstArgKind::Path(qpath),
|
||||
is_desugared_from_effects: false,
|
||||
};
|
||||
}
|
||||
|
||||
let lowered_anon = self.lower_anon_const_to_anon_const(anon);
|
||||
ConstArg {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::ConstArgKind::Anon(lowered_anon),
|
||||
is_desugared_from_effects: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// See [`hir::ConstArg`] for when to use this function vs
|
||||
/// [`Self::lower_anon_const_to_const_arg`].
|
||||
fn lower_anon_const_to_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst {
|
||||
if c.value.is_potential_trivial_const_arg() {
|
||||
// HACK(min_generic_const_args): see DefCollector::visit_anon_const
|
||||
// Over there, we guess if this is a bare param and only create a def if
|
||||
// we think it's not. However we may can guess wrong (see there for example)
|
||||
// in which case we have to create the def here.
|
||||
self.create_def(
|
||||
self.current_def_id_parent,
|
||||
c.id,
|
||||
kw::Empty,
|
||||
DefKind::AnonConst,
|
||||
c.value.span,
|
||||
);
|
||||
}
|
||||
|
||||
self.arena.alloc(self.with_new_scopes(c.value.span, |this| {
|
||||
let def_id = this.local_def_id(c.id);
|
||||
let hir_id = this.lower_node_id(c.id);
|
||||
hir::AnonConst {
|
||||
def_id,
|
||||
hir_id,
|
||||
body: this.with_def_id_parent(def_id, |this| {
|
||||
this.lower_const_body(c.value.span, Some(&c.value))
|
||||
}),
|
||||
span: this.lower_span(c.value.span),
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
@ -2570,6 +2685,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
trait_ref: hir::TraitRef { path, hir_ref_id: hir_id },
|
||||
span: self.lower_span(span),
|
||||
};
|
||||
let principal = (principal, hir::TraitBoundModifier::None);
|
||||
|
||||
// The original ID is taken by the `PolyTraitRef`,
|
||||
// so the `Ty` itself needs a different one.
|
||||
|
|
|
|||
|
|
@ -44,13 +44,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
let mut res = self.lower_res(base_res);
|
||||
|
||||
// When we have an `async` kw on a bound, map the trait it resolves to.
|
||||
let mut bound_modifier_allowed_features = None;
|
||||
if let Some(TraitBoundModifiers { asyncness: BoundAsyncness::Async(_), .. }) = modifiers {
|
||||
match res {
|
||||
Res::Def(DefKind::Trait, def_id) => {
|
||||
if let Some((async_def_id, features)) = self.map_trait_to_async_trait(def_id) {
|
||||
if let Some(async_def_id) = self.map_trait_to_async_trait(def_id) {
|
||||
res = Res::Def(DefKind::Trait, async_def_id);
|
||||
bound_modifier_allowed_features = Some(features);
|
||||
} else {
|
||||
self.dcx().emit_err(AsyncBoundOnlyForFnTraits { span: p.span });
|
||||
}
|
||||
|
|
@ -67,6 +65,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
// Ungate the `async_fn_traits` feature in the path if the trait is
|
||||
// named via either `async Fn*()` or `AsyncFn*()`.
|
||||
let bound_modifier_allowed_features = if let Res::Def(DefKind::Trait, async_def_id) = res
|
||||
&& self.tcx.async_fn_trait_kind_from_def_id(async_def_id).is_some()
|
||||
{
|
||||
Some(self.allow_async_fn_traits.clone())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let path_span_lo = p.span.shrink_to_lo();
|
||||
let proj_start = p.segments.len() - unresolved_segments;
|
||||
let path = self.arena.alloc(hir::Path {
|
||||
|
|
@ -506,14 +514,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
/// This only needs to be done until we unify `AsyncFn` and `Fn` traits into one
|
||||
/// that is generic over `async`ness, if that's ever possible, or modify the
|
||||
/// lowering of `async Fn()` bounds to desugar to another trait like `LendingFn`.
|
||||
fn map_trait_to_async_trait(&self, def_id: DefId) -> Option<(DefId, Lrc<[Symbol]>)> {
|
||||
fn map_trait_to_async_trait(&self, def_id: DefId) -> Option<DefId> {
|
||||
let lang_items = self.tcx.lang_items();
|
||||
if Some(def_id) == lang_items.fn_trait() {
|
||||
Some((lang_items.async_fn_trait()?, self.allow_async_fn_traits.clone()))
|
||||
lang_items.async_fn_trait()
|
||||
} else if Some(def_id) == lang_items.fn_mut_trait() {
|
||||
Some((lang_items.async_fn_mut_trait()?, self.allow_async_fn_traits.clone()))
|
||||
lang_items.async_fn_mut_trait()
|
||||
} else if Some(def_id) == lang_items.fn_once_trait() {
|
||||
Some((lang_items.async_fn_once_trait()?, self.allow_async_fn_traits.clone()))
|
||||
lang_items.async_fn_once_trait()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,6 +120,9 @@ ast_passes_fn_without_body =
|
|||
ast_passes_forbidden_bound =
|
||||
bounds cannot be used in this context
|
||||
|
||||
ast_passes_forbidden_const_param =
|
||||
late-bound const parameters cannot be used currently
|
||||
|
||||
ast_passes_forbidden_default =
|
||||
`default` is only allowed on items in trait impls
|
||||
.label = `default` because of this
|
||||
|
|
@ -152,16 +155,11 @@ ast_passes_impl_trait_path = `impl Trait` is not allowed in path parameters
|
|||
ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
|
||||
.help = remove one of these features
|
||||
|
||||
ast_passes_incompatible_trait_bound_modifiers = `{$left}` and `{$right}` are mutually exclusive
|
||||
|
||||
ast_passes_inherent_cannot_be = inherent impls cannot be {$annotation}
|
||||
.because = {$annotation} because of this
|
||||
.type = inherent impl for this type
|
||||
.only_trait = only trait implementations may be annotated with {$annotation}
|
||||
|
||||
ast_passes_invalid_label =
|
||||
invalid label name `{$name}`
|
||||
|
||||
ast_passes_invalid_unnamed_field =
|
||||
unnamed fields are not allowed outside of structs or unions
|
||||
.label = unnamed field declared here
|
||||
|
|
@ -176,9 +174,6 @@ ast_passes_item_invalid_safety = items outside of `unsafe extern {"{ }"}` cannot
|
|||
ast_passes_item_underscore = `{$kind}` items in this context need a name
|
||||
.label = `_` is not a valid name for this `{$kind}` item
|
||||
|
||||
ast_passes_keyword_lifetime =
|
||||
lifetimes cannot use keyword names
|
||||
|
||||
ast_passes_match_arm_with_no_body =
|
||||
`match` arm with no body
|
||||
.suggestion = add a body after the pattern
|
||||
|
|
@ -275,6 +270,9 @@ ast_passes_unsafe_negative_impl = negative impls cannot be unsafe
|
|||
.negative = negative because of this
|
||||
.unsafe = unsafe because of this
|
||||
|
||||
ast_passes_unsafe_static =
|
||||
static items cannot be declared with `unsafe` safety qualifier outside of `extern` block
|
||||
|
||||
ast_passes_visibility_not_permitted =
|
||||
visibility qualifiers are not permitted here
|
||||
.enum_variant = enum variants and their fields always share the visibility of the enum they are in
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ use std::mem;
|
|||
use std::ops::{Deref, DerefMut};
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
use crate::errors;
|
||||
use crate::errors::{self, TildeConstReason};
|
||||
|
||||
/// Is `self` allowed semantically as the first parameter in an `FnDecl`?
|
||||
enum SelfSemantic {
|
||||
|
|
@ -46,27 +46,12 @@ enum SelfSemantic {
|
|||
No,
|
||||
}
|
||||
|
||||
/// What is the context that prevents using `~const`?
|
||||
// FIXME(effects): Consider getting rid of this in favor of `errors::TildeConstReason`, they're
|
||||
// almost identical. This gets rid of an abstraction layer which might be considered bad.
|
||||
enum DisallowTildeConstContext<'a> {
|
||||
TraitObject,
|
||||
Fn(FnKind<'a>),
|
||||
Trait(Span),
|
||||
TraitImpl(Span),
|
||||
Impl(Span),
|
||||
TraitAssocTy(Span),
|
||||
TraitImplAssocTy(Span),
|
||||
InherentAssocTy(Span),
|
||||
Item,
|
||||
}
|
||||
|
||||
enum TraitOrTraitImpl<'a> {
|
||||
enum TraitOrTraitImpl {
|
||||
Trait { span: Span, constness: Option<Span> },
|
||||
TraitImpl { constness: Const, polarity: ImplPolarity, trait_ref: &'a TraitRef },
|
||||
TraitImpl { constness: Const, polarity: ImplPolarity, trait_ref: Span },
|
||||
}
|
||||
|
||||
impl<'a> TraitOrTraitImpl<'a> {
|
||||
impl TraitOrTraitImpl {
|
||||
fn constness(&self) -> Option<Span> {
|
||||
match self {
|
||||
Self::Trait { constness: Some(span), .. }
|
||||
|
|
@ -81,9 +66,9 @@ struct AstValidator<'a> {
|
|||
features: &'a Features,
|
||||
|
||||
/// The span of the `extern` in an `extern { ... }` block, if any.
|
||||
extern_mod: Option<&'a Item>,
|
||||
extern_mod: Option<Span>,
|
||||
|
||||
outer_trait_or_trait_impl: Option<TraitOrTraitImpl<'a>>,
|
||||
outer_trait_or_trait_impl: Option<TraitOrTraitImpl>,
|
||||
|
||||
has_proc_macro_decls: bool,
|
||||
|
||||
|
|
@ -92,7 +77,7 @@ struct AstValidator<'a> {
|
|||
/// e.g., `impl Iterator<Item = impl Debug>`.
|
||||
outer_impl_trait: Option<Span>,
|
||||
|
||||
disallow_tilde_const: Option<DisallowTildeConstContext<'a>>,
|
||||
disallow_tilde_const: Option<TildeConstReason>,
|
||||
|
||||
/// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
|
||||
/// or `Foo::Bar<impl Trait>`
|
||||
|
|
@ -115,7 +100,7 @@ impl<'a> AstValidator<'a> {
|
|||
trait_.map(|(constness, polarity, trait_ref)| TraitOrTraitImpl::TraitImpl {
|
||||
constness,
|
||||
polarity,
|
||||
trait_ref,
|
||||
trait_ref: trait_ref.path.span,
|
||||
}),
|
||||
);
|
||||
f(self);
|
||||
|
|
@ -145,7 +130,7 @@ impl<'a> AstValidator<'a> {
|
|||
|
||||
fn with_tilde_const(
|
||||
&mut self,
|
||||
disallowed: Option<DisallowTildeConstContext<'a>>,
|
||||
disallowed: Option<TildeConstReason>,
|
||||
f: impl FnOnce(&mut Self),
|
||||
) {
|
||||
let old = mem::replace(&mut self.disallow_tilde_const, disallowed);
|
||||
|
|
@ -224,7 +209,7 @@ impl<'a> AstValidator<'a> {
|
|||
}
|
||||
}
|
||||
TyKind::TraitObject(..) => self
|
||||
.with_tilde_const(Some(DisallowTildeConstContext::TraitObject), |this| {
|
||||
.with_tilde_const(Some(TildeConstReason::TraitObject), |this| {
|
||||
visit::walk_ty(this, t)
|
||||
}),
|
||||
TyKind::Path(qself, path) => {
|
||||
|
|
@ -284,19 +269,6 @@ impl<'a> AstValidator<'a> {
|
|||
self.session.dcx()
|
||||
}
|
||||
|
||||
fn check_lifetime(&self, ident: Ident) {
|
||||
let valid_names = [kw::UnderscoreLifetime, kw::StaticLifetime, kw::Empty];
|
||||
if !valid_names.contains(&ident.name) && ident.without_first_quote().is_reserved() {
|
||||
self.dcx().emit_err(errors::KeywordLifetime { span: ident.span });
|
||||
}
|
||||
}
|
||||
|
||||
fn check_label(&self, ident: Ident) {
|
||||
if ident.without_first_quote().is_reserved() {
|
||||
self.dcx().emit_err(errors::InvalidLabel { span: ident.span, name: ident.name });
|
||||
}
|
||||
}
|
||||
|
||||
fn visibility_not_permitted(&self, vis: &Visibility, note: errors::VisibilityNotPermittedNote) {
|
||||
if let VisibilityKind::Inherited = vis.kind {
|
||||
return;
|
||||
|
|
@ -354,7 +326,7 @@ impl<'a> AstValidator<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrTraitImpl<'a>) {
|
||||
fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrTraitImpl) {
|
||||
let Const::Yes(span) = constness else {
|
||||
return;
|
||||
};
|
||||
|
|
@ -367,7 +339,7 @@ impl<'a> AstValidator<'a> {
|
|||
..
|
||||
} = parent
|
||||
{
|
||||
Some(trait_ref.path.span.shrink_to_lo())
|
||||
Some(trait_ref.shrink_to_lo())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
@ -466,6 +438,11 @@ impl<'a> AstValidator<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// This ensures that items can only be `unsafe` (or unmarked) outside of extern
|
||||
/// blocks.
|
||||
///
|
||||
/// This additionally ensures that within extern blocks, items can only be
|
||||
/// `safe`/`unsafe` inside of a `unsafe`-adorned extern block.
|
||||
fn check_item_safety(&self, span: Span, safety: Safety) {
|
||||
match self.extern_mod_safety {
|
||||
Some(extern_safety) => {
|
||||
|
|
@ -579,7 +556,7 @@ impl<'a> AstValidator<'a> {
|
|||
}
|
||||
|
||||
fn current_extern_span(&self) -> Span {
|
||||
self.session.source_map().guess_head_span(self.extern_mod.unwrap().span)
|
||||
self.session.source_map().guess_head_span(self.extern_mod.unwrap())
|
||||
}
|
||||
|
||||
/// An `fn` in `extern { ... }` cannot have qualifiers, e.g. `async fn`.
|
||||
|
|
@ -923,16 +900,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
self.walk_ty(ty)
|
||||
}
|
||||
|
||||
fn visit_label(&mut self, label: &'a Label) {
|
||||
self.check_label(label.ident);
|
||||
visit::walk_label(self, label);
|
||||
}
|
||||
|
||||
fn visit_lifetime(&mut self, lifetime: &'a Lifetime, _: visit::LifetimeCtxt) {
|
||||
self.check_lifetime(lifetime.ident);
|
||||
visit::walk_lifetime(self, lifetime);
|
||||
}
|
||||
|
||||
fn visit_field_def(&mut self, field: &'a FieldDef) {
|
||||
self.deny_unnamed_field(field);
|
||||
visit::walk_field_def(self, field)
|
||||
|
|
@ -980,7 +947,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
this.visit_vis(&item.vis);
|
||||
this.visit_ident(item.ident);
|
||||
let disallowed = matches!(constness, Const::No)
|
||||
.then(|| DisallowTildeConstContext::TraitImpl(item.span));
|
||||
.then(|| TildeConstReason::TraitImpl { span: item.span });
|
||||
this.with_tilde_const(disallowed, |this| this.visit_generics(generics));
|
||||
this.visit_trait_ref(t);
|
||||
this.visit_ty(self_ty);
|
||||
|
|
@ -1035,7 +1002,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
this.visit_vis(&item.vis);
|
||||
this.visit_ident(item.ident);
|
||||
this.with_tilde_const(
|
||||
Some(DisallowTildeConstContext::Impl(item.span)),
|
||||
Some(TildeConstReason::Impl { span: item.span }),
|
||||
|this| this.visit_generics(generics),
|
||||
);
|
||||
this.visit_ty(self_ty);
|
||||
|
|
@ -1080,7 +1047,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
}
|
||||
ItemKind::ForeignMod(ForeignMod { abi, safety, .. }) => {
|
||||
self.with_in_extern_mod(*safety, |this| {
|
||||
let old_item = mem::replace(&mut this.extern_mod, Some(item));
|
||||
let old_item = mem::replace(&mut this.extern_mod, Some(item.span));
|
||||
this.visibility_not_permitted(
|
||||
&item.vis,
|
||||
errors::VisibilityNotPermittedNote::IndividualForeignItems,
|
||||
|
|
@ -1154,7 +1121,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
this.visit_ident(item.ident);
|
||||
let disallowed = is_const_trait
|
||||
.is_none()
|
||||
.then(|| DisallowTildeConstContext::Trait(item.span));
|
||||
.then(|| TildeConstReason::Trait { span: item.span });
|
||||
this.with_tilde_const(disallowed, |this| {
|
||||
this.visit_generics(generics);
|
||||
walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
|
||||
|
|
@ -1215,6 +1182,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
}
|
||||
ItemKind::Static(box StaticItem { expr, safety, .. }) => {
|
||||
self.check_item_safety(item.span, *safety);
|
||||
if matches!(safety, Safety::Unsafe(_)) {
|
||||
self.dcx().emit_err(errors::UnsafeStatic { span: item.span });
|
||||
}
|
||||
|
||||
if expr.is_none() {
|
||||
self.dcx().emit_err(errors::StaticWithoutBody {
|
||||
|
|
@ -1371,25 +1341,32 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn visit_generic_param(&mut self, param: &'a GenericParam) {
|
||||
if let GenericParamKind::Lifetime { .. } = param.kind {
|
||||
self.check_lifetime(param.ident);
|
||||
}
|
||||
visit::walk_generic_param(self, param);
|
||||
}
|
||||
|
||||
fn visit_param_bound(&mut self, bound: &'a GenericBound, ctxt: BoundKind) {
|
||||
match bound {
|
||||
GenericBound::Trait(trait_ref, modifiers) => {
|
||||
match (ctxt, modifiers.constness, modifiers.polarity) {
|
||||
(BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_)) => {
|
||||
self.dcx().emit_err(errors::OptionalTraitSupertrait {
|
||||
span: trait_ref.span,
|
||||
path_str: pprust::path_to_string(&trait_ref.trait_ref.path),
|
||||
});
|
||||
(BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_))
|
||||
if !self.features.more_maybe_bounds =>
|
||||
{
|
||||
self.session
|
||||
.create_feature_err(
|
||||
errors::OptionalTraitSupertrait {
|
||||
span: trait_ref.span,
|
||||
path_str: pprust::path_to_string(&trait_ref.trait_ref.path),
|
||||
},
|
||||
sym::more_maybe_bounds,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
(BoundKind::TraitObject, BoundConstness::Never, BoundPolarity::Maybe(_)) => {
|
||||
self.dcx().emit_err(errors::OptionalTraitObject { span: trait_ref.span });
|
||||
(BoundKind::TraitObject, BoundConstness::Never, BoundPolarity::Maybe(_))
|
||||
if !self.features.more_maybe_bounds =>
|
||||
{
|
||||
self.session
|
||||
.create_feature_err(
|
||||
errors::OptionalTraitObject { span: trait_ref.span },
|
||||
sym::more_maybe_bounds,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
(
|
||||
BoundKind::TraitObject,
|
||||
|
|
@ -1399,53 +1376,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
self.dcx().emit_err(errors::ConstBoundTraitObject { span: trait_ref.span });
|
||||
}
|
||||
(_, BoundConstness::Maybe(span), BoundPolarity::Positive)
|
||||
if let Some(reason) = &self.disallow_tilde_const =>
|
||||
if let Some(reason) = self.disallow_tilde_const =>
|
||||
{
|
||||
let reason = match reason {
|
||||
DisallowTildeConstContext::Fn(FnKind::Closure(..)) => {
|
||||
errors::TildeConstReason::Closure
|
||||
}
|
||||
DisallowTildeConstContext::Fn(FnKind::Fn(_, ident, ..)) => {
|
||||
errors::TildeConstReason::Function { ident: ident.span }
|
||||
}
|
||||
&DisallowTildeConstContext::Trait(span) => {
|
||||
errors::TildeConstReason::Trait { span }
|
||||
}
|
||||
&DisallowTildeConstContext::TraitImpl(span) => {
|
||||
errors::TildeConstReason::TraitImpl { span }
|
||||
}
|
||||
&DisallowTildeConstContext::Impl(span) => {
|
||||
// FIXME(effects): Consider providing a help message or even a structured
|
||||
// suggestion for moving such bounds to the assoc const fns if available.
|
||||
errors::TildeConstReason::Impl { span }
|
||||
}
|
||||
&DisallowTildeConstContext::TraitAssocTy(span) => {
|
||||
errors::TildeConstReason::TraitAssocTy { span }
|
||||
}
|
||||
&DisallowTildeConstContext::TraitImplAssocTy(span) => {
|
||||
errors::TildeConstReason::TraitImplAssocTy { span }
|
||||
}
|
||||
&DisallowTildeConstContext::InherentAssocTy(span) => {
|
||||
errors::TildeConstReason::InherentAssocTy { span }
|
||||
}
|
||||
DisallowTildeConstContext::TraitObject => {
|
||||
errors::TildeConstReason::TraitObject
|
||||
}
|
||||
DisallowTildeConstContext::Item => errors::TildeConstReason::Item,
|
||||
};
|
||||
self.dcx().emit_err(errors::TildeConstDisallowed { span, reason });
|
||||
}
|
||||
(
|
||||
_,
|
||||
BoundConstness::Always(_) | BoundConstness::Maybe(_),
|
||||
BoundPolarity::Negative(_) | BoundPolarity::Maybe(_),
|
||||
) => {
|
||||
self.dcx().emit_err(errors::IncompatibleTraitBoundModifiers {
|
||||
span: bound.span(),
|
||||
left: modifiers.constness.as_str(),
|
||||
right: modifiers.polarity.as_str(),
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
|
@ -1569,7 +1503,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
.and_then(TraitOrTraitImpl::constness)
|
||||
.is_some();
|
||||
|
||||
let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk));
|
||||
let disallowed = (!tilde_const_allowed).then(|| match fk {
|
||||
FnKind::Fn(_, ident, _, _, _, _) => TildeConstReason::Function { ident: ident.span },
|
||||
FnKind::Closure(_, _, _) => TildeConstReason::Closure,
|
||||
});
|
||||
self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
|
||||
}
|
||||
|
||||
|
|
@ -1664,12 +1601,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
AssocItemKind::Type(_) => {
|
||||
let disallowed = (!parent_is_const).then(|| match self.outer_trait_or_trait_impl {
|
||||
Some(TraitOrTraitImpl::Trait { .. }) => {
|
||||
DisallowTildeConstContext::TraitAssocTy(item.span)
|
||||
TildeConstReason::TraitAssocTy { span: item.span }
|
||||
}
|
||||
Some(TraitOrTraitImpl::TraitImpl { .. }) => {
|
||||
DisallowTildeConstContext::TraitImplAssocTy(item.span)
|
||||
TildeConstReason::TraitImplAssocTy { span: item.span }
|
||||
}
|
||||
None => DisallowTildeConstContext::InherentAssocTy(item.span),
|
||||
None => TildeConstReason::InherentAssocTy { span: item.span },
|
||||
});
|
||||
self.with_tilde_const(disallowed, |this| {
|
||||
this.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt))
|
||||
|
|
@ -1852,7 +1789,7 @@ pub fn check_crate(
|
|||
outer_trait_or_trait_impl: None,
|
||||
has_proc_macro_decls: false,
|
||||
outer_impl_trait: None,
|
||||
disallow_tilde_const: Some(DisallowTildeConstContext::Item),
|
||||
disallow_tilde_const: Some(TildeConstReason::Item),
|
||||
is_impl_trait_banned: false,
|
||||
extern_mod_safety: None,
|
||||
lint_buffer: lints,
|
||||
|
|
|
|||
|
|
@ -9,21 +9,6 @@ use rustc_span::{symbol::Ident, Span, Symbol};
|
|||
|
||||
use crate::fluent_generated as fluent;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_keyword_lifetime)]
|
||||
pub struct KeywordLifetime {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_invalid_label)]
|
||||
pub struct InvalidLabel {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_visibility_not_permitted, code = E0449)]
|
||||
pub struct VisibilityNotPermitted {
|
||||
|
|
@ -84,6 +69,13 @@ pub struct ForbiddenBound {
|
|||
pub spans: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_forbidden_const_param)]
|
||||
pub struct ForbiddenConstParam {
|
||||
#[primary_span]
|
||||
pub const_param_spans: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_fn_param_too_many)]
|
||||
pub struct FnParamTooMany {
|
||||
|
|
@ -239,6 +231,13 @@ pub struct InvalidSafetyOnBareFn {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_unsafe_static)]
|
||||
pub struct UnsafeStatic {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_bound_in_context)]
|
||||
pub struct BoundInContext<'a> {
|
||||
|
|
@ -612,7 +611,7 @@ pub struct TildeConstDisallowed {
|
|||
pub reason: TildeConstReason,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[derive(Subdiagnostic, Copy, Clone)]
|
||||
pub enum TildeConstReason {
|
||||
#[note(ast_passes_closure)]
|
||||
Closure,
|
||||
|
|
@ -657,15 +656,6 @@ pub enum TildeConstReason {
|
|||
Item,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_incompatible_trait_bound_modifiers)]
|
||||
pub struct IncompatibleTraitBoundModifiers {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub left: &'static str,
|
||||
pub right: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_const_and_async)]
|
||||
pub struct ConstAndAsync {
|
||||
|
|
|
|||
|
|
@ -162,6 +162,22 @@ impl<'a> PostExpansionVisitor<'a> {
|
|||
crate::fluent_generated::ast_passes_forbidden_non_lifetime_param
|
||||
);
|
||||
|
||||
// FIXME(non_lifetime_binders): Const bound params are pretty broken.
|
||||
// Let's keep users from using this feature accidentally.
|
||||
if self.features.non_lifetime_binders {
|
||||
let const_param_spans: Vec<_> = params
|
||||
.iter()
|
||||
.filter_map(|param| match param.kind {
|
||||
ast::GenericParamKind::Const { .. } => Some(param.ident.span),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
|
||||
if !const_param_spans.is_empty() {
|
||||
self.sess.dcx().emit_err(errors::ForbiddenConstParam { const_param_spans });
|
||||
}
|
||||
}
|
||||
|
||||
for param in params {
|
||||
if !param.bounds.is_empty() {
|
||||
let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
|
||||
|
|
|
|||
|
|
@ -1505,35 +1505,7 @@ impl<'a> State<'a> {
|
|||
AsmArg::Options(opts) => {
|
||||
s.word("options");
|
||||
s.popen();
|
||||
let mut options = vec![];
|
||||
if opts.contains(InlineAsmOptions::PURE) {
|
||||
options.push("pure");
|
||||
}
|
||||
if opts.contains(InlineAsmOptions::NOMEM) {
|
||||
options.push("nomem");
|
||||
}
|
||||
if opts.contains(InlineAsmOptions::READONLY) {
|
||||
options.push("readonly");
|
||||
}
|
||||
if opts.contains(InlineAsmOptions::PRESERVES_FLAGS) {
|
||||
options.push("preserves_flags");
|
||||
}
|
||||
if opts.contains(InlineAsmOptions::NORETURN) {
|
||||
options.push("noreturn");
|
||||
}
|
||||
if opts.contains(InlineAsmOptions::NOSTACK) {
|
||||
options.push("nostack");
|
||||
}
|
||||
if opts.contains(InlineAsmOptions::ATT_SYNTAX) {
|
||||
options.push("att_syntax");
|
||||
}
|
||||
if opts.contains(InlineAsmOptions::RAW) {
|
||||
options.push("raw");
|
||||
}
|
||||
if opts.contains(InlineAsmOptions::MAY_UNWIND) {
|
||||
options.push("may_unwind");
|
||||
}
|
||||
s.commasep(Inconsistent, &options, |s, &opt| {
|
||||
s.commasep(Inconsistent, &opts.human_readable_names(), |s, &opt| {
|
||||
s.word(opt);
|
||||
});
|
||||
s.pclose();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_errors::{codes::*, struct_span_code_err, Diag, DiagCtxtHandle};
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
|
|
@ -382,13 +384,35 @@ impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
|||
yield_span: Span,
|
||||
) -> Diag<'infcx> {
|
||||
let coroutine_kind = self.body.coroutine.as_ref().unwrap().coroutine_kind;
|
||||
struct_span_code_err!(
|
||||
let mut diag = struct_span_code_err!(
|
||||
self.dcx(),
|
||||
span,
|
||||
E0626,
|
||||
"borrow may still be in use when {coroutine_kind:#} yields",
|
||||
)
|
||||
.with_span_label(yield_span, "possible yield occurs here")
|
||||
);
|
||||
diag.span_label(
|
||||
self.infcx.tcx.def_span(self.body.source.def_id()),
|
||||
format!("within this {coroutine_kind:#}"),
|
||||
);
|
||||
diag.span_label(yield_span, "possible yield occurs here");
|
||||
if matches!(coroutine_kind, hir::CoroutineKind::Coroutine(_)) {
|
||||
let hir::Closure { capture_clause, fn_decl_span, .. } = self
|
||||
.infcx
|
||||
.tcx
|
||||
.hir_node_by_def_id(self.body.source.def_id().expect_local())
|
||||
.expect_closure();
|
||||
let span = match capture_clause {
|
||||
rustc_hir::CaptureBy::Value { move_kw } => move_kw.shrink_to_lo(),
|
||||
rustc_hir::CaptureBy::Ref => fn_decl_span.shrink_to_lo(),
|
||||
};
|
||||
diag.span_suggestion_verbose(
|
||||
span,
|
||||
"add `static` to mark this coroutine as unmovable",
|
||||
"static ",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
diag
|
||||
}
|
||||
|
||||
pub(crate) fn cannot_borrow_across_destructor(&self, borrow_span: Span) -> Diag<'infcx> {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use rustc_errors::Diag;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_infer::infer::canonical::Canonical;
|
||||
use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError;
|
||||
use rustc_infer::infer::region_constraints::Constraint;
|
||||
use rustc_infer::infer::region_constraints::RegionConstraintData;
|
||||
use rustc_infer::infer::RegionVariableOrigin;
|
||||
|
|
@ -14,6 +13,8 @@ use rustc_middle::ty::RegionVid;
|
|||
use rustc_middle::ty::UniverseIndex;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::error_reporting::infer::nice_region_error::NiceRegionError;
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
use rustc_trait_selection::traits::query::type_op;
|
||||
use rustc_trait_selection::traits::ObligationCtxt;
|
||||
use rustc_traits::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_cause};
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ use rustc_span::def_id::LocalDefId;
|
|||
use rustc_span::hygiene::DesugaringKind;
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::{BytePos, Span, Symbol};
|
||||
use rustc_trait_selection::error_reporting::traits::suggestions::TypeErrCtxtExt;
|
||||
use rustc_trait_selection::error_reporting::traits::FindExprBySpan;
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::{Obligation, ObligationCause, ObligationCtxt};
|
||||
use std::iter;
|
||||
|
|
@ -205,9 +205,17 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
|||
is_loop_move = true;
|
||||
}
|
||||
|
||||
let mut has_suggest_reborrow = false;
|
||||
if !seen_spans.contains(&move_span) {
|
||||
if !closure {
|
||||
self.suggest_ref_or_clone(mpi, &mut err, &mut in_pattern, move_spans);
|
||||
self.suggest_ref_or_clone(
|
||||
mpi,
|
||||
&mut err,
|
||||
&mut in_pattern,
|
||||
move_spans,
|
||||
moved_place.as_ref(),
|
||||
&mut has_suggest_reborrow,
|
||||
);
|
||||
}
|
||||
|
||||
let msg_opt = CapturedMessageOpt {
|
||||
|
|
@ -215,6 +223,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
|||
is_loop_message,
|
||||
is_move_msg,
|
||||
is_loop_move,
|
||||
has_suggest_reborrow,
|
||||
maybe_reinitialized_locations_is_empty: maybe_reinitialized_locations
|
||||
.is_empty(),
|
||||
};
|
||||
|
|
@ -259,17 +268,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
|||
if is_loop_move & !in_pattern && !matches!(use_spans, UseSpans::ClosureUse { .. }) {
|
||||
if let ty::Ref(_, _, hir::Mutability::Mut) = ty.kind() {
|
||||
// We have a `&mut` ref, we need to reborrow on each iteration (#62112).
|
||||
err.span_suggestion_verbose(
|
||||
span.shrink_to_lo(),
|
||||
format!(
|
||||
"consider creating a fresh reborrow of {} here",
|
||||
self.describe_place(moved_place)
|
||||
.map(|n| format!("`{n}`"))
|
||||
.unwrap_or_else(|| "the mutable reference".to_string()),
|
||||
),
|
||||
"&mut *",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
self.suggest_reborrow(&mut err, span, moved_place);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -346,6 +345,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
|||
err: &mut Diag<'infcx>,
|
||||
in_pattern: &mut bool,
|
||||
move_spans: UseSpans<'tcx>,
|
||||
moved_place: PlaceRef<'tcx>,
|
||||
has_suggest_reborrow: &mut bool,
|
||||
) {
|
||||
let move_span = match move_spans {
|
||||
UseSpans::ClosureUse { capture_kind_span, .. } => capture_kind_span,
|
||||
|
|
@ -435,20 +436,49 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
|||
let parent = self.infcx.tcx.parent_hir_node(expr.hir_id);
|
||||
let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent
|
||||
&& let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind
|
||||
&& let Some(def_id) = typeck.type_dependent_def_id(parent_expr.hir_id)
|
||||
{
|
||||
(def_id.as_local(), args, 1)
|
||||
(typeck.type_dependent_def_id(parent_expr.hir_id), args, 1)
|
||||
} else if let hir::Node::Expr(parent_expr) = parent
|
||||
&& let hir::ExprKind::Call(call, args) = parent_expr.kind
|
||||
&& let ty::FnDef(def_id, _) = typeck.node_type(call.hir_id).kind()
|
||||
{
|
||||
(def_id.as_local(), args, 0)
|
||||
(Some(*def_id), args, 0)
|
||||
} else {
|
||||
(None, &[][..], 0)
|
||||
};
|
||||
|
||||
// If the moved value is a mut reference, it is used in a
|
||||
// generic function and it's type is a generic param, it can be
|
||||
// reborrowed to avoid moving.
|
||||
// for example:
|
||||
// struct Y(u32);
|
||||
// x's type is '& mut Y' and it is used in `fn generic<T>(x: T) {}`.
|
||||
if let Some(def_id) = def_id
|
||||
&& self.infcx.tcx.def_kind(def_id).is_fn_like()
|
||||
&& let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id)
|
||||
&& let Some(arg) = self
|
||||
.infcx
|
||||
.tcx
|
||||
.fn_sig(def_id)
|
||||
.skip_binder()
|
||||
.skip_binder()
|
||||
.inputs()
|
||||
.get(pos + offset)
|
||||
&& let ty::Param(_) = arg.kind()
|
||||
{
|
||||
let place = &self.move_data.move_paths[mpi].place;
|
||||
let ty = place.ty(self.body, self.infcx.tcx).ty;
|
||||
if let ty::Ref(_, _, hir::Mutability::Mut) = ty.kind() {
|
||||
*has_suggest_reborrow = true;
|
||||
self.suggest_reborrow(err, expr.span, moved_place);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let mut can_suggest_clone = true;
|
||||
if let Some(def_id) = def_id
|
||||
&& let node = self.infcx.tcx.hir_node_by_def_id(def_id)
|
||||
&& let Some(local_def_id) = def_id.as_local()
|
||||
&& let node = self.infcx.tcx.hir_node_by_def_id(local_def_id)
|
||||
&& let Some(fn_sig) = node.fn_sig()
|
||||
&& let Some(ident) = node.ident()
|
||||
&& let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id)
|
||||
|
|
@ -622,6 +652,25 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn suggest_reborrow(
|
||||
&self,
|
||||
err: &mut Diag<'infcx>,
|
||||
span: Span,
|
||||
moved_place: PlaceRef<'tcx>,
|
||||
) {
|
||||
err.span_suggestion_verbose(
|
||||
span.shrink_to_lo(),
|
||||
format!(
|
||||
"consider creating a fresh reborrow of {} here",
|
||||
self.describe_place(moved_place)
|
||||
.map(|n| format!("`{n}`"))
|
||||
.unwrap_or_else(|| "the mutable reference".to_string()),
|
||||
),
|
||||
"&mut *",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
|
||||
fn report_use_of_uninitialized(
|
||||
&self,
|
||||
mpi: MovePathIndex,
|
||||
|
|
@ -1257,37 +1306,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
|||
// result of `foo(...)` won't help.
|
||||
break 'outer;
|
||||
}
|
||||
|
||||
// We're suggesting `.clone()` on an borrowed value. See if the expression we have
|
||||
// is an argument to a function or method call, and try to suggest cloning the
|
||||
// *result* of the call, instead of the argument. This is closest to what people
|
||||
// would actually be looking for in most cases, with maybe the exception of things
|
||||
// like `fn(T) -> T`, but even then it is reasonable.
|
||||
let typeck_results = self.infcx.tcx.typeck(self.mir_def_id());
|
||||
let mut prev = expr;
|
||||
while let hir::Node::Expr(parent) = self.infcx.tcx.parent_hir_node(prev.hir_id) {
|
||||
if let hir::ExprKind::Call(..) | hir::ExprKind::MethodCall(..) = parent.kind
|
||||
&& let Some(call_ty) = typeck_results.node_type_opt(parent.hir_id)
|
||||
&& let call_ty = call_ty.peel_refs()
|
||||
&& (!call_ty
|
||||
.walk()
|
||||
.any(|t| matches!(t.unpack(), ty::GenericArgKind::Lifetime(_)))
|
||||
|| if let ty::Alias(ty::Projection, _) = call_ty.kind() {
|
||||
// FIXME: this isn't quite right with lifetimes on assoc types,
|
||||
// but ignore for now. We will only suggest cloning if
|
||||
// `<Ty as Trait>::Assoc: Clone`, which should keep false positives
|
||||
// down to a managable ammount.
|
||||
true
|
||||
} else {
|
||||
false
|
||||
})
|
||||
&& self.implements_clone(call_ty)
|
||||
&& self.suggest_cloning_inner(err, call_ty, parent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
prev = parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
let ty = ty.peel_refs();
|
||||
|
|
@ -1393,9 +1411,14 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
|||
// See `tests/ui/moves/needs-clone-through-deref.rs`
|
||||
return false;
|
||||
}
|
||||
// We don't want to suggest `.clone()` in a move closure, since the value has already been captured.
|
||||
if self.in_move_closure(expr) {
|
||||
return false;
|
||||
}
|
||||
// We also don't want to suggest cloning a closure itself, since the value has already been captured.
|
||||
if let hir::ExprKind::Closure(_) = expr.kind {
|
||||
return false;
|
||||
}
|
||||
// Try to find predicates on *generic params* that would allow copying `ty`
|
||||
let mut suggestion =
|
||||
if let Some(symbol) = tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
|
||||
|
|
@ -4255,17 +4278,35 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
|||
// search for relevant arguments.
|
||||
let mut arguments = Vec::new();
|
||||
for (index, argument) in sig.inputs().skip_binder().iter().enumerate() {
|
||||
if let ty::Ref(argument_region, _, _) = argument.kind() {
|
||||
if argument_region == return_region {
|
||||
// Need to use the `rustc_middle::ty` types to compare against the
|
||||
// `return_region`. Then use the `rustc_hir` type to get only
|
||||
// the lifetime span.
|
||||
if let hir::TyKind::Ref(lifetime, _) = &fn_decl.inputs[index].kind {
|
||||
if let ty::Ref(argument_region, _, _) = argument.kind()
|
||||
&& argument_region == return_region
|
||||
{
|
||||
// Need to use the `rustc_middle::ty` types to compare against the
|
||||
// `return_region`. Then use the `rustc_hir` type to get only
|
||||
// the lifetime span.
|
||||
match &fn_decl.inputs[index].kind {
|
||||
hir::TyKind::Ref(lifetime, _) => {
|
||||
// With access to the lifetime, we can get
|
||||
// the span of it.
|
||||
arguments.push((*argument, lifetime.ident.span));
|
||||
} else {
|
||||
bug!("ty type is a ref but hir type is not");
|
||||
}
|
||||
// Resolve `self` whose self type is `&T`.
|
||||
hir::TyKind::Path(hir::QPath::Resolved(None, path)) => {
|
||||
if let Res::SelfTyAlias { alias_to, .. } = path.res
|
||||
&& let Some(alias_to) = alias_to.as_local()
|
||||
&& let hir::Impl { self_ty, .. } = self
|
||||
.infcx
|
||||
.tcx
|
||||
.hir_node_by_def_id(alias_to)
|
||||
.expect_item()
|
||||
.expect_impl()
|
||||
&& let hir::TyKind::Ref(lifetime, _) = self_ty.kind
|
||||
{
|
||||
arguments.push((*argument, lifetime.ident.span));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// Don't ICE though. It might be a type alias.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ use rustc_span::def_id::LocalDefId;
|
|||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
|
||||
use rustc_target::abi::{FieldIdx, VariantIdx};
|
||||
use rustc_trait_selection::error_reporting::traits::suggestions::TypeErrCtxtExt as _;
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::{
|
||||
type_known_to_meet_bound_modulo_regions, FulfillmentErrorCode,
|
||||
|
|
@ -768,10 +768,11 @@ struct CapturedMessageOpt {
|
|||
is_loop_message: bool,
|
||||
is_move_msg: bool,
|
||||
is_loop_move: bool,
|
||||
has_suggest_reborrow: bool,
|
||||
maybe_reinitialized_locations_is_empty: bool,
|
||||
}
|
||||
|
||||
impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
||||
impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
||||
/// Finds the spans associated to a move or copy of move_place at location.
|
||||
pub(super) fn move_spans(
|
||||
&self,
|
||||
|
|
@ -997,7 +998,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
fn explain_captures(
|
||||
&mut self,
|
||||
err: &mut Diag<'_>,
|
||||
err: &mut Diag<'infcx>,
|
||||
span: Span,
|
||||
move_span: Span,
|
||||
move_spans: UseSpans<'tcx>,
|
||||
|
|
@ -1009,6 +1010,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
is_loop_message,
|
||||
is_move_msg,
|
||||
is_loop_move,
|
||||
has_suggest_reborrow,
|
||||
maybe_reinitialized_locations_is_empty,
|
||||
} = msg_opt;
|
||||
if let UseSpans::FnSelfUse { var_span, fn_call_span, fn_span, kind } = move_spans {
|
||||
|
|
@ -1182,18 +1184,15 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
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 !is_loop_move {
|
||||
err.span_suggestion_verbose(
|
||||
// Suggest `reborrow` in other place for following situations:
|
||||
// 1. If we are in a loop this will be suggested later.
|
||||
// 2. If the moved value is a mut reference, it is used in a
|
||||
// generic function and the corresponding arg's type is generic param.
|
||||
if !is_loop_move && !has_suggest_reborrow {
|
||||
self.suggest_reborrow(
|
||||
err,
|
||||
move_span.shrink_to_lo(),
|
||||
format!(
|
||||
"consider creating a fresh reborrow of {} here",
|
||||
self.describe_place(moved_place.as_ref())
|
||||
.map(|n| format!("`{n}`"))
|
||||
.unwrap_or_else(|| "the mutable reference".to_string()),
|
||||
),
|
||||
"&mut *",
|
||||
Applicability::MachineApplicable,
|
||||
moved_place.as_ref(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -554,6 +554,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
|||
is_loop_message: false,
|
||||
is_move_msg: false,
|
||||
is_loop_move: false,
|
||||
has_suggest_reborrow: false,
|
||||
maybe_reinitialized_locations_is_empty: true,
|
||||
};
|
||||
if let Some(use_spans) = use_spans {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use rustc_middle::{
|
|||
use rustc_span::symbol::{kw, Symbol};
|
||||
use rustc_span::{sym, BytePos, DesugaringKind, Span};
|
||||
use rustc_target::abi::FieldIdx;
|
||||
use rustc_trait_selection::error_reporting::traits::suggestions::TypeErrCtxtExt;
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,11 +10,6 @@ use rustc_hir::GenericBound::Trait;
|
|||
use rustc_hir::QPath::Resolved;
|
||||
use rustc_hir::WherePredicate::BoundPredicate;
|
||||
use rustc_hir::{PolyTraitRef, TyKind, WhereBoundPredicate};
|
||||
use rustc_infer::infer::error_reporting::nice_region_error::{
|
||||
self, find_anon_type, find_param_with_region, suggest_adding_lifetime_params,
|
||||
HirTraitObjectVisitor, NiceRegionError, TraitObjectVisitor,
|
||||
};
|
||||
use rustc_infer::infer::error_reporting::region::unexpected_hidden_region_diagnostic;
|
||||
use rustc_infer::infer::{NllRegionVariableOrigin, RelateParamBound};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::hir::place::PlaceBase;
|
||||
|
|
@ -25,6 +20,12 @@ use rustc_middle::ty::{self, RegionVid, Ty};
|
|||
use rustc_middle::ty::{Region, TyCtxt};
|
||||
use rustc_span::symbol::{kw, Ident};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::error_reporting::infer::nice_region_error::{
|
||||
self, find_anon_type, find_param_with_region, suggest_adding_lifetime_params,
|
||||
HirTraitObjectVisitor, NiceRegionError, TraitObjectVisitor,
|
||||
};
|
||||
use rustc_trait_selection::error_reporting::infer::region::unexpected_hidden_region_diagnostic;
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::{Obligation, ObligationCtxt};
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ use rustc_middle::ty::{GenericArgKind, GenericArgsRef};
|
|||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::symbol::{kw, sym, Symbol};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
|
||||
use crate::{universal_regions::DefiningTy, MirBorrowckCtxt};
|
||||
|
||||
|
|
@ -457,8 +458,11 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
) -> RegionNameHighlight {
|
||||
let mut highlight = RegionHighlightMode::default();
|
||||
highlight.highlighting_region_vid(self.infcx.tcx, needle_fr, counter);
|
||||
let type_name =
|
||||
self.infcx.extract_inference_diagnostics_data(ty.into(), Some(highlight)).name;
|
||||
let type_name = self
|
||||
.infcx
|
||||
.err_ctxt()
|
||||
.extract_inference_diagnostics_data(ty.into(), Some(highlight))
|
||||
.name;
|
||||
|
||||
debug!(
|
||||
"highlight_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}",
|
||||
|
|
@ -872,8 +876,11 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||
|
||||
let mut highlight = RegionHighlightMode::default();
|
||||
highlight.highlighting_region_vid(tcx, fr, *self.next_region_name.try_borrow().unwrap());
|
||||
let type_name =
|
||||
self.infcx.extract_inference_diagnostics_data(yield_ty.into(), Some(highlight)).name;
|
||||
let type_name = self
|
||||
.infcx
|
||||
.err_ctxt()
|
||||
.extract_inference_diagnostics_data(yield_ty.into(), Some(highlight))
|
||||
.name;
|
||||
|
||||
let yield_span = match tcx.hir_node(self.mir_hir_id()) {
|
||||
hir::Node::Expr(hir::Expr {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use rustc_middle::ty::visit::TypeVisitableExt;
|
|||
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_middle::ty::{GenericArgKind, GenericArgs};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt as _;
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
use rustc_trait_selection::traits::ObligationCtxt;
|
||||
|
||||
use crate::session_diagnostics::LifetimeMismatchOpaqueParam;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use rustc_middle::traits::query::OutlivesBound;
|
|||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::{self, RegionVid, Ty, TypeVisitableExt};
|
||||
use rustc_span::{ErrorGuaranteed, Span};
|
||||
use rustc_trait_selection::error_reporting::traits::TypeErrCtxtExt;
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
use rustc_trait_selection::solve::deeply_normalize;
|
||||
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
|
||||
use std::rc::Rc;
|
||||
|
|
|
|||
|
|
@ -309,14 +309,10 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> {
|
|||
}
|
||||
|
||||
impl<'bccx, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx> {
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
fn cx(&self) -> TyCtxt<'tcx> {
|
||||
self.type_checker.infcx.tcx
|
||||
}
|
||||
|
||||
fn tag(&self) -> &'static str {
|
||||
"nll::subtype"
|
||||
}
|
||||
|
||||
#[instrument(skip(self, info), level = "trace", ret)]
|
||||
fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
|
||||
&mut self,
|
||||
|
|
@ -370,7 +366,7 @@ impl<'bccx, 'tcx> TypeRelation<TyCtxt<'tcx>> for NllTypeRelating<'_, 'bccx, 'tcx
|
|||
// shouldn't ever fail. Instead, it unconditionally emits an
|
||||
// alias-relate goal.
|
||||
assert!(!self.type_checker.infcx.next_trait_solver());
|
||||
self.tcx().dcx().span_delayed_bug(
|
||||
self.cx().dcx().span_delayed_bug(
|
||||
self.span(),
|
||||
"failure to relate an opaque to itself should result in an error later on",
|
||||
);
|
||||
|
|
@ -540,7 +536,7 @@ impl<'bccx, 'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for NllTypeRelating
|
|||
&mut self,
|
||||
obligations: impl IntoIterator<Item: ty::Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>,
|
||||
) {
|
||||
let tcx = self.tcx();
|
||||
let tcx = self.cx();
|
||||
let param_env = self.param_env();
|
||||
self.register_goals(
|
||||
obligations.into_iter().map(|to_pred| Goal::new(tcx, param_env, to_pred)),
|
||||
|
|
@ -559,7 +555,7 @@ impl<'bccx, 'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for NllTypeRelating
|
|||
.into_iter()
|
||||
.map(|goal| {
|
||||
Obligation::new(
|
||||
self.tcx(),
|
||||
self.cx(),
|
||||
ObligationCause::dummy_with_span(self.span()),
|
||||
goal.param_env,
|
||||
goal.predicate,
|
||||
|
|
|
|||
|
|
@ -199,6 +199,10 @@ builtin_macros_format_use_positional = consider using a positional formatting ar
|
|||
|
||||
builtin_macros_global_asm_clobber_abi = `clobber_abi` cannot be used with `global_asm!`
|
||||
|
||||
builtin_macros_global_asm_unsupported_option = the `{$symbol}` option cannot be used with `global_asm!`
|
||||
.label = the `{$symbol}` option is not meaningful for global-scoped inline assembly
|
||||
.suggestion = remove this option
|
||||
|
||||
builtin_macros_invalid_crate_attribute = invalid crate attribute
|
||||
|
||||
builtin_macros_multiple_default_attrs = multiple `#[default]` attributes
|
||||
|
|
@ -216,6 +220,11 @@ builtin_macros_multiple_defaults = multiple declared defaults
|
|||
.note = only one variant can be default
|
||||
.suggestion = make `{$ident}` default
|
||||
|
||||
builtin_macros_naked_functions_testing_attribute =
|
||||
cannot use `#[naked]` with testing attributes
|
||||
.label = function marked with testing attribute here
|
||||
.naked_attribute = `#[naked]` is incompatible with testing attributes
|
||||
|
||||
builtin_macros_no_default_variant = no default declared
|
||||
.help = make a unit variant default by placing `#[default]` above it
|
||||
.suggestion = make `{$ident}` default
|
||||
|
|
|
|||
|
|
@ -310,6 +310,16 @@ fn err_duplicate_option(p: &Parser<'_>, symbol: Symbol, span: Span) {
|
|||
p.dcx().emit_err(errors::AsmOptAlreadyprovided { span, symbol, full_span });
|
||||
}
|
||||
|
||||
/// Report an invalid option error.
|
||||
///
|
||||
/// This function must be called immediately after the option token is parsed.
|
||||
/// Otherwise, the suggestion will be incorrect.
|
||||
fn err_unsupported_option(p: &Parser<'_>, symbol: Symbol, span: Span) {
|
||||
// Tool-only output
|
||||
let full_span = if p.token.kind == token::Comma { span.to(p.token.span) } else { span };
|
||||
p.dcx().emit_err(errors::GlobalAsmUnsupportedOption { span, symbol, full_span });
|
||||
}
|
||||
|
||||
/// Try to set the provided option in the provided `AsmArgs`.
|
||||
/// If it is already set, report a duplicate option error.
|
||||
///
|
||||
|
|
@ -318,13 +328,16 @@ fn err_duplicate_option(p: &Parser<'_>, symbol: Symbol, span: Span) {
|
|||
fn try_set_option<'a>(
|
||||
p: &Parser<'a>,
|
||||
args: &mut AsmArgs,
|
||||
is_global_asm: bool,
|
||||
symbol: Symbol,
|
||||
option: ast::InlineAsmOptions,
|
||||
) {
|
||||
if !args.options.contains(option) {
|
||||
args.options |= option;
|
||||
} else {
|
||||
if is_global_asm && !ast::InlineAsmOptions::GLOBAL_OPTIONS.contains(option) {
|
||||
err_unsupported_option(p, symbol, p.prev_token.span);
|
||||
} else if args.options.contains(option) {
|
||||
err_duplicate_option(p, symbol, p.prev_token.span);
|
||||
} else {
|
||||
args.options |= option;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -338,25 +351,33 @@ fn parse_options<'a>(
|
|||
p.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
|
||||
|
||||
while !p.eat(&token::CloseDelim(Delimiter::Parenthesis)) {
|
||||
if !is_global_asm && p.eat_keyword(sym::pure) {
|
||||
try_set_option(p, args, sym::pure, ast::InlineAsmOptions::PURE);
|
||||
} else if !is_global_asm && p.eat_keyword(sym::nomem) {
|
||||
try_set_option(p, args, sym::nomem, ast::InlineAsmOptions::NOMEM);
|
||||
} else if !is_global_asm && p.eat_keyword(sym::readonly) {
|
||||
try_set_option(p, args, sym::readonly, ast::InlineAsmOptions::READONLY);
|
||||
} else if !is_global_asm && p.eat_keyword(sym::preserves_flags) {
|
||||
try_set_option(p, args, sym::preserves_flags, ast::InlineAsmOptions::PRESERVES_FLAGS);
|
||||
} else if !is_global_asm && p.eat_keyword(sym::noreturn) {
|
||||
try_set_option(p, args, sym::noreturn, ast::InlineAsmOptions::NORETURN);
|
||||
} else if !is_global_asm && p.eat_keyword(sym::nostack) {
|
||||
try_set_option(p, args, sym::nostack, ast::InlineAsmOptions::NOSTACK);
|
||||
} else if !is_global_asm && p.eat_keyword(sym::may_unwind) {
|
||||
try_set_option(p, args, kw::Raw, ast::InlineAsmOptions::MAY_UNWIND);
|
||||
} else if p.eat_keyword(sym::att_syntax) {
|
||||
try_set_option(p, args, sym::att_syntax, ast::InlineAsmOptions::ATT_SYNTAX);
|
||||
} else if p.eat_keyword(kw::Raw) {
|
||||
try_set_option(p, args, kw::Raw, ast::InlineAsmOptions::RAW);
|
||||
} else {
|
||||
const OPTIONS: [(Symbol, ast::InlineAsmOptions); ast::InlineAsmOptions::COUNT] = [
|
||||
(sym::pure, ast::InlineAsmOptions::PURE),
|
||||
(sym::nomem, ast::InlineAsmOptions::NOMEM),
|
||||
(sym::readonly, ast::InlineAsmOptions::READONLY),
|
||||
(sym::preserves_flags, ast::InlineAsmOptions::PRESERVES_FLAGS),
|
||||
(sym::noreturn, ast::InlineAsmOptions::NORETURN),
|
||||
(sym::nostack, ast::InlineAsmOptions::NOSTACK),
|
||||
(sym::may_unwind, ast::InlineAsmOptions::MAY_UNWIND),
|
||||
(sym::att_syntax, ast::InlineAsmOptions::ATT_SYNTAX),
|
||||
(kw::Raw, ast::InlineAsmOptions::RAW),
|
||||
];
|
||||
|
||||
'blk: {
|
||||
for (symbol, option) in OPTIONS {
|
||||
let kw_matched =
|
||||
if !is_global_asm || ast::InlineAsmOptions::GLOBAL_OPTIONS.contains(option) {
|
||||
p.eat_keyword(symbol)
|
||||
} else {
|
||||
p.eat_keyword_noexpect(symbol)
|
||||
};
|
||||
|
||||
if kw_matched {
|
||||
try_set_option(p, args, is_global_asm, symbol, option);
|
||||
break 'blk;
|
||||
}
|
||||
}
|
||||
|
||||
return p.unexpected();
|
||||
}
|
||||
|
||||
|
|
@ -459,7 +480,7 @@ fn expand_preparsed_asm(
|
|||
|
||||
for (i, template_expr) in args.templates.into_iter().enumerate() {
|
||||
if i != 0 {
|
||||
template.push(ast::InlineAsmTemplatePiece::String("\n".to_string()));
|
||||
template.push(ast::InlineAsmTemplatePiece::String("\n".into()));
|
||||
}
|
||||
|
||||
let msg = "asm template must be a string literal";
|
||||
|
|
@ -527,7 +548,7 @@ fn expand_preparsed_asm(
|
|||
|
||||
// Don't treat raw asm as a format string.
|
||||
if args.options.contains(ast::InlineAsmOptions::RAW) {
|
||||
template.push(ast::InlineAsmTemplatePiece::String(template_str.to_string()));
|
||||
template.push(ast::InlineAsmTemplatePiece::String(template_str.to_string().into()));
|
||||
let template_num_lines = 1 + template_str.matches('\n').count();
|
||||
line_spans.extend(std::iter::repeat(template_sp).take(template_num_lines));
|
||||
continue;
|
||||
|
|
@ -577,7 +598,7 @@ fn expand_preparsed_asm(
|
|||
for piece in unverified_pieces {
|
||||
match piece {
|
||||
parse::Piece::String(s) => {
|
||||
template.push(ast::InlineAsmTemplatePiece::String(s.to_string()))
|
||||
template.push(ast::InlineAsmTemplatePiece::String(s.to_string().into()))
|
||||
}
|
||||
parse::Piece::NextArgument(arg) => {
|
||||
let span = arg_spans.next().unwrap_or(template_sp);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use core::ops::ControlFlow;
|
|||
use rustc_ast as ast;
|
||||
use rustc_ast::mut_visit::MutVisitor;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::visit::Visitor;
|
||||
use rustc_ast::visit::{AssocCtxt, Visitor};
|
||||
use rustc_ast::NodeId;
|
||||
use rustc_ast::{mut_visit, visit};
|
||||
use rustc_ast::{Attribute, HasAttrs, HasTokens};
|
||||
|
|
@ -53,11 +53,8 @@ fn flat_map_annotatable(
|
|||
) -> Option<Annotatable> {
|
||||
match annotatable {
|
||||
Annotatable::Item(item) => vis.flat_map_item(item).pop().map(Annotatable::Item),
|
||||
Annotatable::TraitItem(item) => {
|
||||
vis.flat_map_trait_item(item).pop().map(Annotatable::TraitItem)
|
||||
}
|
||||
Annotatable::ImplItem(item) => {
|
||||
vis.flat_map_impl_item(item).pop().map(Annotatable::ImplItem)
|
||||
Annotatable::AssocItem(item, ctxt) => {
|
||||
Some(Annotatable::AssocItem(vis.flat_map_assoc_item(item, ctxt).pop()?, ctxt))
|
||||
}
|
||||
Annotatable::ForeignItem(item) => {
|
||||
vis.flat_map_foreign_item(item).pop().map(Annotatable::ForeignItem)
|
||||
|
|
@ -106,8 +103,7 @@ fn has_cfg_or_cfg_attr(annotatable: &Annotatable) -> bool {
|
|||
|
||||
let res = match annotatable {
|
||||
Annotatable::Item(item) => CfgFinder.visit_item(item),
|
||||
Annotatable::TraitItem(item) => CfgFinder.visit_assoc_item(item, visit::AssocCtxt::Trait),
|
||||
Annotatable::ImplItem(item) => CfgFinder.visit_assoc_item(item, visit::AssocCtxt::Impl),
|
||||
Annotatable::AssocItem(item, ctxt) => CfgFinder.visit_assoc_item(item, *ctxt),
|
||||
Annotatable::ForeignItem(item) => CfgFinder.visit_foreign_item(item),
|
||||
Annotatable::Stmt(stmt) => CfgFinder.visit_stmt(stmt),
|
||||
Annotatable::Expr(expr) => CfgFinder.visit_expr(expr),
|
||||
|
|
@ -150,14 +146,16 @@ impl CfgEval<'_> {
|
|||
Annotatable::Item(_) => {
|
||||
|parser| Ok(Annotatable::Item(parser.parse_item(ForceCollect::Yes)?.unwrap()))
|
||||
}
|
||||
Annotatable::TraitItem(_) => |parser| {
|
||||
Ok(Annotatable::TraitItem(
|
||||
Annotatable::AssocItem(_, AssocCtxt::Trait) => |parser| {
|
||||
Ok(Annotatable::AssocItem(
|
||||
parser.parse_trait_item(ForceCollect::Yes)?.unwrap().unwrap(),
|
||||
AssocCtxt::Trait,
|
||||
))
|
||||
},
|
||||
Annotatable::ImplItem(_) => |parser| {
|
||||
Ok(Annotatable::ImplItem(
|
||||
Annotatable::AssocItem(_, AssocCtxt::Impl) => |parser| {
|
||||
Ok(Annotatable::AssocItem(
|
||||
parser.parse_impl_item(ForceCollect::Yes)?.unwrap().unwrap(),
|
||||
AssocCtxt::Impl,
|
||||
))
|
||||
},
|
||||
Annotatable::ForeignItem(_) => |parser| {
|
||||
|
|
@ -214,18 +212,18 @@ impl MutVisitor for CfgEval<'_> {
|
|||
#[instrument(level = "trace", skip(self))]
|
||||
fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
|
||||
self.0.configure_expr(expr, false);
|
||||
mut_visit::noop_visit_expr(expr, self);
|
||||
mut_visit::walk_expr(self, expr);
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
fn visit_method_receiver_expr(&mut self, expr: &mut P<ast::Expr>) {
|
||||
self.0.configure_expr(expr, true);
|
||||
mut_visit::noop_visit_expr(expr, self);
|
||||
mut_visit::walk_expr(self, expr);
|
||||
}
|
||||
|
||||
fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
|
||||
let mut expr = configure!(self, expr);
|
||||
mut_visit::noop_visit_expr(&mut expr, self);
|
||||
mut_visit::walk_expr(self, &mut expr);
|
||||
Some(expr)
|
||||
}
|
||||
|
||||
|
|
@ -233,53 +231,64 @@ impl MutVisitor for CfgEval<'_> {
|
|||
&mut self,
|
||||
param: ast::GenericParam,
|
||||
) -> SmallVec<[ast::GenericParam; 1]> {
|
||||
mut_visit::noop_flat_map_generic_param(configure!(self, param), self)
|
||||
let param = configure!(self, param);
|
||||
mut_visit::walk_flat_map_generic_param(self, param)
|
||||
}
|
||||
|
||||
fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
|
||||
mut_visit::noop_flat_map_stmt(configure!(self, stmt), self)
|
||||
let stmt = configure!(self, stmt);
|
||||
mut_visit::walk_flat_map_stmt(self, stmt)
|
||||
}
|
||||
|
||||
fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
|
||||
mut_visit::noop_flat_map_item(configure!(self, item), self)
|
||||
let item = configure!(self, item);
|
||||
mut_visit::walk_flat_map_item(self, item)
|
||||
}
|
||||
|
||||
fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
|
||||
mut_visit::noop_flat_map_item(configure!(self, item), self)
|
||||
}
|
||||
|
||||
fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
|
||||
mut_visit::noop_flat_map_item(configure!(self, item), self)
|
||||
fn flat_map_assoc_item(
|
||||
&mut self,
|
||||
item: P<ast::AssocItem>,
|
||||
_ctxt: AssocCtxt,
|
||||
) -> SmallVec<[P<ast::AssocItem>; 1]> {
|
||||
let item = configure!(self, item);
|
||||
mut_visit::walk_flat_map_item(self, item)
|
||||
}
|
||||
|
||||
fn flat_map_foreign_item(
|
||||
&mut self,
|
||||
foreign_item: P<ast::ForeignItem>,
|
||||
) -> SmallVec<[P<ast::ForeignItem>; 1]> {
|
||||
mut_visit::noop_flat_map_item(configure!(self, foreign_item), self)
|
||||
let foreign_item = configure!(self, foreign_item);
|
||||
mut_visit::walk_flat_map_item(self, foreign_item)
|
||||
}
|
||||
|
||||
fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
|
||||
mut_visit::noop_flat_map_arm(configure!(self, arm), self)
|
||||
let arm = configure!(self, arm);
|
||||
mut_visit::walk_flat_map_arm(self, arm)
|
||||
}
|
||||
|
||||
fn flat_map_expr_field(&mut self, field: ast::ExprField) -> SmallVec<[ast::ExprField; 1]> {
|
||||
mut_visit::noop_flat_map_expr_field(configure!(self, field), self)
|
||||
let field = configure!(self, field);
|
||||
mut_visit::walk_flat_map_expr_field(self, field)
|
||||
}
|
||||
|
||||
fn flat_map_pat_field(&mut self, fp: ast::PatField) -> SmallVec<[ast::PatField; 1]> {
|
||||
mut_visit::noop_flat_map_pat_field(configure!(self, fp), self)
|
||||
let fp = configure!(self, fp);
|
||||
mut_visit::walk_flat_map_pat_field(self, fp)
|
||||
}
|
||||
|
||||
fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
|
||||
mut_visit::noop_flat_map_param(configure!(self, p), self)
|
||||
let p = configure!(self, p);
|
||||
mut_visit::walk_flat_map_param(self, p)
|
||||
}
|
||||
|
||||
fn flat_map_field_def(&mut self, sf: ast::FieldDef) -> SmallVec<[ast::FieldDef; 1]> {
|
||||
mut_visit::noop_flat_map_field_def(configure!(self, sf), self)
|
||||
let sf = configure!(self, sf);
|
||||
mut_visit::walk_flat_map_field_def(self, sf)
|
||||
}
|
||||
|
||||
fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
|
||||
mut_visit::noop_flat_map_variant(configure!(self, variant), self)
|
||||
let variant = configure!(self, variant);
|
||||
mut_visit::walk_flat_map_variant(self, variant)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use crate::errors;
|
|||
use rustc_ast::attr::mk_attr;
|
||||
use rustc_ast::token;
|
||||
use rustc_ast::{self as ast, AttrItem, AttrStyle};
|
||||
use rustc_parse::parser::ForceCollect;
|
||||
use rustc_parse::{new_parser_from_source_str, unwrap_or_emit_fatal};
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::FileName;
|
||||
|
|
@ -17,13 +18,14 @@ pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) {
|
|||
));
|
||||
|
||||
let start_span = parser.token.span;
|
||||
let AttrItem { unsafety, path, args, tokens: _ } = match parser.parse_attr_item(false) {
|
||||
Ok(ai) => ai,
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let AttrItem { unsafety, path, args, tokens: _ } =
|
||||
match parser.parse_attr_item(ForceCollect::No) {
|
||||
Ok(ai) => ai,
|
||||
Err(err) => {
|
||||
err.emit();
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let end_span = parser.token.span;
|
||||
if parser.token != token::Eof {
|
||||
psess.dcx().emit_err(errors::InvalidCrateAttr { span: start_span.to(end_span) });
|
||||
|
|
|
|||
|
|
@ -38,7 +38,44 @@ pub(crate) fn expand_deriving_const_param_ty(
|
|||
) {
|
||||
let trait_def = TraitDef {
|
||||
span,
|
||||
path: path_std!(marker::ConstParamTy),
|
||||
path: path_std!(marker::ConstParamTy_),
|
||||
skip_path_as_bound: false,
|
||||
needs_copy_as_bound_if_packed: false,
|
||||
additional_bounds: vec![ty::Ty::Path(path_std!(cmp::Eq))],
|
||||
supports_unions: false,
|
||||
methods: Vec::new(),
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push);
|
||||
|
||||
let trait_def = TraitDef {
|
||||
span,
|
||||
path: path_std!(marker::UnsizedConstParamTy),
|
||||
skip_path_as_bound: false,
|
||||
needs_copy_as_bound_if_packed: false,
|
||||
additional_bounds: vec![ty::Ty::Path(path_std!(cmp::Eq))],
|
||||
supports_unions: false,
|
||||
methods: Vec::new(),
|
||||
associated_types: Vec::new(),
|
||||
is_const,
|
||||
};
|
||||
|
||||
trait_def.expand(cx, mitem, item, push);
|
||||
}
|
||||
|
||||
pub(crate) fn expand_deriving_unsized_const_param_ty(
|
||||
cx: &ExtCtxt<'_>,
|
||||
span: Span,
|
||||
mitem: &MetaItem,
|
||||
item: &Annotatable,
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
is_const: bool,
|
||||
) {
|
||||
let trait_def = TraitDef {
|
||||
span,
|
||||
path: path_std!(marker::UnsizedConstParamTy),
|
||||
skip_path_as_bound: false,
|
||||
needs_copy_as_bound_if_packed: false,
|
||||
additional_bounds: vec![ty::Ty::Path(path_std!(cmp::Eq))],
|
||||
|
|
|
|||
|
|
@ -845,6 +845,17 @@ pub(crate) struct AsmOptAlreadyprovided {
|
|||
pub(crate) full_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_global_asm_unsupported_option)]
|
||||
pub(crate) struct GlobalAsmUnsupportedOption {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub(crate) span: Span,
|
||||
pub(crate) symbol: Symbol,
|
||||
#[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")]
|
||||
pub(crate) full_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_test_runner_invalid)]
|
||||
pub(crate) struct TestRunnerInvalid {
|
||||
|
|
@ -912,3 +923,13 @@ pub(crate) struct ExpectedItem<'a> {
|
|||
pub span: Span,
|
||||
pub token: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_naked_functions_testing_attribute, code = E0736)]
|
||||
pub struct NakedFunctionTestingAttribute {
|
||||
#[primary_span]
|
||||
#[label(builtin_macros_naked_attribute)]
|
||||
pub naked_span: Span,
|
||||
#[label]
|
||||
pub testing_span: Span,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
|
|||
Clone: clone::expand_deriving_clone,
|
||||
Copy: bounds::expand_deriving_copy,
|
||||
ConstParamTy: bounds::expand_deriving_const_param_ty,
|
||||
UnsizedConstParamTy: bounds::expand_deriving_unsized_const_param_ty,
|
||||
Debug: debug::expand_deriving_debug,
|
||||
Default: default::expand_deriving_default,
|
||||
Eq: eq::expand_deriving_eq,
|
||||
|
|
|
|||
|
|
@ -133,6 +133,14 @@ pub(crate) fn expand_test_or_bench(
|
|||
};
|
||||
};
|
||||
|
||||
if let Some(attr) = attr::find_by_name(&item.attrs, sym::naked) {
|
||||
cx.dcx().emit_err(errors::NakedFunctionTestingAttribute {
|
||||
testing_span: attr_sp,
|
||||
naked_span: attr.span,
|
||||
});
|
||||
return vec![Annotatable::Item(item)];
|
||||
}
|
||||
|
||||
// check_*_signature will report any errors in the type so compilation
|
||||
// will fail. We shouldn't try to expand in this case because the errors
|
||||
// would be spurious.
|
||||
|
|
|
|||
|
|
@ -122,15 +122,15 @@ impl TestHarnessGenerator<'_> {
|
|||
impl<'a> MutVisitor for TestHarnessGenerator<'a> {
|
||||
fn visit_crate(&mut self, c: &mut ast::Crate) {
|
||||
let prev_tests = mem::take(&mut self.tests);
|
||||
noop_visit_crate(c, self);
|
||||
walk_crate(self, c);
|
||||
self.add_test_cases(ast::CRATE_NODE_ID, c.spans.inner_span, prev_tests);
|
||||
|
||||
// Create a main function to run our tests
|
||||
c.items.push(mk_main(&mut self.cx));
|
||||
}
|
||||
|
||||
fn flat_map_item(&mut self, i: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
|
||||
let mut item = i.into_inner();
|
||||
fn flat_map_item(&mut self, mut i: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
|
||||
let item = &mut *i;
|
||||
if let Some(name) = get_test_name(&item) {
|
||||
debug!("this is a test item");
|
||||
|
||||
|
|
@ -144,13 +144,13 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
|
|||
item.kind
|
||||
{
|
||||
let prev_tests = mem::take(&mut self.tests);
|
||||
noop_visit_item_kind(&mut item.kind, self);
|
||||
walk_item_kind(&mut item.kind, item.span, item.id, self);
|
||||
self.add_test_cases(item.id, span, prev_tests);
|
||||
} else {
|
||||
// But in those cases, we emit a lint to warn the user of these missing tests.
|
||||
walk_item(&mut InnerItemLinter { sess: self.cx.ext_cx.sess }, &item);
|
||||
}
|
||||
smallvec![P(item)]
|
||||
smallvec![i]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -192,7 +192,7 @@ struct EntryPointCleaner<'a> {
|
|||
impl<'a> MutVisitor for EntryPointCleaner<'a> {
|
||||
fn flat_map_item(&mut self, i: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
|
||||
self.depth += 1;
|
||||
let item = noop_flat_map_item(i, self).expect_one("noop did something");
|
||||
let item = walk_flat_map_item(self, i).expect_one("noop did something");
|
||||
self.depth -= 1;
|
||||
|
||||
// Remove any #[rustc_main] or #[start] from the AST so it doesn't
|
||||
|
|
|
|||
|
|
@ -27,8 +27,7 @@ pub(crate) fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaI
|
|||
pub(crate) fn warn_on_duplicate_attribute(ecx: &ExtCtxt<'_>, item: &Annotatable, name: Symbol) {
|
||||
let attrs: Option<&[Attribute]> = match item {
|
||||
Annotatable::Item(item) => Some(&item.attrs),
|
||||
Annotatable::TraitItem(item) => Some(&item.attrs),
|
||||
Annotatable::ImplItem(item) => Some(&item.attrs),
|
||||
Annotatable::AssocItem(item, _) => Some(&item.attrs),
|
||||
Annotatable::ForeignItem(item) => Some(&item.attrs),
|
||||
Annotatable::Expr(expr) => Some(&expr.attrs),
|
||||
Annotatable::Arm(arm) => Some(&arm.attrs),
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ For more docs on how to build and test see [build_system/usage.txt](build_system
|
|||
|FreeBSD|✅[^no-rustup]|❓|❓|❓|
|
||||
|AIX|❌[^xcoff]|N/A|N/A|❌[^xcoff]|
|
||||
|Other unixes|❓|❓|❓|❓|
|
||||
|macOS|✅|✅[^no-rustup]|N/A|N/A|
|
||||
|macOS|✅|✅|N/A|N/A|
|
||||
|Windows|✅[^no-rustup]|❌|N/A|N/A|
|
||||
|
||||
✅: Fully supported and tested
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
coroutines,
|
||||
stmt_expr_attributes,
|
||||
coroutine_trait,
|
||||
is_sorted,
|
||||
repr_simd,
|
||||
tuple_trait,
|
||||
unboxed_closures
|
||||
|
|
|
|||
|
|
@ -10,12 +10,12 @@ use std::mem;
|
|||
use cranelift_codegen::ir::{ArgumentPurpose, SigRef};
|
||||
use cranelift_codegen::isa::CallConv;
|
||||
use cranelift_module::ModuleError;
|
||||
use rustc_codegen_ssa::base::is_call_from_compiler_builtins_to_upstream_monomorphization;
|
||||
use rustc_codegen_ssa::errors::CompilerBuiltinsCannotCall;
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use rustc_middle::ty::layout::FnAbiOf;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::TypeVisitableExt;
|
||||
use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphization;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_target::abi::call::{Conv, FnAbi, PassMode};
|
||||
|
|
@ -505,7 +505,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
|||
let nop_inst = fx.bcx.ins().nop();
|
||||
fx.add_comment(
|
||||
nop_inst,
|
||||
format!("virtual call; self arg pass mode: {:?}", &fn_abi.args[0]),
|
||||
format!("virtual call; self arg pass mode: {:?}", fn_abi.args[0]),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
use rustc_codegen_ssa::back::archive::{
|
||||
get_native_object_symbols, ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder,
|
||||
ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER,
|
||||
};
|
||||
use rustc_session::Session;
|
||||
|
||||
|
|
@ -9,7 +9,7 @@ pub(crate) struct ArArchiveBuilderBuilder;
|
|||
|
||||
impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
|
||||
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a> {
|
||||
Box::new(ArArchiveBuilder::new(sess, get_native_object_symbols))
|
||||
Box::new(ArArchiveBuilder::new(sess, &DEFAULT_OBJECT_READER))
|
||||
}
|
||||
|
||||
fn create_dll_import_lib(
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@ use cranelift_codegen::CodegenError;
|
|||
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
|
||||
use cranelift_module::ModuleError;
|
||||
use rustc_ast::InlineAsmOptions;
|
||||
use rustc_codegen_ssa::base::is_call_from_compiler_builtins_to_upstream_monomorphization;
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use rustc_middle::ty::adjustment::PointerCoercion;
|
||||
use rustc_middle::ty::layout::FnAbiOf;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::TypeVisitableExt;
|
||||
use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphization;
|
||||
|
||||
use crate::constant::ConstantCx;
|
||||
use crate::debuginfo::{FunctionDebugContext, TypeDebugContext};
|
||||
|
|
|
|||
|
|
@ -46,9 +46,7 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>(
|
|||
// Used by panic_abort on Windows, but uses a syntax which only happens to work with
|
||||
// asm!() by accident and breaks with the GNU assembler as well as global_asm!() for
|
||||
// the LLVM backend.
|
||||
if template.len() == 1
|
||||
&& template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string())
|
||||
{
|
||||
if template.len() == 1 && template[0] == InlineAsmTemplatePiece::String("int $$0x29".into()) {
|
||||
fx.bcx.ins().trap(TrapCode::User(1));
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
|
|||
shl rdx, 32
|
||||
or rax, rdx
|
||||
"
|
||||
.to_string(),
|
||||
.into(),
|
||||
)],
|
||||
&[
|
||||
CInlineAsmOperand::In {
|
||||
|
|
@ -471,7 +471,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
|
|||
// into 0x80000000 for which Cranelift doesn't have a native instruction.
|
||||
codegen_inline_asm_inner(
|
||||
fx,
|
||||
&[InlineAsmTemplatePiece::String(format!("cvtps2dq xmm0, xmm0"))],
|
||||
&[InlineAsmTemplatePiece::String("cvtps2dq xmm0, xmm0".into())],
|
||||
&[CInlineAsmOperand::InOut {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)),
|
||||
_late: true,
|
||||
|
|
@ -875,7 +875,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
|
|||
|
||||
codegen_inline_asm_inner(
|
||||
fx,
|
||||
&[InlineAsmTemplatePiece::String(asm.to_string())],
|
||||
&[InlineAsmTemplatePiece::String(asm.into())],
|
||||
&[
|
||||
CInlineAsmOperand::InOut {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)),
|
||||
|
|
@ -914,7 +914,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
|
|||
|
||||
codegen_inline_asm_inner(
|
||||
fx,
|
||||
&[InlineAsmTemplatePiece::String(format!("pcmpestri xmm0, xmm1, {imm8}"))],
|
||||
&[InlineAsmTemplatePiece::String(format!("pcmpestri xmm0, xmm1, {imm8}").into())],
|
||||
&[
|
||||
CInlineAsmOperand::In {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)),
|
||||
|
|
@ -967,7 +967,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
|
|||
|
||||
codegen_inline_asm_inner(
|
||||
fx,
|
||||
&[InlineAsmTemplatePiece::String(format!("pcmpestrm xmm0, xmm1, {imm8}"))],
|
||||
&[InlineAsmTemplatePiece::String(format!("pcmpestrm xmm0, xmm1, {imm8}").into())],
|
||||
&[
|
||||
CInlineAsmOperand::InOut {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)),
|
||||
|
|
@ -1015,7 +1015,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
|
|||
|
||||
codegen_inline_asm_inner(
|
||||
fx,
|
||||
&[InlineAsmTemplatePiece::String(format!("pclmulqdq xmm0, xmm1, {imm8}"))],
|
||||
&[InlineAsmTemplatePiece::String(format!("pclmulqdq xmm0, xmm1, {imm8}").into())],
|
||||
&[
|
||||
CInlineAsmOperand::InOut {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)),
|
||||
|
|
@ -1052,7 +1052,9 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
|
|||
|
||||
codegen_inline_asm_inner(
|
||||
fx,
|
||||
&[InlineAsmTemplatePiece::String(format!("aeskeygenassist xmm0, xmm0, {imm8}"))],
|
||||
&[InlineAsmTemplatePiece::String(
|
||||
format!("aeskeygenassist xmm0, xmm0, {imm8}").into(),
|
||||
)],
|
||||
&[CInlineAsmOperand::InOut {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)),
|
||||
_late: true,
|
||||
|
|
@ -1071,7 +1073,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
|
|||
|
||||
codegen_inline_asm_inner(
|
||||
fx,
|
||||
&[InlineAsmTemplatePiece::String("aesimc xmm0, xmm0".to_string())],
|
||||
&[InlineAsmTemplatePiece::String("aesimc xmm0, xmm0".into())],
|
||||
&[CInlineAsmOperand::InOut {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)),
|
||||
_late: true,
|
||||
|
|
@ -1091,7 +1093,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
|
|||
|
||||
codegen_inline_asm_inner(
|
||||
fx,
|
||||
&[InlineAsmTemplatePiece::String("aesenc xmm0, xmm1".to_string())],
|
||||
&[InlineAsmTemplatePiece::String("aesenc xmm0, xmm1".into())],
|
||||
&[
|
||||
CInlineAsmOperand::InOut {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)),
|
||||
|
|
@ -1117,7 +1119,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
|
|||
|
||||
codegen_inline_asm_inner(
|
||||
fx,
|
||||
&[InlineAsmTemplatePiece::String("aesenclast xmm0, xmm1".to_string())],
|
||||
&[InlineAsmTemplatePiece::String("aesenclast xmm0, xmm1".into())],
|
||||
&[
|
||||
CInlineAsmOperand::InOut {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)),
|
||||
|
|
@ -1143,7 +1145,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
|
|||
|
||||
codegen_inline_asm_inner(
|
||||
fx,
|
||||
&[InlineAsmTemplatePiece::String("aesdec xmm0, xmm1".to_string())],
|
||||
&[InlineAsmTemplatePiece::String("aesdec xmm0, xmm1".into())],
|
||||
&[
|
||||
CInlineAsmOperand::InOut {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)),
|
||||
|
|
@ -1169,7 +1171,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
|
|||
|
||||
codegen_inline_asm_inner(
|
||||
fx,
|
||||
&[InlineAsmTemplatePiece::String("aesdeclast xmm0, xmm1".to_string())],
|
||||
&[InlineAsmTemplatePiece::String("aesdeclast xmm0, xmm1".into())],
|
||||
&[
|
||||
CInlineAsmOperand::InOut {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm0)),
|
||||
|
|
@ -1207,7 +1209,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
|
|||
|
||||
codegen_inline_asm_inner(
|
||||
fx,
|
||||
&[InlineAsmTemplatePiece::String(format!("sha1rnds4 xmm1, xmm2, {func}"))],
|
||||
&[InlineAsmTemplatePiece::String(format!("sha1rnds4 xmm1, xmm2, {func}").into())],
|
||||
&[
|
||||
CInlineAsmOperand::InOut {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)),
|
||||
|
|
@ -1233,7 +1235,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
|
|||
|
||||
codegen_inline_asm_inner(
|
||||
fx,
|
||||
&[InlineAsmTemplatePiece::String("sha1msg1 xmm1, xmm2".to_string())],
|
||||
&[InlineAsmTemplatePiece::String("sha1msg1 xmm1, xmm2".into())],
|
||||
&[
|
||||
CInlineAsmOperand::InOut {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)),
|
||||
|
|
@ -1259,7 +1261,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
|
|||
|
||||
codegen_inline_asm_inner(
|
||||
fx,
|
||||
&[InlineAsmTemplatePiece::String("sha1msg2 xmm1, xmm2".to_string())],
|
||||
&[InlineAsmTemplatePiece::String("sha1msg2 xmm1, xmm2".into())],
|
||||
&[
|
||||
CInlineAsmOperand::InOut {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)),
|
||||
|
|
@ -1285,7 +1287,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
|
|||
|
||||
codegen_inline_asm_inner(
|
||||
fx,
|
||||
&[InlineAsmTemplatePiece::String("sha1nexte xmm1, xmm2".to_string())],
|
||||
&[InlineAsmTemplatePiece::String("sha1nexte xmm1, xmm2".into())],
|
||||
&[
|
||||
CInlineAsmOperand::InOut {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)),
|
||||
|
|
@ -1312,7 +1314,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
|
|||
|
||||
codegen_inline_asm_inner(
|
||||
fx,
|
||||
&[InlineAsmTemplatePiece::String("sha256rnds2 xmm1, xmm2".to_string())],
|
||||
&[InlineAsmTemplatePiece::String("sha256rnds2 xmm1, xmm2".into())],
|
||||
&[
|
||||
CInlineAsmOperand::InOut {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)),
|
||||
|
|
@ -1343,7 +1345,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
|
|||
|
||||
codegen_inline_asm_inner(
|
||||
fx,
|
||||
&[InlineAsmTemplatePiece::String("sha256msg1 xmm1, xmm2".to_string())],
|
||||
&[InlineAsmTemplatePiece::String("sha256msg1 xmm1, xmm2".into())],
|
||||
&[
|
||||
CInlineAsmOperand::InOut {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)),
|
||||
|
|
@ -1369,7 +1371,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
|
|||
|
||||
codegen_inline_asm_inner(
|
||||
fx,
|
||||
&[InlineAsmTemplatePiece::String("sha256msg2 xmm1, xmm2".to_string())],
|
||||
&[InlineAsmTemplatePiece::String("sha256msg2 xmm1, xmm2".into())],
|
||||
&[
|
||||
CInlineAsmOperand::InOut {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::xmm1)),
|
||||
|
|
@ -1435,7 +1437,7 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
|
|||
let edx_place = res_place.place_field(fx, FieldIdx::new(1));
|
||||
codegen_inline_asm_inner(
|
||||
fx,
|
||||
&[InlineAsmTemplatePiece::String("rdtsc".to_string())],
|
||||
&[InlineAsmTemplatePiece::String("rdtsc".into())],
|
||||
&[
|
||||
CInlineAsmOperand::Out {
|
||||
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)),
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ extern crate rustc_hir;
|
|||
extern crate rustc_incremental;
|
||||
extern crate rustc_index;
|
||||
extern crate rustc_metadata;
|
||||
extern crate rustc_monomorphize;
|
||||
extern crate rustc_session;
|
||||
extern crate rustc_span;
|
||||
extern crate rustc_target;
|
||||
|
|
|
|||
|
|
@ -1 +1,3 @@
|
|||
version = "Two"
|
||||
use_small_heuristics = "Max"
|
||||
merge_derives = false
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ impl Args {
|
|||
"--out-path" => match args.next() {
|
||||
Some(path) if !path.is_empty() => out_path = Some(path),
|
||||
_ => {
|
||||
return Err("Expected an argument after `--out-path`, found nothing".into())
|
||||
return Err("Expected an argument after `--out-path`, found nothing".into());
|
||||
}
|
||||
},
|
||||
"--help" => {
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ impl ConfigFile {
|
|||
config.gcc_path = Some(value.as_str().to_string())
|
||||
}
|
||||
("gcc-path", _) => {
|
||||
return failed_config_parsing(config_file, "Expected a string for `gcc-path`")
|
||||
return failed_config_parsing(config_file, "Expected a string for `gcc-path`");
|
||||
}
|
||||
("download-gccjit", TomlValue::Boolean(value)) => {
|
||||
config.download_gccjit = Some(*value)
|
||||
|
|
@ -63,7 +63,7 @@ impl ConfigFile {
|
|||
return failed_config_parsing(
|
||||
config_file,
|
||||
"Expected a boolean for `download-gccjit`",
|
||||
)
|
||||
);
|
||||
}
|
||||
_ => return failed_config_parsing(config_file, &format!("Unknown key `{}`", key)),
|
||||
}
|
||||
|
|
@ -73,7 +73,7 @@ impl ConfigFile {
|
|||
return failed_config_parsing(
|
||||
config_file,
|
||||
"At least one of `gcc-path` or `download-gccjit` value must be set",
|
||||
)
|
||||
);
|
||||
}
|
||||
(Some(_), Some(true)) => {
|
||||
println!(
|
||||
|
|
@ -144,7 +144,7 @@ impl ConfigInfo {
|
|||
_ => {
|
||||
return Err(
|
||||
"Expected a value after `--target-triple`, found nothing".to_string()
|
||||
)
|
||||
);
|
||||
}
|
||||
},
|
||||
"--out-dir" => match args.next() {
|
||||
|
|
@ -158,7 +158,7 @@ impl ConfigInfo {
|
|||
self.config_file = Some(arg.to_string());
|
||||
}
|
||||
_ => {
|
||||
return Err("Expected a value after `--config-file`, found nothing".to_string())
|
||||
return Err("Expected a value after `--config-file`, found nothing".to_string());
|
||||
}
|
||||
},
|
||||
"--release-sysroot" => self.sysroot_release_channel = true,
|
||||
|
|
@ -169,7 +169,7 @@ impl ConfigInfo {
|
|||
self.cg_gcc_path = Some(arg.into());
|
||||
}
|
||||
_ => {
|
||||
return Err("Expected a value after `--cg_gcc-path`, found nothing".to_string())
|
||||
return Err("Expected a value after `--cg_gcc-path`, found nothing".to_string());
|
||||
}
|
||||
},
|
||||
"--use-backend" => match args.next() {
|
||||
|
|
@ -277,7 +277,7 @@ impl ConfigInfo {
|
|||
self.gcc_path = match gcc_path {
|
||||
Some(path) => path,
|
||||
None => {
|
||||
return Err(format!("missing `gcc-path` value from `{}`", config_file.display(),))
|
||||
return Err(format!("missing `gcc-path` value from `{}`", config_file.display(),));
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ impl TestArg {
|
|||
test_arg.flags.extend_from_slice(&["--features".into(), feature]);
|
||||
}
|
||||
_ => {
|
||||
return Err("Expected an argument after `--features`, found nothing".into())
|
||||
return Err("Expected an argument after `--features`, found nothing".into());
|
||||
}
|
||||
},
|
||||
"--use-system-gcc" => {
|
||||
|
|
@ -458,11 +458,7 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<PathBuf, String> {
|
|||
.map_err(|error| format!("Failed to retrieve cargo path: {:?}", error))
|
||||
.and_then(|cargo| {
|
||||
let cargo = cargo.trim().to_owned();
|
||||
if cargo.is_empty() {
|
||||
Err(format!("`cargo` path is empty"))
|
||||
} else {
|
||||
Ok(cargo)
|
||||
}
|
||||
if cargo.is_empty() { Err(format!("`cargo` path is empty")) } else { Ok(cargo) }
|
||||
})?;
|
||||
let rustc = String::from_utf8(
|
||||
run_command_with_env(&[&"rustup", &toolchain, &"which", &"rustc"], rust_dir, Some(env))?
|
||||
|
|
@ -471,11 +467,7 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<PathBuf, String> {
|
|||
.map_err(|error| format!("Failed to retrieve rustc path: {:?}", error))
|
||||
.and_then(|rustc| {
|
||||
let rustc = rustc.trim().to_owned();
|
||||
if rustc.is_empty() {
|
||||
Err(format!("`rustc` path is empty"))
|
||||
} else {
|
||||
Ok(rustc)
|
||||
}
|
||||
if rustc.is_empty() { Err(format!("`rustc` path is empty")) } else { Ok(rustc) }
|
||||
})?;
|
||||
let llvm_filecheck = match run_command_with_env(
|
||||
&[
|
||||
|
|
|
|||
|
|
@ -175,11 +175,7 @@ pub fn cargo_install(to_install: &str) -> Result<(), String> {
|
|||
pub fn get_os_name() -> Result<String, String> {
|
||||
let output = run_command(&[&"uname"], None)?;
|
||||
let name = std::str::from_utf8(&output.stdout).unwrap_or("").trim().to_string();
|
||||
if !name.is_empty() {
|
||||
Ok(name)
|
||||
} else {
|
||||
Err("Failed to retrieve the OS name".to_string())
|
||||
}
|
||||
if !name.is_empty() { Ok(name) } else { Err("Failed to retrieve the OS name".to_string()) }
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq)]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#![allow(internal_features)]
|
||||
#![feature(core_intrinsics, coroutines, coroutine_trait, is_sorted, stmt_expr_attributes)]
|
||||
#![feature(core_intrinsics, coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
|
|
|
|||
|
|
@ -26,11 +26,7 @@ impl<'a, 'gcc, 'tcx> AbiBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
} else {
|
||||
false
|
||||
};
|
||||
if on_stack {
|
||||
param.to_lvalue().get_address(None)
|
||||
} else {
|
||||
param.to_rvalue()
|
||||
}
|
||||
if on_stack { param.to_lvalue().get_address(None) } else { param.to_rvalue() }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
use rustc_codegen_ssa::back::archive::{
|
||||
get_native_object_symbols, ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder,
|
||||
ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER,
|
||||
};
|
||||
use rustc_session::Session;
|
||||
|
||||
|
|
@ -11,7 +11,7 @@ pub(crate) struct ArArchiveBuilderBuilder;
|
|||
|
||||
impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
|
||||
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a> {
|
||||
Box::new(ArArchiveBuilder::new(sess, get_native_object_symbols))
|
||||
Box::new(ArArchiveBuilder::new(sess, &DEFAULT_OBJECT_READER))
|
||||
}
|
||||
|
||||
fn create_dll_import_lib(
|
||||
|
|
|
|||
|
|
@ -858,11 +858,7 @@ fn modifier_to_gcc(
|
|||
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => modifier,
|
||||
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg)
|
||||
| InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => {
|
||||
if modifier == Some('v') {
|
||||
None
|
||||
} else {
|
||||
modifier
|
||||
}
|
||||
if modifier == Some('v') { None } else { modifier }
|
||||
}
|
||||
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
|
||||
unreachable!("clobber-only")
|
||||
|
|
|
|||
|
|
@ -1043,11 +1043,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
let llty = place.layout.scalar_pair_element_gcc_type(self, i);
|
||||
let load = self.load(llty, llptr, align);
|
||||
scalar_load_metadata(self, load, scalar);
|
||||
if scalar.is_bool() {
|
||||
self.trunc(load, self.type_i1())
|
||||
} else {
|
||||
load
|
||||
}
|
||||
if scalar.is_bool() { self.trunc(load, self.type_i1()) } else { load }
|
||||
};
|
||||
|
||||
OperandValue::Pair(
|
||||
|
|
@ -1795,18 +1791,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
|||
// This already happens today with u128::MAX = 2^128 - 1 > f32::MAX.
|
||||
let int_max = |signed: bool, int_width: u64| -> u128 {
|
||||
let shift_amount = 128 - int_width;
|
||||
if signed {
|
||||
i128::MAX as u128 >> shift_amount
|
||||
} else {
|
||||
u128::MAX >> shift_amount
|
||||
}
|
||||
if signed { i128::MAX as u128 >> shift_amount } else { u128::MAX >> shift_amount }
|
||||
};
|
||||
let int_min = |signed: bool, int_width: u64| -> i128 {
|
||||
if signed {
|
||||
i128::MIN >> (128 - int_width)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
if signed { i128::MIN >> (128 - int_width) } else { 0 }
|
||||
};
|
||||
|
||||
let compute_clamp_bounds_single = |signed: bool, int_width: u64| -> (u128, u128) {
|
||||
|
|
|
|||
|
|
@ -58,11 +58,7 @@ pub fn type_is_pointer(typ: Type<'_>) -> bool {
|
|||
|
||||
impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
fn const_null(&self, typ: Type<'gcc>) -> RValue<'gcc> {
|
||||
if type_is_pointer(typ) {
|
||||
self.context.new_null(typ)
|
||||
} else {
|
||||
self.const_int(typ, 0)
|
||||
}
|
||||
if type_is_pointer(typ) { self.context.new_null(typ) } else { self.const_int(typ, 0) }
|
||||
}
|
||||
|
||||
fn const_undef(&self, typ: Type<'gcc>) -> RValue<'gcc> {
|
||||
|
|
|
|||
|
|
@ -21,14 +21,16 @@ pub(crate) unsafe fn codegen(
|
|||
) {
|
||||
let llcx = &*module_llvm.llcx;
|
||||
let llmod = module_llvm.llmod();
|
||||
let usize = match tcx.sess.target.pointer_width {
|
||||
16 => llvm::LLVMInt16TypeInContext(llcx),
|
||||
32 => llvm::LLVMInt32TypeInContext(llcx),
|
||||
64 => llvm::LLVMInt64TypeInContext(llcx),
|
||||
tws => bug!("Unsupported target word size for int: {}", tws),
|
||||
let usize = unsafe {
|
||||
match tcx.sess.target.pointer_width {
|
||||
16 => llvm::LLVMInt16TypeInContext(llcx),
|
||||
32 => llvm::LLVMInt32TypeInContext(llcx),
|
||||
64 => llvm::LLVMInt64TypeInContext(llcx),
|
||||
tws => bug!("Unsupported target word size for int: {}", tws),
|
||||
}
|
||||
};
|
||||
let i8 = llvm::LLVMInt8TypeInContext(llcx);
|
||||
let i8p = llvm::LLVMPointerTypeInContext(llcx, 0);
|
||||
let i8 = unsafe { llvm::LLVMInt8TypeInContext(llcx) };
|
||||
let i8p = unsafe { llvm::LLVMPointerTypeInContext(llcx, 0) };
|
||||
|
||||
if kind == AllocatorKind::Default {
|
||||
for method in ALLOCATOR_METHODS {
|
||||
|
|
@ -73,23 +75,25 @@ pub(crate) unsafe fn codegen(
|
|||
true,
|
||||
);
|
||||
|
||||
// __rust_alloc_error_handler_should_panic
|
||||
let name = OomStrategy::SYMBOL;
|
||||
let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8);
|
||||
if tcx.sess.default_hidden_visibility() {
|
||||
llvm::LLVMRustSetVisibility(ll_g, llvm::Visibility::Hidden);
|
||||
}
|
||||
let val = tcx.sess.opts.unstable_opts.oom.should_panic();
|
||||
let llval = llvm::LLVMConstInt(i8, val as u64, False);
|
||||
llvm::LLVMSetInitializer(ll_g, llval);
|
||||
unsafe {
|
||||
// __rust_alloc_error_handler_should_panic
|
||||
let name = OomStrategy::SYMBOL;
|
||||
let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8);
|
||||
if tcx.sess.default_hidden_visibility() {
|
||||
llvm::LLVMRustSetVisibility(ll_g, llvm::Visibility::Hidden);
|
||||
}
|
||||
let val = tcx.sess.opts.unstable_opts.oom.should_panic();
|
||||
let llval = llvm::LLVMConstInt(i8, val as u64, False);
|
||||
llvm::LLVMSetInitializer(ll_g, llval);
|
||||
|
||||
let name = NO_ALLOC_SHIM_IS_UNSTABLE;
|
||||
let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8);
|
||||
if tcx.sess.default_hidden_visibility() {
|
||||
llvm::LLVMRustSetVisibility(ll_g, llvm::Visibility::Hidden);
|
||||
let name = NO_ALLOC_SHIM_IS_UNSTABLE;
|
||||
let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8);
|
||||
if tcx.sess.default_hidden_visibility() {
|
||||
llvm::LLVMRustSetVisibility(ll_g, llvm::Visibility::Hidden);
|
||||
}
|
||||
let llval = llvm::LLVMConstInt(i8, 0, False);
|
||||
llvm::LLVMSetInitializer(ll_g, llval);
|
||||
}
|
||||
let llval = llvm::LLVMConstInt(i8, 0, False);
|
||||
llvm::LLVMSetInitializer(ll_g, llval);
|
||||
|
||||
if tcx.sess.opts.debuginfo != DebugInfo::None {
|
||||
let dbg_cx = debuginfo::CodegenUnitDebugContext::new(llmod);
|
||||
|
|
|
|||
|
|
@ -271,6 +271,17 @@ fn stackprotector_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
|
|||
Some(sspattr.create_attr(cx.llcx))
|
||||
}
|
||||
|
||||
fn backchain_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
|
||||
if cx.sess().target.arch != "s390x" {
|
||||
return None;
|
||||
}
|
||||
|
||||
let requested_features = cx.sess().opts.cg.target_feature.split(',');
|
||||
let found_positive = requested_features.clone().any(|r| r == "+backchain");
|
||||
|
||||
if found_positive { Some(llvm::CreateAttrString(cx.llcx, "backchain")) } else { None }
|
||||
}
|
||||
|
||||
pub fn target_cpu_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll Attribute {
|
||||
let target_cpu = llvm_util::target_cpu(cx.tcx.sess);
|
||||
llvm::CreateAttrStringValue(cx.llcx, "target-cpu", target_cpu)
|
||||
|
|
@ -447,6 +458,9 @@ pub fn from_fn_attrs<'ll, 'tcx>(
|
|||
if let Some(align) = codegen_fn_attrs.alignment {
|
||||
llvm::set_alignment(llfn, align);
|
||||
}
|
||||
if let Some(backchain) = backchain_attr(cx) {
|
||||
to_add.push(backchain);
|
||||
}
|
||||
to_add.extend(sanitize_attrs(cx, codegen_fn_attrs.no_sanitize));
|
||||
to_add.extend(patchable_function_entry_attrs(cx, codegen_fn_attrs.patchable_function_entry));
|
||||
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ use crate::errors::{
|
|||
use crate::llvm::archive_ro::{ArchiveRO, Child};
|
||||
use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
|
||||
use rustc_codegen_ssa::back::archive::{
|
||||
get_native_object_symbols, try_extract_macho_fat_archive, ArArchiveBuilder,
|
||||
ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder, UnknownArchiveKind,
|
||||
try_extract_macho_fat_archive, ArArchiveBuilder, ArchiveBuildFailure, ArchiveBuilder,
|
||||
ArchiveBuilderBuilder, ObjectReader, UnknownArchiveKind, DEFAULT_OBJECT_READER,
|
||||
};
|
||||
use tracing::trace;
|
||||
|
||||
|
|
@ -115,7 +115,7 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
|||
if true {
|
||||
Box::new(LlvmArchiveBuilder { sess, additions: Vec::new() })
|
||||
} else {
|
||||
Box::new(ArArchiveBuilder::new(sess, get_llvm_object_symbols))
|
||||
Box::new(ArArchiveBuilder::new(sess, &LLVM_OBJECT_READER))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -291,57 +291,82 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
|||
|
||||
// The object crate doesn't know how to get symbols for LLVM bitcode and COFF bigobj files.
|
||||
// As such we need to use LLVM for them.
|
||||
#[deny(unsafe_op_in_unsafe_fn)]
|
||||
fn get_llvm_object_symbols(
|
||||
buf: &[u8],
|
||||
f: &mut dyn FnMut(&[u8]) -> io::Result<()>,
|
||||
) -> io::Result<bool> {
|
||||
|
||||
static LLVM_OBJECT_READER: ObjectReader = ObjectReader {
|
||||
get_symbols: get_llvm_object_symbols,
|
||||
is_64_bit_object_file: llvm_is_64_bit_object_file,
|
||||
is_ec_object_file: llvm_is_ec_object_file,
|
||||
get_xcoff_member_alignment: DEFAULT_OBJECT_READER.get_xcoff_member_alignment,
|
||||
};
|
||||
|
||||
fn should_use_llvm_reader(buf: &[u8]) -> bool {
|
||||
let is_bitcode = unsafe { llvm::LLVMRustIsBitcode(buf.as_ptr(), buf.len()) };
|
||||
|
||||
// COFF bigobj file, msvc LTO file or import library. See
|
||||
// https://github.com/llvm/llvm-project/blob/453f27bc9/llvm/lib/BinaryFormat/Magic.cpp#L38-L51
|
||||
let is_unsupported_windows_obj_file = buf.get(0..4) == Some(b"\0\0\xFF\xFF");
|
||||
|
||||
if is_bitcode || is_unsupported_windows_obj_file {
|
||||
let mut state = Box::new(f);
|
||||
is_bitcode || is_unsupported_windows_obj_file
|
||||
}
|
||||
|
||||
let err = unsafe {
|
||||
llvm::LLVMRustGetSymbols(
|
||||
buf.as_ptr(),
|
||||
buf.len(),
|
||||
std::ptr::addr_of_mut!(*state) as *mut c_void,
|
||||
callback,
|
||||
error_callback,
|
||||
)
|
||||
};
|
||||
|
||||
if err.is_null() {
|
||||
return Ok(true);
|
||||
} else {
|
||||
return Err(unsafe { *Box::from_raw(err as *mut io::Error) });
|
||||
}
|
||||
|
||||
unsafe extern "C" fn callback(
|
||||
state: *mut c_void,
|
||||
symbol_name: *const c_char,
|
||||
) -> *mut c_void {
|
||||
let f = unsafe { &mut *(state as *mut &mut dyn FnMut(&[u8]) -> io::Result<()>) };
|
||||
match f(unsafe { CStr::from_ptr(symbol_name) }.to_bytes()) {
|
||||
Ok(()) => std::ptr::null_mut(),
|
||||
Err(err) => Box::into_raw(Box::new(err)) as *mut c_void,
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn error_callback(error: *const c_char) -> *mut c_void {
|
||||
let error = unsafe { CStr::from_ptr(error) };
|
||||
Box::into_raw(Box::new(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("LLVM error: {}", error.to_string_lossy()),
|
||||
))) as *mut c_void
|
||||
}
|
||||
} else {
|
||||
get_native_object_symbols(buf, f)
|
||||
#[deny(unsafe_op_in_unsafe_fn)]
|
||||
fn get_llvm_object_symbols(
|
||||
buf: &[u8],
|
||||
f: &mut dyn FnMut(&[u8]) -> io::Result<()>,
|
||||
) -> io::Result<bool> {
|
||||
if !should_use_llvm_reader(buf) {
|
||||
return (DEFAULT_OBJECT_READER.get_symbols)(buf, f);
|
||||
}
|
||||
|
||||
let mut state = Box::new(f);
|
||||
|
||||
let err = unsafe {
|
||||
llvm::LLVMRustGetSymbols(
|
||||
buf.as_ptr(),
|
||||
buf.len(),
|
||||
std::ptr::addr_of_mut!(*state) as *mut c_void,
|
||||
callback,
|
||||
error_callback,
|
||||
)
|
||||
};
|
||||
|
||||
if err.is_null() {
|
||||
return Ok(true);
|
||||
} else {
|
||||
return Err(unsafe { *Box::from_raw(err as *mut io::Error) });
|
||||
}
|
||||
|
||||
unsafe extern "C" fn callback(state: *mut c_void, symbol_name: *const c_char) -> *mut c_void {
|
||||
let f = unsafe { &mut *(state as *mut &mut dyn FnMut(&[u8]) -> io::Result<()>) };
|
||||
match f(unsafe { CStr::from_ptr(symbol_name) }.to_bytes()) {
|
||||
Ok(()) => std::ptr::null_mut(),
|
||||
Err(err) => Box::into_raw(Box::new(err)) as *mut c_void,
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn error_callback(error: *const c_char) -> *mut c_void {
|
||||
let error = unsafe { CStr::from_ptr(error) };
|
||||
Box::into_raw(Box::new(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("LLVM error: {}", error.to_string_lossy()),
|
||||
))) as *mut c_void
|
||||
}
|
||||
}
|
||||
|
||||
fn llvm_is_64_bit_object_file(buf: &[u8]) -> bool {
|
||||
if !should_use_llvm_reader(buf) {
|
||||
return (DEFAULT_OBJECT_READER.is_64_bit_object_file)(buf);
|
||||
}
|
||||
|
||||
unsafe { llvm::LLVMRustIs64BitSymbolicFile(buf.as_ptr(), buf.len()) }
|
||||
}
|
||||
|
||||
fn llvm_is_ec_object_file(buf: &[u8]) -> bool {
|
||||
if !should_use_llvm_reader(buf) {
|
||||
return (DEFAULT_OBJECT_READER.is_ec_object_file)(buf);
|
||||
}
|
||||
|
||||
unsafe { llvm::LLVMRustIsECObject(buf.as_ptr(), buf.len()) }
|
||||
}
|
||||
|
||||
impl<'a> LlvmArchiveBuilder<'a> {
|
||||
|
|
|
|||
|
|
@ -727,7 +727,7 @@ pub unsafe fn optimize_thin_module(
|
|||
// into that context. One day, however, we may do this for upstream
|
||||
// crates but for locally codegened modules we may be able to reuse
|
||||
// that LLVM Context and Module.
|
||||
let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
|
||||
let llcx = unsafe { llvm::LLVMRustContextCreate(cgcx.fewer_names) };
|
||||
let llmod_raw = parse_module(llcx, module_name, thin_module.data(), dcx)? as *const _;
|
||||
let mut module = ModuleCodegen {
|
||||
module_llvm: ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) },
|
||||
|
|
@ -750,7 +750,9 @@ pub unsafe fn optimize_thin_module(
|
|||
{
|
||||
let _timer =
|
||||
cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_rename", thin_module.name());
|
||||
if !llvm::LLVMRustPrepareThinLTORename(thin_module.shared.data.0, llmod, target) {
|
||||
if unsafe {
|
||||
!llvm::LLVMRustPrepareThinLTORename(thin_module.shared.data.0, llmod, target)
|
||||
} {
|
||||
return Err(write::llvm_err(dcx, LlvmError::PrepareThinLtoModule));
|
||||
}
|
||||
save_temp_bitcode(cgcx, &module, "thin-lto-after-rename");
|
||||
|
|
@ -760,7 +762,8 @@ pub unsafe fn optimize_thin_module(
|
|||
let _timer = cgcx
|
||||
.prof
|
||||
.generic_activity_with_arg("LLVM_thin_lto_resolve_weak", thin_module.name());
|
||||
if !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) {
|
||||
if unsafe { !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) }
|
||||
{
|
||||
return Err(write::llvm_err(dcx, LlvmError::PrepareThinLtoModule));
|
||||
}
|
||||
save_temp_bitcode(cgcx, &module, "thin-lto-after-resolve");
|
||||
|
|
@ -770,7 +773,8 @@ pub unsafe fn optimize_thin_module(
|
|||
let _timer = cgcx
|
||||
.prof
|
||||
.generic_activity_with_arg("LLVM_thin_lto_internalize", thin_module.name());
|
||||
if !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) {
|
||||
if unsafe { !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) }
|
||||
{
|
||||
return Err(write::llvm_err(dcx, LlvmError::PrepareThinLtoModule));
|
||||
}
|
||||
save_temp_bitcode(cgcx, &module, "thin-lto-after-internalize");
|
||||
|
|
@ -779,7 +783,9 @@ pub unsafe fn optimize_thin_module(
|
|||
{
|
||||
let _timer =
|
||||
cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_import", thin_module.name());
|
||||
if !llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod, target) {
|
||||
if unsafe {
|
||||
!llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod, target)
|
||||
} {
|
||||
return Err(write::llvm_err(dcx, LlvmError::PrepareThinLtoModule));
|
||||
}
|
||||
save_temp_bitcode(cgcx, &module, "thin-lto-after-import");
|
||||
|
|
|
|||
|
|
@ -46,13 +46,15 @@ pub unsafe extern "C" fn selfprofile_before_pass_callback(
|
|||
pass_name: *const c_char,
|
||||
ir_name: *const c_char,
|
||||
) {
|
||||
let llvm_self_profiler = &mut *(llvm_self_profiler as *mut LlvmSelfProfiler<'_>);
|
||||
let pass_name = CStr::from_ptr(pass_name).to_str().expect("valid UTF-8");
|
||||
let ir_name = CStr::from_ptr(ir_name).to_str().expect("valid UTF-8");
|
||||
llvm_self_profiler.before_pass_callback(pass_name, ir_name);
|
||||
unsafe {
|
||||
let llvm_self_profiler = &mut *(llvm_self_profiler as *mut LlvmSelfProfiler<'_>);
|
||||
let pass_name = CStr::from_ptr(pass_name).to_str().expect("valid UTF-8");
|
||||
let ir_name = CStr::from_ptr(ir_name).to_str().expect("valid UTF-8");
|
||||
llvm_self_profiler.before_pass_callback(pass_name, ir_name);
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn selfprofile_after_pass_callback(llvm_self_profiler: *mut c_void) {
|
||||
let llvm_self_profiler = &mut *(llvm_self_profiler as *mut LlvmSelfProfiler<'_>);
|
||||
let llvm_self_profiler = unsafe { &mut *(llvm_self_profiler as *mut LlvmSelfProfiler<'_>) };
|
||||
llvm_self_profiler.after_pass_callback();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -428,9 +428,10 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void
|
|||
if user.is_null() {
|
||||
return;
|
||||
}
|
||||
let (cgcx, dcx) = *(user as *const (&CodegenContext<LlvmCodegenBackend>, DiagCtxtHandle<'_>));
|
||||
let (cgcx, dcx) =
|
||||
unsafe { *(user as *const (&CodegenContext<LlvmCodegenBackend>, DiagCtxtHandle<'_>)) };
|
||||
|
||||
match llvm::diagnostic::Diagnostic::unpack(info) {
|
||||
match unsafe { llvm::diagnostic::Diagnostic::unpack(info) } {
|
||||
llvm::diagnostic::InlineAsm(inline) => {
|
||||
report_inline_asm(cgcx, inline.message, inline.level, inline.cookie, inline.source);
|
||||
}
|
||||
|
|
@ -454,14 +455,14 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void
|
|||
});
|
||||
}
|
||||
llvm::diagnostic::PGO(diagnostic_ref) | llvm::diagnostic::Linker(diagnostic_ref) => {
|
||||
let message = llvm::build_string(|s| {
|
||||
let message = llvm::build_string(|s| unsafe {
|
||||
llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s)
|
||||
})
|
||||
.expect("non-UTF8 diagnostic");
|
||||
dcx.emit_warn(FromLlvmDiag { message });
|
||||
}
|
||||
llvm::diagnostic::Unsupported(diagnostic_ref) => {
|
||||
let message = llvm::build_string(|s| {
|
||||
let message = llvm::build_string(|s| unsafe {
|
||||
llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s)
|
||||
})
|
||||
.expect("non-UTF8 diagnostic");
|
||||
|
|
@ -564,37 +565,39 @@ pub(crate) unsafe fn llvm_optimize(
|
|||
|
||||
let llvm_plugins = config.llvm_plugins.join(",");
|
||||
|
||||
let result = llvm::LLVMRustOptimize(
|
||||
module.module_llvm.llmod(),
|
||||
&*module.module_llvm.tm,
|
||||
to_pass_builder_opt_level(opt_level),
|
||||
opt_stage,
|
||||
cgcx.opts.cg.linker_plugin_lto.enabled(),
|
||||
config.no_prepopulate_passes,
|
||||
config.verify_llvm_ir,
|
||||
using_thin_buffers,
|
||||
config.merge_functions,
|
||||
unroll_loops,
|
||||
config.vectorize_slp,
|
||||
config.vectorize_loop,
|
||||
config.no_builtins,
|
||||
config.emit_lifetime_markers,
|
||||
sanitizer_options.as_ref(),
|
||||
pgo_gen_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
|
||||
pgo_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
|
||||
config.instrument_coverage,
|
||||
instr_profile_output_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
|
||||
config.instrument_gcov,
|
||||
pgo_sample_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
|
||||
config.debug_info_for_profiling,
|
||||
llvm_selfprofiler,
|
||||
selfprofile_before_pass_callback,
|
||||
selfprofile_after_pass_callback,
|
||||
extra_passes.as_ptr().cast(),
|
||||
extra_passes.len(),
|
||||
llvm_plugins.as_ptr().cast(),
|
||||
llvm_plugins.len(),
|
||||
);
|
||||
let result = unsafe {
|
||||
llvm::LLVMRustOptimize(
|
||||
module.module_llvm.llmod(),
|
||||
&*module.module_llvm.tm,
|
||||
to_pass_builder_opt_level(opt_level),
|
||||
opt_stage,
|
||||
cgcx.opts.cg.linker_plugin_lto.enabled(),
|
||||
config.no_prepopulate_passes,
|
||||
config.verify_llvm_ir,
|
||||
using_thin_buffers,
|
||||
config.merge_functions,
|
||||
unroll_loops,
|
||||
config.vectorize_slp,
|
||||
config.vectorize_loop,
|
||||
config.no_builtins,
|
||||
config.emit_lifetime_markers,
|
||||
sanitizer_options.as_ref(),
|
||||
pgo_gen_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
|
||||
pgo_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
|
||||
config.instrument_coverage,
|
||||
instr_profile_output_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
|
||||
config.instrument_gcov,
|
||||
pgo_sample_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
|
||||
config.debug_info_for_profiling,
|
||||
llvm_selfprofiler,
|
||||
selfprofile_before_pass_callback,
|
||||
selfprofile_after_pass_callback,
|
||||
extra_passes.as_ptr().cast(),
|
||||
extra_passes.len(),
|
||||
llvm_plugins.as_ptr().cast(),
|
||||
llvm_plugins.len(),
|
||||
)
|
||||
};
|
||||
result.into_result().map_err(|()| llvm_err(dcx, LlvmError::RunLlvmPasses))
|
||||
}
|
||||
|
||||
|
|
@ -617,7 +620,7 @@ pub(crate) unsafe fn optimize(
|
|||
if config.emit_no_opt_bc {
|
||||
let out = cgcx.output_filenames.temp_path_ext("no-opt.bc", module_name);
|
||||
let out = path_to_c_string(&out);
|
||||
llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
|
||||
unsafe { llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr()) };
|
||||
}
|
||||
|
||||
if let Some(opt_level) = config.opt_level {
|
||||
|
|
@ -627,7 +630,7 @@ pub(crate) unsafe fn optimize(
|
|||
_ if cgcx.opts.cg.linker_plugin_lto.enabled() => llvm::OptStage::PreLinkThinLTO,
|
||||
_ => llvm::OptStage::PreLinkNoLTO,
|
||||
};
|
||||
return llvm_optimize(cgcx, dcx, module, config, opt_level, opt_stage);
|
||||
return unsafe { llvm_optimize(cgcx, dcx, module, config, opt_level, opt_stage) };
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -692,10 +695,12 @@ pub(crate) unsafe fn codegen(
|
|||
where
|
||||
F: FnOnce(&'ll mut PassManager<'ll>) -> R,
|
||||
{
|
||||
let cpm = llvm::LLVMCreatePassManager();
|
||||
llvm::LLVMAddAnalysisPasses(tm, cpm);
|
||||
llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
|
||||
f(cpm)
|
||||
unsafe {
|
||||
let cpm = llvm::LLVMCreatePassManager();
|
||||
llvm::LLVMAddAnalysisPasses(tm, cpm);
|
||||
llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
|
||||
f(cpm)
|
||||
}
|
||||
}
|
||||
|
||||
// Two things to note:
|
||||
|
|
@ -757,7 +762,9 @@ pub(crate) unsafe fn codegen(
|
|||
let _timer = cgcx
|
||||
.prof
|
||||
.generic_activity_with_arg("LLVM_module_codegen_embed_bitcode", &*module.name);
|
||||
embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data);
|
||||
unsafe {
|
||||
embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -793,7 +800,8 @@ pub(crate) unsafe fn codegen(
|
|||
cursor.position() as size_t
|
||||
}
|
||||
|
||||
let result = llvm::LLVMRustPrintModule(llmod, out_c.as_ptr(), demangle_callback);
|
||||
let result =
|
||||
unsafe { llvm::LLVMRustPrintModule(llmod, out_c.as_ptr(), demangle_callback) };
|
||||
|
||||
if result == llvm::LLVMRustResult::Success {
|
||||
record_artifact_size(&cgcx.prof, "llvm_ir", &out);
|
||||
|
|
@ -812,22 +820,24 @@ pub(crate) unsafe fn codegen(
|
|||
// binaries. So we must clone the module to produce the asm output
|
||||
// if we are also producing object code.
|
||||
let llmod = if let EmitObj::ObjectCode(_) = config.emit_obj {
|
||||
llvm::LLVMCloneModule(llmod)
|
||||
unsafe { llvm::LLVMCloneModule(llmod) }
|
||||
} else {
|
||||
llmod
|
||||
};
|
||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||
write_output_file(
|
||||
dcx,
|
||||
tm,
|
||||
cpm,
|
||||
llmod,
|
||||
&path,
|
||||
None,
|
||||
llvm::FileType::AssemblyFile,
|
||||
&cgcx.prof,
|
||||
)
|
||||
})?;
|
||||
unsafe {
|
||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||
write_output_file(
|
||||
dcx,
|
||||
tm,
|
||||
cpm,
|
||||
llmod,
|
||||
&path,
|
||||
None,
|
||||
llvm::FileType::AssemblyFile,
|
||||
&cgcx.prof,
|
||||
)
|
||||
})?;
|
||||
}
|
||||
}
|
||||
|
||||
match config.emit_obj {
|
||||
|
|
@ -851,18 +861,20 @@ pub(crate) unsafe fn codegen(
|
|||
(_, SplitDwarfKind::Split) => Some(dwo_out.as_path()),
|
||||
};
|
||||
|
||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||
write_output_file(
|
||||
dcx,
|
||||
tm,
|
||||
cpm,
|
||||
llmod,
|
||||
&obj_out,
|
||||
dwo_out,
|
||||
llvm::FileType::ObjectFile,
|
||||
&cgcx.prof,
|
||||
)
|
||||
})?;
|
||||
unsafe {
|
||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||
write_output_file(
|
||||
dcx,
|
||||
tm,
|
||||
cpm,
|
||||
llmod,
|
||||
&obj_out,
|
||||
dwo_out,
|
||||
llvm::FileType::ObjectFile,
|
||||
&cgcx.prof,
|
||||
)
|
||||
})?;
|
||||
}
|
||||
}
|
||||
|
||||
EmitObj::Bitcode => {
|
||||
|
|
@ -1013,44 +1025,46 @@ unsafe fn embed_bitcode(
|
|||
// reason (see issue #90326 for historical background).
|
||||
let is_aix = target_is_aix(cgcx);
|
||||
let is_apple = target_is_apple(cgcx);
|
||||
if is_apple || is_aix || cgcx.opts.target_triple.triple().starts_with("wasm") {
|
||||
// We don't need custom section flags, create LLVM globals.
|
||||
let llconst = common::bytes_in_context(llcx, bitcode);
|
||||
let llglobal = llvm::LLVMAddGlobal(
|
||||
llmod,
|
||||
common::val_ty(llconst),
|
||||
c"rustc.embedded.module".as_ptr().cast(),
|
||||
);
|
||||
llvm::LLVMSetInitializer(llglobal, llconst);
|
||||
unsafe {
|
||||
if is_apple || is_aix || cgcx.opts.target_triple.triple().starts_with("wasm") {
|
||||
// We don't need custom section flags, create LLVM globals.
|
||||
let llconst = common::bytes_in_context(llcx, bitcode);
|
||||
let llglobal = llvm::LLVMAddGlobal(
|
||||
llmod,
|
||||
common::val_ty(llconst),
|
||||
c"rustc.embedded.module".as_ptr().cast(),
|
||||
);
|
||||
llvm::LLVMSetInitializer(llglobal, llconst);
|
||||
|
||||
let section = bitcode_section_name(cgcx);
|
||||
llvm::LLVMSetSection(llglobal, section.as_ptr().cast());
|
||||
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||
llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
|
||||
let section = bitcode_section_name(cgcx);
|
||||
llvm::LLVMSetSection(llglobal, section.as_ptr().cast());
|
||||
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||
llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
|
||||
|
||||
let llconst = common::bytes_in_context(llcx, cmdline.as_bytes());
|
||||
let llglobal = llvm::LLVMAddGlobal(
|
||||
llmod,
|
||||
common::val_ty(llconst),
|
||||
c"rustc.embedded.cmdline".as_ptr().cast(),
|
||||
);
|
||||
llvm::LLVMSetInitializer(llglobal, llconst);
|
||||
let section = if is_apple {
|
||||
c"__LLVM,__cmdline"
|
||||
} else if is_aix {
|
||||
c".info"
|
||||
let llconst = common::bytes_in_context(llcx, cmdline.as_bytes());
|
||||
let llglobal = llvm::LLVMAddGlobal(
|
||||
llmod,
|
||||
common::val_ty(llconst),
|
||||
c"rustc.embedded.cmdline".as_ptr().cast(),
|
||||
);
|
||||
llvm::LLVMSetInitializer(llglobal, llconst);
|
||||
let section = if is_apple {
|
||||
c"__LLVM,__cmdline"
|
||||
} else if is_aix {
|
||||
c".info"
|
||||
} else {
|
||||
c".llvmcmd"
|
||||
};
|
||||
llvm::LLVMSetSection(llglobal, section.as_ptr().cast());
|
||||
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||
} else {
|
||||
c".llvmcmd"
|
||||
};
|
||||
llvm::LLVMSetSection(llglobal, section.as_ptr().cast());
|
||||
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||
} else {
|
||||
// We need custom section flags, so emit module-level inline assembly.
|
||||
let section_flags = if cgcx.is_pe_coff { "n" } else { "e" };
|
||||
let asm = create_section_with_flags_asm(".llvmbc", section_flags, bitcode);
|
||||
llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len());
|
||||
let asm = create_section_with_flags_asm(".llvmcmd", section_flags, cmdline.as_bytes());
|
||||
llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len());
|
||||
// We need custom section flags, so emit module-level inline assembly.
|
||||
let section_flags = if cgcx.is_pe_coff { "n" } else { "e" };
|
||||
let asm = create_section_with_flags_asm(".llvmbc", section_flags, bitcode);
|
||||
llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len());
|
||||
let asm = create_section_with_flags_asm(".llvmcmd", section_flags, cmdline.as_bytes());
|
||||
llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -330,7 +330,7 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
|
||||
// If this assertion triggers, there's something wrong with commandline
|
||||
// argument validation.
|
||||
debug_assert!(
|
||||
assert!(
|
||||
!(self.tcx.sess.opts.cg.linker_plugin_lto.enabled()
|
||||
&& self.tcx.sess.target.is_like_windows
|
||||
&& self.tcx.sess.opts.cg.prefer_dynamic)
|
||||
|
|
@ -495,8 +495,14 @@ impl<'ll> CodegenCx<'ll, '_> {
|
|||
}
|
||||
|
||||
// Wasm statics with custom link sections get special treatment as they
|
||||
// go into custom sections of the wasm executable.
|
||||
if self.tcx.sess.target.is_like_wasm {
|
||||
// go into custom sections of the wasm executable. The exception to this
|
||||
// is the `.init_array` section which are treated specially by the wasm linker.
|
||||
if self.tcx.sess.target.is_like_wasm
|
||||
&& attrs
|
||||
.link_section
|
||||
.map(|link_section| !link_section.as_str().starts_with(".init_array"))
|
||||
.unwrap_or(true)
|
||||
{
|
||||
if let Some(section) = attrs.link_section {
|
||||
let section = llvm::LLVMMDStringInContext2(
|
||||
self.llcx,
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ pub unsafe fn create_module<'ll>(
|
|||
) -> &'ll llvm::Module {
|
||||
let sess = tcx.sess;
|
||||
let mod_name = SmallCStr::new(mod_name);
|
||||
let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
|
||||
let llmod = unsafe { llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx) };
|
||||
|
||||
let mut target_data_layout = sess.target.data_layout.to_string();
|
||||
let llvm_version = llvm_util::get_version();
|
||||
|
|
@ -153,11 +153,14 @@ pub unsafe fn create_module<'ll>(
|
|||
// Ensure the data-layout values hardcoded remain the defaults.
|
||||
{
|
||||
let tm = crate::back::write::create_informational_target_machine(tcx.sess);
|
||||
llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, &tm);
|
||||
unsafe {
|
||||
llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, &tm);
|
||||
}
|
||||
|
||||
let llvm_data_layout = llvm::LLVMGetDataLayoutStr(llmod);
|
||||
let llvm_data_layout = str::from_utf8(CStr::from_ptr(llvm_data_layout).to_bytes())
|
||||
.expect("got a non-UTF8 data-layout from LLVM");
|
||||
let llvm_data_layout = unsafe { llvm::LLVMGetDataLayoutStr(llmod) };
|
||||
let llvm_data_layout =
|
||||
str::from_utf8(unsafe { CStr::from_ptr(llvm_data_layout) }.to_bytes())
|
||||
.expect("got a non-UTF8 data-layout from LLVM");
|
||||
|
||||
if target_data_layout != llvm_data_layout {
|
||||
tcx.dcx().emit_err(crate::errors::MismatchedDataLayout {
|
||||
|
|
@ -170,20 +173,28 @@ pub unsafe fn create_module<'ll>(
|
|||
}
|
||||
|
||||
let data_layout = SmallCStr::new(&target_data_layout);
|
||||
llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr());
|
||||
unsafe {
|
||||
llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr());
|
||||
}
|
||||
|
||||
let llvm_target = SmallCStr::new(&sess.target.llvm_target);
|
||||
llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
|
||||
unsafe {
|
||||
llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
|
||||
}
|
||||
|
||||
let reloc_model = sess.relocation_model();
|
||||
if matches!(reloc_model, RelocModel::Pic | RelocModel::Pie) {
|
||||
llvm::LLVMRustSetModulePICLevel(llmod);
|
||||
unsafe {
|
||||
llvm::LLVMRustSetModulePICLevel(llmod);
|
||||
}
|
||||
// PIE is potentially more effective than PIC, but can only be used in executables.
|
||||
// If all our outputs are executables, then we can relax PIC to PIE.
|
||||
if reloc_model == RelocModel::Pie
|
||||
|| tcx.crate_types().iter().all(|ty| *ty == CrateType::Executable)
|
||||
{
|
||||
llvm::LLVMRustSetModulePIELevel(llmod);
|
||||
unsafe {
|
||||
llvm::LLVMRustSetModulePIELevel(llmod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -192,95 +203,109 @@ pub unsafe fn create_module<'ll>(
|
|||
// longer jumps) if a larger code model is used with a smaller one.
|
||||
//
|
||||
// See https://reviews.llvm.org/D52322 and https://reviews.llvm.org/D52323.
|
||||
llvm::LLVMRustSetModuleCodeModel(llmod, to_llvm_code_model(sess.code_model()));
|
||||
unsafe {
|
||||
llvm::LLVMRustSetModuleCodeModel(llmod, to_llvm_code_model(sess.code_model()));
|
||||
}
|
||||
|
||||
// If skipping the PLT is enabled, we need to add some module metadata
|
||||
// to ensure intrinsic calls don't use it.
|
||||
if !sess.needs_plt() {
|
||||
let avoid_plt = c"RtLibUseGOT".as_ptr().cast();
|
||||
llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Warning, avoid_plt, 1);
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Warning, avoid_plt, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Enable canonical jump tables if CFI is enabled. (See https://reviews.llvm.org/D65629.)
|
||||
if sess.is_sanitizer_cfi_canonical_jump_tables_enabled() && sess.is_sanitizer_cfi_enabled() {
|
||||
let canonical_jump_tables = c"CFI Canonical Jump Tables".as_ptr().cast();
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
canonical_jump_tables,
|
||||
1,
|
||||
);
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
canonical_jump_tables,
|
||||
1,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Enable LTO unit splitting if specified or if CFI is enabled. (See https://reviews.llvm.org/D53891.)
|
||||
if sess.is_split_lto_unit_enabled() || sess.is_sanitizer_cfi_enabled() {
|
||||
let enable_split_lto_unit = c"EnableSplitLTOUnit".as_ptr().cast();
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
enable_split_lto_unit,
|
||||
1,
|
||||
);
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
enable_split_lto_unit,
|
||||
1,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Add "kcfi" module flag if KCFI is enabled. (See https://reviews.llvm.org/D119296.)
|
||||
if sess.is_sanitizer_kcfi_enabled() {
|
||||
let kcfi = c"kcfi".as_ptr().cast();
|
||||
llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Override, kcfi, 1);
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Override, kcfi, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Control Flow Guard is currently only supported by the MSVC linker on Windows.
|
||||
if sess.target.is_like_msvc {
|
||||
match sess.opts.cg.control_flow_guard {
|
||||
CFGuard::Disabled => {}
|
||||
CFGuard::NoChecks => {
|
||||
// Set `cfguard=1` module flag to emit metadata only.
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"cfguard".as_ptr() as *const _,
|
||||
1,
|
||||
)
|
||||
}
|
||||
CFGuard::Checks => {
|
||||
// Set `cfguard=2` module flag to emit metadata and checks.
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"cfguard".as_ptr() as *const _,
|
||||
2,
|
||||
)
|
||||
unsafe {
|
||||
match sess.opts.cg.control_flow_guard {
|
||||
CFGuard::Disabled => {}
|
||||
CFGuard::NoChecks => {
|
||||
// Set `cfguard=1` module flag to emit metadata only.
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"cfguard".as_ptr() as *const _,
|
||||
1,
|
||||
)
|
||||
}
|
||||
CFGuard::Checks => {
|
||||
// Set `cfguard=2` module flag to emit metadata and checks.
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"cfguard".as_ptr() as *const _,
|
||||
2,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection {
|
||||
if sess.target.arch == "aarch64" {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"branch-target-enforcement".as_ptr().cast(),
|
||||
bti.into(),
|
||||
);
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"sign-return-address".as_ptr().cast(),
|
||||
pac_ret.is_some().into(),
|
||||
);
|
||||
let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A });
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"sign-return-address-all".as_ptr().cast(),
|
||||
pac_opts.leaf.into(),
|
||||
);
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"sign-return-address-with-bkey".as_ptr().cast(),
|
||||
u32::from(pac_opts.key == PAuthKey::B),
|
||||
);
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"branch-target-enforcement".as_ptr().cast(),
|
||||
bti.into(),
|
||||
);
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"sign-return-address".as_ptr().cast(),
|
||||
pac_ret.is_some().into(),
|
||||
);
|
||||
let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A });
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"sign-return-address-all".as_ptr().cast(),
|
||||
pac_opts.leaf.into(),
|
||||
);
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"sign-return-address-with-bkey".as_ptr().cast(),
|
||||
u32::from(pac_opts.key == PAuthKey::B),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
bug!(
|
||||
"branch-protection used on non-AArch64 target; \
|
||||
|
|
@ -291,39 +316,47 @@ pub unsafe fn create_module<'ll>(
|
|||
|
||||
// Pass on the control-flow protection flags to LLVM (equivalent to `-fcf-protection` in Clang).
|
||||
if let CFProtection::Branch | CFProtection::Full = sess.opts.unstable_opts.cf_protection {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
c"cf-protection-branch".as_ptr().cast(),
|
||||
1,
|
||||
)
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
c"cf-protection-branch".as_ptr().cast(),
|
||||
1,
|
||||
);
|
||||
}
|
||||
}
|
||||
if let CFProtection::Return | CFProtection::Full = sess.opts.unstable_opts.cf_protection {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
c"cf-protection-return".as_ptr().cast(),
|
||||
1,
|
||||
)
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
c"cf-protection-return".as_ptr().cast(),
|
||||
1,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if sess.opts.unstable_opts.virtual_function_elimination {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Error,
|
||||
c"Virtual Function Elim".as_ptr().cast(),
|
||||
1,
|
||||
);
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Error,
|
||||
c"Virtual Function Elim".as_ptr().cast(),
|
||||
1,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Set module flag to enable Windows EHCont Guard (/guard:ehcont).
|
||||
if sess.opts.unstable_opts.ehcont_guard {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"ehcontguard".as_ptr() as *const _,
|
||||
1,
|
||||
)
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"ehcontguard".as_ptr() as *const _,
|
||||
1,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Insert `llvm.ident` metadata.
|
||||
|
|
@ -333,16 +366,20 @@ pub unsafe fn create_module<'ll>(
|
|||
#[allow(clippy::option_env_unwrap)]
|
||||
let rustc_producer =
|
||||
format!("rustc version {}", option_env!("CFG_VERSION").expect("CFG_VERSION"));
|
||||
let name_metadata = llvm::LLVMMDStringInContext(
|
||||
llcx,
|
||||
rustc_producer.as_ptr().cast(),
|
||||
rustc_producer.as_bytes().len() as c_uint,
|
||||
);
|
||||
llvm::LLVMAddNamedMetadataOperand(
|
||||
llmod,
|
||||
c"llvm.ident".as_ptr(),
|
||||
llvm::LLVMMDNodeInContext(llcx, &name_metadata, 1),
|
||||
);
|
||||
let name_metadata = unsafe {
|
||||
llvm::LLVMMDStringInContext(
|
||||
llcx,
|
||||
rustc_producer.as_ptr().cast(),
|
||||
rustc_producer.as_bytes().len() as c_uint,
|
||||
)
|
||||
};
|
||||
unsafe {
|
||||
llvm::LLVMAddNamedMetadataOperand(
|
||||
llmod,
|
||||
c"llvm.ident".as_ptr(),
|
||||
llvm::LLVMMDNodeInContext(llcx, &name_metadata, 1),
|
||||
);
|
||||
}
|
||||
|
||||
// Emit RISC-V specific target-abi metadata
|
||||
// to workaround lld as the LTO plugin not
|
||||
|
|
@ -351,13 +388,15 @@ pub unsafe fn create_module<'ll>(
|
|||
// If llvm_abiname is empty, emit nothing.
|
||||
let llvm_abiname = &sess.target.options.llvm_abiname;
|
||||
if matches!(sess.target.arch.as_ref(), "riscv32" | "riscv64") && !llvm_abiname.is_empty() {
|
||||
llvm::LLVMRustAddModuleFlagString(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Error,
|
||||
c"target-abi".as_ptr(),
|
||||
llvm_abiname.as_ptr().cast(),
|
||||
llvm_abiname.len(),
|
||||
);
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagString(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Error,
|
||||
c"target-abi".as_ptr(),
|
||||
llvm_abiname.as_ptr().cast(),
|
||||
llvm_abiname.len(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Add module flags specified via -Z llvm_module_flag
|
||||
|
|
@ -375,7 +414,7 @@ pub unsafe fn create_module<'ll>(
|
|||
// We already checked this during option parsing
|
||||
_ => unreachable!(),
|
||||
};
|
||||
llvm::LLVMRustAddModuleFlagU32(llmod, behavior, key.as_ptr().cast(), *value)
|
||||
unsafe { llvm::LLVMRustAddModuleFlagU32(llmod, behavior, key.as_ptr().cast(), *value) }
|
||||
}
|
||||
|
||||
llmod
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
|||
) -> DINodeCreationResult<'ll> {
|
||||
// The debuginfo generated by this function is only valid if `ptr_type` is really just
|
||||
// a (fat) pointer. Make sure it is not called for e.g. `Box<T, NonZSTAllocator>`.
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
cx.size_and_align_of(ptr_type),
|
||||
cx.size_and_align_of(Ty::new_mut_ptr(cx.tcx, pointee_type))
|
||||
);
|
||||
|
|
@ -185,7 +185,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
|||
match fat_pointer_kind(cx, pointee_type) {
|
||||
None => {
|
||||
// This is a thin pointer. Create a regular pointer type and give it the correct name.
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
(data_layout.pointer_size, data_layout.pointer_align.abi),
|
||||
cx.size_and_align_of(ptr_type),
|
||||
"ptr_type={ptr_type}, pointee_type={pointee_type}",
|
||||
|
|
@ -240,8 +240,8 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
|||
FatPtrKind::Slice => ("data_ptr", "length"),
|
||||
};
|
||||
|
||||
debug_assert_eq!(abi::FAT_PTR_ADDR, 0);
|
||||
debug_assert_eq!(abi::FAT_PTR_EXTRA, 1);
|
||||
assert_eq!(abi::FAT_PTR_ADDR, 0);
|
||||
assert_eq!(abi::FAT_PTR_EXTRA, 1);
|
||||
|
||||
// The data pointer type is a regular, thin pointer, regardless of whether this
|
||||
// is a slice or a trait object.
|
||||
|
|
@ -498,7 +498,7 @@ pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll D
|
|||
}
|
||||
};
|
||||
|
||||
debug_assert_eq!(di_node_for_uid as *const _, di_node as *const _);
|
||||
assert_eq!(di_node_for_uid as *const _, di_node as *const _);
|
||||
} else {
|
||||
debug_context(cx).type_map.insert(unique_type_id, di_node);
|
||||
}
|
||||
|
|
@ -1060,7 +1060,7 @@ fn build_struct_type_di_node<'ll, 'tcx>(
|
|||
let ty::Adt(adt_def, _) = struct_type.kind() else {
|
||||
bug!("build_struct_type_di_node() called with non-struct-type: {:?}", struct_type);
|
||||
};
|
||||
debug_assert!(adt_def.is_struct());
|
||||
assert!(adt_def.is_struct());
|
||||
let containing_scope = get_namespace_for_item(cx, adt_def.did());
|
||||
let struct_type_and_layout = cx.layout_of(struct_type);
|
||||
let variant_def = adt_def.non_enum_variant();
|
||||
|
|
@ -1130,7 +1130,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>(
|
|||
}
|
||||
};
|
||||
|
||||
debug_assert!(
|
||||
assert!(
|
||||
up_var_tys.iter().all(|t| t == cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t))
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
|
|||
let enum_type_and_layout = cx.layout_of(enum_type);
|
||||
let enum_type_name = compute_debuginfo_type_name(cx.tcx, enum_type, false);
|
||||
|
||||
debug_assert!(!wants_c_like_enum_debuginfo(enum_type_and_layout));
|
||||
assert!(!wants_c_like_enum_debuginfo(enum_type_and_layout));
|
||||
|
||||
type_map::build_type_with_children(
|
||||
cx,
|
||||
|
|
@ -279,7 +279,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
|
|||
let coroutine_type_and_layout = cx.layout_of(coroutine_type);
|
||||
let coroutine_type_name = compute_debuginfo_type_name(cx.tcx, coroutine_type, false);
|
||||
|
||||
debug_assert!(!wants_c_like_enum_debuginfo(coroutine_type_and_layout));
|
||||
assert!(!wants_c_like_enum_debuginfo(coroutine_type_and_layout));
|
||||
|
||||
type_map::build_type_with_children(
|
||||
cx,
|
||||
|
|
@ -517,7 +517,7 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>(
|
|||
if is_128_bits {
|
||||
DiscrKind::Exact128(discr_val)
|
||||
} else {
|
||||
debug_assert_eq!(discr_val, discr_val as u64 as u128);
|
||||
assert_eq!(discr_val, discr_val as u64 as u128);
|
||||
DiscrKind::Exact(discr_val as u64)
|
||||
}
|
||||
}
|
||||
|
|
@ -526,8 +526,8 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>(
|
|||
if is_128_bits {
|
||||
DiscrKind::Range128(min, max)
|
||||
} else {
|
||||
debug_assert_eq!(min, min as u64 as u128);
|
||||
debug_assert_eq!(max, max as u64 as u128);
|
||||
assert_eq!(min, min as u64 as u128);
|
||||
assert_eq!(max, max as u64 as u128);
|
||||
DiscrKind::Range(min as u64, max as u64)
|
||||
}
|
||||
}
|
||||
|
|
@ -815,7 +815,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
|
|||
}
|
||||
}));
|
||||
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
cx.size_and_align_of(enum_type_and_layout.field(cx, tag_field).ty),
|
||||
cx.size_and_align_of(super::tag_base_type(cx, enum_type_and_layout))
|
||||
);
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ fn tag_base_type<'ll, 'tcx>(
|
|||
cx: &CodegenCx<'ll, 'tcx>,
|
||||
enum_type_and_layout: TyAndLayout<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
debug_assert!(match enum_type_and_layout.ty.kind() {
|
||||
assert!(match enum_type_and_layout.ty.kind() {
|
||||
ty::Coroutine(..) => true,
|
||||
ty::Adt(adt_def, _) => adt_def.is_enum(),
|
||||
_ => false,
|
||||
|
|
@ -251,7 +251,7 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>(
|
|||
variant_layout: TyAndLayout<'tcx>,
|
||||
di_flags: DIFlags,
|
||||
) -> &'ll DIType {
|
||||
debug_assert_eq!(variant_layout.ty, enum_type_and_layout.ty);
|
||||
assert_eq!(variant_layout.ty, enum_type_and_layout.ty);
|
||||
|
||||
type_map::build_type_with_children(
|
||||
cx,
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
|
|||
|
||||
let visibility_flags = visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did());
|
||||
|
||||
debug_assert!(!wants_c_like_enum_debuginfo(enum_type_and_layout));
|
||||
assert!(!wants_c_like_enum_debuginfo(enum_type_and_layout));
|
||||
|
||||
type_map::build_type_with_children(
|
||||
cx,
|
||||
|
|
@ -142,7 +142,7 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
|
|||
let containing_scope = get_namespace_for_item(cx, coroutine_def_id);
|
||||
let coroutine_type_and_layout = cx.layout_of(coroutine_type);
|
||||
|
||||
debug_assert!(!wants_c_like_enum_debuginfo(coroutine_type_and_layout));
|
||||
assert!(!wants_c_like_enum_debuginfo(coroutine_type_and_layout));
|
||||
|
||||
let coroutine_type_name = compute_debuginfo_type_name(cx.tcx, coroutine_type, false);
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ mod private {
|
|||
|
||||
/// A unique identifier for anything that we create a debuginfo node for.
|
||||
/// The types it contains are expected to already be normalized (which
|
||||
/// is debug_asserted in the constructors).
|
||||
/// is asserted in the constructors).
|
||||
///
|
||||
/// Note that there are some things that only show up in debuginfo, like
|
||||
/// the separate type descriptions for each enum variant. These get an ID
|
||||
|
|
@ -58,12 +58,12 @@ pub(super) enum UniqueTypeId<'tcx> {
|
|||
|
||||
impl<'tcx> UniqueTypeId<'tcx> {
|
||||
pub fn for_ty(tcx: TyCtxt<'tcx>, t: Ty<'tcx>) -> Self {
|
||||
debug_assert_eq!(t, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t));
|
||||
assert_eq!(t, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t));
|
||||
UniqueTypeId::Ty(t, private::HiddenZst)
|
||||
}
|
||||
|
||||
pub fn for_enum_variant_part(tcx: TyCtxt<'tcx>, enum_ty: Ty<'tcx>) -> Self {
|
||||
debug_assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty));
|
||||
assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty));
|
||||
UniqueTypeId::VariantPart(enum_ty, private::HiddenZst)
|
||||
}
|
||||
|
||||
|
|
@ -72,7 +72,7 @@ impl<'tcx> UniqueTypeId<'tcx> {
|
|||
enum_ty: Ty<'tcx>,
|
||||
variant_idx: VariantIdx,
|
||||
) -> Self {
|
||||
debug_assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty));
|
||||
assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty));
|
||||
UniqueTypeId::VariantStructType(enum_ty, variant_idx, private::HiddenZst)
|
||||
}
|
||||
|
||||
|
|
@ -81,7 +81,7 @@ impl<'tcx> UniqueTypeId<'tcx> {
|
|||
enum_ty: Ty<'tcx>,
|
||||
variant_idx: VariantIdx,
|
||||
) -> Self {
|
||||
debug_assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty));
|
||||
assert_eq!(enum_ty, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), enum_ty));
|
||||
UniqueTypeId::VariantStructTypeCppLikeWrapper(enum_ty, variant_idx, private::HiddenZst)
|
||||
}
|
||||
|
||||
|
|
@ -90,11 +90,8 @@ impl<'tcx> UniqueTypeId<'tcx> {
|
|||
self_type: Ty<'tcx>,
|
||||
implemented_trait: Option<PolyExistentialTraitRef<'tcx>>,
|
||||
) -> Self {
|
||||
debug_assert_eq!(
|
||||
self_type,
|
||||
tcx.normalize_erasing_regions(ParamEnv::reveal_all(), self_type)
|
||||
);
|
||||
debug_assert_eq!(
|
||||
assert_eq!(self_type, tcx.normalize_erasing_regions(ParamEnv::reveal_all(), self_type));
|
||||
assert_eq!(
|
||||
implemented_trait,
|
||||
tcx.normalize_erasing_regions(ParamEnv::reveal_all(), implemented_trait)
|
||||
);
|
||||
|
|
@ -252,10 +249,7 @@ pub(super) fn build_type_with_children<'ll, 'tcx>(
|
|||
members: impl FnOnce(&CodegenCx<'ll, 'tcx>, &'ll DIType) -> SmallVec<&'ll DIType>,
|
||||
generics: impl FnOnce(&CodegenCx<'ll, 'tcx>) -> SmallVec<&'ll DIType>,
|
||||
) -> DINodeCreationResult<'ll> {
|
||||
debug_assert_eq!(
|
||||
debug_context(cx).type_map.di_node_for_unique_id(stub_info.unique_type_id),
|
||||
None
|
||||
);
|
||||
assert_eq!(debug_context(cx).type_map.di_node_for_unique_id(stub_info.unique_type_id), None);
|
||||
|
||||
debug_context(cx).type_map.insert(stub_info.unique_type_id, stub_info.metadata);
|
||||
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ pub(crate) fn fat_pointer_kind<'ll, 'tcx>(
|
|||
ty::Dynamic(..) => Some(FatPtrKind::Dyn),
|
||||
ty::Foreign(_) => {
|
||||
// Assert that pointers to foreign types really are thin:
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
cx.size_of(Ty::new_imm_ptr(cx.tcx, pointee_tail_ty)),
|
||||
cx.size_of(Ty::new_imm_ptr(cx.tcx, cx.tcx.types.u8))
|
||||
);
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ impl WriteBackendMethods for LlvmCodegenBackend {
|
|||
module: &ModuleCodegen<Self::Module>,
|
||||
config: &ModuleConfig,
|
||||
) -> Result<(), FatalError> {
|
||||
back::write::optimize(cgcx, dcx, module, config)
|
||||
unsafe { back::write::optimize(cgcx, dcx, module, config) }
|
||||
}
|
||||
fn optimize_fat(
|
||||
cgcx: &CodegenContext<Self>,
|
||||
|
|
@ -230,7 +230,7 @@ impl WriteBackendMethods for LlvmCodegenBackend {
|
|||
cgcx: &CodegenContext<Self>,
|
||||
thin: ThinModule<Self>,
|
||||
) -> Result<ModuleCodegen<Self::Module>, FatalError> {
|
||||
back::lto::optimize_thin_module(thin, cgcx)
|
||||
unsafe { back::lto::optimize_thin_module(thin, cgcx) }
|
||||
}
|
||||
unsafe fn codegen(
|
||||
cgcx: &CodegenContext<Self>,
|
||||
|
|
@ -238,7 +238,7 @@ impl WriteBackendMethods for LlvmCodegenBackend {
|
|||
module: ModuleCodegen<Self::Module>,
|
||||
config: &ModuleConfig,
|
||||
) -> Result<CompiledModule, FatalError> {
|
||||
back::write::codegen(cgcx, dcx, module, config)
|
||||
unsafe { back::write::codegen(cgcx, dcx, module, config) }
|
||||
}
|
||||
fn prepare_thin(
|
||||
module: ModuleCodegen<Self::Module>,
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ impl<'ll> OptimizationDiagnostic<'ll> {
|
|||
let mut filename = None;
|
||||
let pass_name = super::build_string(|pass_name| {
|
||||
message = super::build_string(|message| {
|
||||
filename = super::build_string(|filename| {
|
||||
filename = super::build_string(|filename| unsafe {
|
||||
super::LLVMRustUnpackOptimizationDiagnostic(
|
||||
di,
|
||||
pass_name,
|
||||
|
|
@ -91,7 +91,7 @@ impl SrcMgrDiagnostic {
|
|||
let mut ranges = [0; 8];
|
||||
let mut num_ranges = ranges.len() / 2;
|
||||
let message = super::build_string(|message| {
|
||||
buffer = super::build_string(|buffer| {
|
||||
buffer = super::build_string(|buffer| unsafe {
|
||||
have_source = super::LLVMRustUnpackSMDiagnostic(
|
||||
diag,
|
||||
message,
|
||||
|
|
@ -134,7 +134,9 @@ impl InlineAsmDiagnostic {
|
|||
let mut message = None;
|
||||
let mut level = super::DiagnosticLevel::Error;
|
||||
|
||||
super::LLVMRustUnpackInlineAsmDiagnostic(di, &mut level, &mut cookie, &mut message);
|
||||
unsafe {
|
||||
super::LLVMRustUnpackInlineAsmDiagnostic(di, &mut level, &mut cookie, &mut message);
|
||||
}
|
||||
|
||||
InlineAsmDiagnostic {
|
||||
level,
|
||||
|
|
@ -146,7 +148,8 @@ impl InlineAsmDiagnostic {
|
|||
|
||||
unsafe fn unpackSrcMgr(di: &DiagnosticInfo) -> Self {
|
||||
let mut cookie = 0;
|
||||
let smdiag = SrcMgrDiagnostic::unpack(super::LLVMRustGetSMDiagnostic(di, &mut cookie));
|
||||
let smdiag =
|
||||
unsafe { SrcMgrDiagnostic::unpack(super::LLVMRustGetSMDiagnostic(di, &mut cookie)) };
|
||||
InlineAsmDiagnostic {
|
||||
level: smdiag.level,
|
||||
cookie: cookie.into(),
|
||||
|
|
@ -170,44 +173,46 @@ pub enum Diagnostic<'ll> {
|
|||
impl<'ll> Diagnostic<'ll> {
|
||||
pub unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self {
|
||||
use super::DiagnosticKind as Dk;
|
||||
let kind = super::LLVMRustGetDiagInfoKind(di);
|
||||
|
||||
match kind {
|
||||
Dk::InlineAsm => InlineAsm(InlineAsmDiagnostic::unpackInlineAsm(di)),
|
||||
unsafe {
|
||||
let kind = super::LLVMRustGetDiagInfoKind(di);
|
||||
match kind {
|
||||
Dk::InlineAsm => InlineAsm(InlineAsmDiagnostic::unpackInlineAsm(di)),
|
||||
|
||||
Dk::OptimizationRemark => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di))
|
||||
Dk::OptimizationRemark => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di))
|
||||
}
|
||||
Dk::OptimizationRemarkOther => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationRemarkOther, di))
|
||||
}
|
||||
Dk::OptimizationRemarkMissed => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationMissed, di))
|
||||
}
|
||||
|
||||
Dk::OptimizationRemarkAnalysis => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysis, di))
|
||||
}
|
||||
|
||||
Dk::OptimizationRemarkAnalysisFPCommute => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysisFPCommute, di))
|
||||
}
|
||||
|
||||
Dk::OptimizationRemarkAnalysisAliasing => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysisAliasing, di))
|
||||
}
|
||||
|
||||
Dk::OptimizationFailure => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationFailure, di))
|
||||
}
|
||||
|
||||
Dk::PGOProfile => PGO(di),
|
||||
Dk::Linker => Linker(di),
|
||||
Dk::Unsupported => Unsupported(di),
|
||||
|
||||
Dk::SrcMgr => InlineAsm(InlineAsmDiagnostic::unpackSrcMgr(di)),
|
||||
|
||||
_ => UnknownDiagnostic(di),
|
||||
}
|
||||
Dk::OptimizationRemarkOther => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationRemarkOther, di))
|
||||
}
|
||||
Dk::OptimizationRemarkMissed => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationMissed, di))
|
||||
}
|
||||
|
||||
Dk::OptimizationRemarkAnalysis => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysis, di))
|
||||
}
|
||||
|
||||
Dk::OptimizationRemarkAnalysisFPCommute => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysisFPCommute, di))
|
||||
}
|
||||
|
||||
Dk::OptimizationRemarkAnalysisAliasing => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysisAliasing, di))
|
||||
}
|
||||
|
||||
Dk::OptimizationFailure => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationFailure, di))
|
||||
}
|
||||
|
||||
Dk::PGOProfile => PGO(di),
|
||||
Dk::Linker => Linker(di),
|
||||
Dk::Unsupported => Unsupported(di),
|
||||
|
||||
Dk::SrcMgr => InlineAsm(InlineAsmDiagnostic::unpackSrcMgr(di)),
|
||||
|
||||
_ => UnknownDiagnostic(di),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -305,7 +305,6 @@ pub enum TypeKind {
|
|||
Pointer = 12,
|
||||
Vector = 13,
|
||||
Metadata = 14,
|
||||
X86_MMX = 15,
|
||||
Token = 16,
|
||||
ScalableVector = 17,
|
||||
BFloat = 18,
|
||||
|
|
@ -330,7 +329,6 @@ impl TypeKind {
|
|||
TypeKind::Pointer => rustc_codegen_ssa::common::TypeKind::Pointer,
|
||||
TypeKind::Vector => rustc_codegen_ssa::common::TypeKind::Vector,
|
||||
TypeKind::Metadata => rustc_codegen_ssa::common::TypeKind::Metadata,
|
||||
TypeKind::X86_MMX => rustc_codegen_ssa::common::TypeKind::X86_MMX,
|
||||
TypeKind::Token => rustc_codegen_ssa::common::TypeKind::Token,
|
||||
TypeKind::ScalableVector => rustc_codegen_ssa::common::TypeKind::ScalableVector,
|
||||
TypeKind::BFloat => rustc_codegen_ssa::common::TypeKind::BFloat,
|
||||
|
|
@ -2440,4 +2438,8 @@ extern "C" {
|
|||
callback: GetSymbolsCallback,
|
||||
error_callback: GetSymbolsErrorCallback,
|
||||
) -> *mut c_void;
|
||||
|
||||
pub fn LLVMRustIs64BitSymbolicFile(buf_ptr: *const u8, buf_len: usize) -> bool;
|
||||
|
||||
pub fn LLVMRustIsECObject(buf_ptr: *const u8, buf_len: usize) -> bool;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use rustc_session::config::{PrintKind, PrintRequest};
|
|||
use rustc_session::Session;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_target::spec::{MergeFunctions, PanicStrategy};
|
||||
use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES;
|
||||
use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES};
|
||||
|
||||
use std::ffi::{c_char, c_void, CStr, CString};
|
||||
use std::fmt::Write;
|
||||
|
|
@ -49,12 +49,16 @@ unsafe fn configure_llvm(sess: &Session) {
|
|||
let mut llvm_c_strs = Vec::with_capacity(n_args + 1);
|
||||
let mut llvm_args = Vec::with_capacity(n_args + 1);
|
||||
|
||||
llvm::LLVMRustInstallErrorHandlers();
|
||||
unsafe {
|
||||
llvm::LLVMRustInstallErrorHandlers();
|
||||
}
|
||||
// On Windows, an LLVM assertion will open an Abort/Retry/Ignore dialog
|
||||
// box for the purpose of launching a debugger. However, on CI this will
|
||||
// cause it to hang until it times out, which can take several hours.
|
||||
if std::env::var_os("CI").is_some() {
|
||||
llvm::LLVMRustDisableSystemDialogsOnCrash();
|
||||
unsafe {
|
||||
llvm::LLVMRustDisableSystemDialogsOnCrash();
|
||||
}
|
||||
}
|
||||
|
||||
fn llvm_arg_to_arg_name(full_arg: &str) -> &str {
|
||||
|
|
@ -124,12 +128,12 @@ unsafe fn configure_llvm(sess: &Session) {
|
|||
}
|
||||
|
||||
if sess.opts.unstable_opts.llvm_time_trace {
|
||||
llvm::LLVMRustTimeTraceProfilerInitialize();
|
||||
unsafe { llvm::LLVMRustTimeTraceProfilerInitialize() };
|
||||
}
|
||||
|
||||
rustc_llvm::initialize_available_targets();
|
||||
|
||||
llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr());
|
||||
unsafe { llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr()) };
|
||||
}
|
||||
|
||||
pub fn time_trace_profiler_finish(file_name: &Path) {
|
||||
|
|
@ -317,6 +321,10 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
|
|||
}
|
||||
})
|
||||
.filter(|feature| {
|
||||
// skip checking special features, as LLVM may not understands them
|
||||
if RUSTC_SPECIAL_FEATURES.contains(feature) {
|
||||
return true;
|
||||
}
|
||||
// check that all features in a given smallvec are enabled
|
||||
for llvm_feature in to_llvm_features(sess, feature) {
|
||||
let cstr = SmallCStr::new(llvm_feature);
|
||||
|
|
@ -442,8 +450,8 @@ pub(crate) fn print(req: &PrintRequest, mut out: &mut String, sess: &Session) {
|
|||
let cpu_cstring = CString::new(handle_native(sess.target.cpu.as_ref()))
|
||||
.unwrap_or_else(|e| bug!("failed to convert to cstring: {}", e));
|
||||
unsafe extern "C" fn callback(out: *mut c_void, string: *const c_char, len: usize) {
|
||||
let out = &mut *(out as *mut &mut String);
|
||||
let bytes = slice::from_raw_parts(string as *const u8, len);
|
||||
let out = unsafe { &mut *(out as *mut &mut String) };
|
||||
let bytes = unsafe { slice::from_raw_parts(string as *const u8, len) };
|
||||
write!(out, "{}", String::from_utf8_lossy(bytes)).unwrap();
|
||||
}
|
||||
unsafe {
|
||||
|
|
@ -542,6 +550,7 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
|
|||
|
||||
// -Ctarget-features
|
||||
let supported_features = sess.target.supported_target_features();
|
||||
let (llvm_major, _, _) = get_version();
|
||||
let mut featsmap = FxHashMap::default();
|
||||
let feats = sess
|
||||
.opts
|
||||
|
|
@ -600,6 +609,13 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
|
|||
if RUSTC_SPECIFIC_FEATURES.contains(&feature) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// if the target-feature is "backchain" and LLVM version is greater than 18
|
||||
// then we also need to add "+backchain" to the target-features attribute.
|
||||
// otherwise, we will only add the naked `backchain` attribute to the attribute-group.
|
||||
if feature == "backchain" && llvm_major < 18 {
|
||||
return None;
|
||||
}
|
||||
// ... otherwise though we run through `to_llvm_features` when
|
||||
// passing requests down to LLVM. This means that all in-language
|
||||
// features also work on the command line instead of having two
|
||||
|
|
|
|||
|
|
@ -108,8 +108,8 @@ impl CodegenCx<'_, '_> {
|
|||
llval: &llvm::Value,
|
||||
is_declaration: bool,
|
||||
) -> bool {
|
||||
let linkage = llvm::LLVMRustGetLinkage(llval);
|
||||
let visibility = llvm::LLVMRustGetVisibility(llval);
|
||||
let linkage = unsafe { llvm::LLVMRustGetLinkage(llval) };
|
||||
let visibility = unsafe { llvm::LLVMRustGetVisibility(llval) };
|
||||
|
||||
if matches!(linkage, llvm::Linkage::InternalLinkage | llvm::Linkage::PrivateLinkage) {
|
||||
return true;
|
||||
|
|
@ -145,8 +145,8 @@ impl CodegenCx<'_, '_> {
|
|||
}
|
||||
|
||||
// Thread-local variables generally don't support copy relocations.
|
||||
let is_thread_local_var = llvm::LLVMIsAGlobalVariable(llval)
|
||||
.is_some_and(|v| llvm::LLVMIsThreadLocal(v) == llvm::True);
|
||||
let is_thread_local_var = unsafe { llvm::LLVMIsAGlobalVariable(llval) }
|
||||
.is_some_and(|v| unsafe { llvm::LLVMIsThreadLocal(v) } == llvm::True);
|
||||
if is_thread_local_var {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
ar_archive_writer = "0.2.0"
|
||||
ar_archive_writer = "0.3.0"
|
||||
arrayvec = { version = "0.7", default-features = false }
|
||||
bitflags = "2.4.1"
|
||||
cc = "1.0.90"
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ use rustc_span::symbol::Symbol;
|
|||
|
||||
use super::metadata::search_for_section;
|
||||
|
||||
pub use ar_archive_writer::get_native_object_symbols;
|
||||
use ar_archive_writer::{write_archive_to_stream, ArchiveKind, NewArchiveMember};
|
||||
pub use ar_archive_writer::{ObjectReader, DEFAULT_OBJECT_READER};
|
||||
use object::read::archive::ArchiveFile;
|
||||
use object::read::macho::FatArch;
|
||||
use tempfile::Builder as TempFileBuilder;
|
||||
|
|
@ -89,8 +89,7 @@ pub trait ArchiveBuilder {
|
|||
#[must_use = "must call build() to finish building the archive"]
|
||||
pub struct ArArchiveBuilder<'a> {
|
||||
sess: &'a Session,
|
||||
get_object_symbols:
|
||||
fn(buf: &[u8], f: &mut dyn FnMut(&[u8]) -> io::Result<()>) -> io::Result<bool>,
|
||||
object_reader: &'static ObjectReader,
|
||||
|
||||
src_archives: Vec<(PathBuf, Mmap)>,
|
||||
// Don't use an `HashMap` here, as the order is important. `lib.rmeta` needs
|
||||
|
|
@ -105,14 +104,8 @@ enum ArchiveEntry {
|
|||
}
|
||||
|
||||
impl<'a> ArArchiveBuilder<'a> {
|
||||
pub fn new(
|
||||
sess: &'a Session,
|
||||
get_object_symbols: fn(
|
||||
buf: &[u8],
|
||||
f: &mut dyn FnMut(&[u8]) -> io::Result<()>,
|
||||
) -> io::Result<bool>,
|
||||
) -> ArArchiveBuilder<'a> {
|
||||
ArArchiveBuilder { sess, get_object_symbols, src_archives: vec![], entries: vec![] }
|
||||
pub fn new(sess: &'a Session, object_reader: &'static ObjectReader) -> ArArchiveBuilder<'a> {
|
||||
ArArchiveBuilder { sess, object_reader, src_archives: vec![], entries: vec![] }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -267,7 +260,7 @@ impl<'a> ArArchiveBuilder<'a> {
|
|||
|
||||
entries.push(NewArchiveMember {
|
||||
buf: data,
|
||||
get_symbols: self.get_object_symbols,
|
||||
object_reader: self.object_reader,
|
||||
member_name: String::from_utf8(entry_name).unwrap(),
|
||||
mtime: 0,
|
||||
uid: 0,
|
||||
|
|
@ -294,7 +287,13 @@ impl<'a> ArArchiveBuilder<'a> {
|
|||
let mut archive_tmpfile = File::create_new(&archive_tmpfile_path)
|
||||
.map_err(|err| io_error_context("couldn't create the temp file", err))?;
|
||||
|
||||
write_archive_to_stream(&mut archive_tmpfile, &entries, archive_kind, false)?;
|
||||
write_archive_to_stream(
|
||||
&mut archive_tmpfile,
|
||||
&entries,
|
||||
archive_kind,
|
||||
false,
|
||||
/* is_ec = */ self.sess.target.arch == "arm64ec",
|
||||
)?;
|
||||
|
||||
let any_entries = !entries.is_empty();
|
||||
drop(entries);
|
||||
|
|
|
|||
|
|
@ -750,7 +750,7 @@ fn link_natively(
|
|||
|
||||
for print in &sess.opts.prints {
|
||||
if print.kind == PrintKind::LinkArgs {
|
||||
let content = format!("{cmd:?}");
|
||||
let content = format!("{cmd:?}\n");
|
||||
print.out.overwrite(&content, sess);
|
||||
}
|
||||
}
|
||||
|
|
@ -759,7 +759,7 @@ fn link_natively(
|
|||
sess.dcx().abort_if_errors();
|
||||
|
||||
// Invoke the system linker
|
||||
info!("{:?}", &cmd);
|
||||
info!("{cmd:?}");
|
||||
let retry_on_segfault = env::var("RUSTC_RETRY_LINKER_ON_SEGFAULT").is_ok();
|
||||
let unknown_arg_regex =
|
||||
Regex::new(r"(unknown|unrecognized) (command line )?(option|argument)").unwrap();
|
||||
|
|
@ -796,7 +796,7 @@ fn link_natively(
|
|||
cmd.arg(arg);
|
||||
}
|
||||
}
|
||||
info!("{:?}", &cmd);
|
||||
info!("{cmd:?}");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -817,7 +817,7 @@ fn link_natively(
|
|||
cmd.arg(arg);
|
||||
}
|
||||
}
|
||||
info!("{:?}", &cmd);
|
||||
info!("{cmd:?}");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -878,7 +878,7 @@ fn link_natively(
|
|||
cmd.arg(arg);
|
||||
}
|
||||
}
|
||||
info!("{:?}", &cmd);
|
||||
info!("{cmd:?}");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -996,7 +996,7 @@ fn link_natively(
|
|||
sess.dcx().emit_err(errors::UnableToExeLinker {
|
||||
linker_path,
|
||||
error: e,
|
||||
command_formatted: format!("{:?}", &cmd),
|
||||
command_formatted: format!("{cmd:?}"),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1567,7 +1567,7 @@ fn print_native_static_libs(
|
|||
sess.dcx().emit_note(errors::StaticLibraryNativeArtifacts);
|
||||
// Prefix for greppability
|
||||
// Note: This must not be translated as tools are allowed to depend on this exact string.
|
||||
sess.dcx().note(format!("native-static-libs: {}", &lib_args.join(" ")));
|
||||
sess.dcx().note(format!("native-static-libs: {}", lib_args.join(" ")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ impl<B: WriteBackendMethods> LtoModuleCodegen<B> {
|
|||
B::optimize_fat(cgcx, &mut module)?;
|
||||
Ok(module)
|
||||
}
|
||||
LtoModuleCodegen::Thin(thin) => B::optimize_thin(cgcx, thin),
|
||||
LtoModuleCodegen::Thin(thin) => unsafe { B::optimize_thin(cgcx, thin) },
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -352,7 +352,7 @@ fn exported_symbols_provider_local(
|
|||
}
|
||||
MonoItem::Fn(Instance { def: InstanceKind::DropGlue(def_id, Some(ty)), args }) => {
|
||||
// A little sanity-check
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
args.non_erasable_generics(tcx, def_id).next(),
|
||||
Some(GenericArgKind::Type(ty))
|
||||
);
|
||||
|
|
@ -370,7 +370,7 @@ fn exported_symbols_provider_local(
|
|||
args,
|
||||
}) => {
|
||||
// A little sanity-check
|
||||
debug_assert_eq!(
|
||||
assert_eq!(
|
||||
args.non_erasable_generics(tcx, def_id).next(),
|
||||
Some(GenericArgKind::Type(ty))
|
||||
);
|
||||
|
|
@ -462,7 +462,7 @@ fn upstream_monomorphizations_for_provider(
|
|||
tcx: TyCtxt<'_>,
|
||||
def_id: DefId,
|
||||
) -> Option<&UnordMap<GenericArgsRef<'_>, CrateNum>> {
|
||||
debug_assert!(!def_id.is_local());
|
||||
assert!(!def_id.is_local());
|
||||
tcx.upstream_monomorphizations(()).get(&def_id)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1512,7 +1512,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
|||
// We reduce the `running` counter by one. The
|
||||
// `tokens.truncate()` below will take care of
|
||||
// giving the Token back.
|
||||
debug_assert!(running_with_own_token > 0);
|
||||
assert!(running_with_own_token > 0);
|
||||
running_with_own_token -= 1;
|
||||
main_thread_state = MainThreadState::Lending;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -806,6 +806,34 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
|||
ongoing_codegen
|
||||
}
|
||||
|
||||
/// Returns whether a call from the current crate to the [`Instance`] would produce a call
|
||||
/// from `compiler_builtins` to a symbol the linker must resolve.
|
||||
///
|
||||
/// Such calls from `compiler_bultins` are effectively impossible for the linker to handle. Some
|
||||
/// linkers will optimize such that dead calls to unresolved symbols are not an error, but this is
|
||||
/// not guaranteed. So we used this function in codegen backends to ensure we do not generate any
|
||||
/// unlinkable calls.
|
||||
///
|
||||
/// Note that calls to LLVM intrinsics are uniquely okay because they won't make it to the linker.
|
||||
pub fn is_call_from_compiler_builtins_to_upstream_monomorphization<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
instance: Instance<'tcx>,
|
||||
) -> bool {
|
||||
fn is_llvm_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
||||
if let Some(name) = tcx.codegen_fn_attrs(def_id).link_name {
|
||||
name.as_str().starts_with("llvm.")
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
let def_id = instance.def_id();
|
||||
!def_id.is_local()
|
||||
&& tcx.is_compiler_builtins(LOCAL_CRATE)
|
||||
&& !is_llvm_intrinsic(tcx, def_id)
|
||||
&& !tcx.should_codegen_locally(instance)
|
||||
}
|
||||
|
||||
impl CrateInfo {
|
||||
pub fn new(tcx: TyCtxt<'_>, target_cpu: String) -> CrateInfo {
|
||||
let crate_types = tcx.crate_types().to_vec();
|
||||
|
|
|
|||
|
|
@ -328,7 +328,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||
sym::link_section => {
|
||||
if let Some(val) = attr.value_str() {
|
||||
if val.as_str().bytes().any(|b| b == 0) {
|
||||
let msg = format!("illegal null byte in link_section value: `{}`", &val);
|
||||
let msg = format!("illegal null byte in link_section value: `{val}`");
|
||||
tcx.dcx().span_err(attr.span, msg);
|
||||
} else {
|
||||
codegen_fn_attrs.link_section = Some(val);
|
||||
|
|
@ -726,7 +726,7 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option<u16> {
|
|||
if *ordinal <= u16::MAX as u128 {
|
||||
Some(ordinal.get() as u16)
|
||||
} else {
|
||||
let msg = format!("ordinal value in `link_ordinal` is too large: `{}`", &ordinal);
|
||||
let msg = format!("ordinal value in `link_ordinal` is too large: `{ordinal}`");
|
||||
tcx.dcx()
|
||||
.struct_span_err(attr.span, msg)
|
||||
.with_note("the value may not exceed `u16::MAX`")
|
||||
|
|
|
|||
|
|
@ -91,7 +91,6 @@ pub enum TypeKind {
|
|||
Pointer,
|
||||
Vector,
|
||||
Metadata,
|
||||
X86_MMX,
|
||||
Token,
|
||||
ScalableVector,
|
||||
BFloat,
|
||||
|
|
|
|||
|
|
@ -459,7 +459,7 @@ fn push_debuginfo_type_name<'tcx>(
|
|||
output: &mut String,
|
||||
visited: &mut FxHashSet<Ty<'tcx>>,
|
||||
) {
|
||||
debug_assert!(!wants_c_like_enum_debuginfo(ty_and_layout));
|
||||
assert!(!wants_c_like_enum_debuginfo(ty_and_layout));
|
||||
output.push_str("enum2$<");
|
||||
push_inner(output, visited);
|
||||
push_close_angle_bracket(true, output);
|
||||
|
|
@ -660,7 +660,7 @@ fn push_generic_params_internal<'tcx>(
|
|||
output: &mut String,
|
||||
visited: &mut FxHashSet<Ty<'tcx>>,
|
||||
) -> bool {
|
||||
debug_assert_eq!(args, tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args));
|
||||
assert_eq!(args, tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args));
|
||||
let mut args = args.non_erasable_generics(tcx, def_id).peekable();
|
||||
if args.peek().is_none() {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use super::operand::OperandValue::{Immediate, Pair, Ref, ZeroSized};
|
|||
use super::place::{PlaceRef, PlaceValue};
|
||||
use super::{CachedLlbb, FunctionCx, LocalRef};
|
||||
|
||||
use crate::base;
|
||||
use crate::base::{self, is_call_from_compiler_builtins_to_upstream_monomorphization};
|
||||
use crate::common::{self, IntPredicate};
|
||||
use crate::errors::CompilerBuiltinsCannotCall;
|
||||
use crate::meth;
|
||||
|
|
@ -18,7 +18,6 @@ use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
|
|||
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
||||
use rustc_middle::ty::{self, Instance, Ty};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphization;
|
||||
use rustc_session::config::OptLevel;
|
||||
use rustc_span::{source_map::Spanned, sym, Span};
|
||||
use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode, Reg};
|
||||
|
|
@ -85,7 +84,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
|
|||
}
|
||||
if is_cleanupret {
|
||||
// Cross-funclet jump - need a trampoline
|
||||
debug_assert!(base::wants_new_eh_instructions(fx.cx.tcx().sess));
|
||||
assert!(base::wants_new_eh_instructions(fx.cx.tcx().sess));
|
||||
debug!("llbb_with_cleanup: creating cleanup trampoline for {:?}", target);
|
||||
let name = &format!("{:?}_cleanup_trampoline_{:?}", self.bb, target);
|
||||
let trampoline_llbb = Bx::append_block(fx.cx, fx.llfn, name);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue