mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-03 21:47:36 +00:00
Merge from rustc
This commit is contained in:
commit
f18c39e98c
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -9,7 +9,6 @@
|
|||||||
src/etc/installer/gfx/* binary
|
src/etc/installer/gfx/* binary
|
||||||
src/vendor/** -text
|
src/vendor/** -text
|
||||||
Cargo.lock linguist-generated=false
|
Cargo.lock linguist-generated=false
|
||||||
config.toml.example linguist-language=TOML
|
|
||||||
|
|
||||||
# Older git versions try to fix line endings on images and fonts, this prevents it.
|
# Older git versions try to fix line endings on images and fonts, this prevents it.
|
||||||
*.png binary
|
*.png binary
|
||||||
|
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -443,7 +443,7 @@ jobs:
|
|||||||
os: windows-latest-xl
|
os: windows-latest-xl
|
||||||
- name: dist-x86_64-msvc
|
- name: dist-x86_64-msvc
|
||||||
env:
|
env:
|
||||||
RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=x86_64-pc-windows-msvc --target=x86_64-pc-windows-msvc --enable-full-tools --enable-profiler --set rust.lto=thin"
|
RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=x86_64-pc-windows-msvc --target=x86_64-pc-windows-msvc --enable-full-tools --enable-profiler"
|
||||||
SCRIPT: PGO_HOST=x86_64-pc-windows-msvc python src/ci/stage-build.py python x.py dist bootstrap --include-default-paths
|
SCRIPT: PGO_HOST=x86_64-pc-windows-msvc python src/ci/stage-build.py python x.py dist bootstrap --include-default-paths
|
||||||
DIST_REQUIRE_ALL_TOOLS: 1
|
DIST_REQUIRE_ALL_TOOLS: 1
|
||||||
os: windows-latest-xl
|
os: windows-latest-xl
|
||||||
|
88
.reuse/dep5
88
.reuse/dep5
@ -1,13 +1,79 @@
|
|||||||
|
# WARNING: this metadata is currently incomplete, do not rely on it yet.
|
||||||
|
|
||||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
Files-Excluded:
|
Files-Excluded:
|
||||||
src/llvm-project
|
src/llvm-project
|
||||||
|
|
||||||
Files: *
|
# 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
|
||||||
|
LICENSE-APACHE
|
||||||
|
LICENSE-MIT
|
||||||
|
README.md
|
||||||
|
RELEASES.md
|
||||||
|
rustfmt.toml
|
||||||
|
triagebot.toml
|
||||||
|
x
|
||||||
|
x.ps1
|
||||||
|
x.py
|
||||||
|
.editorconfig
|
||||||
|
.git-blame-ignore-revs
|
||||||
|
.gitattributes
|
||||||
|
.gitignore
|
||||||
|
.gitmodules
|
||||||
|
.mailmap
|
||||||
Copyright: The Rust Project Developers (see https://thanks.rust-lang.org)
|
Copyright: The Rust Project Developers (see https://thanks.rust-lang.org)
|
||||||
License: MIT or Apache-2.0
|
License: MIT or Apache-2.0
|
||||||
|
|
||||||
|
Files: compiler/rustc_apfloat/*
|
||||||
|
Copyright: LLVM APFloat authors
|
||||||
|
The Rust Project Developers (see https://thanks.rust-lang.org)
|
||||||
|
License: NCSA AND (MIT OR Apache-2.0)
|
||||||
|
|
||||||
|
Files: compiler/rustc_codegen_cranelift/src/cranelift_native.rs
|
||||||
|
Copyright: The Cranelift Project Developers
|
||||||
|
The Rust Project Developers (see https://thanks.rust-lang.org)
|
||||||
|
License: Apache-2.0 WITH LLVM-exception AND (Apache-2.0 OR MIT)
|
||||||
|
|
||||||
|
Files: compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp
|
||||||
|
Copyright: LLVM authors
|
||||||
|
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/unix/locks/fuchsia_mutex.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*
|
Files: src/librustdoc/html/static/fonts/FiraSans*
|
||||||
Copyright: 2014, Mozilla Foundation, 2014, Telefonica S.A.
|
Copyright: 2014, Mozilla Foundation
|
||||||
|
2014, Telefonica S.A.
|
||||||
License: OFL-1.1
|
License: OFL-1.1
|
||||||
|
|
||||||
Files: src/librustdoc/html/static/fonts/NanumBarun*
|
Files: src/librustdoc/html/static/fonts/NanumBarun*
|
||||||
@ -15,9 +81,19 @@ Copyright: 2010 NAVER Corporation
|
|||||||
License: OFL-1.1
|
License: OFL-1.1
|
||||||
|
|
||||||
Files: src/librustdoc/html/static/fonts/SourceCodePro*
|
Files: src/librustdoc/html/static/fonts/SourceCodePro*
|
||||||
Copyright: 2010, 2012 Adobe Systems Incorporated
|
src/librustdoc/html/static/fonts/SourceSerif4*
|
||||||
|
Copyright: 2010, 2012, 2014-2023, Adobe Systems Incorporated
|
||||||
License: OFL-1.1
|
License: OFL-1.1
|
||||||
|
|
||||||
Files: src/librustdoc/html/static/fonts/SourceSerif4*
|
Files: src/librustdoc/html/static/css/normalize.css
|
||||||
Copyright: 2014-2021 Adobe Systems Incorporated
|
Copyright: Nicolas Gallagher and Jonathan Neal
|
||||||
License: OFL-1.1
|
License: MIT
|
||||||
|
|
||||||
|
Files: src/librustdoc/html/static/css/themes/ayu.css
|
||||||
|
Copyright: Ike Ku, Jessica Stokes, 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: Knut Sveidqvist
|
||||||
|
License: MIT
|
||||||
|
@ -738,7 +738,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clippy"
|
name = "clippy"
|
||||||
version = "0.1.69"
|
version = "0.1.70"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap 4.1.4",
|
"clap 4.1.4",
|
||||||
"clippy_lints",
|
"clippy_lints",
|
||||||
@ -781,7 +781,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clippy_lints"
|
name = "clippy_lints"
|
||||||
version = "0.1.69"
|
version = "0.1.70"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cargo_metadata 0.15.3",
|
"cargo_metadata 0.15.3",
|
||||||
"clippy_utils",
|
"clippy_utils",
|
||||||
@ -804,7 +804,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clippy_utils"
|
name = "clippy_utils"
|
||||||
version = "0.1.69"
|
version = "0.1.70"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec 0.7.0",
|
"arrayvec 0.7.0",
|
||||||
"if_chain",
|
"if_chain",
|
||||||
@ -1150,7 +1150,7 @@ checksum = "a0afaad2b26fa326569eb264b1363e8ae3357618c43982b3f285f0774ce76b69"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "declare_clippy_lint"
|
name = "declare_clippy_lint"
|
||||||
version = "0.1.69"
|
version = "0.1.70"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itertools",
|
"itertools",
|
||||||
"quote",
|
"quote",
|
||||||
|
9
LICENSES/BSD-2-Clause.txt
Normal file
9
LICENSES/BSD-2-Clause.txt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
Copyright (c) <year> <owner>
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
15
LICENSES/NCSA.txt
Normal file
15
LICENSES/NCSA.txt
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
University of Illinois/NCSA Open Source License
|
||||||
|
|
||||||
|
Copyright (c) <Year> <Owner Organization Name>. All rights reserved.
|
||||||
|
|
||||||
|
Developed by: <Name of Development Group> <Name of Institution> <URL for Development Group/Institution>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal with the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the names of <Name of Development Group, Name of Institution>, nor the names of its contributors may be used to endorse or promote products derived from this Software without specific prior written permission.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
|
22
LICENSES/Unicode-DFS-2016.txt
Normal file
22
LICENSES/Unicode-DFS-2016.txt
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE
|
||||||
|
|
||||||
|
Unicode Data Files include all data files under the directories http://www.unicode.org/Public/, http://www.unicode.org/reports/, http://www.unicode.org/cldr/data/, http://source.icu-project.org/repos/icu/, and http://www.unicode.org/utility/trac/browser/.
|
||||||
|
|
||||||
|
Unicode Data Files do not include PDF online code charts under the directory http://www.unicode.org/Public/.
|
||||||
|
|
||||||
|
Software includes any source code published in the Unicode Standard or under the directories http://www.unicode.org/Public/, http://www.unicode.org/reports/, http://www.unicode.org/cldr/data/, http://source.icu-project.org/repos/icu/, and http://www.unicode.org/utility/trac/browser/.
|
||||||
|
|
||||||
|
NOTICE TO USER: Carefully read the following legal agreement. BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"), YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE.
|
||||||
|
|
||||||
|
COPYRIGHT AND PERMISSION NOTICE
|
||||||
|
|
||||||
|
Copyright © 1991-2016 Unicode, Inc. All rights reserved. Distributed under the Terms of Use in http://www.unicode.org/copyright.html.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of the Unicode data files and any associated documentation (the "Data Files") or Unicode software and any associated documentation (the "Software") to deal in the Data Files or Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, and/or sell copies of the Data Files or Software, and to permit persons to whom the Data Files or Software are furnished to do so, provided that either
|
||||||
|
|
||||||
|
(a) this copyright and permission notice appear with all copies of the Data Files or Software, or
|
||||||
|
(b) this copyright and permission notice appear in associated Documentation.
|
||||||
|
|
||||||
|
THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA FILES OR SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of a copyright holder shall not be used in advertising or otherwise to promote the sale, use or other dealings in these Data Files or Software without prior written authorization of the copyright holder.
|
@ -99,7 +99,7 @@ See [the rustc-dev-guide for more info][sysllvm].
|
|||||||
The Rust build system uses a file named `config.toml` in the root of the
|
The Rust build system uses a file named `config.toml` in the root of the
|
||||||
source tree to determine various configuration settings for the build.
|
source tree to determine various configuration settings for the build.
|
||||||
Set up the defaults intended for distros to get started. You can see a full
|
Set up the defaults intended for distros to get started. You can see a full
|
||||||
list of options in `config.toml.example`.
|
list of options in `config.example.toml`.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
printf 'profile = "user" \nchangelog-seen = 2 \n' > config.toml
|
printf 'profile = "user" \nchangelog-seen = 2 \n' > config.toml
|
||||||
|
@ -24,6 +24,15 @@
|
|||||||
// The two crates we link to here, `std` and `rustc_driver`, are both dynamic
|
// The two crates we link to here, `std` and `rustc_driver`, are both dynamic
|
||||||
// libraries. So we must reference jemalloc symbols one way or another, because
|
// libraries. So we must reference jemalloc symbols one way or another, because
|
||||||
// this file is the only object code in the rustc executable.
|
// this file is the only object code in the rustc executable.
|
||||||
|
//
|
||||||
|
// NOTE: if you are reading this comment because you want to set a custom `global_allocator` for
|
||||||
|
// benchmarking, consider using the benchmarks in the `rustc-perf` collector suite instead:
|
||||||
|
// https://github.com/rust-lang/rustc-perf/blob/master/collector/README.md#profiling
|
||||||
|
//
|
||||||
|
// NOTE: if you are reading this comment because you want to replace jemalloc with another allocator
|
||||||
|
// to compare their performance, see
|
||||||
|
// https://github.com/rust-lang/rust/commit/b90cfc887c31c3e7a9e6d462e2464db1fe506175#diff-43914724af6e464c1da2171e4a9b6c7e607d5bc1203fa95c0ab85be4122605ef
|
||||||
|
// for an example of how to do so.
|
||||||
|
|
||||||
#[unix_sigpipe = "sig_dfl"]
|
#[unix_sigpipe = "sig_dfl"]
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -1230,7 +1230,6 @@ impl Expr {
|
|||||||
|
|
||||||
pub fn precedence(&self) -> ExprPrecedence {
|
pub fn precedence(&self) -> ExprPrecedence {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
ExprKind::Box(_) => ExprPrecedence::Box,
|
|
||||||
ExprKind::Array(_) => ExprPrecedence::Array,
|
ExprKind::Array(_) => ExprPrecedence::Array,
|
||||||
ExprKind::ConstBlock(_) => ExprPrecedence::ConstBlock,
|
ExprKind::ConstBlock(_) => ExprPrecedence::ConstBlock,
|
||||||
ExprKind::Call(..) => ExprPrecedence::Call,
|
ExprKind::Call(..) => ExprPrecedence::Call,
|
||||||
@ -1291,8 +1290,7 @@ impl Expr {
|
|||||||
/// To a first-order approximation, is this a pattern?
|
/// To a first-order approximation, is this a pattern?
|
||||||
pub fn is_approximately_pattern(&self) -> bool {
|
pub fn is_approximately_pattern(&self) -> bool {
|
||||||
match &self.peel_parens().kind {
|
match &self.peel_parens().kind {
|
||||||
ExprKind::Box(_)
|
ExprKind::Array(_)
|
||||||
| ExprKind::Array(_)
|
|
||||||
| ExprKind::Call(_, _)
|
| ExprKind::Call(_, _)
|
||||||
| ExprKind::Tup(_)
|
| ExprKind::Tup(_)
|
||||||
| ExprKind::Lit(_)
|
| ExprKind::Lit(_)
|
||||||
@ -1363,8 +1361,6 @@ pub struct StructExpr {
|
|||||||
|
|
||||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||||
pub enum ExprKind {
|
pub enum ExprKind {
|
||||||
/// A `box x` expression.
|
|
||||||
Box(P<Expr>),
|
|
||||||
/// An array (`[a, b, c, d]`)
|
/// An array (`[a, b, c, d]`)
|
||||||
Array(ThinVec<P<Expr>>),
|
Array(ThinVec<P<Expr>>),
|
||||||
/// Allow anonymous constants from an inline `const` block
|
/// Allow anonymous constants from an inline `const` block
|
||||||
|
@ -1316,7 +1316,6 @@ pub fn noop_visit_expr<T: MutVisitor>(
|
|||||||
vis: &mut T,
|
vis: &mut T,
|
||||||
) {
|
) {
|
||||||
match kind {
|
match kind {
|
||||||
ExprKind::Box(expr) => vis.visit_expr(expr),
|
|
||||||
ExprKind::Array(exprs) => visit_thin_exprs(exprs, vis),
|
ExprKind::Array(exprs) => visit_thin_exprs(exprs, vis),
|
||||||
ExprKind::ConstBlock(anon_const) => {
|
ExprKind::ConstBlock(anon_const) => {
|
||||||
vis.visit_anon_const(anon_const);
|
vis.visit_anon_const(anon_const);
|
||||||
|
@ -35,7 +35,6 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
|
|||||||
| Assign(_, e, _)
|
| Assign(_, e, _)
|
||||||
| AssignOp(_, _, e)
|
| AssignOp(_, _, e)
|
||||||
| Binary(_, _, e)
|
| Binary(_, _, e)
|
||||||
| Box(e)
|
|
||||||
| Break(_, Some(e))
|
| Break(_, Some(e))
|
||||||
| Let(_, e, _)
|
| Let(_, e, _)
|
||||||
| Range(_, Some(e), _)
|
| Range(_, Some(e), _)
|
||||||
|
@ -772,7 +772,6 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
|
|||||||
walk_list!(visitor, visit_attribute, expression.attrs.iter());
|
walk_list!(visitor, visit_attribute, expression.attrs.iter());
|
||||||
|
|
||||||
match &expression.kind {
|
match &expression.kind {
|
||||||
ExprKind::Box(subexpression) => visitor.visit_expr(subexpression),
|
|
||||||
ExprKind::Array(subexpressions) => {
|
ExprKind::Array(subexpressions) => {
|
||||||
walk_list!(visitor, visit_expr, subexpressions);
|
walk_list!(visitor, visit_expr, subexpressions);
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
|
pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
|
||||||
ensure_sufficient_stack(|| {
|
ensure_sufficient_stack(|| {
|
||||||
match &e.kind {
|
match &e.kind {
|
||||||
// Paranthesis expression does not have a HirId and is handled specially.
|
// Parenthesis expression does not have a HirId and is handled specially.
|
||||||
ExprKind::Paren(ex) => {
|
ExprKind::Paren(ex) => {
|
||||||
let mut ex = self.lower_expr_mut(ex);
|
let mut ex = self.lower_expr_mut(ex);
|
||||||
// Include parens in span, but only if it is a super-span.
|
// Include parens in span, but only if it is a super-span.
|
||||||
@ -63,6 +63,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
ExprKind::ForLoop(pat, head, body, opt_label) => {
|
ExprKind::ForLoop(pat, head, body, opt_label) => {
|
||||||
return self.lower_expr_for(e, pat, head, body, *opt_label);
|
return self.lower_expr_for(e, pat, head, body, *opt_label);
|
||||||
}
|
}
|
||||||
|
// Similarly, async blocks do not use `e.id` but rather `closure_node_id`.
|
||||||
|
ExprKind::Async(capture_clause, closure_node_id, block) => {
|
||||||
|
let hir_id = self.lower_node_id(*closure_node_id);
|
||||||
|
self.lower_attrs(hir_id, &e.attrs);
|
||||||
|
return self.make_async_expr(
|
||||||
|
*capture_clause,
|
||||||
|
hir_id,
|
||||||
|
*closure_node_id,
|
||||||
|
None,
|
||||||
|
e.span,
|
||||||
|
hir::AsyncGeneratorKind::Block,
|
||||||
|
|this| this.with_new_scopes(|this| this.lower_block_expr(block)),
|
||||||
|
);
|
||||||
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +84,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
self.lower_attrs(hir_id, &e.attrs);
|
self.lower_attrs(hir_id, &e.attrs);
|
||||||
|
|
||||||
let kind = match &e.kind {
|
let kind = match &e.kind {
|
||||||
ExprKind::Box(inner) => hir::ExprKind::Box(self.lower_expr(inner)),
|
|
||||||
ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
|
ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
|
||||||
ExprKind::ConstBlock(anon_const) => {
|
ExprKind::ConstBlock(anon_const) => {
|
||||||
let anon_const = self.lower_anon_const(anon_const);
|
let anon_const = self.lower_anon_const(anon_const);
|
||||||
@ -174,15 +187,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))),
|
self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))),
|
||||||
hir::MatchSource::Normal,
|
hir::MatchSource::Normal,
|
||||||
),
|
),
|
||||||
ExprKind::Async(capture_clause, closure_node_id, block) => self.make_async_expr(
|
|
||||||
*capture_clause,
|
|
||||||
hir_id,
|
|
||||||
*closure_node_id,
|
|
||||||
None,
|
|
||||||
e.span,
|
|
||||||
hir::AsyncGeneratorKind::Block,
|
|
||||||
|this| this.with_new_scopes(|this| this.lower_block_expr(block)),
|
|
||||||
),
|
|
||||||
ExprKind::Await(expr) => {
|
ExprKind::Await(expr) => {
|
||||||
let dot_await_span = if expr.span.hi() < e.span.hi() {
|
let dot_await_span = if expr.span.hi() < e.span.hi() {
|
||||||
let span_with_whitespace = self
|
let span_with_whitespace = self
|
||||||
@ -316,7 +320,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
),
|
),
|
||||||
ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr),
|
ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr),
|
||||||
|
|
||||||
ExprKind::Paren(_) | ExprKind::ForLoop(..) => unreachable!("already handled"),
|
ExprKind::Paren(_) | ExprKind::ForLoop(..) | ExprKind::Async(..) => {
|
||||||
|
unreachable!("already handled")
|
||||||
|
}
|
||||||
|
|
||||||
ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span),
|
ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span),
|
||||||
};
|
};
|
||||||
@ -578,9 +584,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
/// This results in:
|
/// This results in:
|
||||||
///
|
///
|
||||||
/// ```text
|
/// ```text
|
||||||
/// std::future::identity_future(static move? |_task_context| -> <ret_ty> {
|
/// static move? |_task_context| -> <ret_ty> {
|
||||||
/// <body>
|
/// <body>
|
||||||
/// })
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub(super) fn make_async_expr(
|
pub(super) fn make_async_expr(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -591,7 +597,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
span: Span,
|
span: Span,
|
||||||
async_gen_kind: hir::AsyncGeneratorKind,
|
async_gen_kind: hir::AsyncGeneratorKind,
|
||||||
body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
|
body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
|
||||||
) -> hir::ExprKind<'hir> {
|
) -> hir::Expr<'hir> {
|
||||||
let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span)));
|
let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span)));
|
||||||
|
|
||||||
// Resume argument type: `ResumeTy`
|
// Resume argument type: `ResumeTy`
|
||||||
@ -656,13 +662,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let hir_id = self.lower_node_id(closure_node_id);
|
let hir_id = self.lower_node_id(closure_node_id);
|
||||||
let unstable_span =
|
|
||||||
self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
|
|
||||||
|
|
||||||
if self.tcx.features().closure_track_caller
|
if self.tcx.features().closure_track_caller
|
||||||
&& let Some(attrs) = self.attrs.get(&outer_hir_id.local_id)
|
&& let Some(attrs) = self.attrs.get(&outer_hir_id.local_id)
|
||||||
&& attrs.into_iter().any(|attr| attr.has_name(sym::track_caller))
|
&& attrs.into_iter().any(|attr| attr.has_name(sym::track_caller))
|
||||||
{
|
{
|
||||||
|
let unstable_span =
|
||||||
|
self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
|
||||||
self.lower_attrs(
|
self.lower_attrs(
|
||||||
hir_id,
|
hir_id,
|
||||||
&[Attribute {
|
&[Attribute {
|
||||||
@ -681,22 +686,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let generator = hir::Expr { hir_id, kind: generator_kind, span: self.lower_span(span) };
|
hir::Expr { hir_id, kind: generator_kind, span: self.lower_span(span) }
|
||||||
|
|
||||||
// FIXME(swatinem):
|
|
||||||
// For some reason, the async block needs to flow through *any*
|
|
||||||
// call (like the identity function), as otherwise type and lifetime
|
|
||||||
// inference have a hard time figuring things out.
|
|
||||||
// Without this, we would get:
|
|
||||||
// E0720 in tests/ui/impl-trait/in-trait/default-body-with-rpit.rs
|
|
||||||
// E0700 in tests/ui/self/self_lifetime-async.rs
|
|
||||||
|
|
||||||
// `future::identity_future`:
|
|
||||||
let identity_future =
|
|
||||||
self.expr_lang_item_path(unstable_span, hir::LangItem::IdentityFuture, None);
|
|
||||||
|
|
||||||
// `future::identity_future(generator)`:
|
|
||||||
hir::ExprKind::Call(self.arena.alloc(identity_future), arena_vec![self; generator])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Desugar `<expr>.await` into:
|
/// Desugar `<expr>.await` into:
|
||||||
@ -1002,7 +992,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Transform `async |x: u8| -> X { ... }` into
|
// Transform `async |x: u8| -> X { ... }` into
|
||||||
// `|x: u8| identity_future(|| -> X { ... })`.
|
// `|x: u8| || -> X { ... }`.
|
||||||
let body_id = this.lower_fn_body(&outer_decl, |this| {
|
let body_id = this.lower_fn_body(&outer_decl, |this| {
|
||||||
let async_ret_ty = if let FnRetTy::Ty(ty) = &decl.output {
|
let async_ret_ty = if let FnRetTy::Ty(ty) = &decl.output {
|
||||||
let itctx = ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock);
|
let itctx = ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock);
|
||||||
@ -1011,7 +1001,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let async_body = this.make_async_expr(
|
this.make_async_expr(
|
||||||
capture_clause,
|
capture_clause,
|
||||||
closure_hir_id,
|
closure_hir_id,
|
||||||
inner_closure_id,
|
inner_closure_id,
|
||||||
@ -1019,8 +1009,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
body.span,
|
body.span,
|
||||||
hir::AsyncGeneratorKind::Closure,
|
hir::AsyncGeneratorKind::Closure,
|
||||||
|this| this.with_new_scopes(|this| this.lower_expr_mut(body)),
|
|this| this.with_new_scopes(|this| this.lower_expr_mut(body)),
|
||||||
);
|
)
|
||||||
this.expr(fn_decl_span, async_body)
|
|
||||||
});
|
});
|
||||||
body_id
|
body_id
|
||||||
});
|
});
|
||||||
|
@ -1180,7 +1180,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
(this.arena.alloc_from_iter(parameters), this.expr(body.span, async_expr))
|
(this.arena.alloc_from_iter(parameters), async_expr)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ mod lifetime_collector;
|
|||||||
mod pat;
|
mod pat;
|
||||||
mod path;
|
mod path;
|
||||||
|
|
||||||
fluent_messages! { "../locales/en-US.ftl" }
|
fluent_messages! { "../messages.ftl" }
|
||||||
|
|
||||||
struct LoweringContext<'a, 'hir> {
|
struct LoweringContext<'a, 'hir> {
|
||||||
tcx: TyCtxt<'hir>,
|
tcx: TyCtxt<'hir>,
|
||||||
@ -435,7 +435,9 @@ fn compute_hir_hash(
|
|||||||
|
|
||||||
pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> {
|
pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> {
|
||||||
let sess = tcx.sess;
|
let sess = tcx.sess;
|
||||||
tcx.ensure().output_filenames(());
|
// Queries that borrow `resolver_for_lowering`.
|
||||||
|
tcx.ensure_with_value().output_filenames(());
|
||||||
|
tcx.ensure_with_value().early_lint_checks(());
|
||||||
let (mut resolver, krate) = tcx.resolver_for_lowering(()).steal();
|
let (mut resolver, krate) = tcx.resolver_for_lowering(()).steal();
|
||||||
|
|
||||||
let ast_index = index_crate(&resolver.node_id_to_def_id, &krate);
|
let ast_index = index_crate(&resolver.node_id_to_def_id, &krate);
|
||||||
@ -463,8 +465,10 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> {
|
|||||||
rustc_span::hygiene::clear_syntax_context_map();
|
rustc_span::hygiene::clear_syntax_context_map();
|
||||||
}
|
}
|
||||||
|
|
||||||
let hir_hash = compute_hir_hash(tcx, &owners);
|
// Don't hash unless necessary, because it's expensive.
|
||||||
hir::Crate { owners, hir_hash }
|
let opt_hir_hash =
|
||||||
|
if tcx.sess.needs_crate_hash() { Some(compute_hir_hash(tcx, &owners)) } else { None };
|
||||||
|
hir::Crate { owners, opt_hir_hash }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||||
@ -657,42 +661,33 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
|
|
||||||
bodies.sort_by_key(|(k, _)| *k);
|
bodies.sort_by_key(|(k, _)| *k);
|
||||||
let bodies = SortedMap::from_presorted_elements(bodies);
|
let bodies = SortedMap::from_presorted_elements(bodies);
|
||||||
let (hash_including_bodies, hash_without_bodies) = self.hash_owner(node, &bodies);
|
|
||||||
let (nodes, parenting) =
|
// Don't hash unless necessary, because it's expensive.
|
||||||
index::index_hir(self.tcx.sess, &*self.tcx.definitions_untracked(), node, &bodies);
|
let (opt_hash_including_bodies, attrs_hash) = if self.tcx.sess.needs_crate_hash() {
|
||||||
let nodes = hir::OwnerNodes { hash_including_bodies, hash_without_bodies, nodes, bodies };
|
self.tcx.with_stable_hashing_context(|mut hcx| {
|
||||||
let attrs = {
|
let mut stable_hasher = StableHasher::new();
|
||||||
let hash = self.tcx.with_stable_hashing_context(|mut hcx| {
|
hcx.with_hir_bodies(node.def_id(), &bodies, |hcx| {
|
||||||
|
node.hash_stable(hcx, &mut stable_hasher)
|
||||||
|
});
|
||||||
|
let h1 = stable_hasher.finish();
|
||||||
|
|
||||||
let mut stable_hasher = StableHasher::new();
|
let mut stable_hasher = StableHasher::new();
|
||||||
attrs.hash_stable(&mut hcx, &mut stable_hasher);
|
attrs.hash_stable(&mut hcx, &mut stable_hasher);
|
||||||
stable_hasher.finish()
|
let h2 = stable_hasher.finish();
|
||||||
});
|
|
||||||
hir::AttributeMap { map: attrs, hash }
|
(Some(h1), Some(h2))
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
(None, None)
|
||||||
};
|
};
|
||||||
|
let (nodes, parenting) =
|
||||||
|
index::index_hir(self.tcx.sess, &*self.tcx.definitions_untracked(), node, &bodies);
|
||||||
|
let nodes = hir::OwnerNodes { opt_hash_including_bodies, nodes, bodies };
|
||||||
|
let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash };
|
||||||
|
|
||||||
self.arena.alloc(hir::OwnerInfo { nodes, parenting, attrs, trait_map })
|
self.arena.alloc(hir::OwnerInfo { nodes, parenting, attrs, trait_map })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hash the HIR node twice, one deep and one shallow hash. This allows to differentiate
|
|
||||||
/// queries which depend on the full HIR tree and those which only depend on the item signature.
|
|
||||||
fn hash_owner(
|
|
||||||
&mut self,
|
|
||||||
node: hir::OwnerNode<'hir>,
|
|
||||||
bodies: &SortedMap<hir::ItemLocalId, &'hir hir::Body<'hir>>,
|
|
||||||
) -> (Fingerprint, Fingerprint) {
|
|
||||||
self.tcx.with_stable_hashing_context(|mut hcx| {
|
|
||||||
let mut stable_hasher = StableHasher::new();
|
|
||||||
hcx.with_hir_bodies(node.def_id(), bodies, |hcx| {
|
|
||||||
node.hash_stable(hcx, &mut stable_hasher)
|
|
||||||
});
|
|
||||||
let hash_including_bodies = stable_hasher.finish();
|
|
||||||
let mut stable_hasher = StableHasher::new();
|
|
||||||
hcx.without_hir_bodies(|hcx| node.hash_stable(hcx, &mut stable_hasher));
|
|
||||||
let hash_without_bodies = stable_hasher.finish();
|
|
||||||
(hash_including_bodies, hash_without_bodies)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This method allocates a new `HirId` for the given `NodeId` and stores it in
|
/// This method allocates a new `HirId` for the given `NodeId` and stores it in
|
||||||
/// the `LoweringContext`'s `NodeId => HirId` map.
|
/// the `LoweringContext`'s `NodeId => HirId` map.
|
||||||
/// Take care not to call this method if the resulting `HirId` is then not
|
/// Take care not to call this method if the resulting `HirId` is then not
|
||||||
|
@ -337,9 +337,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||||||
ast::TyKind::Never => {
|
ast::TyKind::Never => {
|
||||||
gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental");
|
gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental");
|
||||||
}
|
}
|
||||||
ast::TyKind::TraitObject(_, ast::TraitObjectSyntax::DynStar, ..) => {
|
|
||||||
gate_feature_post!(&self, dyn_star, ty.span, "dyn* trait objects are unstable");
|
|
||||||
}
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
visit::walk_ty(self, ty)
|
visit::walk_ty(self, ty)
|
||||||
@ -395,14 +392,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||||||
|
|
||||||
fn visit_expr(&mut self, e: &'a ast::Expr) {
|
fn visit_expr(&mut self, e: &'a ast::Expr) {
|
||||||
match e.kind {
|
match e.kind {
|
||||||
ast::ExprKind::Box(_) => {
|
|
||||||
gate_feature_post!(
|
|
||||||
&self,
|
|
||||||
box_syntax,
|
|
||||||
e.span,
|
|
||||||
"box expression syntax is experimental; you can call `Box::new` instead"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
ast::ExprKind::Type(..) => {
|
ast::ExprKind::Type(..) => {
|
||||||
if self.sess.parse_sess.span_diagnostic.err_count() == 0 {
|
if self.sess.parse_sess.span_diagnostic.err_count() == 0 {
|
||||||
// To avoid noise about type ascription in common syntax errors,
|
// To avoid noise about type ascription in common syntax errors,
|
||||||
@ -425,14 +414,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||||||
ast::ExprKind::TryBlock(_) => {
|
ast::ExprKind::TryBlock(_) => {
|
||||||
gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental");
|
gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental");
|
||||||
}
|
}
|
||||||
ast::ExprKind::Closure(box ast::Closure { constness: ast::Const::Yes(_), .. }) => {
|
|
||||||
gate_feature_post!(
|
|
||||||
&self,
|
|
||||||
const_closures,
|
|
||||||
e.span,
|
|
||||||
"const closures are experimental"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
visit::walk_expr(self, e)
|
visit::walk_expr(self, e)
|
||||||
@ -594,6 +575,8 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
|
|||||||
gate_all!(inline_const_pat, "inline-const in pattern position is experimental");
|
gate_all!(inline_const_pat, "inline-const in pattern position is experimental");
|
||||||
gate_all!(associated_const_equality, "associated const equality is incomplete");
|
gate_all!(associated_const_equality, "associated const equality is incomplete");
|
||||||
gate_all!(yeet_expr, "`do yeet` expression is experimental");
|
gate_all!(yeet_expr, "`do yeet` expression is experimental");
|
||||||
|
gate_all!(dyn_star, "`dyn*` trait objects are experimental");
|
||||||
|
gate_all!(const_closures, "const closures are experimental");
|
||||||
|
|
||||||
// All uses of `gate_all!` below this point were added in #65742,
|
// All uses of `gate_all!` below this point were added in #65742,
|
||||||
// and subsequently disabled (with the non-early gating readded).
|
// and subsequently disabled (with the non-early gating readded).
|
||||||
@ -613,7 +596,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
|
|||||||
gate_all!(box_patterns, "box pattern syntax is experimental");
|
gate_all!(box_patterns, "box pattern syntax is experimental");
|
||||||
gate_all!(exclusive_range_pattern, "exclusive range pattern syntax is experimental");
|
gate_all!(exclusive_range_pattern, "exclusive range pattern syntax is experimental");
|
||||||
gate_all!(try_blocks, "`try` blocks are unstable");
|
gate_all!(try_blocks, "`try` blocks are unstable");
|
||||||
gate_all!(box_syntax, "box expression syntax is experimental; you can call `Box::new` instead");
|
|
||||||
gate_all!(type_ascription, "type ascription is experimental");
|
gate_all!(type_ascription, "type ascription is experimental");
|
||||||
|
|
||||||
visit::walk_crate(&mut visitor, krate);
|
visit::walk_crate(&mut visitor, krate);
|
||||||
|
@ -21,4 +21,4 @@ pub mod feature_gate;
|
|||||||
pub mod node_count;
|
pub mod node_count;
|
||||||
pub mod show_span;
|
pub mod show_span;
|
||||||
|
|
||||||
fluent_messages! { "../locales/en-US.ftl" }
|
fluent_messages! { "../messages.ftl" }
|
||||||
|
@ -244,6 +244,10 @@ impl<'a> State<'a> {
|
|||||||
(&ast::ExprKind::Let { .. }, _) if !parser::needs_par_as_let_scrutinee(prec) => {
|
(&ast::ExprKind::Let { .. }, _) if !parser::needs_par_as_let_scrutinee(prec) => {
|
||||||
parser::PREC_FORCE_PAREN
|
parser::PREC_FORCE_PAREN
|
||||||
}
|
}
|
||||||
|
// For a binary expression like `(match () { _ => a }) OP b`, the parens are required
|
||||||
|
// otherwise the parser would interpret `match () { _ => a }` as a statement,
|
||||||
|
// with the remaining `OP b` not making sense. So we force parens.
|
||||||
|
(&ast::ExprKind::Match(..), _) => parser::PREC_FORCE_PAREN,
|
||||||
_ => left_prec,
|
_ => left_prec,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -292,10 +296,6 @@ impl<'a> State<'a> {
|
|||||||
self.ibox(INDENT_UNIT);
|
self.ibox(INDENT_UNIT);
|
||||||
self.ann.pre(self, AnnNode::Expr(expr));
|
self.ann.pre(self, AnnNode::Expr(expr));
|
||||||
match &expr.kind {
|
match &expr.kind {
|
||||||
ast::ExprKind::Box(expr) => {
|
|
||||||
self.word_space("box");
|
|
||||||
self.print_expr_maybe_paren(expr, parser::PREC_PREFIX);
|
|
||||||
}
|
|
||||||
ast::ExprKind::Array(exprs) => {
|
ast::ExprKind::Array(exprs) => {
|
||||||
self.print_expr_vec(exprs);
|
self.print_expr_vec(exprs);
|
||||||
}
|
}
|
||||||
|
@ -26,4 +26,4 @@ pub use rustc_ast::attr::*;
|
|||||||
|
|
||||||
pub(crate) use rustc_ast::HashStableContext;
|
pub(crate) use rustc_ast::HashStableContext;
|
||||||
|
|
||||||
fluent_messages! { "../locales/en-US.ftl" }
|
fluent_messages! { "../messages.ftl" }
|
||||||
|
@ -1985,16 +1985,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
let (place_desc, note) = if let Some(place_desc) = opt_place_desc {
|
let (place_desc, note) = if let Some(place_desc) = opt_place_desc {
|
||||||
let local_kind = if let Some(local) = borrow.borrowed_place.as_local() {
|
let local_kind = if let Some(local) = borrow.borrowed_place.as_local() {
|
||||||
match self.body.local_kind(local) {
|
match self.body.local_kind(local) {
|
||||||
LocalKind::ReturnPointer | LocalKind::Temp => {
|
LocalKind::Temp if self.body.local_decls[local].is_user_variable() => {
|
||||||
bug!("temporary or return pointer with a name")
|
"local variable "
|
||||||
}
|
}
|
||||||
LocalKind::Var => "local variable ",
|
|
||||||
LocalKind::Arg
|
LocalKind::Arg
|
||||||
if !self.upvars.is_empty() && local == ty::CAPTURE_STRUCT_LOCAL =>
|
if !self.upvars.is_empty() && local == ty::CAPTURE_STRUCT_LOCAL =>
|
||||||
{
|
{
|
||||||
"variable captured by `move` "
|
"variable captured by `move` "
|
||||||
}
|
}
|
||||||
LocalKind::Arg => "function parameter ",
|
LocalKind::Arg => "function parameter ",
|
||||||
|
LocalKind::ReturnPointer | LocalKind::Temp => {
|
||||||
|
bug!("temporary or return pointer with a name")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
"local data "
|
"local data "
|
||||||
@ -2008,16 +2010,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
self.prefixes(borrow.borrowed_place.as_ref(), PrefixSet::All).last().unwrap();
|
self.prefixes(borrow.borrowed_place.as_ref(), PrefixSet::All).last().unwrap();
|
||||||
let local = root_place.local;
|
let local = root_place.local;
|
||||||
match self.body.local_kind(local) {
|
match self.body.local_kind(local) {
|
||||||
LocalKind::ReturnPointer | LocalKind::Temp => {
|
|
||||||
("temporary value".to_string(), "temporary value created here".to_string())
|
|
||||||
}
|
|
||||||
LocalKind::Arg => (
|
LocalKind::Arg => (
|
||||||
"function parameter".to_string(),
|
"function parameter".to_string(),
|
||||||
"function parameter borrowed here".to_string(),
|
"function parameter borrowed here".to_string(),
|
||||||
),
|
),
|
||||||
LocalKind::Var => {
|
LocalKind::Temp if self.body.local_decls[local].is_user_variable() => {
|
||||||
("local binding".to_string(), "local binding introduced here".to_string())
|
("local binding".to_string(), "local binding introduced here".to_string())
|
||||||
}
|
}
|
||||||
|
LocalKind::ReturnPointer | LocalKind::Temp => {
|
||||||
|
("temporary value".to_string(), "temporary value created here".to_string())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2482,15 +2484,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
let (place_description, assigned_span) = match local_decl {
|
let (place_description, assigned_span) = match local_decl {
|
||||||
Some(LocalDecl {
|
Some(LocalDecl {
|
||||||
local_info:
|
local_info:
|
||||||
Some(box LocalInfo::User(
|
ClearCrossCrate::Set(
|
||||||
ClearCrossCrate::Clear
|
box LocalInfo::User(BindingForm::Var(VarBindingForm {
|
||||||
| ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
|
|
||||||
opt_match_place: None,
|
opt_match_place: None,
|
||||||
..
|
..
|
||||||
})),
|
}))
|
||||||
))
|
| box LocalInfo::StaticRef { .. }
|
||||||
| Some(box LocalInfo::StaticRef { .. })
|
| box LocalInfo::Boring,
|
||||||
| None,
|
),
|
||||||
..
|
..
|
||||||
})
|
})
|
||||||
| None => (self.describe_any_place(place.as_ref()), assigned_span),
|
| None => (self.describe_any_place(place.as_ref()), assigned_span),
|
||||||
|
@ -6,8 +6,8 @@ use rustc_hir::intravisit::Visitor;
|
|||||||
use rustc_index::vec::IndexVec;
|
use rustc_index::vec::IndexVec;
|
||||||
use rustc_infer::infer::NllRegionVariableOrigin;
|
use rustc_infer::infer::NllRegionVariableOrigin;
|
||||||
use rustc_middle::mir::{
|
use rustc_middle::mir::{
|
||||||
Body, CastKind, ConstraintCategory, FakeReadCause, Local, Location, Operand, Place, Rvalue,
|
Body, CastKind, ConstraintCategory, FakeReadCause, Local, LocalInfo, Location, Operand, Place,
|
||||||
Statement, StatementKind, TerminatorKind,
|
Rvalue, Statement, StatementKind, TerminatorKind,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::adjustment::PointerCast;
|
use rustc_middle::ty::adjustment::PointerCast;
|
||||||
use rustc_middle::ty::{self, RegionVid, TyCtxt};
|
use rustc_middle::ty::{self, RegionVid, TyCtxt};
|
||||||
@ -220,7 +220,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
|
|||||||
);
|
);
|
||||||
err.span_label(body.source_info(drop_loc).span, message);
|
err.span_label(body.source_info(drop_loc).span, message);
|
||||||
|
|
||||||
if let Some(info) = &local_decl.is_block_tail {
|
if let LocalInfo::BlockTailTemp(info) = local_decl.local_info() {
|
||||||
if info.tail_result_is_ignored {
|
if info.tail_result_is_ignored {
|
||||||
// #85581: If the first mutable borrow's scope contains
|
// #85581: If the first mutable borrow's scope contains
|
||||||
// the second borrow, this suggestion isn't helpful.
|
// the second borrow, this suggestion isn't helpful.
|
||||||
|
@ -196,10 +196,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
if self.body.local_decls[local].is_ref_for_guard() {
|
if self.body.local_decls[local].is_ref_for_guard() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Some(box LocalInfo::StaticRef { def_id, .. }) =
|
if let LocalInfo::StaticRef { def_id, .. } =
|
||||||
&self.body.local_decls[local].local_info
|
*self.body.local_decls[local].local_info()
|
||||||
{
|
{
|
||||||
buf.push_str(self.infcx.tcx.item_name(*def_id).as_str());
|
buf.push_str(self.infcx.tcx.item_name(def_id).as_str());
|
||||||
ok = Ok(());
|
ok = Ok(());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -102,14 +102,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
//
|
//
|
||||||
// opt_match_place is None for let [mut] x = ... statements,
|
// opt_match_place is None for let [mut] x = ... statements,
|
||||||
// whether or not the right-hand side is a place expression
|
// whether or not the right-hand side is a place expression
|
||||||
if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
|
if let LocalInfo::User(BindingForm::Var(VarBindingForm {
|
||||||
VarBindingForm {
|
opt_match_place: Some((opt_match_place, match_span)),
|
||||||
opt_match_place: Some((opt_match_place, match_span)),
|
binding_mode: _,
|
||||||
binding_mode: _,
|
opt_ty_info: _,
|
||||||
opt_ty_info: _,
|
pat_span: _,
|
||||||
pat_span: _,
|
})) = *local_decl.local_info()
|
||||||
},
|
|
||||||
)))) = local_decl.local_info
|
|
||||||
{
|
{
|
||||||
let stmt_source_info = self.body.source_info(location);
|
let stmt_source_info = self.body.source_info(location);
|
||||||
self.append_binding_error(
|
self.append_binding_error(
|
||||||
@ -478,9 +476,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
let mut suggestions: Vec<(Span, String, String)> = Vec::new();
|
let mut suggestions: Vec<(Span, String, String)> = Vec::new();
|
||||||
for local in binds_to {
|
for local in binds_to {
|
||||||
let bind_to = &self.body.local_decls[*local];
|
let bind_to = &self.body.local_decls[*local];
|
||||||
if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
|
if let LocalInfo::User(BindingForm::Var(VarBindingForm { pat_span, .. })) =
|
||||||
VarBindingForm { pat_span, .. },
|
*bind_to.local_info()
|
||||||
)))) = bind_to.local_info
|
|
||||||
{
|
{
|
||||||
let Ok(pat_snippet) =
|
let Ok(pat_snippet) =
|
||||||
self.infcx.tcx.sess.source_map().span_to_snippet(pat_span) else { continue; };
|
self.infcx.tcx.sess.source_map().span_to_snippet(pat_span) else { continue; };
|
||||||
|
@ -7,7 +7,7 @@ use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem};
|
|||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_middle::{
|
use rustc_middle::{
|
||||||
hir::place::PlaceBase,
|
hir::place::PlaceBase,
|
||||||
mir::{self, BindingForm, ClearCrossCrate, Local, LocalDecl, LocalInfo, LocalKind, Location},
|
mir::{self, BindingForm, Local, LocalDecl, LocalInfo, LocalKind, Location},
|
||||||
};
|
};
|
||||||
use rustc_span::source_map::DesugaringKind;
|
use rustc_span::source_map::DesugaringKind;
|
||||||
use rustc_span::symbol::{kw, Symbol};
|
use rustc_span::symbol::{kw, Symbol};
|
||||||
@ -105,8 +105,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
reason = String::new();
|
reason = String::new();
|
||||||
} else {
|
} else {
|
||||||
item_msg = access_place_desc;
|
item_msg = access_place_desc;
|
||||||
let local_info = &self.body.local_decls[local].local_info;
|
let local_info = self.body.local_decls[local].local_info();
|
||||||
if let Some(box LocalInfo::StaticRef { def_id, .. }) = *local_info {
|
if let LocalInfo::StaticRef { def_id, .. } = *local_info {
|
||||||
let static_name = &self.infcx.tcx.item_name(def_id);
|
let static_name = &self.infcx.tcx.item_name(def_id);
|
||||||
reason = format!(", as `{static_name}` is an immutable static item");
|
reason = format!(", as `{static_name}` is an immutable static item");
|
||||||
} else {
|
} else {
|
||||||
@ -305,15 +305,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
..
|
..
|
||||||
}) = &self.body[location.block].statements.get(location.statement_index)
|
}) = &self.body[location.block].statements.get(location.statement_index)
|
||||||
{
|
{
|
||||||
match decl.local_info {
|
match *decl.local_info() {
|
||||||
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
|
LocalInfo::User(BindingForm::Var(mir::VarBindingForm {
|
||||||
mir::VarBindingForm {
|
binding_mode: ty::BindingMode::BindByValue(Mutability::Not),
|
||||||
binding_mode: ty::BindingMode::BindByValue(Mutability::Not),
|
opt_ty_info: Some(sp),
|
||||||
opt_ty_info: Some(sp),
|
opt_match_place: _,
|
||||||
opt_match_place: _,
|
pat_span: _,
|
||||||
pat_span: _,
|
})) => {
|
||||||
},
|
|
||||||
)))) => {
|
|
||||||
if suggest {
|
if suggest {
|
||||||
err.span_note(sp, "the binding is already a mutable borrow");
|
err.span_note(sp, "the binding is already a mutable borrow");
|
||||||
}
|
}
|
||||||
@ -346,10 +344,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
} else if decl.mutability.is_not() {
|
} else if decl.mutability.is_not() {
|
||||||
if matches!(
|
if matches!(
|
||||||
decl.local_info,
|
decl.local_info(),
|
||||||
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(
|
LocalInfo::User(BindingForm::ImplicitSelf(hir::ImplicitSelfKind::MutRef))
|
||||||
hir::ImplicitSelfKind::MutRef
|
|
||||||
),)))
|
|
||||||
) {
|
) {
|
||||||
err.note(
|
err.note(
|
||||||
"as `Self` may be unsized, this call attempts to take `&mut &mut self`",
|
"as `Self` may be unsized, this call attempts to take `&mut &mut self`",
|
||||||
@ -482,22 +478,18 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
match self.local_names[local] {
|
match self.local_names[local] {
|
||||||
Some(name) if !local_decl.from_compiler_desugaring() => {
|
Some(name) if !local_decl.from_compiler_desugaring() => {
|
||||||
let label = match local_decl.local_info.as_deref().unwrap() {
|
let label = match *local_decl.local_info() {
|
||||||
LocalInfo::User(ClearCrossCrate::Set(
|
LocalInfo::User(mir::BindingForm::ImplicitSelf(_)) => {
|
||||||
mir::BindingForm::ImplicitSelf(_),
|
|
||||||
)) => {
|
|
||||||
let (span, suggestion) =
|
let (span, suggestion) =
|
||||||
suggest_ampmut_self(self.infcx.tcx, local_decl);
|
suggest_ampmut_self(self.infcx.tcx, local_decl);
|
||||||
Some((true, span, suggestion))
|
Some((true, span, suggestion))
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
|
LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm {
|
||||||
mir::VarBindingForm {
|
binding_mode: ty::BindingMode::BindByValue(_),
|
||||||
binding_mode: ty::BindingMode::BindByValue(_),
|
opt_ty_info,
|
||||||
opt_ty_info,
|
..
|
||||||
..
|
})) => {
|
||||||
},
|
|
||||||
))) => {
|
|
||||||
// check if the RHS is from desugaring
|
// check if the RHS is from desugaring
|
||||||
let opt_assignment_rhs_span =
|
let opt_assignment_rhs_span =
|
||||||
self.body.find_assignments(local).first().map(|&location| {
|
self.body.find_assignments(local).first().map(|&location| {
|
||||||
@ -534,16 +526,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
self.infcx.tcx,
|
self.infcx.tcx,
|
||||||
local_decl,
|
local_decl,
|
||||||
opt_assignment_rhs_span,
|
opt_assignment_rhs_span,
|
||||||
*opt_ty_info,
|
opt_ty_info,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
match local_decl.local_info.as_deref() {
|
match local_decl.local_info() {
|
||||||
Some(LocalInfo::User(ClearCrossCrate::Set(
|
LocalInfo::User(mir::BindingForm::Var(
|
||||||
mir::BindingForm::Var(mir::VarBindingForm {
|
mir::VarBindingForm {
|
||||||
opt_ty_info: None,
|
opt_ty_info: None, ..
|
||||||
..
|
},
|
||||||
}),
|
)) => {
|
||||||
))) => {
|
|
||||||
let (span, sugg) = suggest_ampmut_self(
|
let (span, sugg) = suggest_ampmut_self(
|
||||||
self.infcx.tcx,
|
self.infcx.tcx,
|
||||||
local_decl,
|
local_decl,
|
||||||
@ -555,7 +546,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
self.infcx.tcx,
|
self.infcx.tcx,
|
||||||
local_decl,
|
local_decl,
|
||||||
opt_assignment_rhs_span,
|
opt_assignment_rhs_span,
|
||||||
*opt_ty_info,
|
opt_ty_info,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -564,21 +555,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
|
LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm {
|
||||||
mir::VarBindingForm {
|
binding_mode: ty::BindingMode::BindByReference(_),
|
||||||
binding_mode: ty::BindingMode::BindByReference(_),
|
..
|
||||||
..
|
})) => {
|
||||||
},
|
|
||||||
))) => {
|
|
||||||
let pattern_span = local_decl.source_info.span;
|
let pattern_span = local_decl.source_info.span;
|
||||||
suggest_ref_mut(self.infcx.tcx, pattern_span)
|
suggest_ref_mut(self.infcx.tcx, pattern_span)
|
||||||
.map(|replacement| (true, pattern_span, replacement))
|
.map(|replacement| (true, pattern_span, replacement))
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalInfo::User(ClearCrossCrate::Clear) => {
|
|
||||||
bug!("saw cleared local state")
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1151,20 +1136,19 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
pub fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option<Symbol>) -> bool {
|
pub fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option<Symbol>) -> bool {
|
||||||
debug!("local_info: {:?}, ty.kind(): {:?}", local_decl.local_info, local_decl.ty.kind());
|
debug!("local_info: {:?}, ty.kind(): {:?}", local_decl.local_info, local_decl.ty.kind());
|
||||||
|
|
||||||
match local_decl.local_info.as_deref() {
|
match *local_decl.local_info() {
|
||||||
// Check if mutably borrowing a mutable reference.
|
// Check if mutably borrowing a mutable reference.
|
||||||
Some(LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
|
LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm {
|
||||||
mir::VarBindingForm {
|
binding_mode: ty::BindingMode::BindByValue(Mutability::Not),
|
||||||
binding_mode: ty::BindingMode::BindByValue(Mutability::Not), ..
|
..
|
||||||
},
|
})) => matches!(local_decl.ty.kind(), ty::Ref(_, _, hir::Mutability::Mut)),
|
||||||
)))) => matches!(local_decl.ty.kind(), ty::Ref(_, _, hir::Mutability::Mut)),
|
LocalInfo::User(mir::BindingForm::ImplicitSelf(kind)) => {
|
||||||
Some(LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf(kind)))) => {
|
|
||||||
// Check if the user variable is a `&mut self` and we can therefore
|
// Check if the user variable is a `&mut self` and we can therefore
|
||||||
// suggest removing the `&mut`.
|
// suggest removing the `&mut`.
|
||||||
//
|
//
|
||||||
// Deliberately fall into this case for all implicit self types,
|
// Deliberately fall into this case for all implicit self types,
|
||||||
// so that we don't fall in to the next case with them.
|
// so that we don't fall in to the next case with them.
|
||||||
*kind == hir::ImplicitSelfKind::MutRef
|
kind == hir::ImplicitSelfKind::MutRef
|
||||||
}
|
}
|
||||||
_ if Some(kw::SelfLower) == local_name => {
|
_ if Some(kw::SelfLower) == local_name => {
|
||||||
// Otherwise, check if the name is the `self` keyword - in which case
|
// Otherwise, check if the name is the `self` keyword - in which case
|
||||||
|
@ -100,7 +100,7 @@ use places_conflict::{places_conflict, PlaceConflictBias};
|
|||||||
use region_infer::RegionInferenceContext;
|
use region_infer::RegionInferenceContext;
|
||||||
use renumber::RegionCtxt;
|
use renumber::RegionCtxt;
|
||||||
|
|
||||||
fluent_messages! { "../locales/en-US.ftl" }
|
fluent_messages! { "../messages.ftl" }
|
||||||
|
|
||||||
// FIXME(eddyb) perhaps move this somewhere more centrally.
|
// FIXME(eddyb) perhaps move this somewhere more centrally.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -325,7 +325,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
|
|||||||
if errors.is_empty() {
|
if errors.is_empty() {
|
||||||
definition_ty
|
definition_ty
|
||||||
} else {
|
} else {
|
||||||
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||||
self.tcx.ty_error(reported)
|
self.tcx.ty_error(reported)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1180,10 +1180,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(l)
|
Some(l)
|
||||||
if matches!(
|
if matches!(body.local_decls[l].local_info(), LocalInfo::AggregateTemp) =>
|
||||||
body.local_decls[l].local_info,
|
|
||||||
Some(box LocalInfo::AggregateTemp)
|
|
||||||
) =>
|
|
||||||
{
|
{
|
||||||
ConstraintCategory::Usage
|
ConstraintCategory::Usage
|
||||||
}
|
}
|
||||||
@ -1684,7 +1681,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
// - maybe we should make that a warning.
|
// - maybe we should make that a warning.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LocalKind::Var | LocalKind::Temp => {}
|
LocalKind::Temp => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// When `unsized_fn_params` or `unsized_locals` is enabled, only function calls
|
// When `unsized_fn_params` or `unsized_locals` is enabled, only function calls
|
||||||
|
@ -203,17 +203,6 @@ pub fn parse_asm_args<'a>(
|
|||||||
// Validate the order of named, positional & explicit register operands and
|
// Validate the order of named, positional & explicit register operands and
|
||||||
// clobber_abi/options. We do this at the end once we have the full span
|
// clobber_abi/options. We do this at the end once we have the full span
|
||||||
// of the argument available.
|
// of the argument available.
|
||||||
if !args.options_spans.is_empty() {
|
|
||||||
diag.struct_span_err(span, "arguments are not allowed after options")
|
|
||||||
.span_labels(args.options_spans.clone(), "previous options")
|
|
||||||
.span_label(span, "argument")
|
|
||||||
.emit();
|
|
||||||
} else if let Some((_, abi_span)) = args.clobber_abis.last() {
|
|
||||||
diag.struct_span_err(span, "arguments are not allowed after clobber_abi")
|
|
||||||
.span_label(*abi_span, "clobber_abi")
|
|
||||||
.span_label(span, "argument")
|
|
||||||
.emit();
|
|
||||||
}
|
|
||||||
if explicit_reg {
|
if explicit_reg {
|
||||||
if name.is_some() {
|
if name.is_some() {
|
||||||
diag.struct_span_err(span, "explicit register arguments cannot have names").emit();
|
diag.struct_span_err(span, "explicit register arguments cannot have names").emit();
|
||||||
@ -227,17 +216,6 @@ pub fn parse_asm_args<'a>(
|
|||||||
.emit();
|
.emit();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if !args.reg_args.is_empty() {
|
|
||||||
let mut err = diag.struct_span_err(
|
|
||||||
span,
|
|
||||||
"named arguments cannot follow explicit register arguments",
|
|
||||||
);
|
|
||||||
err.span_label(span, "named argument");
|
|
||||||
for pos in &args.reg_args {
|
|
||||||
err.span_label(args.operands[*pos].1, "explicit register argument");
|
|
||||||
}
|
|
||||||
err.emit();
|
|
||||||
}
|
|
||||||
args.named_args.insert(name, slot);
|
args.named_args.insert(name, slot);
|
||||||
} else {
|
} else {
|
||||||
if !args.named_args.is_empty() || !args.reg_args.is_empty() {
|
if !args.named_args.is_empty() || !args.reg_args.is_empty() {
|
||||||
@ -478,15 +456,6 @@ fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a,
|
|||||||
|
|
||||||
let full_span = span_start.to(p.prev_token.span);
|
let full_span = span_start.to(p.prev_token.span);
|
||||||
|
|
||||||
if !args.options_spans.is_empty() {
|
|
||||||
let mut err = p
|
|
||||||
.sess
|
|
||||||
.span_diagnostic
|
|
||||||
.struct_span_err(full_span, "clobber_abi is not allowed after options");
|
|
||||||
err.span_labels(args.options_spans.clone(), "options");
|
|
||||||
return Err(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
match &new_abis[..] {
|
match &new_abis[..] {
|
||||||
// should have errored above during parsing
|
// should have errored above during parsing
|
||||||
[] => unreachable!(),
|
[] => unreachable!(),
|
||||||
@ -699,6 +668,10 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
|
|||||||
args.operands[idx].1,
|
args.operands[idx].1,
|
||||||
"explicit register arguments cannot be used in the asm template",
|
"explicit register arguments cannot be used in the asm template",
|
||||||
);
|
);
|
||||||
|
err.span_help(
|
||||||
|
args.operands[idx].1,
|
||||||
|
"use the register name directly in the assembly code",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
err.emit();
|
err.emit();
|
||||||
None
|
None
|
||||||
|
@ -290,7 +290,6 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
|||||||
| ExprKind::Async(_, _, _)
|
| ExprKind::Async(_, _, _)
|
||||||
| ExprKind::Await(_)
|
| ExprKind::Await(_)
|
||||||
| ExprKind::Block(_, _)
|
| ExprKind::Block(_, _)
|
||||||
| ExprKind::Box(_)
|
|
||||||
| ExprKind::Break(_, _)
|
| ExprKind::Break(_, _)
|
||||||
| ExprKind::Closure(_)
|
| ExprKind::Closure(_)
|
||||||
| ExprKind::ConstBlock(_)
|
| ExprKind::ConstBlock(_)
|
||||||
|
@ -42,6 +42,18 @@ pub fn expand_concat(
|
|||||||
has_errors = true;
|
has_errors = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// We also want to allow negative numeric literals.
|
||||||
|
ast::ExprKind::Unary(ast::UnOp::Neg, ref expr) if let ast::ExprKind::Lit(token_lit) = expr.kind => {
|
||||||
|
match ast::LitKind::from_token_lit(token_lit) {
|
||||||
|
Ok(ast::LitKind::Int(i, _)) => accumulator.push_str(&format!("-{i}")),
|
||||||
|
Ok(ast::LitKind::Float(f, _)) => accumulator.push_str(&format!("-{f}")),
|
||||||
|
Err(err) => {
|
||||||
|
report_lit_error(&cx.sess.parse_sess, err, token_lit, e.span);
|
||||||
|
has_errors = true;
|
||||||
|
}
|
||||||
|
_ => missing_literal.push(e.span),
|
||||||
|
}
|
||||||
|
}
|
||||||
ast::ExprKind::IncludedBytes(..) => {
|
ast::ExprKind::IncludedBytes(..) => {
|
||||||
cx.span_err(e.span, "cannot concatenate a byte string literal")
|
cx.span_err(e.span, "cannot concatenate a byte string literal")
|
||||||
}
|
}
|
||||||
@ -53,9 +65,10 @@ pub fn expand_concat(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !missing_literal.is_empty() {
|
if !missing_literal.is_empty() {
|
||||||
let mut err = cx.struct_span_err(missing_literal, "expected a literal");
|
let mut err = cx.struct_span_err(missing_literal, "expected a literal");
|
||||||
err.note("only literals (like `\"foo\"`, `42` and `3.14`) can be passed to `concat!()`");
|
err.note("only literals (like `\"foo\"`, `-42` and `3.14`) can be passed to `concat!()`");
|
||||||
err.emit();
|
err.emit();
|
||||||
return DummyResult::any(sp);
|
return DummyResult::any(sp);
|
||||||
} else if has_errors {
|
} else if has_errors {
|
||||||
|
@ -1052,6 +1052,7 @@ impl<'a> MethodDef<'a> {
|
|||||||
/// ::core::hash::Hash::hash(&{ self.y }, state)
|
/// ::core::hash::Hash::hash(&{ self.y }, state)
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
|
/// ```
|
||||||
fn expand_struct_method_body<'b>(
|
fn expand_struct_method_body<'b>(
|
||||||
&self,
|
&self,
|
||||||
cx: &mut ExtCtxt<'_>,
|
cx: &mut ExtCtxt<'_>,
|
||||||
|
@ -36,6 +36,21 @@ enum PositionUsedAs {
|
|||||||
}
|
}
|
||||||
use PositionUsedAs::*;
|
use PositionUsedAs::*;
|
||||||
|
|
||||||
|
struct MacroInput {
|
||||||
|
fmtstr: P<Expr>,
|
||||||
|
args: FormatArguments,
|
||||||
|
/// Whether the first argument was a string literal or a result from eager macro expansion.
|
||||||
|
/// If it's not a string literal, we disallow implicit arugment capturing.
|
||||||
|
///
|
||||||
|
/// This does not correspond to whether we can treat spans to the literal normally, as the whole
|
||||||
|
/// invocation might be the result of another macro expansion, in which case this flag may still be true.
|
||||||
|
///
|
||||||
|
/// See [RFC 2795] for more information.
|
||||||
|
///
|
||||||
|
/// [RFC 2795]: https://rust-lang.github.io/rfcs/2795-format-args-implicit-identifiers.html#macro-hygiene
|
||||||
|
is_direct_literal: bool,
|
||||||
|
}
|
||||||
|
|
||||||
/// Parses the arguments from the given list of tokens, returning the diagnostic
|
/// Parses the arguments from the given list of tokens, returning the diagnostic
|
||||||
/// if there's a parse error so we can continue parsing other format!
|
/// if there's a parse error so we can continue parsing other format!
|
||||||
/// expressions.
|
/// expressions.
|
||||||
@ -45,11 +60,7 @@ use PositionUsedAs::*;
|
|||||||
/// ```text
|
/// ```text
|
||||||
/// Ok((fmtstr, parsed arguments))
|
/// Ok((fmtstr, parsed arguments))
|
||||||
/// ```
|
/// ```
|
||||||
fn parse_args<'a>(
|
fn parse_args<'a>(ecx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<'a, MacroInput> {
|
||||||
ecx: &mut ExtCtxt<'a>,
|
|
||||||
sp: Span,
|
|
||||||
tts: TokenStream,
|
|
||||||
) -> PResult<'a, (P<Expr>, FormatArguments)> {
|
|
||||||
let mut args = FormatArguments::new();
|
let mut args = FormatArguments::new();
|
||||||
|
|
||||||
let mut p = ecx.new_parser_from_tts(tts);
|
let mut p = ecx.new_parser_from_tts(tts);
|
||||||
@ -59,25 +70,21 @@ fn parse_args<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let first_token = &p.token;
|
let first_token = &p.token;
|
||||||
let fmtstr = match first_token.kind {
|
|
||||||
token::TokenKind::Literal(token::Lit {
|
let fmtstr = if let token::Literal(lit) = first_token.kind && matches!(lit.kind, token::Str | token::StrRaw(_)) {
|
||||||
kind: token::LitKind::Str | token::LitKind::StrRaw(_),
|
// This allows us to properly handle cases when the first comma
|
||||||
..
|
// after the format string is mistakenly replaced with any operator,
|
||||||
}) => {
|
// which cause the expression parser to eat too much tokens.
|
||||||
// If the first token is a string literal, then a format expression
|
p.parse_literal_maybe_minus()?
|
||||||
// is constructed from it.
|
} else {
|
||||||
//
|
// Otherwise, we fall back to the expression parser.
|
||||||
// This allows us to properly handle cases when the first comma
|
p.parse_expr()?
|
||||||
// after the format string is mistakenly replaced with any operator,
|
|
||||||
// which cause the expression parser to eat too much tokens.
|
|
||||||
p.parse_literal_maybe_minus()?
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
// Otherwise, we fall back to the expression parser.
|
|
||||||
p.parse_expr()?
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Only allow implicit captures to be used when the argument is a direct literal
|
||||||
|
// instead of a macro expanding to one.
|
||||||
|
let is_direct_literal = matches!(fmtstr.kind, ExprKind::Lit(_));
|
||||||
|
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
|
|
||||||
while p.token != token::Eof {
|
while p.token != token::Eof {
|
||||||
@ -147,17 +154,19 @@ fn parse_args<'a>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok((fmtstr, args))
|
Ok(MacroInput { fmtstr, args, is_direct_literal })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_format_args(
|
fn make_format_args(
|
||||||
ecx: &mut ExtCtxt<'_>,
|
ecx: &mut ExtCtxt<'_>,
|
||||||
efmt: P<Expr>,
|
input: MacroInput,
|
||||||
mut args: FormatArguments,
|
|
||||||
append_newline: bool,
|
append_newline: bool,
|
||||||
) -> Result<FormatArgs, ()> {
|
) -> Result<FormatArgs, ()> {
|
||||||
let msg = "format argument must be a string literal";
|
let msg = "format argument must be a string literal";
|
||||||
let unexpanded_fmt_span = efmt.span;
|
let unexpanded_fmt_span = input.fmtstr.span;
|
||||||
|
|
||||||
|
let MacroInput { fmtstr: efmt, mut args, is_direct_literal } = input;
|
||||||
|
|
||||||
let (fmt_str, fmt_style, fmt_span) = match expr_to_spanned_string(ecx, efmt, msg) {
|
let (fmt_str, fmt_style, fmt_span) = match expr_to_spanned_string(ecx, efmt, msg) {
|
||||||
Ok(mut fmt) if append_newline => {
|
Ok(mut fmt) if append_newline => {
|
||||||
fmt.0 = Symbol::intern(&format!("{}\n", fmt.0));
|
fmt.0 = Symbol::intern(&format!("{}\n", fmt.0));
|
||||||
@ -208,11 +217,11 @@ pub fn make_format_args(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_literal = parser.is_literal;
|
let is_source_literal = parser.is_source_literal;
|
||||||
|
|
||||||
if !parser.errors.is_empty() {
|
if !parser.errors.is_empty() {
|
||||||
let err = parser.errors.remove(0);
|
let err = parser.errors.remove(0);
|
||||||
let sp = if is_literal {
|
let sp = if is_source_literal {
|
||||||
fmt_span.from_inner(InnerSpan::new(err.span.start, err.span.end))
|
fmt_span.from_inner(InnerSpan::new(err.span.start, err.span.end))
|
||||||
} else {
|
} else {
|
||||||
// The format string could be another macro invocation, e.g.:
|
// The format string could be another macro invocation, e.g.:
|
||||||
@ -230,7 +239,7 @@ pub fn make_format_args(
|
|||||||
if let Some(note) = err.note {
|
if let Some(note) = err.note {
|
||||||
e.note(¬e);
|
e.note(¬e);
|
||||||
}
|
}
|
||||||
if let Some((label, span)) = err.secondary_label && is_literal {
|
if let Some((label, span)) = err.secondary_label && is_source_literal {
|
||||||
e.span_label(fmt_span.from_inner(InnerSpan::new(span.start, span.end)), label);
|
e.span_label(fmt_span.from_inner(InnerSpan::new(span.start, span.end)), label);
|
||||||
}
|
}
|
||||||
if err.should_be_replaced_with_positional_argument {
|
if err.should_be_replaced_with_positional_argument {
|
||||||
@ -256,7 +265,7 @@ pub fn make_format_args(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let to_span = |inner_span: rustc_parse_format::InnerSpan| {
|
let to_span = |inner_span: rustc_parse_format::InnerSpan| {
|
||||||
is_literal.then(|| {
|
is_source_literal.then(|| {
|
||||||
fmt_span.from_inner(InnerSpan { start: inner_span.start, end: inner_span.end })
|
fmt_span.from_inner(InnerSpan { start: inner_span.start, end: inner_span.end })
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
@ -304,7 +313,7 @@ pub fn make_format_args(
|
|||||||
// Name not found in `args`, so we add it as an implicitly captured argument.
|
// Name not found in `args`, so we add it as an implicitly captured argument.
|
||||||
let span = span.unwrap_or(fmt_span);
|
let span = span.unwrap_or(fmt_span);
|
||||||
let ident = Ident::new(name, span);
|
let ident = Ident::new(name, span);
|
||||||
let expr = if is_literal {
|
let expr = if is_direct_literal {
|
||||||
ecx.expr_ident(span, ident)
|
ecx.expr_ident(span, ident)
|
||||||
} else {
|
} else {
|
||||||
// For the moment capturing variables from format strings expanded from macros is
|
// For the moment capturing variables from format strings expanded from macros is
|
||||||
@ -814,7 +823,7 @@ fn report_invalid_references(
|
|||||||
// for `println!("{7:7$}", 1);`
|
// for `println!("{7:7$}", 1);`
|
||||||
indexes.sort();
|
indexes.sort();
|
||||||
indexes.dedup();
|
indexes.dedup();
|
||||||
let span: MultiSpan = if !parser.is_literal || parser.arg_places.is_empty() {
|
let span: MultiSpan = if !parser.is_source_literal || parser.arg_places.is_empty() {
|
||||||
MultiSpan::from_span(fmt_span)
|
MultiSpan::from_span(fmt_span)
|
||||||
} else {
|
} else {
|
||||||
MultiSpan::from_spans(invalid_refs.iter().filter_map(|&(_, span, _, _)| span).collect())
|
MultiSpan::from_spans(invalid_refs.iter().filter_map(|&(_, span, _, _)| span).collect())
|
||||||
@ -855,8 +864,8 @@ fn expand_format_args_impl<'cx>(
|
|||||||
) -> Box<dyn base::MacResult + 'cx> {
|
) -> Box<dyn base::MacResult + 'cx> {
|
||||||
sp = ecx.with_def_site_ctxt(sp);
|
sp = ecx.with_def_site_ctxt(sp);
|
||||||
match parse_args(ecx, sp, tts) {
|
match parse_args(ecx, sp, tts) {
|
||||||
Ok((efmt, args)) => {
|
Ok(input) => {
|
||||||
if let Ok(format_args) = make_format_args(ecx, efmt, args, nl) {
|
if let Ok(format_args) = make_format_args(ecx, input, nl) {
|
||||||
MacEager::expr(ecx.expr(sp, ExprKind::FormatArgs(P(format_args))))
|
MacEager::expr(ecx.expr(sp, ExprKind::FormatArgs(P(format_args))))
|
||||||
} else {
|
} else {
|
||||||
MacEager::expr(DummyResult::raw_expr(sp, true))
|
MacEager::expr(DummyResult::raw_expr(sp, true))
|
||||||
|
@ -56,7 +56,7 @@ pub mod proc_macro_harness;
|
|||||||
pub mod standard_library_imports;
|
pub mod standard_library_imports;
|
||||||
pub mod test_harness;
|
pub mod test_harness;
|
||||||
|
|
||||||
fluent_messages! { "../locales/en-US.ftl" }
|
fluent_messages! { "../messages.ftl" }
|
||||||
|
|
||||||
pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
|
pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
|
||||||
let mut register = |name, kind| resolver.register_builtin_macro(name, kind);
|
let mut register = |name, kind| resolver.register_builtin_macro(name, kind);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#![feature(start, core_intrinsics, alloc_error_handler, box_syntax)]
|
#![feature(start, core_intrinsics, alloc_error_handler)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
@ -29,7 +29,7 @@ fn alloc_error_handler(_: alloc::alloc::Layout) -> ! {
|
|||||||
|
|
||||||
#[start]
|
#[start]
|
||||||
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||||
let world: Box<&str> = box "Hello World!\0";
|
let world: Box<&str> = Box::new("Hello World!\0");
|
||||||
unsafe {
|
unsafe {
|
||||||
puts(*world as *const str as *const u8);
|
puts(*world as *const str as *const u8);
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
// file at the top-level directory of this distribution and at
|
// SPDX-FileCopyrightText: The Rust Project Developers (see https://thanks.rust-lang.org)
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
// option. This file may not be copied, modified, or distributed
|
|
||||||
// except according to those terms.
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
pub struct System;
|
pub struct System;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#![feature(no_core, lang_items, never_type, linkage, extern_types, thread_local, box_syntax)]
|
#![feature(no_core, lang_items, never_type, linkage, extern_types, thread_local)]
|
||||||
#![no_core]
|
#![no_core]
|
||||||
#![allow(dead_code, non_camel_case_types)]
|
#![allow(dead_code, non_camel_case_types)]
|
||||||
|
|
||||||
@ -178,7 +178,7 @@ fn main() {
|
|||||||
let ptr: *const i8 = hello as *const [u8] as *const i8;
|
let ptr: *const i8 = hello as *const [u8] as *const i8;
|
||||||
puts(ptr);
|
puts(ptr);
|
||||||
|
|
||||||
let world: Box<&str> = box "World!\0";
|
let world: Box<&str> = Box::new("World!\0");
|
||||||
puts(*world as *const str as *const i8);
|
puts(*world as *const str as *const i8);
|
||||||
world as Box<dyn SomeTrait>;
|
world as Box<dyn SomeTrait>;
|
||||||
|
|
||||||
@ -238,10 +238,10 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = box NoisyDrop {
|
let _ = Box::new(NoisyDrop {
|
||||||
text: "Boxed outer got dropped!\0",
|
text: "Boxed outer got dropped!\0",
|
||||||
inner: NoisyDropInner,
|
inner: NoisyDropInner,
|
||||||
} as Box<dyn SomeTrait>;
|
}) as Box<dyn SomeTrait>;
|
||||||
|
|
||||||
const FUNC_REF: Option<fn()> = Some(main);
|
const FUNC_REF: Option<fn()> = Some(main);
|
||||||
match FUNC_REF {
|
match FUNC_REF {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
|
use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
|
||||||
|
use rustc_codegen_ssa::base::allocator_kind_for_codegen;
|
||||||
use rustc_session::config::OomStrategy;
|
use rustc_session::config::OomStrategy;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
|
|
||||||
@ -13,24 +14,15 @@ pub(crate) fn codegen(
|
|||||||
module: &mut impl Module,
|
module: &mut impl Module,
|
||||||
unwind_context: &mut UnwindContext,
|
unwind_context: &mut UnwindContext,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let any_dynamic_crate = tcx.dependency_formats(()).iter().any(|(_, list)| {
|
let Some(kind) = allocator_kind_for_codegen(tcx) else { return false };
|
||||||
use rustc_middle::middle::dependency_format::Linkage;
|
codegen_inner(
|
||||||
list.iter().any(|&linkage| linkage == Linkage::Dynamic)
|
module,
|
||||||
});
|
unwind_context,
|
||||||
if any_dynamic_crate {
|
kind,
|
||||||
false
|
tcx.alloc_error_handler_kind(()).unwrap(),
|
||||||
} else if let Some(kind) = tcx.allocator_kind(()) {
|
tcx.sess.opts.unstable_opts.oom,
|
||||||
codegen_inner(
|
);
|
||||||
module,
|
true
|
||||||
unwind_context,
|
|
||||||
kind,
|
|
||||||
tcx.alloc_error_handler_kind(()).unwrap(),
|
|
||||||
tcx.sess.opts.unstable_opts.oom,
|
|
||||||
);
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn codegen_inner(
|
fn codegen_inner(
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#![feature(start, box_syntax, core_intrinsics, alloc_error_handler, lang_items)]
|
#![feature(start, core_intrinsics, alloc_error_handler, lang_items)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
@ -38,7 +38,7 @@ unsafe extern "C" fn _Unwind_Resume() {
|
|||||||
|
|
||||||
#[start]
|
#[start]
|
||||||
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||||
let world: Box<&str> = box "Hello World!\0";
|
let world: Box<&str> = Box::new("Hello World!\0");
|
||||||
unsafe {
|
unsafe {
|
||||||
puts(*world as *const str as *const u8);
|
puts(*world as *const str as *const u8);
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
// file at the top-level directory of this distribution and at
|
// SPDX-FileCopyrightText: The Rust Project Developers (see https://thanks.rust-lang.org)
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
// option. This file may not be copied, modified, or distributed
|
|
||||||
// except according to those terms.
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![feature(allocator_api, rustc_private)]
|
#![feature(allocator_api, rustc_private)]
|
||||||
#![cfg_attr(any(unix, target_os = "redox"), feature(libc))]
|
#![cfg_attr(any(unix, target_os = "redox"), feature(libc))]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Adapted from https://github.com/sunfishcode/mir2cranelift/blob/master/rust-examples/nocore-hello-world.rs
|
// Adapted from https://github.com/sunfishcode/mir2cranelift/blob/master/rust-examples/nocore-hello-world.rs
|
||||||
|
|
||||||
#![feature(
|
#![feature(
|
||||||
no_core, unboxed_closures, start, lang_items, box_syntax, never_type, linkage,
|
no_core, unboxed_closures, start, lang_items, never_type, linkage,
|
||||||
extern_types, thread_local
|
extern_types, thread_local
|
||||||
)]
|
)]
|
||||||
#![no_core]
|
#![no_core]
|
||||||
@ -163,7 +163,7 @@ fn main() {
|
|||||||
let ptr: *const u8 = hello as *const [u8] as *const u8;
|
let ptr: *const u8 = hello as *const [u8] as *const u8;
|
||||||
puts(ptr);
|
puts(ptr);
|
||||||
|
|
||||||
let world: Box<&str> = box "World!\0";
|
let world: Box<&str> = Box::new("World!\0");
|
||||||
puts(*world as *const str as *const u8);
|
puts(*world as *const str as *const u8);
|
||||||
world as Box<dyn SomeTrait>;
|
world as Box<dyn SomeTrait>;
|
||||||
|
|
||||||
@ -223,10 +223,10 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = box NoisyDrop {
|
let _ = Box::new(NoisyDrop {
|
||||||
text: "Boxed outer got dropped!\0",
|
text: "Boxed outer got dropped!\0",
|
||||||
inner: NoisyDropInner,
|
inner: NoisyDropInner,
|
||||||
} as Box<dyn SomeTrait>;
|
}) as Box<dyn SomeTrait>;
|
||||||
|
|
||||||
const FUNC_REF: Option<fn()> = Some(main);
|
const FUNC_REF: Option<fn()> = Some(main);
|
||||||
#[allow(unreachable_code)]
|
#[allow(unreachable_code)]
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#![feature(start, box_syntax, core_intrinsics, lang_items)]
|
#![feature(start, core_intrinsics, lang_items)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[link(name = "c")]
|
#[link(name = "c")]
|
||||||
|
@ -87,7 +87,7 @@ use rustc_span::Symbol;
|
|||||||
use rustc_span::fatal_error::FatalError;
|
use rustc_span::fatal_error::FatalError;
|
||||||
use tempfile::TempDir;
|
use tempfile::TempDir;
|
||||||
|
|
||||||
fluent_messages! { "../locales/en-US.ftl" }
|
fluent_messages! { "../messages.ftl" }
|
||||||
|
|
||||||
pub struct PrintOnPanic<F: Fn() -> String>(pub F);
|
pub struct PrintOnPanic<F: Fn() -> String>(pub F);
|
||||||
|
|
||||||
|
@ -438,6 +438,7 @@ fn build_enum_variant_member_di_node<'ll, 'tcx>(
|
|||||||
/// DW_TAG_structure_type (type of variant 1)
|
/// DW_TAG_structure_type (type of variant 1)
|
||||||
/// DW_TAG_structure_type (type of variant 2)
|
/// DW_TAG_structure_type (type of variant 2)
|
||||||
/// DW_TAG_structure_type (type of variant 3)
|
/// DW_TAG_structure_type (type of variant 3)
|
||||||
|
/// ```
|
||||||
struct VariantMemberInfo<'a, 'll> {
|
struct VariantMemberInfo<'a, 'll> {
|
||||||
variant_index: VariantIdx,
|
variant_index: VariantIdx,
|
||||||
variant_name: Cow<'a, str>,
|
variant_name: Cow<'a, str>,
|
||||||
|
@ -84,7 +84,7 @@ mod type_of;
|
|||||||
mod va_arg;
|
mod va_arg;
|
||||||
mod value;
|
mod value;
|
||||||
|
|
||||||
fluent_messages! { "../locales/en-US.ftl" }
|
fluent_messages! { "../messages.ftl" }
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct LlvmCodegenBackend(());
|
pub struct LlvmCodegenBackend(());
|
||||||
|
@ -720,6 +720,7 @@ impl<'a> Linker for GccLinker<'a> {
|
|||||||
let mut arg = OsString::from("--version-script=");
|
let mut arg = OsString::from("--version-script=");
|
||||||
arg.push(path);
|
arg.push(path);
|
||||||
self.linker_arg(arg);
|
self.linker_arg(arg);
|
||||||
|
self.linker_arg("--no-undefined-version");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use crate::base::allocator_kind_for_codegen;
|
||||||
|
|
||||||
use std::collections::hash_map::Entry::*;
|
use std::collections::hash_map::Entry::*;
|
||||||
|
|
||||||
use rustc_ast::expand::allocator::ALLOCATOR_METHODS;
|
use rustc_ast::expand::allocator::ALLOCATOR_METHODS;
|
||||||
@ -200,7 +202,8 @@ fn exported_symbols_provider_local(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if tcx.allocator_kind(()).is_some() {
|
// Mark allocator shim symbols as exported only if they were generated.
|
||||||
|
if allocator_kind_for_codegen(tcx).is_some() {
|
||||||
for symbol_name in ALLOCATOR_METHODS
|
for symbol_name in ALLOCATOR_METHODS
|
||||||
.iter()
|
.iter()
|
||||||
.map(|method| format!("__rust_{}", method.name))
|
.map(|method| format!("__rust_{}", method.name))
|
||||||
|
@ -13,6 +13,7 @@ use crate::mir::place::PlaceRef;
|
|||||||
use crate::traits::*;
|
use crate::traits::*;
|
||||||
use crate::{CachedModuleCodegen, CompiledModule, CrateInfo, MemFlags, ModuleCodegen, ModuleKind};
|
use crate::{CachedModuleCodegen, CompiledModule, CrateInfo, MemFlags, ModuleCodegen, ModuleKind};
|
||||||
|
|
||||||
|
use rustc_ast::expand::allocator::AllocatorKind;
|
||||||
use rustc_attr as attr;
|
use rustc_attr as attr;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
|
use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
|
||||||
@ -545,6 +546,23 @@ pub fn collect_debugger_visualizers_transitive(
|
|||||||
.collect::<BTreeSet<_>>()
|
.collect::<BTreeSet<_>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Decide allocator kind to codegen. If `Some(_)` this will be the same as
|
||||||
|
/// `tcx.allocator_kind`, but it may be `None` in more cases (e.g. if using
|
||||||
|
/// allocator definitions from a dylib dependency).
|
||||||
|
pub fn allocator_kind_for_codegen(tcx: TyCtxt<'_>) -> Option<AllocatorKind> {
|
||||||
|
// If the crate doesn't have an `allocator_kind` set then there's definitely
|
||||||
|
// no shim to generate. Otherwise we also check our dependency graph for all
|
||||||
|
// our output crate types. If anything there looks like its a `Dynamic`
|
||||||
|
// linkage, then it's already got an allocator shim and we'll be using that
|
||||||
|
// one instead. If nothing exists then it's our job to generate the
|
||||||
|
// allocator!
|
||||||
|
let any_dynamic_crate = tcx.dependency_formats(()).iter().any(|(_, list)| {
|
||||||
|
use rustc_middle::middle::dependency_format::Linkage;
|
||||||
|
list.iter().any(|&linkage| linkage == Linkage::Dynamic)
|
||||||
|
});
|
||||||
|
if any_dynamic_crate { None } else { tcx.allocator_kind(()) }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn codegen_crate<B: ExtraBackendMethods>(
|
pub fn codegen_crate<B: ExtraBackendMethods>(
|
||||||
backend: B,
|
backend: B,
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
@ -615,20 +633,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Codegen an allocator shim, if necessary.
|
// Codegen an allocator shim, if necessary.
|
||||||
//
|
if let Some(kind) = allocator_kind_for_codegen(tcx) {
|
||||||
// If the crate doesn't have an `allocator_kind` set then there's definitely
|
|
||||||
// no shim to generate. Otherwise we also check our dependency graph for all
|
|
||||||
// our output crate types. If anything there looks like its a `Dynamic`
|
|
||||||
// linkage, then it's already got an allocator shim and we'll be using that
|
|
||||||
// one instead. If nothing exists then it's our job to generate the
|
|
||||||
// allocator!
|
|
||||||
let any_dynamic_crate = tcx.dependency_formats(()).iter().any(|(_, list)| {
|
|
||||||
use rustc_middle::middle::dependency_format::Linkage;
|
|
||||||
list.iter().any(|&linkage| linkage == Linkage::Dynamic)
|
|
||||||
});
|
|
||||||
let allocator_module = if any_dynamic_crate {
|
|
||||||
None
|
|
||||||
} else if let Some(kind) = tcx.allocator_kind(()) {
|
|
||||||
let llmod_id =
|
let llmod_id =
|
||||||
cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string();
|
cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string();
|
||||||
let module_llvm = tcx.sess.time("write_allocator_module", || {
|
let module_llvm = tcx.sess.time("write_allocator_module", || {
|
||||||
@ -642,13 +647,10 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
|||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
Some(ModuleCodegen { name: llmod_id, module_llvm, kind: ModuleKind::Allocator })
|
ongoing_codegen.submit_pre_codegened_module_to_llvm(
|
||||||
} else {
|
tcx,
|
||||||
None
|
ModuleCodegen { name: llmod_id, module_llvm, kind: ModuleKind::Allocator },
|
||||||
};
|
);
|
||||||
|
|
||||||
if let Some(allocator_module) = allocator_module {
|
|
||||||
ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, allocator_module);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For better throughput during parallel processing by LLVM, we used to sort
|
// For better throughput during parallel processing by LLVM, we used to sort
|
||||||
|
@ -247,6 +247,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
|
|||||||
// Note that this is also allowed if `actually_rustdoc` so
|
// Note that this is also allowed if `actually_rustdoc` so
|
||||||
// if a target is documenting some wasm-specific code then
|
// if a target is documenting some wasm-specific code then
|
||||||
// it's not spuriously denied.
|
// it's not spuriously denied.
|
||||||
|
//
|
||||||
|
// This exception needs to be kept in sync with allowing
|
||||||
|
// `#[target_feature]` on `main` and `start`.
|
||||||
} else if !tcx.features().target_feature_11 {
|
} else if !tcx.features().target_feature_11 {
|
||||||
let mut err = feature_err(
|
let mut err = feature_err(
|
||||||
&tcx.sess.parse_sess,
|
&tcx.sess.parse_sess,
|
||||||
|
@ -56,7 +56,7 @@ pub mod mono_item;
|
|||||||
pub mod target_features;
|
pub mod target_features;
|
||||||
pub mod traits;
|
pub mod traits;
|
||||||
|
|
||||||
fluent_messages! { "../locales/en-US.ftl" }
|
fluent_messages! { "../messages.ftl" }
|
||||||
|
|
||||||
pub struct ModuleCodegen<M> {
|
pub struct ModuleCodegen<M> {
|
||||||
/// The name of the module. When the crate may be saved between
|
/// The name of the module. When the crate may be saved between
|
||||||
|
@ -241,12 +241,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
pub fn debug_introduce_local(&self, bx: &mut Bx, local: mir::Local) {
|
pub fn debug_introduce_local(&self, bx: &mut Bx, local: mir::Local) {
|
||||||
let full_debug_info = bx.sess().opts.debuginfo == DebugInfo::Full;
|
let full_debug_info = bx.sess().opts.debuginfo == DebugInfo::Full;
|
||||||
|
|
||||||
// FIXME(eddyb) maybe name the return place as `_0` or `return`?
|
|
||||||
if local == mir::RETURN_PLACE && !self.mir.local_decls[mir::RETURN_PLACE].is_user_variable()
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let vars = match &self.per_local_var_debug_info {
|
let vars = match &self.per_local_var_debug_info {
|
||||||
Some(per_local) => &per_local[local],
|
Some(per_local) => &per_local[local],
|
||||||
None => return,
|
None => return,
|
||||||
@ -303,7 +297,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
|
|
||||||
let local_ref = &self.locals[local];
|
let local_ref = &self.locals[local];
|
||||||
|
|
||||||
let name = if bx.sess().fewer_names() {
|
// FIXME Should the return place be named?
|
||||||
|
let name = if bx.sess().fewer_names() || local == mir::RETURN_PLACE {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(match whole_local_var.or(fallback_var.clone()) {
|
Some(match whole_local_var.or(fallback_var.clone()) {
|
||||||
|
@ -258,6 +258,10 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||||||
// Apply debuginfo to the newly allocated locals.
|
// Apply debuginfo to the newly allocated locals.
|
||||||
fx.debug_introduce_locals(&mut start_bx);
|
fx.debug_introduce_locals(&mut start_bx);
|
||||||
|
|
||||||
|
// The builders will be created separately for each basic block at `codegen_block`.
|
||||||
|
// So drop the builder of `start_llbb` to avoid having two at the same time.
|
||||||
|
drop(start_bx);
|
||||||
|
|
||||||
// Codegen the body of each block using reverse postorder
|
// Codegen the body of each block using reverse postorder
|
||||||
for (bb, _) in traversal::reverse_postorder(&mir) {
|
for (bb, _) in traversal::reverse_postorder(&mir) {
|
||||||
fx.codegen_block(bb);
|
fx.codegen_block(bb);
|
||||||
|
@ -192,7 +192,7 @@ const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
|||||||
("fxsr", None),
|
("fxsr", None),
|
||||||
("gfni", Some(sym::avx512_target_feature)),
|
("gfni", Some(sym::avx512_target_feature)),
|
||||||
("lzcnt", None),
|
("lzcnt", None),
|
||||||
("movbe", Some(sym::movbe_target_feature)),
|
("movbe", None),
|
||||||
("pclmulqdq", None),
|
("pclmulqdq", None),
|
||||||
("popcnt", None),
|
("popcnt", None),
|
||||||
("rdrand", None),
|
("rdrand", None),
|
||||||
@ -394,7 +394,6 @@ pub fn from_target_feature(
|
|||||||
Some(sym::sse4a_target_feature) => rust_features.sse4a_target_feature,
|
Some(sym::sse4a_target_feature) => rust_features.sse4a_target_feature,
|
||||||
Some(sym::tbm_target_feature) => rust_features.tbm_target_feature,
|
Some(sym::tbm_target_feature) => rust_features.tbm_target_feature,
|
||||||
Some(sym::wasm_target_feature) => rust_features.wasm_target_feature,
|
Some(sym::wasm_target_feature) => rust_features.wasm_target_feature,
|
||||||
Some(sym::movbe_target_feature) => rust_features.movbe_target_feature,
|
|
||||||
Some(sym::rtm_target_feature) => rust_features.rtm_target_feature,
|
Some(sym::rtm_target_feature) => rust_features.rtm_target_feature,
|
||||||
Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature,
|
Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature,
|
||||||
Some(sym::bpf_target_feature) => rust_features.bpf_target_feature,
|
Some(sym::bpf_target_feature) => rust_features.bpf_target_feature,
|
||||||
@ -442,7 +441,7 @@ fn asm_target_features(tcx: TyCtxt<'_>, did: DefId) -> &FxIndexSet<Symbol> {
|
|||||||
pub fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: Span) {
|
pub fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: Span) {
|
||||||
if let DefKind::AssocFn = tcx.def_kind(id) {
|
if let DefKind::AssocFn = tcx.def_kind(id) {
|
||||||
let parent_id = tcx.local_parent(id);
|
let parent_id = tcx.local_parent(id);
|
||||||
if let DefKind::Impl { of_trait: true } = tcx.def_kind(parent_id) {
|
if let DefKind::Trait | DefKind::Impl { of_trait: true } = tcx.def_kind(parent_id) {
|
||||||
tcx.sess
|
tcx.sess
|
||||||
.struct_span_err(
|
.struct_span_err(
|
||||||
attr_span,
|
attr_span,
|
||||||
|
@ -536,24 +536,20 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
local: mir::Local,
|
local: mir::Local,
|
||||||
layout: Option<TyAndLayout<'tcx>>,
|
layout: Option<TyAndLayout<'tcx>>,
|
||||||
) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
|
) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
|
||||||
// `const_prop` runs into this with an invalid (empty) frame, so we
|
let state = &frame.locals[local];
|
||||||
// have to support that case (mostly by skipping all caching).
|
if let Some(layout) = state.layout.get() {
|
||||||
match frame.locals.get(local).and_then(|state| state.layout.get()) {
|
return Ok(layout);
|
||||||
None => {
|
|
||||||
let layout = from_known_layout(self.tcx, self.param_env, layout, || {
|
|
||||||
let local_ty = frame.body.local_decls[local].ty;
|
|
||||||
let local_ty =
|
|
||||||
self.subst_from_frame_and_normalize_erasing_regions(frame, local_ty)?;
|
|
||||||
self.layout_of(local_ty)
|
|
||||||
})?;
|
|
||||||
if let Some(state) = frame.locals.get(local) {
|
|
||||||
// Layouts of locals are requested a lot, so we cache them.
|
|
||||||
state.layout.set(Some(layout));
|
|
||||||
}
|
|
||||||
Ok(layout)
|
|
||||||
}
|
|
||||||
Some(layout) => Ok(layout),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let layout = from_known_layout(self.tcx, self.param_env, layout, || {
|
||||||
|
let local_ty = frame.body.local_decls[local].ty;
|
||||||
|
let local_ty = self.subst_from_frame_and_normalize_erasing_regions(frame, local_ty)?;
|
||||||
|
self.layout_of(local_ty)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// Layouts of locals are requested a lot, so we cache them.
|
||||||
|
state.layout.set(Some(layout));
|
||||||
|
Ok(layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the actual dynamic size and alignment of the place at the given type.
|
/// Returns the actual dynamic size and alignment of the place at the given type.
|
||||||
|
@ -39,7 +39,7 @@ use rustc_macros::fluent_messages;
|
|||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::Providers;
|
||||||
|
|
||||||
fluent_messages! { "../locales/en-US.ftl" }
|
fluent_messages! { "../messages.ftl" }
|
||||||
|
|
||||||
pub fn provide(providers: &mut Providers) {
|
pub fn provide(providers: &mut Providers) {
|
||||||
const_eval::provide(providers);
|
const_eval::provide(providers);
|
||||||
|
@ -643,7 +643,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||||||
if base_ty.is_unsafe_ptr() {
|
if base_ty.is_unsafe_ptr() {
|
||||||
if proj_base.is_empty() {
|
if proj_base.is_empty() {
|
||||||
let decl = &self.body.local_decls[place_local];
|
let decl = &self.body.local_decls[place_local];
|
||||||
if let Some(box LocalInfo::StaticRef { def_id, .. }) = decl.local_info {
|
if let LocalInfo::StaticRef { def_id, .. } = *decl.local_info() {
|
||||||
let span = decl.source_info.span;
|
let span = decl.source_info.span;
|
||||||
self.check_static(def_id, span);
|
self.check_static(def_id, span);
|
||||||
return;
|
return;
|
||||||
@ -770,7 +770,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||||||
|
|
||||||
let errors = ocx.select_all_or_error();
|
let errors = ocx.select_all_or_error();
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -704,7 +704,7 @@ pub mod ty {
|
|||||||
|
|
||||||
fn importance(&self) -> DiagnosticImportance {
|
fn importance(&self) -> DiagnosticImportance {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
mir::LocalKind::Var | mir::LocalKind::Temp => DiagnosticImportance::Secondary,
|
mir::LocalKind::Temp => DiagnosticImportance::Secondary,
|
||||||
mir::LocalKind::ReturnPointer | mir::LocalKind::Arg => {
|
mir::LocalKind::ReturnPointer | mir::LocalKind::Arg => {
|
||||||
DiagnosticImportance::Primary
|
DiagnosticImportance::Primary
|
||||||
}
|
}
|
||||||
|
@ -106,8 +106,9 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> {
|
|||||||
debug!("visit_local: index={:?} context={:?} location={:?}", index, context, location);
|
debug!("visit_local: index={:?} context={:?} location={:?}", index, context, location);
|
||||||
// We're only interested in temporaries and the return place
|
// We're only interested in temporaries and the return place
|
||||||
match self.ccx.body.local_kind(index) {
|
match self.ccx.body.local_kind(index) {
|
||||||
LocalKind::Temp | LocalKind::ReturnPointer => {}
|
LocalKind::Arg => return,
|
||||||
LocalKind::Arg | LocalKind::Var => return,
|
LocalKind::Temp if self.ccx.body.local_decls[index].is_user_variable() => return,
|
||||||
|
LocalKind::ReturnPointer | LocalKind::Temp => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore drops, if the temp gets promoted,
|
// Ignore drops, if the temp gets promoted,
|
||||||
|
@ -64,7 +64,7 @@ use crate::session_diagnostics::{
|
|||||||
RLinkWrongFileType, RlinkNotAFile, RlinkUnableToRead,
|
RLinkWrongFileType, RlinkNotAFile, RlinkUnableToRead,
|
||||||
};
|
};
|
||||||
|
|
||||||
fluent_messages! { "../locales/en-US.ftl" }
|
fluent_messages! { "../messages.ftl" }
|
||||||
|
|
||||||
pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[
|
pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
@ -331,6 +331,7 @@ fn run_compiler(
|
|||||||
if let Some(ppm) = &sess.opts.pretty {
|
if let Some(ppm) = &sess.opts.pretty {
|
||||||
if ppm.needs_ast_map() {
|
if ppm.needs_ast_map() {
|
||||||
queries.global_ctxt()?.enter(|tcx| {
|
queries.global_ctxt()?.enter(|tcx| {
|
||||||
|
tcx.ensure().early_lint_checks(());
|
||||||
pretty::print_after_hir_lowering(tcx, *ppm);
|
pretty::print_after_hir_lowering(tcx, *ppm);
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
|
@ -5,7 +5,5 @@ the heap at runtime, and therefore cannot be done at compile time.
|
|||||||
Erroneous code example:
|
Erroneous code example:
|
||||||
|
|
||||||
```compile_fail,E0010
|
```compile_fail,E0010
|
||||||
#![feature(box_syntax)]
|
const CON : Vec<i32> = vec![1, 2, 3];
|
||||||
|
|
||||||
const CON : Box<i32> = box 0;
|
|
||||||
```
|
```
|
||||||
|
@ -41,7 +41,7 @@ impl Add for Foo {
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut x: Foo = Foo(5);
|
let mut x: Foo = Foo(5);
|
||||||
x += Foo(7); // error, `+= cannot be applied to the type `Foo`
|
x += Foo(7); // error, `+=` cannot be applied to the type `Foo`
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -3,14 +3,14 @@ An unknown tool name was found in a scoped lint.
|
|||||||
Erroneous code examples:
|
Erroneous code examples:
|
||||||
|
|
||||||
```compile_fail,E0710
|
```compile_fail,E0710
|
||||||
#[allow(clipp::filter_map)] // error!`
|
#[allow(clipp::filter_map)] // error!
|
||||||
fn main() {
|
fn main() {
|
||||||
// business logic
|
// business logic
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```compile_fail,E0710
|
```compile_fail,E0710
|
||||||
#[warn(clipp::filter_map)] // error!`
|
#[warn(clipp::filter_map)] // error!
|
||||||
fn main() {
|
fn main() {
|
||||||
// business logic
|
// business logic
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ use intl_memoizer::IntlLangMemoizer;
|
|||||||
pub use fluent_bundle::{self, types::FluentType, FluentArgs, FluentError, FluentValue};
|
pub use fluent_bundle::{self, types::FluentType, FluentArgs, FluentError, FluentValue};
|
||||||
pub use unic_langid::{langid, LanguageIdentifier};
|
pub use unic_langid::{langid, LanguageIdentifier};
|
||||||
|
|
||||||
fluent_messages! { "../locales/en-US.ftl" }
|
fluent_messages! { "../messages.ftl" }
|
||||||
|
|
||||||
pub type FluentBundle = fluent_bundle::bundle::FluentBundle<FluentResource, IntlLangMemoizer>;
|
pub type FluentBundle = fluent_bundle::bundle::FluentBundle<FluentResource, IntlLangMemoizer>;
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ pub use snippet::Style;
|
|||||||
pub type PErr<'a> = DiagnosticBuilder<'a, ErrorGuaranteed>;
|
pub type PErr<'a> = DiagnosticBuilder<'a, ErrorGuaranteed>;
|
||||||
pub type PResult<'a, T> = Result<T, PErr<'a>>;
|
pub type PResult<'a, T> = Result<T, PErr<'a>>;
|
||||||
|
|
||||||
fluent_messages! { "../locales/en-US.ftl" }
|
fluent_messages! { "../messages.ftl" }
|
||||||
|
|
||||||
// `PResult` is used a lot. Make sure it doesn't unintentionally get bigger.
|
// `PResult` is used a lot. Make sure it doesn't unintentionally get bigger.
|
||||||
// (See also the comment on `DiagnosticBuilderInner`'s `diagnostic` field.)
|
// (See also the comment on `DiagnosticBuilderInner`'s `diagnostic` field.)
|
||||||
|
@ -12,13 +12,13 @@ use rustc_ast::tokenstream::TokenStream;
|
|||||||
use rustc_ast::visit::{AssocCtxt, Visitor};
|
use rustc_ast::visit::{AssocCtxt, Visitor};
|
||||||
use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind};
|
use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind};
|
||||||
use rustc_attr::{self as attr, Deprecation, Stability};
|
use rustc_attr::{self as attr, Deprecation, Stability};
|
||||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
use rustc_data_structures::fx::FxIndexMap;
|
||||||
use rustc_data_structures::sync::{self, Lrc};
|
use rustc_data_structures::sync::{self, Lrc};
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, MultiSpan, PResult,
|
Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, MultiSpan, PResult,
|
||||||
};
|
};
|
||||||
use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
|
use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
|
||||||
use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics};
|
use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics, RegisteredTools};
|
||||||
use rustc_parse::{self, parser, MACRO_ARGUMENTS};
|
use rustc_parse::{self, parser, MACRO_ARGUMENTS};
|
||||||
use rustc_session::errors::report_lit_error;
|
use rustc_session::errors::report_lit_error;
|
||||||
use rustc_session::{parse::ParseSess, Limit, Session};
|
use rustc_session::{parse::ParseSess, Limit, Session};
|
||||||
@ -947,14 +947,14 @@ pub trait ResolverExpand {
|
|||||||
fn declare_proc_macro(&mut self, id: NodeId);
|
fn declare_proc_macro(&mut self, id: NodeId);
|
||||||
|
|
||||||
/// Tools registered with `#![register_tool]` and used by tool attributes and lints.
|
/// Tools registered with `#![register_tool]` and used by tool attributes and lints.
|
||||||
fn registered_tools(&self) -> &FxHashSet<Ident>;
|
fn registered_tools(&self) -> &RegisteredTools;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait LintStoreExpand {
|
pub trait LintStoreExpand {
|
||||||
fn pre_expansion_lint(
|
fn pre_expansion_lint(
|
||||||
&self,
|
&self,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
registered_tools: &FxHashSet<Ident>,
|
registered_tools: &RegisteredTools,
|
||||||
node_id: NodeId,
|
node_id: NodeId,
|
||||||
attrs: &[Attribute],
|
attrs: &[Attribute],
|
||||||
items: &[P<Item>],
|
items: &[P<Item>],
|
||||||
|
@ -64,4 +64,4 @@ mod mut_visit {
|
|||||||
mod tests;
|
mod tests;
|
||||||
}
|
}
|
||||||
|
|
||||||
fluent_messages! { "../locales/en-US.ftl" }
|
fluent_messages! { "../messages.ftl" }
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
use std::borrow::Cow;
|
|
||||||
|
|
||||||
use crate::base::{DummyResult, ExtCtxt, MacResult};
|
use crate::base::{DummyResult, ExtCtxt, MacResult};
|
||||||
use crate::expand::{parse_ast_fragment, AstFragmentKind};
|
use crate::expand::{parse_ast_fragment, AstFragmentKind};
|
||||||
use crate::mbe::{
|
use crate::mbe::{
|
||||||
macro_parser::{MatcherLoc, NamedParseResult, ParseResult::*, TtParser},
|
macro_parser::{MatcherLoc, NamedParseResult, ParseResult::*, TtParser},
|
||||||
macro_rules::{try_match_macro, Tracker},
|
macro_rules::{try_match_macro, Tracker},
|
||||||
};
|
};
|
||||||
use rustc_ast::token::{self, Token};
|
use rustc_ast::token::{self, Token, TokenKind};
|
||||||
use rustc_ast::tokenstream::TokenStream;
|
use rustc_ast::tokenstream::TokenStream;
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage};
|
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage};
|
||||||
@ -14,6 +12,7 @@ use rustc_parse::parser::{Parser, Recovery};
|
|||||||
use rustc_span::source_map::SourceMap;
|
use rustc_span::source_map::SourceMap;
|
||||||
use rustc_span::symbol::Ident;
|
use rustc_span::symbol::Ident;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use super::macro_rules::{parser_from_cx, NoopTracker};
|
use super::macro_rules::{parser_from_cx, NoopTracker};
|
||||||
|
|
||||||
@ -63,6 +62,13 @@ pub(super) fn failed_to_match_macro<'cx>(
|
|||||||
err.note(format!("while trying to match {remaining_matcher}"));
|
err.note(format!("while trying to match {remaining_matcher}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let MatcherLoc::Token { token: expected_token } = &remaining_matcher
|
||||||
|
&& (matches!(expected_token.kind, TokenKind::Interpolated(_))
|
||||||
|
|| matches!(token.kind, TokenKind::Interpolated(_)))
|
||||||
|
{
|
||||||
|
err.note("captured metavariables except for `$tt`, `$ident` and `$lifetime` cannot be compared to other tokens");
|
||||||
|
}
|
||||||
|
|
||||||
// Check whether there's a missing comma in this macro call, like `println!("{}" a);`
|
// Check whether there's a missing comma in this macro call, like `println!("{}" a);`
|
||||||
if let Some((arg, comma_span)) = arg.add_comma() {
|
if let Some((arg, comma_span)) = arg.add_comma() {
|
||||||
for lhs in lhses {
|
for lhs in lhses {
|
||||||
|
@ -90,7 +90,7 @@ declare_features! (
|
|||||||
(accepted, clone_closures, "1.26.0", Some(44490), None),
|
(accepted, clone_closures, "1.26.0", Some(44490), None),
|
||||||
/// Allows coercing non capturing closures to function pointers.
|
/// Allows coercing non capturing closures to function pointers.
|
||||||
(accepted, closure_to_fn_coercion, "1.19.0", Some(39817), None),
|
(accepted, closure_to_fn_coercion, "1.19.0", Some(39817), None),
|
||||||
/// Allows using `cmpxchg16b` from `core::arch::x86_64`.
|
/// Allows using the CMPXCHG16B target feature.
|
||||||
(accepted, cmpxchg16b_target_feature, "CURRENT_RUSTC_VERSION", Some(44839), None),
|
(accepted, cmpxchg16b_target_feature, "CURRENT_RUSTC_VERSION", Some(44839), None),
|
||||||
/// Allows usage of the `compile_error!` macro.
|
/// Allows usage of the `compile_error!` macro.
|
||||||
(accepted, compile_error, "1.20.0", Some(40872), None),
|
(accepted, compile_error, "1.20.0", Some(40872), None),
|
||||||
@ -238,6 +238,8 @@ declare_features! (
|
|||||||
(accepted, min_const_unsafe_fn, "1.33.0", Some(55607), None),
|
(accepted, min_const_unsafe_fn, "1.33.0", Some(55607), None),
|
||||||
/// Allows using `Self` and associated types in struct expressions and patterns.
|
/// Allows using `Self` and associated types in struct expressions and patterns.
|
||||||
(accepted, more_struct_aliases, "1.16.0", Some(37544), None),
|
(accepted, more_struct_aliases, "1.16.0", Some(37544), None),
|
||||||
|
/// Allows using the MOVBE target feature.
|
||||||
|
(accepted, movbe_target_feature, "CURRENT_RUSTC_VERSION", Some(44839), None),
|
||||||
/// Allows patterns with concurrent by-move and by-ref bindings.
|
/// Allows patterns with concurrent by-move and by-ref bindings.
|
||||||
/// For example, you can write `Foo(a, ref b)` where `a` is by-move and `b` is by-ref.
|
/// For example, you can write `Foo(a, ref b)` where `a` is by-move and `b` is by-ref.
|
||||||
(accepted, move_ref_pattern, "1.49.0", Some(68354), None),
|
(accepted, move_ref_pattern, "1.49.0", Some(68354), None),
|
||||||
|
@ -200,8 +200,6 @@ declare_features! (
|
|||||||
(active, auto_traits, "1.50.0", Some(13231), None),
|
(active, auto_traits, "1.50.0", Some(13231), None),
|
||||||
/// Allows using `box` in patterns (RFC 469).
|
/// Allows using `box` in patterns (RFC 469).
|
||||||
(active, box_patterns, "1.0.0", Some(29641), None),
|
(active, box_patterns, "1.0.0", Some(29641), None),
|
||||||
/// Allows using the `box $expr` syntax.
|
|
||||||
(active, box_syntax, "1.0.0", Some(49733), None),
|
|
||||||
/// Allows `#[doc(notable_trait)]`.
|
/// Allows `#[doc(notable_trait)]`.
|
||||||
/// Renamed from `doc_spotlight`.
|
/// Renamed from `doc_spotlight`.
|
||||||
(active, doc_notable_trait, "1.52.0", Some(45040), None),
|
(active, doc_notable_trait, "1.52.0", Some(45040), None),
|
||||||
@ -259,7 +257,6 @@ declare_features! (
|
|||||||
(active, ermsb_target_feature, "1.49.0", Some(44839), None),
|
(active, ermsb_target_feature, "1.49.0", Some(44839), None),
|
||||||
(active, hexagon_target_feature, "1.27.0", Some(44839), None),
|
(active, hexagon_target_feature, "1.27.0", Some(44839), None),
|
||||||
(active, mips_target_feature, "1.27.0", Some(44839), None),
|
(active, mips_target_feature, "1.27.0", Some(44839), None),
|
||||||
(active, movbe_target_feature, "1.34.0", Some(44839), None),
|
|
||||||
(active, powerpc_target_feature, "1.27.0", Some(44839), None),
|
(active, powerpc_target_feature, "1.27.0", Some(44839), None),
|
||||||
(active, riscv_target_feature, "1.45.0", Some(44839), None),
|
(active, riscv_target_feature, "1.45.0", Some(44839), None),
|
||||||
(active, rtm_target_feature, "1.35.0", Some(44839), None),
|
(active, rtm_target_feature, "1.35.0", Some(44839), None),
|
||||||
|
@ -52,6 +52,8 @@ declare_features! (
|
|||||||
(removed, allow_fail, "1.19.0", Some(46488), None, Some("removed due to no clear use cases")),
|
(removed, allow_fail, "1.19.0", Some(46488), None, Some("removed due to no clear use cases")),
|
||||||
(removed, await_macro, "1.38.0", Some(50547), None,
|
(removed, await_macro, "1.38.0", Some(50547), None,
|
||||||
Some("subsumed by `.await` syntax")),
|
Some("subsumed by `.await` syntax")),
|
||||||
|
/// Allows using the `box $expr` syntax.
|
||||||
|
(removed, box_syntax, "CURRENT_RUSTC_VERSION", Some(49733), None, Some("replaced with `#[rustc_box]`")),
|
||||||
/// Allows capturing disjoint fields in a closure/generator (RFC 2229).
|
/// Allows capturing disjoint fields in a closure/generator (RFC 2229).
|
||||||
(removed, capture_disjoint_fields, "1.49.0", Some(53488), None, Some("stabilized in Rust 2021")),
|
(removed, capture_disjoint_fields, "1.49.0", Some(53488), None, Some("stabilized in Rust 2021")),
|
||||||
/// Allows comparing raw pointers during const eval.
|
/// Allows comparing raw pointers during const eval.
|
||||||
|
@ -815,12 +815,13 @@ pub struct ParentedNode<'tcx> {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct AttributeMap<'tcx> {
|
pub struct AttributeMap<'tcx> {
|
||||||
pub map: SortedMap<ItemLocalId, &'tcx [Attribute]>,
|
pub map: SortedMap<ItemLocalId, &'tcx [Attribute]>,
|
||||||
pub hash: Fingerprint,
|
// Only present when the crate hash is needed.
|
||||||
|
pub opt_hash: Option<Fingerprint>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> AttributeMap<'tcx> {
|
impl<'tcx> AttributeMap<'tcx> {
|
||||||
pub const EMPTY: &'static AttributeMap<'static> =
|
pub const EMPTY: &'static AttributeMap<'static> =
|
||||||
&AttributeMap { map: SortedMap::new(), hash: Fingerprint::ZERO };
|
&AttributeMap { map: SortedMap::new(), opt_hash: Some(Fingerprint::ZERO) };
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get(&self, id: ItemLocalId) -> &'tcx [Attribute] {
|
pub fn get(&self, id: ItemLocalId) -> &'tcx [Attribute] {
|
||||||
@ -832,10 +833,9 @@ impl<'tcx> AttributeMap<'tcx> {
|
|||||||
/// These nodes are mapped by `ItemLocalId` alongside the index of their parent node.
|
/// These nodes are mapped by `ItemLocalId` alongside the index of their parent node.
|
||||||
/// The HIR tree, including bodies, is pre-hashed.
|
/// The HIR tree, including bodies, is pre-hashed.
|
||||||
pub struct OwnerNodes<'tcx> {
|
pub struct OwnerNodes<'tcx> {
|
||||||
/// Pre-computed hash of the full HIR.
|
/// Pre-computed hash of the full HIR. Used in the crate hash. Only present
|
||||||
pub hash_including_bodies: Fingerprint,
|
/// when incr. comp. is enabled.
|
||||||
/// Pre-computed hash of the item signature, without recursing into the body.
|
pub opt_hash_including_bodies: Option<Fingerprint>,
|
||||||
pub hash_without_bodies: Fingerprint,
|
|
||||||
/// Full HIR for the current owner.
|
/// Full HIR for the current owner.
|
||||||
// The zeroth node's parent should never be accessed: the owner's parent is computed by the
|
// The zeroth node's parent should never be accessed: the owner's parent is computed by the
|
||||||
// hir_owner_parent query. It is set to `ItemLocalId::INVALID` to force an ICE if accidentally
|
// hir_owner_parent query. It is set to `ItemLocalId::INVALID` to force an ICE if accidentally
|
||||||
@ -872,8 +872,7 @@ impl fmt::Debug for OwnerNodes<'_> {
|
|||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
)
|
)
|
||||||
.field("bodies", &self.bodies)
|
.field("bodies", &self.bodies)
|
||||||
.field("hash_without_bodies", &self.hash_without_bodies)
|
.field("opt_hash_including_bodies", &self.opt_hash_including_bodies)
|
||||||
.field("hash_including_bodies", &self.hash_including_bodies)
|
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -940,7 +939,8 @@ impl<T> MaybeOwner<T> {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Crate<'hir> {
|
pub struct Crate<'hir> {
|
||||||
pub owners: IndexVec<LocalDefId, MaybeOwner<&'hir OwnerInfo<'hir>>>,
|
pub owners: IndexVec<LocalDefId, MaybeOwner<&'hir OwnerInfo<'hir>>>,
|
||||||
pub hir_hash: Fingerprint,
|
// Only present when incr. comp. is enabled.
|
||||||
|
pub opt_hir_hash: Option<Fingerprint>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, HashStable_Generic)]
|
#[derive(Debug, HashStable_Generic)]
|
||||||
|
@ -296,7 +296,6 @@ language_item_table! {
|
|||||||
// FIXME(swatinem): the following lang items are used for async lowering and
|
// FIXME(swatinem): the following lang items are used for async lowering and
|
||||||
// should become obsolete eventually.
|
// should become obsolete eventually.
|
||||||
ResumeTy, sym::ResumeTy, resume_ty, Target::Struct, GenericRequirement::None;
|
ResumeTy, sym::ResumeTy, resume_ty, Target::Struct, GenericRequirement::None;
|
||||||
IdentityFuture, sym::identity_future, identity_future_fn, Target::Fn, GenericRequirement::None;
|
|
||||||
GetContext, sym::get_context, get_context_fn, Target::Fn, GenericRequirement::None;
|
GetContext, sym::get_context, get_context_fn, Target::Fn, GenericRequirement::None;
|
||||||
|
|
||||||
Context, sym::Context, context, Target::Struct, GenericRequirement::None;
|
Context, sym::Context, context, Target::Struct, GenericRequirement::None;
|
||||||
|
@ -100,24 +100,23 @@ impl<'tcx, HirCtx: crate::HashStableContext> HashStable<HirCtx> for OwnerNodes<'
|
|||||||
// `local_id_to_def_id` is also ignored because is dependent on the body, then just hashing
|
// `local_id_to_def_id` is also ignored because is dependent on the body, then just hashing
|
||||||
// the body satisfies the condition of two nodes being different have different
|
// the body satisfies the condition of two nodes being different have different
|
||||||
// `hash_stable` results.
|
// `hash_stable` results.
|
||||||
let OwnerNodes { hash_including_bodies, hash_without_bodies: _, nodes: _, bodies: _ } =
|
let OwnerNodes { opt_hash_including_bodies, nodes: _, bodies: _ } = *self;
|
||||||
*self;
|
opt_hash_including_bodies.unwrap().hash_stable(hcx, hasher);
|
||||||
hash_including_bodies.hash_stable(hcx, hasher);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx, HirCtx: crate::HashStableContext> HashStable<HirCtx> for AttributeMap<'tcx> {
|
impl<'tcx, HirCtx: crate::HashStableContext> HashStable<HirCtx> for AttributeMap<'tcx> {
|
||||||
fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
|
fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
|
||||||
// We ignore the `map` since it refers to information included in `hash` which is hashed in
|
// We ignore the `map` since it refers to information included in `opt_hash` which is
|
||||||
// the collector and used for the crate hash.
|
// hashed in the collector and used for the crate hash.
|
||||||
let AttributeMap { hash, map: _ } = *self;
|
let AttributeMap { opt_hash, map: _ } = *self;
|
||||||
hash.hash_stable(hcx, hasher);
|
opt_hash.unwrap().hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Crate<'_> {
|
impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Crate<'_> {
|
||||||
fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
|
fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
|
||||||
let Crate { owners: _, hir_hash } = self;
|
let Crate { owners: _, opt_hir_hash } = self;
|
||||||
hir_hash.hash_stable(hcx, hasher)
|
opt_hir_hash.unwrap().hash_stable(hcx, hasher)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,9 @@ hir_analysis_assoc_type_binding_not_allowed =
|
|||||||
associated type bindings are not allowed here
|
associated type bindings are not allowed here
|
||||||
.label = associated type not allowed here
|
.label = associated type not allowed here
|
||||||
|
|
||||||
|
hir_analysis_parenthesized_fn_trait_expansion =
|
||||||
|
parenthesized trait syntax expands to `{$expanded_type}`
|
||||||
|
|
||||||
hir_analysis_typeof_reserved_keyword_used =
|
hir_analysis_typeof_reserved_keyword_used =
|
||||||
`typeof` is a reserved keyword but unimplemented
|
`typeof` is a reserved keyword but unimplemented
|
||||||
.suggestion = consider replacing `typeof(...)` with an actual type
|
.suggestion = consider replacing `typeof(...)` with an actual type
|
||||||
@ -125,9 +128,14 @@ hir_analysis_where_clause_on_main = `main` function is not allowed to have a `wh
|
|||||||
hir_analysis_track_caller_on_main = `main` function is not allowed to be `#[track_caller]`
|
hir_analysis_track_caller_on_main = `main` function is not allowed to be `#[track_caller]`
|
||||||
.suggestion = remove this annotation
|
.suggestion = remove this annotation
|
||||||
|
|
||||||
|
hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]`
|
||||||
|
|
||||||
hir_analysis_start_not_track_caller = `start` is not allowed to be `#[track_caller]`
|
hir_analysis_start_not_track_caller = `start` is not allowed to be `#[track_caller]`
|
||||||
.label = `start` is not allowed to be `#[track_caller]`
|
.label = `start` is not allowed to be `#[track_caller]`
|
||||||
|
|
||||||
|
hir_analysis_start_not_target_feature = `start` is not allowed to have `#[target_feature]`
|
||||||
|
.label = `start` is not allowed to have `#[target_feature]`
|
||||||
|
|
||||||
hir_analysis_start_not_async = `start` is not allowed to be `async`
|
hir_analysis_start_not_async = `start` is not allowed to be `async`
|
||||||
.label = `start` is not allowed to be `async`
|
.label = `start` is not allowed to be `async`
|
||||||
|
|
@ -1,10 +1,14 @@
|
|||||||
use crate::astconv::AstConv;
|
use crate::astconv::AstConv;
|
||||||
use crate::errors::{ManualImplementation, MissingTypeParams};
|
use crate::errors::{
|
||||||
|
AssocTypeBindingNotAllowed, ManualImplementation, MissingTypeParams,
|
||||||
|
ParenthesizedFnTraitExpansion,
|
||||||
|
};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, ErrorGuaranteed};
|
use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, ErrorGuaranteed};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_infer::traits::FulfillmentError;
|
use rustc_infer::traits::FulfillmentError;
|
||||||
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_middle::ty::{self, Ty};
|
use rustc_middle::ty::{self, Ty};
|
||||||
use rustc_session::parse::feature_err;
|
use rustc_session::parse::feature_err;
|
||||||
use rustc_span::edit_distance::find_best_match_for_name;
|
use rustc_span::edit_distance::find_best_match_for_name;
|
||||||
@ -78,43 +82,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
// Do not suggest the other syntax if we are in trait impl:
|
// Do not suggest the other syntax if we are in trait impl:
|
||||||
// the desugaring would contain an associated type constraint.
|
// the desugaring would contain an associated type constraint.
|
||||||
if !is_impl {
|
if !is_impl {
|
||||||
let args = trait_segment
|
|
||||||
.args
|
|
||||||
.as_ref()
|
|
||||||
.and_then(|args| args.args.get(0))
|
|
||||||
.and_then(|arg| match arg {
|
|
||||||
hir::GenericArg::Type(ty) => match ty.kind {
|
|
||||||
hir::TyKind::Tup(t) => t
|
|
||||||
.iter()
|
|
||||||
.map(|e| sess.source_map().span_to_snippet(e.span))
|
|
||||||
.collect::<Result<Vec<_>, _>>()
|
|
||||||
.map(|a| a.join(", ")),
|
|
||||||
_ => sess.source_map().span_to_snippet(ty.span),
|
|
||||||
}
|
|
||||||
.map(|s| format!("({})", s))
|
|
||||||
.ok(),
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
.unwrap_or_else(|| "()".to_string());
|
|
||||||
let ret = trait_segment
|
|
||||||
.args()
|
|
||||||
.bindings
|
|
||||||
.iter()
|
|
||||||
.find_map(|b| match (b.ident.name == sym::Output, &b.kind) {
|
|
||||||
(true, hir::TypeBindingKind::Equality { term }) => {
|
|
||||||
let span = match term {
|
|
||||||
hir::Term::Ty(ty) => ty.span,
|
|
||||||
hir::Term::Const(c) => self.tcx().hir().span(c.hir_id),
|
|
||||||
};
|
|
||||||
sess.source_map().span_to_snippet(span).ok()
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
.unwrap_or_else(|| "()".to_string());
|
|
||||||
err.span_suggestion(
|
err.span_suggestion(
|
||||||
span,
|
span,
|
||||||
"use parenthetical notation instead",
|
"use parenthetical notation instead",
|
||||||
format!("{}{} -> {}", trait_segment.ident, args, ret),
|
fn_trait_to_string(self.tcx(), trait_segment, true),
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -629,3 +600,69 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Emits an error regarding forbidden type binding associations
|
||||||
|
pub fn prohibit_assoc_ty_binding(
|
||||||
|
tcx: TyCtxt<'_>,
|
||||||
|
span: Span,
|
||||||
|
segment: Option<(&hir::PathSegment<'_>, Span)>,
|
||||||
|
) {
|
||||||
|
tcx.sess.emit_err(AssocTypeBindingNotAllowed { span, fn_trait_expansion: if let Some((segment, span)) = segment && segment.args().parenthesized {
|
||||||
|
Some(ParenthesizedFnTraitExpansion { span, expanded_type: fn_trait_to_string(tcx, segment, false) })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn fn_trait_to_string(
|
||||||
|
tcx: TyCtxt<'_>,
|
||||||
|
trait_segment: &hir::PathSegment<'_>,
|
||||||
|
parenthesized: bool,
|
||||||
|
) -> String {
|
||||||
|
let args = trait_segment
|
||||||
|
.args
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|args| args.args.get(0))
|
||||||
|
.and_then(|arg| match arg {
|
||||||
|
hir::GenericArg::Type(ty) => match ty.kind {
|
||||||
|
hir::TyKind::Tup(t) => t
|
||||||
|
.iter()
|
||||||
|
.map(|e| tcx.sess.source_map().span_to_snippet(e.span))
|
||||||
|
.collect::<Result<Vec<_>, _>>()
|
||||||
|
.map(|a| a.join(", ")),
|
||||||
|
_ => tcx.sess.source_map().span_to_snippet(ty.span),
|
||||||
|
}
|
||||||
|
.map(|s| {
|
||||||
|
// `s.empty()` checks to see if the type is the unit tuple, if so we don't want a comma
|
||||||
|
if parenthesized || s.is_empty() { format!("({})", s) } else { format!("({},)", s) }
|
||||||
|
})
|
||||||
|
.ok(),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| "()".to_string());
|
||||||
|
|
||||||
|
let ret = trait_segment
|
||||||
|
.args()
|
||||||
|
.bindings
|
||||||
|
.iter()
|
||||||
|
.find_map(|b| match (b.ident.name == sym::Output, &b.kind) {
|
||||||
|
(true, hir::TypeBindingKind::Equality { term }) => {
|
||||||
|
let span = match term {
|
||||||
|
hir::Term::Ty(ty) => ty.span,
|
||||||
|
hir::Term::Const(c) => tcx.hir().span(c.hir_id),
|
||||||
|
};
|
||||||
|
|
||||||
|
(span != tcx.hir().span(trait_segment.hir_id))
|
||||||
|
.then_some(tcx.sess.source_map().span_to_snippet(span).ok())
|
||||||
|
.flatten()
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| "()".to_string());
|
||||||
|
|
||||||
|
if parenthesized {
|
||||||
|
format!("{}{} -> {}", trait_segment.ident, args, ret)
|
||||||
|
} else {
|
||||||
|
format!("{}<{}, Output={}>", trait_segment.ident, args, ret)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
use super::IsMethodCall;
|
use super::IsMethodCall;
|
||||||
use crate::astconv::{
|
use crate::astconv::{
|
||||||
CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch,
|
errors::prohibit_assoc_ty_binding, CreateSubstsForGenericArgsCtxt, ExplicitLateBound,
|
||||||
GenericArgCountResult, GenericArgPosition,
|
GenericArgCountMismatch, GenericArgCountResult, GenericArgPosition,
|
||||||
};
|
};
|
||||||
use crate::errors::AssocTypeBindingNotAllowed;
|
|
||||||
use crate::structured_errors::{GenericArgsInfo, StructuredDiagnostic, WrongNumberOfGenericArgs};
|
use crate::structured_errors::{GenericArgsInfo, StructuredDiagnostic, WrongNumberOfGenericArgs};
|
||||||
use rustc_ast::ast::ParamKindOrd;
|
use rustc_ast::ast::ParamKindOrd;
|
||||||
use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan};
|
use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan};
|
||||||
@ -433,7 +432,7 @@ pub(crate) fn check_generic_arg_count(
|
|||||||
(gen_pos != GenericArgPosition::Type || infer_args) && !gen_args.has_lifetime_params();
|
(gen_pos != GenericArgPosition::Type || infer_args) && !gen_args.has_lifetime_params();
|
||||||
|
|
||||||
if gen_pos != GenericArgPosition::Type && let Some(b) = gen_args.bindings.first() {
|
if gen_pos != GenericArgPosition::Type && let Some(b) = gen_args.bindings.first() {
|
||||||
prohibit_assoc_ty_binding(tcx, b.span);
|
prohibit_assoc_ty_binding(tcx, b.span, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let explicit_late_bound =
|
let explicit_late_bound =
|
||||||
@ -589,11 +588,6 @@ pub(crate) fn check_generic_arg_count(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Emits an error regarding forbidden type binding associations
|
|
||||||
pub fn prohibit_assoc_ty_binding(tcx: TyCtxt<'_>, span: Span) {
|
|
||||||
tcx.sess.emit_err(AssocTypeBindingNotAllowed { span });
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Prohibits explicit lifetime arguments if late-bound lifetime parameters
|
/// Prohibits explicit lifetime arguments if late-bound lifetime parameters
|
||||||
/// are present. This is used both for datatypes and function calls.
|
/// are present. This is used both for datatypes and function calls.
|
||||||
pub(crate) fn prohibit_explicit_late_bound_lifetimes(
|
pub(crate) fn prohibit_explicit_late_bound_lifetimes(
|
||||||
|
@ -5,9 +5,8 @@
|
|||||||
mod errors;
|
mod errors;
|
||||||
pub mod generics;
|
pub mod generics;
|
||||||
|
|
||||||
use crate::astconv::generics::{
|
use crate::astconv::errors::prohibit_assoc_ty_binding;
|
||||||
check_generic_arg_count, create_substs_for_generic_args, prohibit_assoc_ty_binding,
|
use crate::astconv::generics::{check_generic_arg_count, create_substs_for_generic_args};
|
||||||
};
|
|
||||||
use crate::bounds::Bounds;
|
use crate::bounds::Bounds;
|
||||||
use crate::collect::HirPlaceholderCollector;
|
use crate::collect::HirPlaceholderCollector;
|
||||||
use crate::errors::{
|
use crate::errors::{
|
||||||
@ -295,7 +294,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
ty::BoundConstness::NotConst,
|
ty::BoundConstness::NotConst,
|
||||||
);
|
);
|
||||||
if let Some(b) = item_segment.args().bindings.first() {
|
if let Some(b) = item_segment.args().bindings.first() {
|
||||||
prohibit_assoc_ty_binding(self.tcx(), b.span);
|
prohibit_assoc_ty_binding(self.tcx(), b.span, Some((item_segment, span)));
|
||||||
}
|
}
|
||||||
|
|
||||||
substs
|
substs
|
||||||
@ -631,7 +630,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if let Some(b) = item_segment.args().bindings.first() {
|
if let Some(b) = item_segment.args().bindings.first() {
|
||||||
prohibit_assoc_ty_binding(self.tcx(), b.span);
|
prohibit_assoc_ty_binding(self.tcx(), b.span, Some((item_segment, span)));
|
||||||
}
|
}
|
||||||
|
|
||||||
args
|
args
|
||||||
@ -825,7 +824,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
constness,
|
constness,
|
||||||
);
|
);
|
||||||
if let Some(b) = trait_segment.args().bindings.first() {
|
if let Some(b) = trait_segment.args().bindings.first() {
|
||||||
prohibit_assoc_ty_binding(self.tcx(), b.span);
|
prohibit_assoc_ty_binding(self.tcx(), b.span, Some((trait_segment, span)));
|
||||||
}
|
}
|
||||||
self.tcx().mk_trait_ref(trait_def_id, substs)
|
self.tcx().mk_trait_ref(trait_def_id, substs)
|
||||||
}
|
}
|
||||||
@ -2596,7 +2595,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
for segment in segments {
|
for segment in segments {
|
||||||
// Only emit the first error to avoid overloading the user with error messages.
|
// Only emit the first error to avoid overloading the user with error messages.
|
||||||
if let Some(b) = segment.args().bindings.first() {
|
if let Some(b) = segment.args().bindings.first() {
|
||||||
prohibit_assoc_ty_binding(self.tcx(), b.span);
|
prohibit_assoc_ty_binding(self.tcx(), b.span, None);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3049,10 +3048,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
}
|
}
|
||||||
&hir::TyKind::OpaqueDef(item_id, lifetimes, in_trait) => {
|
&hir::TyKind::OpaqueDef(item_id, lifetimes, in_trait) => {
|
||||||
let opaque_ty = tcx.hir().item(item_id);
|
let opaque_ty = tcx.hir().item(item_id);
|
||||||
let def_id = item_id.owner_id.to_def_id();
|
|
||||||
|
|
||||||
match opaque_ty.kind {
|
match opaque_ty.kind {
|
||||||
hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => {
|
hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => {
|
||||||
|
let local_def_id = item_id.owner_id.def_id;
|
||||||
|
// If this is an RPITIT and we are using the new RPITIT lowering scheme, we
|
||||||
|
// generate the def_id of an associated type for the trait and return as
|
||||||
|
// type a projection.
|
||||||
|
let def_id = if in_trait && tcx.lower_impl_trait_in_trait_to_assoc_ty() {
|
||||||
|
tcx.associated_item_for_impl_trait_in_trait(local_def_id).to_def_id()
|
||||||
|
} else {
|
||||||
|
local_def_id.to_def_id()
|
||||||
|
};
|
||||||
self.impl_trait_ty_to_ty(def_id, lifetimes, origin, in_trait)
|
self.impl_trait_ty_to_ty(def_id, lifetimes, origin, in_trait)
|
||||||
}
|
}
|
||||||
ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
|
ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
|
||||||
|
@ -444,7 +444,7 @@ fn check_opaque_meets_bounds<'tcx>(
|
|||||||
// version.
|
// version.
|
||||||
let errors = ocx.select_all_or_error();
|
let errors = ocx.select_all_or_error();
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||||
}
|
}
|
||||||
match origin {
|
match origin {
|
||||||
// Checked when type checking the function containing them.
|
// Checked when type checking the function containing them.
|
||||||
@ -1545,6 +1545,6 @@ pub(super) fn check_generator_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||||||
let errors = fulfillment_cx.select_all_or_error(&infcx);
|
let errors = fulfillment_cx.select_all_or_error(&infcx);
|
||||||
debug!(?errors);
|
debug!(?errors);
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -320,7 +320,7 @@ fn compare_method_predicate_entailment<'tcx>(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
CheckImpliedWfMode::Skip => {
|
CheckImpliedWfMode::Skip => {
|
||||||
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||||
return Err(reported);
|
return Err(reported);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -720,7 +720,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
|||||||
// RPITs.
|
// RPITs.
|
||||||
let errors = ocx.select_all_or_error();
|
let errors = ocx.select_all_or_error();
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||||
return Err(reported);
|
return Err(reported);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -830,7 +830,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
|
|||||||
|
|
||||||
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||||
if let ty::Alias(ty::Projection, proj) = ty.kind()
|
if let ty::Alias(ty::Projection, proj) = ty.kind()
|
||||||
&& self.interner().def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
|
&& self.interner().is_impl_trait_in_trait(proj.def_id)
|
||||||
{
|
{
|
||||||
if let Some((ty, _)) = self.types.get(&proj.def_id) {
|
if let Some((ty, _)) = self.types.get(&proj.def_id) {
|
||||||
return *ty;
|
return *ty;
|
||||||
@ -1731,7 +1731,7 @@ pub(super) fn compare_impl_const_raw(
|
|||||||
// version.
|
// version.
|
||||||
let errors = ocx.select_all_or_error();
|
let errors = ocx.select_all_or_error();
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
return Err(infcx.err_ctxt().report_fulfillment_errors(&errors, None));
|
return Err(infcx.err_ctxt().report_fulfillment_errors(&errors));
|
||||||
}
|
}
|
||||||
|
|
||||||
let outlives_environment = OutlivesEnvironment::new(param_env);
|
let outlives_environment = OutlivesEnvironment::new(param_env);
|
||||||
@ -1831,7 +1831,7 @@ fn compare_type_predicate_entailment<'tcx>(
|
|||||||
// version.
|
// version.
|
||||||
let errors = ocx.select_all_or_error();
|
let errors = ocx.select_all_or_error();
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||||
return Err(reported);
|
return Err(reported);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1995,13 +1995,20 @@ pub(super) fn check_type_bounds<'tcx>(
|
|||||||
let infcx = tcx.infer_ctxt().build();
|
let infcx = tcx.infer_ctxt().build();
|
||||||
let ocx = ObligationCtxt::new(&infcx);
|
let ocx = ObligationCtxt::new(&infcx);
|
||||||
|
|
||||||
let impl_ty_span = match tcx.hir().get_by_def_id(impl_ty_def_id) {
|
// A synthetic impl Trait for RPITIT desugaring has no HIR, which we currently use to get the
|
||||||
hir::Node::TraitItem(hir::TraitItem {
|
// span for an impl's associated type. Instead, for these, use the def_span for the synthesized
|
||||||
kind: hir::TraitItemKind::Type(_, Some(ty)),
|
// associated type.
|
||||||
..
|
let impl_ty_span = if tcx.opt_rpitit_info(impl_ty.def_id).is_some() {
|
||||||
}) => ty.span,
|
tcx.def_span(impl_ty_def_id)
|
||||||
hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Type(ty), .. }) => ty.span,
|
} else {
|
||||||
_ => bug!(),
|
match tcx.hir().get_by_def_id(impl_ty_def_id) {
|
||||||
|
hir::Node::TraitItem(hir::TraitItem {
|
||||||
|
kind: hir::TraitItemKind::Type(_, Some(ty)),
|
||||||
|
..
|
||||||
|
}) => ty.span,
|
||||||
|
hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Type(ty), .. }) => ty.span,
|
||||||
|
_ => bug!(),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let assumed_wf_types = ocx.assumed_wf_types(param_env, impl_ty_span, impl_ty_def_id);
|
let assumed_wf_types = ocx.assumed_wf_types(param_env, impl_ty_span, impl_ty_def_id);
|
||||||
|
|
||||||
@ -2044,7 +2051,7 @@ pub(super) fn check_type_bounds<'tcx>(
|
|||||||
// version.
|
// version.
|
||||||
let errors = ocx.select_all_or_error();
|
let errors = ocx.select_all_or_error();
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||||
return Err(reported);
|
return Err(reported);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
|
|||||||
|
|
||||||
let errors = wfcx.select_all_or_error();
|
let errors = wfcx.select_all_or_error();
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,7 +345,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, resolve all regions.
|
// Finally, resolve all regions.
|
||||||
@ -585,7 +585,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
|
|||||||
predicate_for_trait_def(tcx, param_env, cause, trait_def_id, 0, [source, target]);
|
predicate_for_trait_def(tcx, param_env, cause, trait_def_id, 0, [source, target]);
|
||||||
let errors = traits::fully_solve_obligation(&infcx, predicate);
|
let errors = traits::fully_solve_obligation(&infcx, predicate);
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, resolve all regions.
|
// Finally, resolve all regions.
|
||||||
|
@ -11,7 +11,7 @@ use rustc_errors::struct_span_err;
|
|||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
|
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
|
||||||
use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams};
|
use rustc_middle::ty::fast_reject::{simplify_type, SimplifiedType, TreatParams, TreatProjections};
|
||||||
use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt};
|
use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
|
|
||||||
@ -99,7 +99,12 @@ impl<'tcx> InherentCollect<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::AsInfer) {
|
if let Some(simp) = simplify_type(
|
||||||
|
self.tcx,
|
||||||
|
self_ty,
|
||||||
|
TreatParams::AsCandidateKey,
|
||||||
|
TreatProjections::AsCandidateKey,
|
||||||
|
) {
|
||||||
self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id);
|
self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id);
|
||||||
} else {
|
} else {
|
||||||
bug!("unexpected self type: {:?}", self_ty);
|
bug!("unexpected self type: {:?}", self_ty);
|
||||||
@ -159,7 +164,12 @@ impl<'tcx> InherentCollect<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(simp) = simplify_type(self.tcx, ty, TreatParams::AsInfer) {
|
if let Some(simp) = simplify_type(
|
||||||
|
self.tcx,
|
||||||
|
ty,
|
||||||
|
TreatParams::AsCandidateKey,
|
||||||
|
TreatProjections::AsCandidateKey,
|
||||||
|
) {
|
||||||
self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id);
|
self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id);
|
||||||
} else {
|
} else {
|
||||||
bug!("unexpected primitive type: {:?}", ty);
|
bug!("unexpected primitive type: {:?}", ty);
|
||||||
|
@ -3,7 +3,7 @@ use crate::astconv::AstConv;
|
|||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_infer::traits::util;
|
use rustc_infer::traits::util;
|
||||||
use rustc_middle::ty::subst::InternalSubsts;
|
use rustc_middle::ty::subst::InternalSubsts;
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, ImplTraitInTraitData, Ty, TyCtxt};
|
||||||
use rustc_span::def_id::DefId;
|
use rustc_span::def_id::DefId;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
@ -58,17 +58,10 @@ fn opaque_type_bounds<'tcx>(
|
|||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
opaque_def_id: DefId,
|
opaque_def_id: DefId,
|
||||||
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
|
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
|
||||||
|
item_ty: Ty<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
in_trait: bool,
|
|
||||||
) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
|
) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
|
||||||
ty::print::with_no_queries!({
|
ty::print::with_no_queries!({
|
||||||
let substs = InternalSubsts::identity_for_item(tcx, opaque_def_id);
|
|
||||||
let item_ty = if in_trait {
|
|
||||||
tcx.mk_projection(opaque_def_id, substs)
|
|
||||||
} else {
|
|
||||||
tcx.mk_opaque(opaque_def_id, substs)
|
|
||||||
};
|
|
||||||
|
|
||||||
let icx = ItemCtxt::new(tcx, opaque_def_id);
|
let icx = ItemCtxt::new(tcx, opaque_def_id);
|
||||||
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds);
|
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds);
|
||||||
// Opaque types are implicitly sized unless a `?Sized` bound is found
|
// Opaque types are implicitly sized unless a `?Sized` bound is found
|
||||||
@ -83,7 +76,18 @@ pub(super) fn explicit_item_bounds(
|
|||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
) -> &'_ [(ty::Predicate<'_>, Span)] {
|
) -> &'_ [(ty::Predicate<'_>, Span)] {
|
||||||
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
|
// If the def_id is about an RPITIT, delegate explicit_item_bounds to the opaque_def_id that
|
||||||
|
// generated the synthesized associate type.
|
||||||
|
let rpitit_info = if let Some(ImplTraitInTraitData::Trait { opaque_def_id, .. }) =
|
||||||
|
tcx.opt_rpitit_info(def_id)
|
||||||
|
{
|
||||||
|
Some(opaque_def_id)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let bounds_def_id = rpitit_info.unwrap_or(def_id);
|
||||||
|
let hir_id = tcx.hir().local_def_id_to_hir_id(bounds_def_id.expect_local());
|
||||||
match tcx.hir().get(hir_id) {
|
match tcx.hir().get(hir_id) {
|
||||||
hir::Node::TraitItem(hir::TraitItem {
|
hir::Node::TraitItem(hir::TraitItem {
|
||||||
kind: hir::TraitItemKind::Type(bounds, _),
|
kind: hir::TraitItemKind::Type(bounds, _),
|
||||||
@ -94,7 +98,15 @@ pub(super) fn explicit_item_bounds(
|
|||||||
kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait, .. }),
|
kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait, .. }),
|
||||||
span,
|
span,
|
||||||
..
|
..
|
||||||
}) => opaque_type_bounds(tcx, def_id, bounds, *span, *in_trait),
|
}) => {
|
||||||
|
let substs = InternalSubsts::identity_for_item(tcx, def_id);
|
||||||
|
let item_ty = if *in_trait || rpitit_info.is_some() {
|
||||||
|
tcx.mk_projection(def_id, substs)
|
||||||
|
} else {
|
||||||
|
tcx.mk_opaque(def_id, substs)
|
||||||
|
};
|
||||||
|
opaque_type_bounds(tcx, bounds_def_id, bounds, item_ty, *span)
|
||||||
|
}
|
||||||
_ => bug!("item_bounds called on {:?}", def_id),
|
_ => bug!("item_bounds called on {:?}", def_id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,8 @@ use rustc_middle::ty::print::with_forced_trimmed_paths;
|
|||||||
use rustc_middle::ty::subst::InternalSubsts;
|
use rustc_middle::ty::subst::InternalSubsts;
|
||||||
use rustc_middle::ty::util::IntTypeExt;
|
use rustc_middle::ty::util::IntTypeExt;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
|
self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable,
|
||||||
|
TypeVisitableExt,
|
||||||
};
|
};
|
||||||
use rustc_span::symbol::Ident;
|
use rustc_span::symbol::Ident;
|
||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
@ -244,6 +245,24 @@ fn get_path_containing_arg_in_pat<'hir>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>> {
|
pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<Ty<'_>> {
|
||||||
|
// If we are computing `type_of` the synthesized associated type for an RPITIT in the impl
|
||||||
|
// side, use `collect_return_position_impl_trait_in_trait_tys` to infer the value of the
|
||||||
|
// associated type in the impl.
|
||||||
|
if let Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) = tcx.opt_rpitit_info(def_id) {
|
||||||
|
match tcx.collect_return_position_impl_trait_in_trait_tys(fn_def_id) {
|
||||||
|
Ok(map) => {
|
||||||
|
let assoc_item = tcx.associated_item(def_id);
|
||||||
|
return ty::EarlyBinder(map[&assoc_item.trait_item_def_id.unwrap()]);
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
return ty::EarlyBinder(tcx.ty_error_with_message(
|
||||||
|
DUMMY_SP,
|
||||||
|
"Could not collect return position impl trait in trait tys",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let def_id = def_id.expect_local();
|
let def_id = def_id.expect_local();
|
||||||
use rustc_hir::*;
|
use rustc_hir::*;
|
||||||
|
|
||||||
|
@ -129,6 +129,18 @@ pub struct AssocTypeBindingNotAllowed {
|
|||||||
#[primary_span]
|
#[primary_span]
|
||||||
#[label]
|
#[label]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub fn_trait_expansion: Option<ParenthesizedFnTraitExpansion>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[help(hir_analysis_parenthesized_fn_trait_expansion)]
|
||||||
|
pub struct ParenthesizedFnTraitExpansion {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
|
||||||
|
pub expanded_type: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
@ -315,6 +327,14 @@ pub(crate) struct TrackCallerOnMain {
|
|||||||
pub annotated: Span,
|
pub annotated: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(hir_analysis_target_feature_on_main)]
|
||||||
|
pub(crate) struct TargetFeatureOnMain {
|
||||||
|
#[primary_span]
|
||||||
|
#[label(hir_analysis_target_feature_on_main)]
|
||||||
|
pub main: Span,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(hir_analysis_start_not_track_caller)]
|
#[diag(hir_analysis_start_not_track_caller)]
|
||||||
pub(crate) struct StartTrackCaller {
|
pub(crate) struct StartTrackCaller {
|
||||||
@ -324,6 +344,15 @@ pub(crate) struct StartTrackCaller {
|
|||||||
pub start: Span,
|
pub start: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(hir_analysis_start_not_target_feature)]
|
||||||
|
pub(crate) struct StartTargetFeature {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
#[label]
|
||||||
|
pub start: Span,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(hir_analysis_start_not_async, code = "E0752")]
|
#[diag(hir_analysis_start_not_async, code = "E0752")]
|
||||||
pub(crate) struct StartAsync {
|
pub(crate) struct StartAsync {
|
||||||
|
@ -174,7 +174,7 @@ fn get_impl_substs(
|
|||||||
|
|
||||||
let errors = ocx.select_all_or_error();
|
let errors = ocx.select_all_or_error();
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
ocx.infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
ocx.infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ use std::ops::Not;
|
|||||||
use astconv::AstConv;
|
use astconv::AstConv;
|
||||||
use bounds::Bounds;
|
use bounds::Bounds;
|
||||||
|
|
||||||
fluent_messages! { "../locales/en-US.ftl" }
|
fluent_messages! { "../messages.ftl" }
|
||||||
|
|
||||||
fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
|
fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
|
||||||
const CONVENTIONS_UNSTABLE: &str = "`C`, `cdecl`, `win64`, `sysv64` or `efiapi`";
|
const CONVENTIONS_UNSTABLE: &str = "`C`, `cdecl`, `win64`, `sysv64` or `efiapi`";
|
||||||
@ -176,7 +176,7 @@ fn require_same_types<'tcx>(
|
|||||||
match &errors[..] {
|
match &errors[..] {
|
||||||
[] => true,
|
[] => true,
|
||||||
errors => {
|
errors => {
|
||||||
infcx.err_ctxt().report_fulfillment_errors(errors, None);
|
infcx.err_ctxt().report_fulfillment_errors(errors);
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -283,6 +283,15 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
|
|||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !tcx.codegen_fn_attrs(main_def_id).target_features.is_empty()
|
||||||
|
// Calling functions with `#[target_feature]` is not unsafe on WASM, see #84988
|
||||||
|
&& !tcx.sess.target.is_like_wasm
|
||||||
|
&& !tcx.sess.opts.actually_rustdoc
|
||||||
|
{
|
||||||
|
tcx.sess.emit_err(errors::TargetFeatureOnMain { main: main_span });
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
|
||||||
if error {
|
if error {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -309,7 +318,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
|
|||||||
ocx.register_bound(cause, param_env, norm_return_ty, term_did);
|
ocx.register_bound(cause, param_env, norm_return_ty, term_did);
|
||||||
let errors = ocx.select_all_or_error();
|
let errors = ocx.select_all_or_error();
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
// now we can take the return type of the given main function
|
// now we can take the return type of the given main function
|
||||||
@ -373,6 +382,18 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
|
|||||||
});
|
});
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
|
if attr.has_name(sym::target_feature)
|
||||||
|
// Calling functions with `#[target_feature]` is
|
||||||
|
// not unsafe on WASM, see #84988
|
||||||
|
&& !tcx.sess.target.is_like_wasm
|
||||||
|
&& !tcx.sess.opts.actually_rustdoc
|
||||||
|
{
|
||||||
|
tcx.sess.emit_err(errors::StartTargetFeature {
|
||||||
|
span: attr.span,
|
||||||
|
start: start_span,
|
||||||
|
});
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if error {
|
if error {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user