mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-29 10:13:54 +00:00
commit
5fde770aec
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -9,7 +9,6 @@
|
||||
src/etc/installer/gfx/* binary
|
||||
src/vendor/** -text
|
||||
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.
|
||||
*.png binary
|
||||
|
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -443,7 +443,7 @@ jobs:
|
||||
os: windows-latest-xl
|
||||
- name: dist-x86_64-msvc
|
||||
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
|
||||
DIST_REQUIRE_ALL_TOOLS: 1
|
||||
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/
|
||||
Files-Excluded:
|
||||
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)
|
||||
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*
|
||||
Copyright: 2014, Mozilla Foundation, 2014, Telefonica S.A.
|
||||
Copyright: 2014, Mozilla Foundation
|
||||
2014, Telefonica S.A.
|
||||
License: OFL-1.1
|
||||
|
||||
Files: src/librustdoc/html/static/fonts/NanumBarun*
|
||||
@ -15,9 +81,19 @@ Copyright: 2010 NAVER Corporation
|
||||
License: OFL-1.1
|
||||
|
||||
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
|
||||
|
||||
Files: src/librustdoc/html/static/fonts/SourceSerif4*
|
||||
Copyright: 2014-2021 Adobe Systems Incorporated
|
||||
License: OFL-1.1
|
||||
Files: src/librustdoc/html/static/css/normalize.css
|
||||
Copyright: Nicolas Gallagher and Jonathan Neal
|
||||
License: MIT
|
||||
|
||||
Files: src/librustdoc/html/static/css/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]]
|
||||
name = "clippy"
|
||||
version = "0.1.69"
|
||||
version = "0.1.70"
|
||||
dependencies = [
|
||||
"clap 4.1.4",
|
||||
"clippy_lints",
|
||||
@ -781,7 +781,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clippy_lints"
|
||||
version = "0.1.69"
|
||||
version = "0.1.70"
|
||||
dependencies = [
|
||||
"cargo_metadata 0.15.3",
|
||||
"clippy_utils",
|
||||
@ -804,7 +804,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clippy_utils"
|
||||
version = "0.1.69"
|
||||
version = "0.1.70"
|
||||
dependencies = [
|
||||
"arrayvec 0.7.0",
|
||||
"if_chain",
|
||||
@ -1150,7 +1150,7 @@ checksum = "a0afaad2b26fa326569eb264b1363e8ae3357618c43982b3f285f0774ce76b69"
|
||||
|
||||
[[package]]
|
||||
name = "declare_clippy_lint"
|
||||
version = "0.1.69"
|
||||
version = "0.1.70"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"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
|
||||
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
|
||||
list of options in `config.toml.example`.
|
||||
list of options in `config.example.toml`.
|
||||
|
||||
```sh
|
||||
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
|
||||
// libraries. So we must reference jemalloc symbols one way or another, because
|
||||
// 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"]
|
||||
fn main() {
|
||||
|
@ -1230,7 +1230,6 @@ impl Expr {
|
||||
|
||||
pub fn precedence(&self) -> ExprPrecedence {
|
||||
match self.kind {
|
||||
ExprKind::Box(_) => ExprPrecedence::Box,
|
||||
ExprKind::Array(_) => ExprPrecedence::Array,
|
||||
ExprKind::ConstBlock(_) => ExprPrecedence::ConstBlock,
|
||||
ExprKind::Call(..) => ExprPrecedence::Call,
|
||||
@ -1291,8 +1290,7 @@ impl Expr {
|
||||
/// To a first-order approximation, is this a pattern?
|
||||
pub fn is_approximately_pattern(&self) -> bool {
|
||||
match &self.peel_parens().kind {
|
||||
ExprKind::Box(_)
|
||||
| ExprKind::Array(_)
|
||||
ExprKind::Array(_)
|
||||
| ExprKind::Call(_, _)
|
||||
| ExprKind::Tup(_)
|
||||
| ExprKind::Lit(_)
|
||||
@ -1363,8 +1361,6 @@ pub struct StructExpr {
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub enum ExprKind {
|
||||
/// A `box x` expression.
|
||||
Box(P<Expr>),
|
||||
/// An array (`[a, b, c, d]`)
|
||||
Array(ThinVec<P<Expr>>),
|
||||
/// Allow anonymous constants from an inline `const` block
|
||||
|
@ -1316,7 +1316,6 @@ pub fn noop_visit_expr<T: MutVisitor>(
|
||||
vis: &mut T,
|
||||
) {
|
||||
match kind {
|
||||
ExprKind::Box(expr) => vis.visit_expr(expr),
|
||||
ExprKind::Array(exprs) => visit_thin_exprs(exprs, vis),
|
||||
ExprKind::ConstBlock(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, _)
|
||||
| AssignOp(_, _, e)
|
||||
| Binary(_, _, e)
|
||||
| Box(e)
|
||||
| Break(_, Some(e))
|
||||
| Let(_, 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());
|
||||
|
||||
match &expression.kind {
|
||||
ExprKind::Box(subexpression) => visitor.visit_expr(subexpression),
|
||||
ExprKind::Array(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> {
|
||||
ensure_sufficient_stack(|| {
|
||||
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) => {
|
||||
let mut ex = self.lower_expr_mut(ex);
|
||||
// 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) => {
|
||||
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);
|
||||
|
||||
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::ConstBlock(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))),
|
||||
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) => {
|
||||
let dot_await_span = if expr.span.hi() < e.span.hi() {
|
||||
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::Paren(_) | ExprKind::ForLoop(..) => unreachable!("already handled"),
|
||||
ExprKind::Paren(_) | ExprKind::ForLoop(..) | ExprKind::Async(..) => {
|
||||
unreachable!("already handled")
|
||||
}
|
||||
|
||||
ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span),
|
||||
};
|
||||
@ -578,9 +584,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
/// This results in:
|
||||
///
|
||||
/// ```text
|
||||
/// std::future::identity_future(static move? |_task_context| -> <ret_ty> {
|
||||
/// static move? |_task_context| -> <ret_ty> {
|
||||
/// <body>
|
||||
/// })
|
||||
/// }
|
||||
/// ```
|
||||
pub(super) fn make_async_expr(
|
||||
&mut self,
|
||||
@ -591,7 +597,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
span: Span,
|
||||
async_gen_kind: hir::AsyncGeneratorKind,
|
||||
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)));
|
||||
|
||||
// Resume argument type: `ResumeTy`
|
||||
@ -656,13 +662,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
};
|
||||
|
||||
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
|
||||
&& let Some(attrs) = self.attrs.get(&outer_hir_id.local_id)
|
||||
&& 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(
|
||||
hir_id,
|
||||
&[Attribute {
|
||||
@ -681,22 +686,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
);
|
||||
}
|
||||
|
||||
let generator = 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])
|
||||
hir::Expr { hir_id, kind: generator_kind, span: self.lower_span(span) }
|
||||
}
|
||||
|
||||
/// Desugar `<expr>.await` into:
|
||||
@ -1002,7 +992,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
}
|
||||
|
||||
// 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 async_ret_ty = if let FnRetTy::Ty(ty) = &decl.output {
|
||||
let itctx = ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock);
|
||||
@ -1011,7 +1001,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
None
|
||||
};
|
||||
|
||||
let async_body = this.make_async_expr(
|
||||
this.make_async_expr(
|
||||
capture_clause,
|
||||
closure_hir_id,
|
||||
inner_closure_id,
|
||||
@ -1019,8 +1009,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
body.span,
|
||||
hir::AsyncGeneratorKind::Closure,
|
||||
|this| this.with_new_scopes(|this| this.lower_expr_mut(body)),
|
||||
);
|
||||
this.expr(fn_decl_span, async_body)
|
||||
)
|
||||
});
|
||||
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 path;
|
||||
|
||||
fluent_messages! { "../locales/en-US.ftl" }
|
||||
fluent_messages! { "../messages.ftl" }
|
||||
|
||||
struct LoweringContext<'a, 'hir> {
|
||||
tcx: TyCtxt<'hir>,
|
||||
@ -435,7 +435,9 @@ fn compute_hir_hash(
|
||||
|
||||
pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> {
|
||||
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 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();
|
||||
}
|
||||
|
||||
let hir_hash = compute_hir_hash(tcx, &owners);
|
||||
hir::Crate { owners, hir_hash }
|
||||
// Don't hash unless necessary, because it's expensive.
|
||||
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)]
|
||||
@ -657,40 +661,31 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
|
||||
bodies.sort_by_key(|(k, _)| *k);
|
||||
let bodies = SortedMap::from_presorted_elements(bodies);
|
||||
let (hash_including_bodies, hash_without_bodies) = self.hash_owner(node, &bodies);
|
||||
let (nodes, parenting) =
|
||||
index::index_hir(self.tcx.sess, &*self.tcx.definitions_untracked(), node, &bodies);
|
||||
let nodes = hir::OwnerNodes { hash_including_bodies, hash_without_bodies, nodes, bodies };
|
||||
let attrs = {
|
||||
let hash = self.tcx.with_stable_hashing_context(|mut hcx| {
|
||||
let mut stable_hasher = StableHasher::new();
|
||||
attrs.hash_stable(&mut hcx, &mut stable_hasher);
|
||||
stable_hasher.finish()
|
||||
});
|
||||
hir::AttributeMap { map: attrs, hash }
|
||||
};
|
||||
|
||||
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) {
|
||||
// Don't hash unless necessary, because it's expensive.
|
||||
let (opt_hash_including_bodies, attrs_hash) = if self.tcx.sess.needs_crate_hash() {
|
||||
self.tcx.with_stable_hashing_context(|mut hcx| {
|
||||
let mut stable_hasher = StableHasher::new();
|
||||
hcx.with_hir_bodies(node.def_id(), bodies, |hcx| {
|
||||
hcx.with_hir_bodies(node.def_id(), &bodies, |hcx| {
|
||||
node.hash_stable(hcx, &mut stable_hasher)
|
||||
});
|
||||
let hash_including_bodies = stable_hasher.finish();
|
||||
let h1 = 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)
|
||||
attrs.hash_stable(&mut hcx, &mut stable_hasher);
|
||||
let h2 = stable_hasher.finish();
|
||||
|
||||
(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 })
|
||||
}
|
||||
|
||||
/// This method allocates a new `HirId` for the given `NodeId` and stores it in
|
||||
|
@ -337,9 +337,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
ast::TyKind::Never => {
|
||||
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)
|
||||
@ -395,14 +392,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
|
||||
fn visit_expr(&mut self, e: &'a ast::Expr) {
|
||||
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(..) => {
|
||||
if self.sess.parse_sess.span_diagnostic.err_count() == 0 {
|
||||
// To avoid noise about type ascription in common syntax errors,
|
||||
@ -425,14 +414,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
ast::ExprKind::TryBlock(_) => {
|
||||
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)
|
||||
@ -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!(associated_const_equality, "associated const equality is incomplete");
|
||||
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,
|
||||
// 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!(exclusive_range_pattern, "exclusive range pattern syntax is experimental");
|
||||
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");
|
||||
|
||||
visit::walk_crate(&mut visitor, krate);
|
||||
|
@ -21,4 +21,4 @@ pub mod feature_gate;
|
||||
pub mod node_count;
|
||||
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) => {
|
||||
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,
|
||||
};
|
||||
|
||||
@ -292,10 +296,6 @@ impl<'a> State<'a> {
|
||||
self.ibox(INDENT_UNIT);
|
||||
self.ann.pre(self, AnnNode::Expr(expr));
|
||||
match &expr.kind {
|
||||
ast::ExprKind::Box(expr) => {
|
||||
self.word_space("box");
|
||||
self.print_expr_maybe_paren(expr, parser::PREC_PREFIX);
|
||||
}
|
||||
ast::ExprKind::Array(exprs) => {
|
||||
self.print_expr_vec(exprs);
|
||||
}
|
||||
|
@ -26,4 +26,4 @@ pub use rustc_ast::attr::*;
|
||||
|
||||
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 local_kind = if let Some(local) = borrow.borrowed_place.as_local() {
|
||||
match self.body.local_kind(local) {
|
||||
LocalKind::ReturnPointer | LocalKind::Temp => {
|
||||
bug!("temporary or return pointer with a name")
|
||||
LocalKind::Temp if self.body.local_decls[local].is_user_variable() => {
|
||||
"local variable "
|
||||
}
|
||||
LocalKind::Var => "local variable ",
|
||||
LocalKind::Arg
|
||||
if !self.upvars.is_empty() && local == ty::CAPTURE_STRUCT_LOCAL =>
|
||||
{
|
||||
"variable captured by `move` "
|
||||
}
|
||||
LocalKind::Arg => "function parameter ",
|
||||
LocalKind::ReturnPointer | LocalKind::Temp => {
|
||||
bug!("temporary or return pointer with a name")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
"local data "
|
||||
@ -2008,16 +2010,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
self.prefixes(borrow.borrowed_place.as_ref(), PrefixSet::All).last().unwrap();
|
||||
let local = root_place.local;
|
||||
match self.body.local_kind(local) {
|
||||
LocalKind::ReturnPointer | LocalKind::Temp => {
|
||||
("temporary value".to_string(), "temporary value created here".to_string())
|
||||
}
|
||||
LocalKind::Arg => (
|
||||
"function parameter".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())
|
||||
}
|
||||
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 {
|
||||
Some(LocalDecl {
|
||||
local_info:
|
||||
Some(box LocalInfo::User(
|
||||
ClearCrossCrate::Clear
|
||||
| ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
|
||||
ClearCrossCrate::Set(
|
||||
box LocalInfo::User(BindingForm::Var(VarBindingForm {
|
||||
opt_match_place: None,
|
||||
..
|
||||
})),
|
||||
))
|
||||
| Some(box LocalInfo::StaticRef { .. })
|
||||
| None,
|
||||
}))
|
||||
| box LocalInfo::StaticRef { .. }
|
||||
| box LocalInfo::Boring,
|
||||
),
|
||||
..
|
||||
})
|
||||
| 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_infer::infer::NllRegionVariableOrigin;
|
||||
use rustc_middle::mir::{
|
||||
Body, CastKind, ConstraintCategory, FakeReadCause, Local, Location, Operand, Place, Rvalue,
|
||||
Statement, StatementKind, TerminatorKind,
|
||||
Body, CastKind, ConstraintCategory, FakeReadCause, Local, LocalInfo, Location, Operand, Place,
|
||||
Rvalue, Statement, StatementKind, TerminatorKind,
|
||||
};
|
||||
use rustc_middle::ty::adjustment::PointerCast;
|
||||
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);
|
||||
|
||||
if let Some(info) = &local_decl.is_block_tail {
|
||||
if let LocalInfo::BlockTailTemp(info) = local_decl.local_info() {
|
||||
if info.tail_result_is_ignored {
|
||||
// #85581: If the first mutable borrow's scope contains
|
||||
// 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() {
|
||||
continue;
|
||||
}
|
||||
if let Some(box LocalInfo::StaticRef { def_id, .. }) =
|
||||
&self.body.local_decls[local].local_info
|
||||
if let LocalInfo::StaticRef { def_id, .. } =
|
||||
*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(());
|
||||
continue;
|
||||
}
|
||||
|
@ -102,14 +102,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
//
|
||||
// opt_match_place is None for let [mut] x = ... statements,
|
||||
// whether or not the right-hand side is a place expression
|
||||
if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
|
||||
VarBindingForm {
|
||||
if let LocalInfo::User(BindingForm::Var(VarBindingForm {
|
||||
opt_match_place: Some((opt_match_place, match_span)),
|
||||
binding_mode: _,
|
||||
opt_ty_info: _,
|
||||
pat_span: _,
|
||||
},
|
||||
)))) = local_decl.local_info
|
||||
})) = *local_decl.local_info()
|
||||
{
|
||||
let stmt_source_info = self.body.source_info(location);
|
||||
self.append_binding_error(
|
||||
@ -478,9 +476,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
let mut suggestions: Vec<(Span, String, String)> = Vec::new();
|
||||
for local in binds_to {
|
||||
let bind_to = &self.body.local_decls[*local];
|
||||
if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
|
||||
VarBindingForm { pat_span, .. },
|
||||
)))) = bind_to.local_info
|
||||
if let LocalInfo::User(BindingForm::Var(VarBindingForm { pat_span, .. })) =
|
||||
*bind_to.local_info()
|
||||
{
|
||||
let Ok(pat_snippet) =
|
||||
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::{
|
||||
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::symbol::{kw, Symbol};
|
||||
@ -105,8 +105,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
reason = String::new();
|
||||
} else {
|
||||
item_msg = access_place_desc;
|
||||
let local_info = &self.body.local_decls[local].local_info;
|
||||
if let Some(box LocalInfo::StaticRef { def_id, .. }) = *local_info {
|
||||
let local_info = self.body.local_decls[local].local_info();
|
||||
if let LocalInfo::StaticRef { def_id, .. } = *local_info {
|
||||
let static_name = &self.infcx.tcx.item_name(def_id);
|
||||
reason = format!(", as `{static_name}` is an immutable static item");
|
||||
} else {
|
||||
@ -305,15 +305,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
..
|
||||
}) = &self.body[location.block].statements.get(location.statement_index)
|
||||
{
|
||||
match decl.local_info {
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
|
||||
mir::VarBindingForm {
|
||||
match *decl.local_info() {
|
||||
LocalInfo::User(BindingForm::Var(mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(Mutability::Not),
|
||||
opt_ty_info: Some(sp),
|
||||
opt_match_place: _,
|
||||
pat_span: _,
|
||||
},
|
||||
)))) => {
|
||||
})) => {
|
||||
if suggest {
|
||||
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() {
|
||||
if matches!(
|
||||
decl.local_info,
|
||||
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(
|
||||
hir::ImplicitSelfKind::MutRef
|
||||
),)))
|
||||
decl.local_info(),
|
||||
LocalInfo::User(BindingForm::ImplicitSelf(hir::ImplicitSelfKind::MutRef))
|
||||
) {
|
||||
err.note(
|
||||
"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] {
|
||||
Some(name) if !local_decl.from_compiler_desugaring() => {
|
||||
let label = match local_decl.local_info.as_deref().unwrap() {
|
||||
LocalInfo::User(ClearCrossCrate::Set(
|
||||
mir::BindingForm::ImplicitSelf(_),
|
||||
)) => {
|
||||
let label = match *local_decl.local_info() {
|
||||
LocalInfo::User(mir::BindingForm::ImplicitSelf(_)) => {
|
||||
let (span, suggestion) =
|
||||
suggest_ampmut_self(self.infcx.tcx, local_decl);
|
||||
Some((true, span, suggestion))
|
||||
}
|
||||
|
||||
LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
|
||||
mir::VarBindingForm {
|
||||
LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(_),
|
||||
opt_ty_info,
|
||||
..
|
||||
},
|
||||
))) => {
|
||||
})) => {
|
||||
// check if the RHS is from desugaring
|
||||
let opt_assignment_rhs_span =
|
||||
self.body.find_assignments(local).first().map(|&location| {
|
||||
@ -534,16 +526,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
self.infcx.tcx,
|
||||
local_decl,
|
||||
opt_assignment_rhs_span,
|
||||
*opt_ty_info,
|
||||
opt_ty_info,
|
||||
)
|
||||
} else {
|
||||
match local_decl.local_info.as_deref() {
|
||||
Some(LocalInfo::User(ClearCrossCrate::Set(
|
||||
mir::BindingForm::Var(mir::VarBindingForm {
|
||||
opt_ty_info: None,
|
||||
..
|
||||
}),
|
||||
))) => {
|
||||
match local_decl.local_info() {
|
||||
LocalInfo::User(mir::BindingForm::Var(
|
||||
mir::VarBindingForm {
|
||||
opt_ty_info: None, ..
|
||||
},
|
||||
)) => {
|
||||
let (span, sugg) = suggest_ampmut_self(
|
||||
self.infcx.tcx,
|
||||
local_decl,
|
||||
@ -555,7 +546,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
self.infcx.tcx,
|
||||
local_decl,
|
||||
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(
|
||||
mir::VarBindingForm {
|
||||
LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByReference(_),
|
||||
..
|
||||
},
|
||||
))) => {
|
||||
})) => {
|
||||
let pattern_span = local_decl.source_info.span;
|
||||
suggest_ref_mut(self.infcx.tcx, pattern_span)
|
||||
.map(|replacement| (true, pattern_span, replacement))
|
||||
}
|
||||
|
||||
LocalInfo::User(ClearCrossCrate::Clear) => {
|
||||
bug!("saw cleared local state")
|
||||
}
|
||||
|
||||
_ => 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 {
|
||||
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.
|
||||
Some(LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var(
|
||||
mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(Mutability::Not), ..
|
||||
},
|
||||
)))) => matches!(local_decl.ty.kind(), ty::Ref(_, _, hir::Mutability::Mut)),
|
||||
Some(LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf(kind)))) => {
|
||||
LocalInfo::User(mir::BindingForm::Var(mir::VarBindingForm {
|
||||
binding_mode: ty::BindingMode::BindByValue(Mutability::Not),
|
||||
..
|
||||
})) => matches!(local_decl.ty.kind(), ty::Ref(_, _, hir::Mutability::Mut)),
|
||||
LocalInfo::User(mir::BindingForm::ImplicitSelf(kind)) => {
|
||||
// Check if the user variable is a `&mut self` and we can therefore
|
||||
// suggest removing the `&mut`.
|
||||
//
|
||||
// Deliberately fall into this case for all implicit self types,
|
||||
// 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 => {
|
||||
// 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 renumber::RegionCtxt;
|
||||
|
||||
fluent_messages! { "../locales/en-US.ftl" }
|
||||
fluent_messages! { "../messages.ftl" }
|
||||
|
||||
// FIXME(eddyb) perhaps move this somewhere more centrally.
|
||||
#[derive(Debug)]
|
||||
|
@ -325,7 +325,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
|
||||
if errors.is_empty() {
|
||||
definition_ty
|
||||
} 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)
|
||||
}
|
||||
}
|
||||
|
@ -1180,10 +1180,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
Some(l)
|
||||
if matches!(
|
||||
body.local_decls[l].local_info,
|
||||
Some(box LocalInfo::AggregateTemp)
|
||||
) =>
|
||||
if matches!(body.local_decls[l].local_info(), LocalInfo::AggregateTemp) =>
|
||||
{
|
||||
ConstraintCategory::Usage
|
||||
}
|
||||
@ -1684,7 +1681,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
// - maybe we should make that a warning.
|
||||
return;
|
||||
}
|
||||
LocalKind::Var | LocalKind::Temp => {}
|
||||
LocalKind::Temp => {}
|
||||
}
|
||||
|
||||
// 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
|
||||
// clobber_abi/options. We do this at the end once we have the full span
|
||||
// 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 name.is_some() {
|
||||
diag.struct_span_err(span, "explicit register arguments cannot have names").emit();
|
||||
@ -227,17 +216,6 @@ pub fn parse_asm_args<'a>(
|
||||
.emit();
|
||||
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);
|
||||
} else {
|
||||
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);
|
||||
|
||||
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[..] {
|
||||
// should have errored above during parsing
|
||||
[] => unreachable!(),
|
||||
@ -699,6 +668,10 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
|
||||
args.operands[idx].1,
|
||||
"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();
|
||||
None
|
||||
|
@ -290,7 +290,6 @@ impl<'cx, 'a> Context<'cx, 'a> {
|
||||
| ExprKind::Async(_, _, _)
|
||||
| ExprKind::Await(_)
|
||||
| ExprKind::Block(_, _)
|
||||
| ExprKind::Box(_)
|
||||
| ExprKind::Break(_, _)
|
||||
| ExprKind::Closure(_)
|
||||
| ExprKind::ConstBlock(_)
|
||||
|
@ -42,6 +42,18 @@ pub fn expand_concat(
|
||||
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(..) => {
|
||||
cx.span_err(e.span, "cannot concatenate a byte string literal")
|
||||
}
|
||||
@ -53,9 +65,10 @@ pub fn expand_concat(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !missing_literal.is_empty() {
|
||||
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();
|
||||
return DummyResult::any(sp);
|
||||
} else if has_errors {
|
||||
|
@ -1052,6 +1052,7 @@ impl<'a> MethodDef<'a> {
|
||||
/// ::core::hash::Hash::hash(&{ self.y }, state)
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
fn expand_struct_method_body<'b>(
|
||||
&self,
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
|
@ -36,6 +36,21 @@ enum 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
|
||||
/// if there's a parse error so we can continue parsing other format!
|
||||
/// expressions.
|
||||
@ -45,11 +60,7 @@ use PositionUsedAs::*;
|
||||
/// ```text
|
||||
/// Ok((fmtstr, parsed arguments))
|
||||
/// ```
|
||||
fn parse_args<'a>(
|
||||
ecx: &mut ExtCtxt<'a>,
|
||||
sp: Span,
|
||||
tts: TokenStream,
|
||||
) -> PResult<'a, (P<Expr>, FormatArguments)> {
|
||||
fn parse_args<'a>(ecx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<'a, MacroInput> {
|
||||
let mut args = FormatArguments::new();
|
||||
|
||||
let mut p = ecx.new_parser_from_tts(tts);
|
||||
@ -59,25 +70,21 @@ fn parse_args<'a>(
|
||||
}
|
||||
|
||||
let first_token = &p.token;
|
||||
let fmtstr = match first_token.kind {
|
||||
token::TokenKind::Literal(token::Lit {
|
||||
kind: token::LitKind::Str | token::LitKind::StrRaw(_),
|
||||
..
|
||||
}) => {
|
||||
// If the first token is a string literal, then a format expression
|
||||
// is constructed from it.
|
||||
//
|
||||
|
||||
let fmtstr = if let token::Literal(lit) = first_token.kind && matches!(lit.kind, token::Str | token::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.
|
||||
p.parse_literal_maybe_minus()?
|
||||
}
|
||||
_ => {
|
||||
} else {
|
||||
// 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;
|
||||
|
||||
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<'_>,
|
||||
efmt: P<Expr>,
|
||||
mut args: FormatArguments,
|
||||
input: MacroInput,
|
||||
append_newline: bool,
|
||||
) -> Result<FormatArgs, ()> {
|
||||
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) {
|
||||
Ok(mut fmt) if append_newline => {
|
||||
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() {
|
||||
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))
|
||||
} else {
|
||||
// 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 {
|
||||
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);
|
||||
}
|
||||
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| {
|
||||
is_literal.then(|| {
|
||||
is_source_literal.then(|| {
|
||||
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.
|
||||
let span = span.unwrap_or(fmt_span);
|
||||
let ident = Ident::new(name, span);
|
||||
let expr = if is_literal {
|
||||
let expr = if is_direct_literal {
|
||||
ecx.expr_ident(span, ident)
|
||||
} else {
|
||||
// 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);`
|
||||
indexes.sort();
|
||||
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)
|
||||
} else {
|
||||
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> {
|
||||
sp = ecx.with_def_site_ctxt(sp);
|
||||
match parse_args(ecx, sp, tts) {
|
||||
Ok((efmt, args)) => {
|
||||
if let Ok(format_args) = make_format_args(ecx, efmt, args, nl) {
|
||||
Ok(input) => {
|
||||
if let Ok(format_args) = make_format_args(ecx, input, nl) {
|
||||
MacEager::expr(ecx.expr(sp, ExprKind::FormatArgs(P(format_args))))
|
||||
} else {
|
||||
MacEager::expr(DummyResult::raw_expr(sp, true))
|
||||
|
@ -56,7 +56,7 @@ pub mod proc_macro_harness;
|
||||
pub mod standard_library_imports;
|
||||
pub mod test_harness;
|
||||
|
||||
fluent_messages! { "../locales/en-US.ftl" }
|
||||
fluent_messages! { "../messages.ftl" }
|
||||
|
||||
pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
|
||||
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]
|
||||
|
||||
extern crate alloc;
|
||||
@ -29,7 +29,7 @@ fn alloc_error_handler(_: alloc::alloc::Layout) -> ! {
|
||||
|
||||
#[start]
|
||||
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 {
|
||||
puts(*world as *const str as *const u8);
|
||||
}
|
||||
|
@ -1,12 +1,6 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// 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.
|
||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
// SPDX-FileCopyrightText: The Rust Project Developers (see https://thanks.rust-lang.org)
|
||||
|
||||
#![no_std]
|
||||
|
||||
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]
|
||||
#![allow(dead_code, non_camel_case_types)]
|
||||
|
||||
@ -178,7 +178,7 @@ fn main() {
|
||||
let ptr: *const i8 = hello as *const [u8] as *const i8;
|
||||
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);
|
||||
world as Box<dyn SomeTrait>;
|
||||
|
||||
@ -238,10 +238,10 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
let _ = box NoisyDrop {
|
||||
let _ = Box::new(NoisyDrop {
|
||||
text: "Boxed outer got dropped!\0",
|
||||
inner: NoisyDropInner,
|
||||
} as Box<dyn SomeTrait>;
|
||||
}) as Box<dyn SomeTrait>;
|
||||
|
||||
const FUNC_REF: Option<fn()> = Some(main);
|
||||
match FUNC_REF {
|
||||
|
@ -4,6 +4,7 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
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_span::symbol::sym;
|
||||
|
||||
@ -13,13 +14,7 @@ pub(crate) fn codegen(
|
||||
module: &mut impl Module,
|
||||
unwind_context: &mut UnwindContext,
|
||||
) -> bool {
|
||||
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 {
|
||||
false
|
||||
} else if let Some(kind) = tcx.allocator_kind(()) {
|
||||
let Some(kind) = allocator_kind_for_codegen(tcx) else { return false };
|
||||
codegen_inner(
|
||||
module,
|
||||
unwind_context,
|
||||
@ -28,9 +23,6 @@ pub(crate) fn codegen(
|
||||
tcx.sess.opts.unstable_opts.oom,
|
||||
);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
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]
|
||||
|
||||
extern crate alloc;
|
||||
@ -38,7 +38,7 @@ unsafe extern "C" fn _Unwind_Resume() {
|
||||
|
||||
#[start]
|
||||
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 {
|
||||
puts(*world as *const str as *const u8);
|
||||
}
|
||||
|
@ -1,12 +1,6 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// 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.
|
||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
// SPDX-FileCopyrightText: The Rust Project Developers (see https://thanks.rust-lang.org)
|
||||
|
||||
#![no_std]
|
||||
#![feature(allocator_api, rustc_private)]
|
||||
#![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
|
||||
|
||||
#![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
|
||||
)]
|
||||
#![no_core]
|
||||
@ -163,7 +163,7 @@ fn main() {
|
||||
let ptr: *const u8 = hello as *const [u8] as *const u8;
|
||||
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);
|
||||
world as Box<dyn SomeTrait>;
|
||||
|
||||
@ -223,10 +223,10 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
let _ = box NoisyDrop {
|
||||
let _ = Box::new(NoisyDrop {
|
||||
text: "Boxed outer got dropped!\0",
|
||||
inner: NoisyDropInner,
|
||||
} as Box<dyn SomeTrait>;
|
||||
}) as Box<dyn SomeTrait>;
|
||||
|
||||
const FUNC_REF: Option<fn()> = Some(main);
|
||||
#[allow(unreachable_code)]
|
||||
|
@ -1,4 +1,4 @@
|
||||
#![feature(start, box_syntax, core_intrinsics, lang_items)]
|
||||
#![feature(start, core_intrinsics, lang_items)]
|
||||
#![no_std]
|
||||
|
||||
#[link(name = "c")]
|
||||
|
@ -87,7 +87,7 @@ use rustc_span::Symbol;
|
||||
use rustc_span::fatal_error::FatalError;
|
||||
use tempfile::TempDir;
|
||||
|
||||
fluent_messages! { "../locales/en-US.ftl" }
|
||||
fluent_messages! { "../messages.ftl" }
|
||||
|
||||
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 2)
|
||||
/// DW_TAG_structure_type (type of variant 3)
|
||||
/// ```
|
||||
struct VariantMemberInfo<'a, 'll> {
|
||||
variant_index: VariantIdx,
|
||||
variant_name: Cow<'a, str>,
|
||||
|
@ -84,7 +84,7 @@ mod type_of;
|
||||
mod va_arg;
|
||||
mod value;
|
||||
|
||||
fluent_messages! { "../locales/en-US.ftl" }
|
||||
fluent_messages! { "../messages.ftl" }
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct LlvmCodegenBackend(());
|
||||
|
@ -720,6 +720,7 @@ impl<'a> Linker for GccLinker<'a> {
|
||||
let mut arg = OsString::from("--version-script=");
|
||||
arg.push(path);
|
||||
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 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
|
||||
.iter()
|
||||
.map(|method| format!("__rust_{}", method.name))
|
||||
|
@ -13,6 +13,7 @@ use crate::mir::place::PlaceRef;
|
||||
use crate::traits::*;
|
||||
use crate::{CachedModuleCodegen, CompiledModule, CrateInfo, MemFlags, ModuleCodegen, ModuleKind};
|
||||
|
||||
use rustc_ast::expand::allocator::AllocatorKind;
|
||||
use rustc_attr as attr;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
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<_>>()
|
||||
}
|
||||
|
||||
/// 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>(
|
||||
backend: B,
|
||||
tcx: TyCtxt<'_>,
|
||||
@ -615,20 +633,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
||||
);
|
||||
|
||||
// Codegen an allocator shim, if necessary.
|
||||
//
|
||||
// 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(()) {
|
||||
if let Some(kind) = allocator_kind_for_codegen(tcx) {
|
||||
let llmod_id =
|
||||
cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string();
|
||||
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 })
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if let Some(allocator_module) = allocator_module {
|
||||
ongoing_codegen.submit_pre_codegened_module_to_llvm(tcx, allocator_module);
|
||||
ongoing_codegen.submit_pre_codegened_module_to_llvm(
|
||||
tcx,
|
||||
ModuleCodegen { name: llmod_id, module_llvm, kind: ModuleKind::Allocator },
|
||||
);
|
||||
}
|
||||
|
||||
// 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
|
||||
// if a target is documenting some wasm-specific code then
|
||||
// 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 {
|
||||
let mut err = feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
|
@ -56,7 +56,7 @@ pub mod mono_item;
|
||||
pub mod target_features;
|
||||
pub mod traits;
|
||||
|
||||
fluent_messages! { "../locales/en-US.ftl" }
|
||||
fluent_messages! { "../messages.ftl" }
|
||||
|
||||
pub struct ModuleCodegen<M> {
|
||||
/// 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) {
|
||||
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 {
|
||||
Some(per_local) => &per_local[local],
|
||||
None => return,
|
||||
@ -303,7 +297,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
|
||||
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
|
||||
} else {
|
||||
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.
|
||||
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
|
||||
for (bb, _) in traversal::reverse_postorder(&mir) {
|
||||
fx.codegen_block(bb);
|
||||
|
@ -192,7 +192,7 @@ const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
||||
("fxsr", None),
|
||||
("gfni", Some(sym::avx512_target_feature)),
|
||||
("lzcnt", None),
|
||||
("movbe", Some(sym::movbe_target_feature)),
|
||||
("movbe", None),
|
||||
("pclmulqdq", None),
|
||||
("popcnt", None),
|
||||
("rdrand", None),
|
||||
@ -394,7 +394,6 @@ pub fn from_target_feature(
|
||||
Some(sym::sse4a_target_feature) => rust_features.sse4a_target_feature,
|
||||
Some(sym::tbm_target_feature) => rust_features.tbm_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::ermsb_target_feature) => rust_features.ermsb_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) {
|
||||
if let DefKind::AssocFn = tcx.def_kind(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
|
||||
.struct_span_err(
|
||||
attr_span,
|
||||
|
@ -536,25 +536,21 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
local: mir::Local,
|
||||
layout: Option<TyAndLayout<'tcx>>,
|
||||
) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
|
||||
// `const_prop` runs into this with an invalid (empty) frame, so we
|
||||
// have to support that case (mostly by skipping all caching).
|
||||
match frame.locals.get(local).and_then(|state| state.layout.get()) {
|
||||
None => {
|
||||
let state = &frame.locals[local];
|
||||
if let Some(layout) = state.layout.get() {
|
||||
return 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)?;
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the actual dynamic size and alignment of the place at the given type.
|
||||
/// Only the "meta" (metadata) part of the place matters.
|
||||
|
@ -39,7 +39,7 @@ use rustc_macros::fluent_messages;
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
|
||||
fluent_messages! { "../locales/en-US.ftl" }
|
||||
fluent_messages! { "../messages.ftl" }
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
const_eval::provide(providers);
|
||||
|
@ -643,7 +643,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||
if base_ty.is_unsafe_ptr() {
|
||||
if proj_base.is_empty() {
|
||||
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;
|
||||
self.check_static(def_id, span);
|
||||
return;
|
||||
@ -770,7 +770,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||
|
||||
let errors = ocx.select_all_or_error();
|
||||
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 {
|
||||
match self.0 {
|
||||
mir::LocalKind::Var | mir::LocalKind::Temp => DiagnosticImportance::Secondary,
|
||||
mir::LocalKind::Temp => DiagnosticImportance::Secondary,
|
||||
mir::LocalKind::ReturnPointer | mir::LocalKind::Arg => {
|
||||
DiagnosticImportance::Primary
|
||||
}
|
||||
|
@ -106,8 +106,9 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> {
|
||||
debug!("visit_local: index={:?} context={:?} location={:?}", index, context, location);
|
||||
// We're only interested in temporaries and the return place
|
||||
match self.ccx.body.local_kind(index) {
|
||||
LocalKind::Temp | LocalKind::ReturnPointer => {}
|
||||
LocalKind::Arg | LocalKind::Var => return,
|
||||
LocalKind::Arg => 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,
|
||||
|
@ -64,7 +64,7 @@ use crate::session_diagnostics::{
|
||||
RLinkWrongFileType, RlinkNotAFile, RlinkUnableToRead,
|
||||
};
|
||||
|
||||
fluent_messages! { "../locales/en-US.ftl" }
|
||||
fluent_messages! { "../messages.ftl" }
|
||||
|
||||
pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[
|
||||
// tidy-alphabetical-start
|
||||
@ -331,6 +331,7 @@ fn run_compiler(
|
||||
if let Some(ppm) = &sess.opts.pretty {
|
||||
if ppm.needs_ast_map() {
|
||||
queries.global_ctxt()?.enter(|tcx| {
|
||||
tcx.ensure().early_lint_checks(());
|
||||
pretty::print_after_hir_lowering(tcx, *ppm);
|
||||
Ok(())
|
||||
})?;
|
||||
|
@ -5,7 +5,5 @@ the heap at runtime, and therefore cannot be done at compile time.
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0010
|
||||
#![feature(box_syntax)]
|
||||
|
||||
const CON : Box<i32> = box 0;
|
||||
const CON : Vec<i32> = vec![1, 2, 3];
|
||||
```
|
||||
|
@ -41,7 +41,7 @@ impl Add for Foo {
|
||||
|
||||
fn main() {
|
||||
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:
|
||||
|
||||
```compile_fail,E0710
|
||||
#[allow(clipp::filter_map)] // error!`
|
||||
#[allow(clipp::filter_map)] // error!
|
||||
fn main() {
|
||||
// business logic
|
||||
}
|
||||
```
|
||||
|
||||
```compile_fail,E0710
|
||||
#[warn(clipp::filter_map)] // error!`
|
||||
#[warn(clipp::filter_map)] // error!
|
||||
fn main() {
|
||||
// business logic
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ use intl_memoizer::IntlLangMemoizer;
|
||||
pub use fluent_bundle::{self, types::FluentType, FluentArgs, FluentError, FluentValue};
|
||||
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>;
|
||||
|
||||
|
@ -76,7 +76,7 @@ pub use snippet::Style;
|
||||
pub type PErr<'a> = DiagnosticBuilder<'a, ErrorGuaranteed>;
|
||||
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.
|
||||
// (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::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind};
|
||||
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_errors::{
|
||||
Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, MultiSpan, PResult,
|
||||
};
|
||||
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_session::errors::report_lit_error;
|
||||
use rustc_session::{parse::ParseSess, Limit, Session};
|
||||
@ -947,14 +947,14 @@ pub trait ResolverExpand {
|
||||
fn declare_proc_macro(&mut self, id: NodeId);
|
||||
|
||||
/// 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 {
|
||||
fn pre_expansion_lint(
|
||||
&self,
|
||||
sess: &Session,
|
||||
registered_tools: &FxHashSet<Ident>,
|
||||
registered_tools: &RegisteredTools,
|
||||
node_id: NodeId,
|
||||
attrs: &[Attribute],
|
||||
items: &[P<Item>],
|
||||
|
@ -64,4 +64,4 @@ mod mut_visit {
|
||||
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::expand::{parse_ast_fragment, AstFragmentKind};
|
||||
use crate::mbe::{
|
||||
macro_parser::{MatcherLoc, NamedParseResult, ParseResult::*, TtParser},
|
||||
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_pretty::pprust;
|
||||
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::symbol::Ident;
|
||||
use rustc_span::Span;
|
||||
use std::borrow::Cow;
|
||||
|
||||
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}"));
|
||||
}
|
||||
|
||||
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);`
|
||||
if let Some((arg, comma_span)) = arg.add_comma() {
|
||||
for lhs in lhses {
|
||||
|
@ -90,7 +90,7 @@ declare_features! (
|
||||
(accepted, clone_closures, "1.26.0", Some(44490), None),
|
||||
/// Allows coercing non capturing closures to function pointers.
|
||||
(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),
|
||||
/// Allows usage of the `compile_error!` macro.
|
||||
(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),
|
||||
/// Allows using `Self` and associated types in struct expressions and patterns.
|
||||
(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.
|
||||
/// 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),
|
||||
|
@ -200,8 +200,6 @@ declare_features! (
|
||||
(active, auto_traits, "1.50.0", Some(13231), None),
|
||||
/// Allows using `box` in patterns (RFC 469).
|
||||
(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)]`.
|
||||
/// Renamed from `doc_spotlight`.
|
||||
(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, hexagon_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, riscv_target_feature, "1.45.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, await_macro, "1.38.0", Some(50547), None,
|
||||
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).
|
||||
(removed, capture_disjoint_fields, "1.49.0", Some(53488), None, Some("stabilized in Rust 2021")),
|
||||
/// Allows comparing raw pointers during const eval.
|
||||
|
@ -815,12 +815,13 @@ pub struct ParentedNode<'tcx> {
|
||||
#[derive(Debug)]
|
||||
pub struct AttributeMap<'tcx> {
|
||||
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> {
|
||||
pub const EMPTY: &'static AttributeMap<'static> =
|
||||
&AttributeMap { map: SortedMap::new(), hash: Fingerprint::ZERO };
|
||||
&AttributeMap { map: SortedMap::new(), opt_hash: Some(Fingerprint::ZERO) };
|
||||
|
||||
#[inline]
|
||||
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.
|
||||
/// The HIR tree, including bodies, is pre-hashed.
|
||||
pub struct OwnerNodes<'tcx> {
|
||||
/// Pre-computed hash of the full HIR.
|
||||
pub hash_including_bodies: Fingerprint,
|
||||
/// Pre-computed hash of the item signature, without recursing into the body.
|
||||
pub hash_without_bodies: Fingerprint,
|
||||
/// Pre-computed hash of the full HIR. Used in the crate hash. Only present
|
||||
/// when incr. comp. is enabled.
|
||||
pub opt_hash_including_bodies: Option<Fingerprint>,
|
||||
/// Full HIR for the current owner.
|
||||
// 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
|
||||
@ -872,8 +872,7 @@ impl fmt::Debug for OwnerNodes<'_> {
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
.field("bodies", &self.bodies)
|
||||
.field("hash_without_bodies", &self.hash_without_bodies)
|
||||
.field("hash_including_bodies", &self.hash_including_bodies)
|
||||
.field("opt_hash_including_bodies", &self.opt_hash_including_bodies)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
@ -940,7 +939,8 @@ impl<T> MaybeOwner<T> {
|
||||
#[derive(Debug)]
|
||||
pub struct Crate<'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)]
|
||||
|
@ -296,7 +296,6 @@ language_item_table! {
|
||||
// FIXME(swatinem): the following lang items are used for async lowering and
|
||||
// should become obsolete eventually.
|
||||
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;
|
||||
|
||||
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
|
||||
// the body satisfies the condition of two nodes being different have different
|
||||
// `hash_stable` results.
|
||||
let OwnerNodes { hash_including_bodies, hash_without_bodies: _, nodes: _, bodies: _ } =
|
||||
*self;
|
||||
hash_including_bodies.hash_stable(hcx, hasher);
|
||||
let OwnerNodes { opt_hash_including_bodies, nodes: _, bodies: _ } = *self;
|
||||
opt_hash_including_bodies.unwrap().hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, HirCtx: crate::HashStableContext> HashStable<HirCtx> for AttributeMap<'tcx> {
|
||||
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
|
||||
// the collector and used for the crate hash.
|
||||
let AttributeMap { hash, map: _ } = *self;
|
||||
hash.hash_stable(hcx, hasher);
|
||||
// We ignore the `map` since it refers to information included in `opt_hash` which is
|
||||
// hashed in the collector and used for the crate hash.
|
||||
let AttributeMap { opt_hash, map: _ } = *self;
|
||||
opt_hash.unwrap().hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
|
||||
impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Crate<'_> {
|
||||
fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
|
||||
let Crate { owners: _, hir_hash } = self;
|
||||
hir_hash.hash_stable(hcx, hasher)
|
||||
let Crate { owners: _, opt_hir_hash } = self;
|
||||
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
|
||||
.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 =
|
||||
`typeof` is a reserved keyword but unimplemented
|
||||
.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]`
|
||||
.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]`
|
||||
.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`
|
||||
.label = `start` is not allowed to be `async`
|
||||
|
@ -1,10 +1,14 @@
|
||||
use crate::astconv::AstConv;
|
||||
use crate::errors::{ManualImplementation, MissingTypeParams};
|
||||
use crate::errors::{
|
||||
AssocTypeBindingNotAllowed, ManualImplementation, MissingTypeParams,
|
||||
ParenthesizedFnTraitExpansion,
|
||||
};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, ErrorGuaranteed};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_infer::traits::FulfillmentError;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_session::parse::feature_err;
|
||||
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:
|
||||
// the desugaring would contain an associated type constraint.
|
||||
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(
|
||||
span,
|
||||
"use parenthetical notation instead",
|
||||
format!("{}{} -> {}", trait_segment.ident, args, ret),
|
||||
fn_trait_to_string(self.tcx(), trait_segment, true),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
@ -629,3 +600,69 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
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 crate::astconv::{
|
||||
CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch,
|
||||
GenericArgCountResult, GenericArgPosition,
|
||||
errors::prohibit_assoc_ty_binding, CreateSubstsForGenericArgsCtxt, ExplicitLateBound,
|
||||
GenericArgCountMismatch, GenericArgCountResult, GenericArgPosition,
|
||||
};
|
||||
use crate::errors::AssocTypeBindingNotAllowed;
|
||||
use crate::structured_errors::{GenericArgsInfo, StructuredDiagnostic, WrongNumberOfGenericArgs};
|
||||
use rustc_ast::ast::ParamKindOrd;
|
||||
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();
|
||||
|
||||
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 =
|
||||
@ -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
|
||||
/// are present. This is used both for datatypes and function calls.
|
||||
pub(crate) fn prohibit_explicit_late_bound_lifetimes(
|
||||
|
@ -5,9 +5,8 @@
|
||||
mod errors;
|
||||
pub mod generics;
|
||||
|
||||
use crate::astconv::generics::{
|
||||
check_generic_arg_count, create_substs_for_generic_args, prohibit_assoc_ty_binding,
|
||||
};
|
||||
use crate::astconv::errors::prohibit_assoc_ty_binding;
|
||||
use crate::astconv::generics::{check_generic_arg_count, create_substs_for_generic_args};
|
||||
use crate::bounds::Bounds;
|
||||
use crate::collect::HirPlaceholderCollector;
|
||||
use crate::errors::{
|
||||
@ -295,7 +294,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
ty::BoundConstness::NotConst,
|
||||
);
|
||||
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
|
||||
@ -631,7 +630,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
);
|
||||
|
||||
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
|
||||
@ -825,7 +824,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
constness,
|
||||
);
|
||||
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)
|
||||
}
|
||||
@ -2596,7 +2595,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
for segment in segments {
|
||||
// Only emit the first error to avoid overloading the user with error messages.
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -3049,10 +3048,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
}
|
||||
&hir::TyKind::OpaqueDef(item_id, lifetimes, in_trait) => {
|
||||
let opaque_ty = tcx.hir().item(item_id);
|
||||
let def_id = item_id.owner_id.to_def_id();
|
||||
|
||||
match opaque_ty.kind {
|
||||
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)
|
||||
}
|
||||
ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
|
||||
|
@ -444,7 +444,7 @@ fn check_opaque_meets_bounds<'tcx>(
|
||||
// version.
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||
}
|
||||
match origin {
|
||||
// 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);
|
||||
debug!(?errors);
|
||||
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 => {
|
||||
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||
return Err(reported);
|
||||
}
|
||||
}
|
||||
@ -720,7 +720,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
||||
// RPITs.
|
||||
let errors = ocx.select_all_or_error();
|
||||
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);
|
||||
}
|
||||
|
||||
@ -830,7 +830,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
|
||||
|
||||
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
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) {
|
||||
return *ty;
|
||||
@ -1731,7 +1731,7 @@ pub(super) fn compare_impl_const_raw(
|
||||
// version.
|
||||
let errors = ocx.select_all_or_error();
|
||||
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);
|
||||
@ -1831,7 +1831,7 @@ fn compare_type_predicate_entailment<'tcx>(
|
||||
// version.
|
||||
let errors = ocx.select_all_or_error();
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1995,13 +1995,20 @@ pub(super) fn check_type_bounds<'tcx>(
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
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
|
||||
// span for an impl's associated type. Instead, for these, use the def_span for the synthesized
|
||||
// associated type.
|
||||
let impl_ty_span = if tcx.opt_rpitit_info(impl_ty.def_id).is_some() {
|
||||
tcx.def_span(impl_ty_def_id)
|
||||
} else {
|
||||
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);
|
||||
|
||||
@ -2044,7 +2051,7 @@ pub(super) fn check_type_bounds<'tcx>(
|
||||
// version.
|
||||
let errors = ocx.select_all_or_error();
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -111,7 +111,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
|
||||
|
||||
let errors = wfcx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -345,7 +345,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
|
||||
}),
|
||||
);
|
||||
if !errors.is_empty() {
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||
}
|
||||
|
||||
// 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]);
|
||||
let errors = traits::fully_solve_obligation(&infcx, predicate);
|
||||
if !errors.is_empty() {
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||
}
|
||||
|
||||
// Finally, resolve all regions.
|
||||
|
@ -11,7 +11,7 @@ use rustc_errors::struct_span_err;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
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_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);
|
||||
} else {
|
||||
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);
|
||||
} else {
|
||||
bug!("unexpected primitive type: {:?}", ty);
|
||||
|
@ -3,7 +3,7 @@ use crate::astconv::AstConv;
|
||||
use rustc_hir as hir;
|
||||
use rustc_infer::traits::util;
|
||||
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::Span;
|
||||
|
||||
@ -58,17 +58,10 @@ fn opaque_type_bounds<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
opaque_def_id: DefId,
|
||||
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
|
||||
item_ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
in_trait: bool,
|
||||
) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
|
||||
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 mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds);
|
||||
// Opaque types are implicitly sized unless a `?Sized` bound is found
|
||||
@ -83,7 +76,18 @@ pub(super) fn explicit_item_bounds(
|
||||
tcx: TyCtxt<'_>,
|
||||
def_id: DefId,
|
||||
) -> &'_ [(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) {
|
||||
hir::Node::TraitItem(hir::TraitItem {
|
||||
kind: hir::TraitItemKind::Type(bounds, _),
|
||||
@ -94,7 +98,15 @@ pub(super) fn explicit_item_bounds(
|
||||
kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait, .. }),
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,8 @@ use rustc_middle::ty::print::with_forced_trimmed_paths;
|
||||
use rustc_middle::ty::subst::InternalSubsts;
|
||||
use rustc_middle::ty::util::IntTypeExt;
|
||||
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::{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<'_>> {
|
||||
// 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();
|
||||
use rustc_hir::*;
|
||||
|
||||
|
@ -129,6 +129,18 @@ pub struct AssocTypeBindingNotAllowed {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
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)]
|
||||
@ -315,6 +327,14 @@ pub(crate) struct TrackCallerOnMain {
|
||||
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)]
|
||||
#[diag(hir_analysis_start_not_track_caller)]
|
||||
pub(crate) struct StartTrackCaller {
|
||||
@ -324,6 +344,15 @@ pub(crate) struct StartTrackCaller {
|
||||
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)]
|
||||
#[diag(hir_analysis_start_not_async, code = "E0752")]
|
||||
pub(crate) struct StartAsync {
|
||||
|
@ -174,7 +174,7 @@ fn get_impl_substs(
|
||||
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
ocx.infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||
ocx.infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,7 @@ use std::ops::Not;
|
||||
use astconv::AstConv;
|
||||
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) {
|
||||
const CONVENTIONS_UNSTABLE: &str = "`C`, `cdecl`, `win64`, `sysv64` or `efiapi`";
|
||||
@ -176,7 +176,7 @@ fn require_same_types<'tcx>(
|
||||
match &errors[..] {
|
||||
[] => true,
|
||||
errors => {
|
||||
infcx.err_ctxt().report_fulfillment_errors(errors, None);
|
||||
infcx.err_ctxt().report_fulfillment_errors(errors);
|
||||
false
|
||||
}
|
||||
}
|
||||
@ -283,6 +283,15 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
|
||||
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 {
|
||||
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);
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors, None);
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||
error = true;
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
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 {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user