diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 398a70ee6a236..2f54d2838cf27 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -417,30 +417,16 @@ jobs:
RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstate/toolstates.json"
DEPLOY_TOOLSTATES_JSON: toolstates-windows.json
os: windows-2019-8core-32gb
- - name: i686-mingw-1
+ - name: i686-mingw
env:
RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-gnu"
- SCRIPT: make ci-mingw-subset-1
+ SCRIPT: make ci-mingw
NO_DOWNLOAD_CI_LLVM: 1
CUSTOM_MINGW: 1
os: windows-2019-8core-32gb
- - name: i686-mingw-2
+ - name: x86_64-mingw
env:
- RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-gnu"
- SCRIPT: make ci-mingw-subset-2
- NO_DOWNLOAD_CI_LLVM: 1
- CUSTOM_MINGW: 1
- os: windows-2019-8core-32gb
- - name: x86_64-mingw-1
- env:
- SCRIPT: make ci-mingw-subset-1
- RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-gnu --enable-profiler"
- NO_DOWNLOAD_CI_LLVM: 1
- CUSTOM_MINGW: 1
- os: windows-2019-8core-32gb
- - name: x86_64-mingw-2
- env:
- SCRIPT: make ci-mingw-subset-2
+ SCRIPT: make ci-mingw
RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-gnu --enable-profiler"
NO_DOWNLOAD_CI_LLVM: 1
CUSTOM_MINGW: 1
diff --git a/Cargo.lock b/Cargo.lock
index 4eafda94037c3..28db406399614 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -360,7 +360,7 @@ dependencies = [
name = "cargo-miri"
version = "0.1.0"
dependencies = [
- "cargo_metadata 0.15.3",
+ "cargo_metadata",
"directories",
"rustc-build-sysroot",
"rustc-workspace-hack",
@@ -381,22 +381,9 @@ dependencies = [
[[package]]
name = "cargo_metadata"
-version = "0.14.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c297bd3135f558552f99a0daa180876984ea2c4ffa7470314540dff8c654109a"
-dependencies = [
- "camino",
- "cargo-platform",
- "semver",
- "serde",
- "serde_json",
-]
-
-[[package]]
-name = "cargo_metadata"
-version = "0.15.3"
+version = "0.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08a1ec454bc3eead8719cb56e15dbbfecdbc14e4b3a3ae4936cc6e31f5fc0d07"
+checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a"
dependencies = [
"camino",
"cargo-platform",
@@ -631,7 +618,7 @@ name = "clippy_lints"
version = "0.1.72"
dependencies = [
"arrayvec",
- "cargo_metadata 0.15.3",
+ "cargo_metadata",
"clippy_utils",
"declare_clippy_lint",
"if_chain",
@@ -710,9 +697,9 @@ dependencies = [
[[package]]
name = "compiler_builtins"
-version = "0.1.92"
+version = "0.1.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64518f1ae689f74db058bbfb3238dfe6eb53f59f4ae712f1ff4348628522e190"
+checksum = "76630810d973ecea3dbf611e1b7aecfb1012751ef1ff8de3998f89014a166781"
dependencies = [
"cc",
"rustc-std-workspace-core",
@@ -4348,35 +4335,33 @@ dependencies = [
"proc-macro2",
"quote",
"serde",
- "syn 1.0.102",
+ "syn 2.0.8",
]
[[package]]
name = "rustfmt-nightly"
-version = "1.5.2"
+version = "1.5.3"
dependencies = [
"annotate-snippets",
"anyhow",
"bytecount",
- "cargo_metadata 0.14.0",
- "clap 3.2.20",
- "derive-new",
+ "cargo_metadata",
+ "clap 4.2.1",
"diff",
"dirs",
- "env_logger 0.9.0",
+ "env_logger 0.10.0",
"getopts",
"ignore",
"itertools",
"lazy_static",
"log",
"regex",
- "rustc-workspace-hack",
"rustfmt-config_proc_macro",
"serde",
"serde_json",
"term",
"thiserror",
- "toml 0.5.7",
+ "toml 0.7.4",
"unicode-segmentation",
"unicode-width",
"unicode_categories",
@@ -4956,7 +4941,7 @@ name = "tidy"
version = "0.1.0"
dependencies = [
"cargo-platform",
- "cargo_metadata 0.15.3",
+ "cargo_metadata",
"ignore",
"lazy_static",
"miropt-test-tools",
@@ -5192,7 +5177,7 @@ checksum = "191a442639ea102fa62671026047e51d574bfda44b7fdf32151d7314624c1cd2"
dependencies = [
"bstr",
"cargo-platform",
- "cargo_metadata 0.15.3",
+ "cargo_metadata",
"color-eyre",
"colored",
"crossbeam-channel",
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 4360fbeb9bbc1..a398fd80119be 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -1295,6 +1295,7 @@ impl Expr {
ExprKind::Yield(..) => ExprPrecedence::Yield,
ExprKind::Yeet(..) => ExprPrecedence::Yeet,
ExprKind::FormatArgs(..) => ExprPrecedence::FormatArgs,
+ ExprKind::Become(..) => ExprPrecedence::Become,
ExprKind::Err => ExprPrecedence::Err,
}
}
@@ -1515,6 +1516,11 @@ pub enum ExprKind {
/// with an optional value to be returned.
Yeet(Option
>),
+ /// A tail call return, with the value to be returned.
+ ///
+ /// While `.0` must be a function call, we check this later, after parsing.
+ Become(P),
+
/// Bytes included via `include_bytes!`
/// Added for optimization purposes to avoid the need to escape
/// large binary blobs - should always behave like [`ExprKind::Lit`]
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 66b94d12a32c6..53a9c9a046ea0 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1457,6 +1457,7 @@ pub fn noop_visit_expr(
ExprKind::Yeet(expr) => {
visit_opt(expr, |expr| vis.visit_expr(expr));
}
+ ExprKind::Become(expr) => vis.visit_expr(expr),
ExprKind::InlineAsm(asm) => vis.visit_inline_asm(asm),
ExprKind::FormatArgs(fmt) => vis.visit_format_args(fmt),
ExprKind::OffsetOf(container, fields) => {
diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs
index 35afd5423721d..096077e09bf76 100644
--- a/compiler/rustc_ast/src/util/parser.rs
+++ b/compiler/rustc_ast/src/util/parser.rs
@@ -245,6 +245,7 @@ pub enum ExprPrecedence {
Ret,
Yield,
Yeet,
+ Become,
Range,
@@ -298,7 +299,8 @@ impl ExprPrecedence {
| ExprPrecedence::Continue
| ExprPrecedence::Ret
| ExprPrecedence::Yield
- | ExprPrecedence::Yeet => PREC_JUMP,
+ | ExprPrecedence::Yeet
+ | ExprPrecedence::Become => PREC_JUMP,
// `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to
// parse, instead of parsing as `(x .. x) = x`. Giving `Range` a lower precedence
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 275692ad5dda7..d9de5b8e197db 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -908,6 +908,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
ExprKind::Yeet(optional_expression) => {
walk_list!(visitor, visit_expr, optional_expression);
}
+ ExprKind::Become(expr) => visitor.visit_expr(expr),
ExprKind::MacCall(mac) => visitor.visit_mac_call(mac),
ExprKind::Paren(subexpression) => visitor.visit_expr(subexpression),
ExprKind::InlineAsm(asm) => visitor.visit_inline_asm(asm),
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index f52797c4f3f1d..225714a13615f 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -275,6 +275,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::ExprKind::Ret(e)
}
ExprKind::Yeet(sub_expr) => self.lower_expr_yeet(e.span, sub_expr.as_deref()),
+ ExprKind::Become(sub_expr) => {
+ let sub_expr = self.lower_expr(sub_expr);
+
+ // FIXME(explicit_tail_calls): Use `hir::ExprKind::Become` once we implemented it
+ hir::ExprKind::Ret(Some(sub_expr))
+ }
ExprKind::InlineAsm(asm) => {
hir::ExprKind::InlineAsm(self.lower_inline_asm(e.span, asm))
}
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 2125349909ef1..b0dbc2c23403e 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -555,6 +555,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
gate_all!(dyn_star, "`dyn*` trait objects are experimental");
gate_all!(const_closures, "const closures are experimental");
gate_all!(builtin_syntax, "`builtin #` syntax is unstable");
+ gate_all!(explicit_tail_calls, "`become` expression is experimental");
if !visitor.features.negative_bounds {
for &span in spans.get(&sym::negative_bounds).iter().copied().flatten() {
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index 87c32ffce1214..609920180a2fa 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -537,6 +537,11 @@ impl<'a> State<'a> {
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
}
}
+ ast::ExprKind::Become(result) => {
+ self.word("become");
+ self.word(" ");
+ self.print_expr_maybe_paren(result, parser::PREC_JUMP);
+ }
ast::ExprKind::InlineAsm(a) => {
// FIXME: This should have its own syntax, distinct from a macro invocation.
self.word("asm!");
diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs
index 6be20b0974ddb..0b44beeb004c4 100644
--- a/compiler/rustc_borrowck/src/borrow_set.rs
+++ b/compiler/rustc_borrowck/src/borrow_set.rs
@@ -72,8 +72,11 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> {
let kind = match self.kind {
mir::BorrowKind::Shared => "",
mir::BorrowKind::Shallow => "shallow ",
- mir::BorrowKind::Unique => "uniq ",
- mir::BorrowKind::Mut { .. } => "mut ",
+ mir::BorrowKind::Mut { kind: mir::MutBorrowKind::ClosureCapture } => "uniq ",
+ // FIXME: differentiate `TwoPhaseBorrow`
+ mir::BorrowKind::Mut {
+ kind: mir::MutBorrowKind::Default | mir::MutBorrowKind::TwoPhaseBorrow,
+ } => "mut ",
};
write!(w, "&{:?} {}{:?}", self.region, kind, self.borrowed_place)
}
diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs
index acca1a1477f25..a4e0e773a81ae 100644
--- a/compiler/rustc_borrowck/src/borrowck_errors.rs
+++ b/compiler/rustc_borrowck/src/borrowck_errors.rs
@@ -278,7 +278,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
move_from_span: Span,
move_from_desc: &str,
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
- struct_span_err!(self, move_from_span, E0507, "cannot move out of {}", move_from_desc,)
+ struct_span_err!(self, move_from_span, E0507, "cannot move out of {}", move_from_desc)
}
/// Signal an error due to an attempt to move out of the interior
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 15d73ed732f50..5c365e98f0bab 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -14,9 +14,10 @@ use rustc_infer::traits::ObligationCause;
use rustc_middle::hir::nested_filter::OnlyBodies;
use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::{
- self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory,
- FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
- ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
+ self, AggregateKind, BindingForm, BorrowKind, CallSource, ClearCrossCrate, ConstraintCategory,
+ FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, MutBorrowKind, Operand, Place,
+ PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
+ VarBindingForm,
};
use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty};
use rustc_middle::util::CallKind;
@@ -678,7 +679,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// Find out if the predicates show that the type is a Fn or FnMut
let find_fn_kind_from_did = |(pred, _): (ty::Predicate<'tcx>, _)| {
- if let ty::PredicateKind::Clause(ty::Clause::Trait(pred)) = pred.kind().skip_binder()
+ if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) = pred.kind().skip_binder()
&& pred.self_ty() == ty
{
if Some(pred.def_id()) == tcx.lang_items().fn_trait() {
@@ -704,7 +705,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => tcx
.explicit_item_bounds(def_id)
.subst_iter_copied(tcx, substs)
- .find_map(find_fn_kind_from_did),
+ .find_map(|(clause, span)| find_fn_kind_from_did((clause.as_predicate(), span))),
ty::Closure(_, substs) => match substs.as_closure().kind() {
ty::ClosureKind::Fn => Some(hir::Mutability::Not),
ty::ClosureKind::FnMut => Some(hir::Mutability::Mut),
@@ -775,7 +776,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let predicates: Result, _> = errors
.into_iter()
.map(|err| match err.obligation.predicate.kind().skip_binder() {
- PredicateKind::Clause(ty::Clause::Trait(predicate)) => {
+ PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) => {
match predicate.self_ty().kind() {
ty::Param(param_ty) => Ok((
generics.type_param(param_ty, tcx),
@@ -926,7 +927,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// FIXME: supply non-"" `opt_via` when appropriate
let first_borrow_desc;
let mut err = match (gen_borrow_kind, issued_borrow.kind) {
- (BorrowKind::Shared, BorrowKind::Mut { .. }) => {
+ (
+ BorrowKind::Shared,
+ BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
+ ) => {
first_borrow_desc = "mutable ";
self.cannot_reborrow_already_borrowed(
span,
@@ -940,7 +944,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
None,
)
}
- (BorrowKind::Mut { .. }, BorrowKind::Shared) => {
+ (
+ BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
+ BorrowKind::Shared,
+ ) => {
first_borrow_desc = "immutable ";
let mut err = self.cannot_reborrow_already_borrowed(
span,
@@ -962,7 +969,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
err
}
- (BorrowKind::Mut { .. }, BorrowKind::Mut { .. }) => {
+ (
+ BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
+ BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow },
+ ) => {
first_borrow_desc = "first ";
let mut err = self.cannot_mutably_borrow_multiply(
span,
@@ -985,12 +995,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
err
}
- (BorrowKind::Unique, BorrowKind::Unique) => {
+ (
+ BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture },
+ BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture },
+ ) => {
first_borrow_desc = "first ";
self.cannot_uniquely_borrow_by_two_closures(span, &desc_place, issued_span, None)
}
- (BorrowKind::Mut { .. } | BorrowKind::Unique, BorrowKind::Shallow) => {
+ (BorrowKind::Mut { .. }, BorrowKind::Shallow) => {
if let Some(immutable_section_description) =
self.classify_immutable_section(issued_borrow.assigned_place)
{
@@ -1004,7 +1017,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
borrow_spans.var_subdiag(
None,
&mut err,
- Some(BorrowKind::Unique),
+ Some(BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }),
|kind, var_span| {
use crate::session_diagnostics::CaptureVarCause::*;
match kind {
@@ -1038,7 +1051,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}
- (BorrowKind::Unique, _) => {
+ (BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }, _) => {
first_borrow_desc = "first ";
self.cannot_uniquely_borrow_by_one_closure(
span,
@@ -1052,7 +1065,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
)
}
- (BorrowKind::Shared, BorrowKind::Unique) => {
+ (BorrowKind::Shared, BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }) => {
first_borrow_desc = "first ";
self.cannot_reborrow_already_uniquely_borrowed(
span,
@@ -1067,7 +1080,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
)
}
- (BorrowKind::Mut { .. }, BorrowKind::Unique) => {
+ (BorrowKind::Mut { .. }, BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }) => {
first_borrow_desc = "first ";
self.cannot_reborrow_already_uniquely_borrowed(
span,
@@ -1085,10 +1098,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
(BorrowKind::Shared, BorrowKind::Shared | BorrowKind::Shallow)
| (
BorrowKind::Shallow,
- BorrowKind::Mut { .. }
- | BorrowKind::Unique
- | BorrowKind::Shared
- | BorrowKind::Shallow,
+ BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Shallow,
) => unreachable!(),
};
@@ -2579,7 +2589,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
fn explain_deref_coercion(&mut self, loan: &BorrowData<'tcx>, err: &mut Diagnostic) {
let tcx = self.infcx.tcx;
if let (
- Some(Terminator { kind: TerminatorKind::Call { from_hir_call: false, .. }, .. }),
+ Some(Terminator {
+ kind: TerminatorKind::Call { call_source: CallSource::OverloadedOperator, .. },
+ ..
+ }),
Some((method_did, method_substs)),
) = (
&self.body[loan.reserve_location.block].terminator,
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 1d430a93a876d..6c01fd63b1ec7 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -6,8 +6,8 @@ use rustc_hir::intravisit::Visitor;
use rustc_index::IndexSlice;
use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_middle::mir::{
- Body, CastKind, ConstraintCategory, FakeReadCause, Local, LocalInfo, Location, Operand, Place,
- Rvalue, Statement, StatementKind, TerminatorKind,
+ Body, CallSource, 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};
@@ -494,7 +494,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} else if self.was_captured_by_trait_object(borrow) {
LaterUseKind::TraitCapture
} else if location.statement_index == block.statements.len() {
- if let TerminatorKind::Call { func, from_hir_call: true, .. } =
+ if let TerminatorKind::Call { func, call_source: CallSource::Normal, .. } =
&block.terminator().kind
{
// Just point to the function, to reduce the chance of overlapping spans.
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 20370e4c6ac3c..2f8c970f806d3 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -13,8 +13,9 @@ use rustc_index::IndexSlice;
use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::{
- AggregateKind, Constant, FakeReadCause, Local, LocalInfo, LocalKind, Location, Operand, Place,
- PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
+ AggregateKind, CallSource, Constant, FakeReadCause, Local, LocalInfo, LocalKind, Location,
+ Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator,
+ TerminatorKind,
};
use rustc_middle::ty::print::Print;
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
@@ -414,7 +415,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if !is_terminator {
continue;
} else if let Some(Terminator {
- kind: TerminatorKind::Call { func, from_hir_call: false, .. },
+ kind:
+ TerminatorKind::Call {
+ func,
+ call_source: CallSource::OverloadedOperator,
+ ..
+ },
..
}) = &bbd.terminator
{
@@ -622,8 +628,7 @@ impl UseSpans<'_> {
err.subdiagnostic(match kind {
Some(kd) => match kd {
rustc_middle::mir::BorrowKind::Shared
- | rustc_middle::mir::BorrowKind::Shallow
- | rustc_middle::mir::BorrowKind::Unique => {
+ | rustc_middle::mir::BorrowKind::Shallow => {
CaptureVarKind::Immut { kind_span: capture_kind_span }
}
@@ -839,7 +844,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
debug!("move_spans: target_temp = {:?}", target_temp);
if let Some(Terminator {
- kind: TerminatorKind::Call { fn_span, from_hir_call, .. }, ..
+ kind: TerminatorKind::Call { fn_span, call_source, .. }, ..
}) = &self.body[location.block].terminator
{
let Some((method_did, method_substs)) =
@@ -859,7 +864,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
method_did,
method_substs,
*fn_span,
- *from_hir_call,
+ call_source.from_hir_call(),
Some(self.infcx.tcx.fn_arg_names(method_did)[0]),
);
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 34d466db2b409..1ba490e9a01c2 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -234,7 +234,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
borrow_spans.var_subdiag(
None,
&mut err,
- Some(mir::BorrowKind::Mut { allow_two_phase_borrow: false }),
+ Some(mir::BorrowKind::Mut { kind: mir::MutBorrowKind::Default }),
|_kind, var_span| {
let place = self.describe_any_place(access_place.as_ref());
crate::session_diagnostics::CaptureVarCause::MutableBorrowUsePlaceClosure {
@@ -300,7 +300,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
_,
mir::Rvalue::Ref(
_,
- mir::BorrowKind::Mut { allow_two_phase_borrow: false },
+ mir::BorrowKind::Mut { kind: mir::MutBorrowKind::Default },
_,
),
)),
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index f38e1605fa5ca..55c9864af8c74 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -939,8 +939,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
{
predicates.iter().any(|pred| {
match pred.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(data)) if data.self_ty() == ty => {}
- ty::PredicateKind::Clause(ty::Clause::Projection(data)) if data.projection_ty.self_ty() == ty => {}
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) if data.self_ty() == ty => {}
+ ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) if data.projection_ty.self_ty() == ty => {}
_ => return false,
}
tcx.any_free_region_meets(pred, |r| {
diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs
index b2ff25ecb96f4..0152d89eb8366 100644
--- a/compiler/rustc_borrowck/src/invalidation.rs
+++ b/compiler/rustc_borrowck/src/invalidation.rs
@@ -128,7 +128,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
destination,
target: _,
unwind: _,
- from_hir_call: _,
+ call_source: _,
fn_span: _,
} => {
self.consume_operand(location, func);
@@ -255,7 +255,7 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
(Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk)))
}
BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))),
- BorrowKind::Unique | BorrowKind::Mut { .. } => {
+ BorrowKind::Mut { .. } => {
let wk = WriteKind::MutableBorrow(bk);
if allow_two_phase_borrow(bk) {
(Deep, Reservation(wk))
@@ -273,7 +273,7 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
Mutability::Mut => (
Deep,
Write(WriteKind::MutableBorrow(BorrowKind::Mut {
- allow_two_phase_borrow: false,
+ kind: mir::MutBorrowKind::Default,
})),
),
Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
@@ -376,14 +376,11 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
}
(Read(_), BorrowKind::Shallow | BorrowKind::Shared)
- | (
- Read(ReadKind::Borrow(BorrowKind::Shallow)),
- BorrowKind::Unique | BorrowKind::Mut { .. },
- ) => {
+ | (Read(ReadKind::Borrow(BorrowKind::Shallow)), BorrowKind::Mut { .. }) => {
// Reads don't invalidate shared or shallow borrows
}
- (Read(_), BorrowKind::Unique | BorrowKind::Mut { .. }) => {
+ (Read(_), BorrowKind::Mut { .. }) => {
// Reading from mere reservations of mutable-borrows is OK.
if !is_active(&this.dominators, borrow, location) {
// If the borrow isn't active yet, reads don't invalidate it
@@ -425,7 +422,7 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
// only mutable borrows should be 2-phase
assert!(match borrow.kind {
BorrowKind::Shared | BorrowKind::Shallow => false,
- BorrowKind::Unique | BorrowKind::Mut { .. } => true,
+ BorrowKind::Mut { .. } => true,
});
self.access_place(
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 99a988f2c629e..be3a3b777971a 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -29,8 +29,8 @@ use rustc_infer::infer::{
InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt,
};
use rustc_middle::mir::{
- traversal, Body, ClearCrossCrate, Local, Location, Mutability, NonDivergingIntrinsic, Operand,
- Place, PlaceElem, PlaceRef, VarDebugInfoContents,
+ traversal, Body, ClearCrossCrate, Local, Location, MutBorrowKind, Mutability,
+ NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef, VarDebugInfoContents,
};
use rustc_middle::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
@@ -710,7 +710,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
destination,
target: _,
unwind: _,
- from_hir_call: _,
+ call_source: _,
fn_span: _,
} => {
self.consume_operand(loc, (func, span), flow_state);
@@ -1071,10 +1071,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
(Read(_), BorrowKind::Shared | BorrowKind::Shallow)
- | (
- Read(ReadKind::Borrow(BorrowKind::Shallow)),
- BorrowKind::Unique | BorrowKind::Mut { .. },
- ) => Control::Continue,
+ | (Read(ReadKind::Borrow(BorrowKind::Shallow)), BorrowKind::Mut { .. }) => {
+ Control::Continue
+ }
(Reservation(_), BorrowKind::Shallow | BorrowKind::Shared) => {
// This used to be a future compatibility warning (to be
@@ -1087,7 +1086,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
Control::Continue
}
- (Read(kind), BorrowKind::Unique | BorrowKind::Mut { .. }) => {
+ (Read(kind), BorrowKind::Mut { .. }) => {
// Reading from mere reservations of mutable-borrows is OK.
if !is_active(this.dominators(), borrow, location) {
assert!(allow_two_phase_borrow(borrow.kind));
@@ -1194,7 +1193,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
(Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk)))
}
BorrowKind::Shared => (Deep, Read(ReadKind::Borrow(bk))),
- BorrowKind::Unique | BorrowKind::Mut { .. } => {
+ BorrowKind::Mut { .. } => {
let wk = WriteKind::MutableBorrow(bk);
if allow_two_phase_borrow(bk) {
(Deep, Reservation(wk))
@@ -1231,7 +1230,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
Mutability::Mut => (
Deep,
Write(WriteKind::MutableBorrow(BorrowKind::Mut {
- allow_two_phase_borrow: false,
+ kind: MutBorrowKind::Default,
})),
),
Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
@@ -1565,7 +1564,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// only mutable borrows should be 2-phase
assert!(match borrow.kind {
BorrowKind::Shared | BorrowKind::Shallow => false,
- BorrowKind::Unique | BorrowKind::Mut { .. } => true,
+ BorrowKind::Mut { .. } => true,
});
self.access_place(
@@ -1959,16 +1958,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let the_place_err;
match kind {
- Reservation(WriteKind::MutableBorrow(
- borrow_kind @ (BorrowKind::Unique | BorrowKind::Mut { .. }),
- ))
- | Write(WriteKind::MutableBorrow(
- borrow_kind @ (BorrowKind::Unique | BorrowKind::Mut { .. }),
- )) => {
- let is_local_mutation_allowed = match borrow_kind {
- BorrowKind::Unique => LocalMutationIsAllowed::Yes,
- BorrowKind::Mut { .. } => is_local_mutation_allowed,
- BorrowKind::Shared | BorrowKind::Shallow => unreachable!(),
+ Reservation(WriteKind::MutableBorrow(BorrowKind::Mut { kind: mut_borrow_kind }))
+ | Write(WriteKind::MutableBorrow(BorrowKind::Mut { kind: mut_borrow_kind })) => {
+ let is_local_mutation_allowed = match mut_borrow_kind {
+ // `ClosureCapture` is used for mutable variable with a immutable binding.
+ // This is only behaviour difference between `ClosureCapture` and mutable borrows.
+ MutBorrowKind::ClosureCapture => LocalMutationIsAllowed::Yes,
+ MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow => {
+ is_local_mutation_allowed
+ }
};
match self.is_mutable(place.as_ref(), is_local_mutation_allowed) {
Ok(root_place) => {
@@ -2031,12 +2029,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
return false;
}
Read(
- ReadKind::Borrow(
- BorrowKind::Unique
- | BorrowKind::Mut { .. }
- | BorrowKind::Shared
- | BorrowKind::Shallow,
- )
+ ReadKind::Borrow(BorrowKind::Mut { .. } | BorrowKind::Shared | BorrowKind::Shallow)
| ReadKind::Copy,
) => {
// Access authorized
diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs
index 25c485b814f4a..c83d045a94e18 100644
--- a/compiler/rustc_borrowck/src/places_conflict.rs
+++ b/compiler/rustc_borrowck/src/places_conflict.rs
@@ -4,7 +4,9 @@ use crate::ArtificialField;
use crate::Overlap;
use crate::{AccessDepth, Deep, Shallow};
use rustc_hir as hir;
-use rustc_middle::mir::{Body, BorrowKind, Local, Place, PlaceElem, PlaceRef, ProjectionElem};
+use rustc_middle::mir::{
+ Body, BorrowKind, Local, MutBorrowKind, Place, PlaceElem, PlaceRef, ProjectionElem,
+};
use rustc_middle::ty::{self, TyCtxt};
use std::cmp::max;
use std::iter;
@@ -35,7 +37,7 @@ pub fn places_conflict<'tcx>(
tcx,
body,
borrow_place,
- BorrowKind::Mut { allow_two_phase_borrow: true },
+ BorrowKind::Mut { kind: MutBorrowKind::TwoPhaseBorrow },
access_place.as_ref(),
AccessDepth::Deep,
bias,
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 6ca702cfdfc3e..4a872eb251c25 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -330,8 +330,9 @@ fn check_opaque_type_well_formed<'tcx>(
// Require the hidden type to be well-formed with only the generics of the opaque type.
// Defining use functions may have more bounds than the opaque type, which is ok, as long as the
// hidden type is well formed even without those bounds.
- let predicate =
- ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::WellFormed(definition_ty.into())));
+ let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
+ definition_ty.into(),
+ )));
ocx.register_obligation(Obligation::misc(tcx, definition_span, def_id, param_env, predicate));
// Check that all obligations are satisfied by the implementation's
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index f527eee7bda05..c19fbf20ca5bc 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -89,11 +89,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
category: ConstraintCategory<'tcx>,
) {
self.prove_predicate(
- ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate {
- trait_ref,
- constness: ty::BoundConstness::NotConst,
- polarity: ty::ImplPolarity::Positive,
- }))),
+ ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::Trait(
+ ty::TraitPredicate {
+ trait_ref,
+ constness: ty::BoundConstness::NotConst,
+ polarity: ty::ImplPolarity::Positive,
+ },
+ ))),
locations,
category,
);
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 33f75437478b5..0a897272d358e 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1065,7 +1065,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
)?;
ocx.infcx.add_item_bounds_for_hidden_type(
- opaque_type_key,
+ opaque_type_key.def_id.to_def_id(),
+ opaque_type_key.substs,
cause,
param_env,
hidden_ty.ty,
@@ -1370,7 +1371,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
// FIXME: check the values
}
- TerminatorKind::Call { func, args, destination, from_hir_call, target, .. } => {
+ TerminatorKind::Call { func, args, destination, call_source, target, .. } => {
self.check_operand(func, term_location);
for arg in args {
self.check_operand(arg, term_location);
@@ -1420,7 +1421,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// See #91068 for an example.
self.prove_predicates(
sig.inputs_and_output.iter().map(|ty| {
- ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::WellFormed(
+ ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
ty.into(),
)))
}),
@@ -1446,7 +1447,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
.add_element(region_vid, term_location);
}
- self.check_call_inputs(body, term, &sig, args, term_location, *from_hir_call);
+ self.check_call_inputs(body, term, &sig, args, term_location, *call_source);
}
TerminatorKind::Assert { cond, msg, .. } => {
self.check_operand(cond, term_location);
@@ -1573,7 +1574,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
sig: &ty::FnSig<'tcx>,
args: &[Operand<'tcx>],
term_location: Location,
- from_hir_call: bool,
+ call_source: CallSource,
) {
debug!("check_call_inputs({:?}, {:?})", sig, args);
if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.c_variadic) {
@@ -1591,7 +1592,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let op_arg_ty = op_arg.ty(body, self.tcx());
let op_arg_ty = self.normalize(op_arg_ty, term_location);
- let category = if from_hir_call {
+ let category = if call_source.from_hir_call() {
ConstraintCategory::CallArgument(self.infcx.tcx.erase_regions(func_ty))
} else {
ConstraintCategory::Boring
@@ -1852,7 +1853,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let array_ty = rvalue.ty(body.local_decls(), tcx);
self.prove_predicate(
- ty::PredicateKind::Clause(ty::Clause::WellFormed(array_ty.into())),
+ ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(array_ty.into())),
Locations::Single(location),
ConstraintCategory::Boring,
);
@@ -2025,10 +2026,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
ConstraintCategory::Cast,
);
- let outlives_predicate =
- tcx.mk_predicate(Binder::dummy(ty::PredicateKind::Clause(
- ty::Clause::TypeOutlives(ty::OutlivesPredicate(self_ty, *region)),
- )));
+ let outlives_predicate = tcx.mk_predicate(Binder::dummy(
+ ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(
+ ty::OutlivesPredicate(self_ty, *region),
+ )),
+ ));
self.prove_predicate(
outlives_predicate,
location.to_locations(),
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index b619e80e15f3c..902c1e40c7541 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -320,6 +320,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
| ExprKind::Underscore
| ExprKind::While(_, _, _)
| ExprKind::Yeet(_)
+ | ExprKind::Become(_)
| ExprKind::Yield(_) => {}
}
}
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs
index 49ee276af4e6f..fcc68010a34c6 100644
--- a/compiler/rustc_builtin_macros/src/test.rs
+++ b/compiler/rustc_builtin_macros/src/test.rs
@@ -3,7 +3,7 @@ use crate::errors;
/// Ideally, this code would be in libtest but for efficiency and error messages it lives here.
use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute};
use rustc_ast::ptr::P;
-use rustc_ast::{self as ast, attr};
+use rustc_ast::{self as ast, attr, GenericParamKind};
use rustc_ast_pretty::pprust;
use rustc_errors::Applicability;
use rustc_expand::base::*;
@@ -122,11 +122,7 @@ pub fn expand_test_or_bench(
let ast::ItemKind::Fn(fn_) = &item.kind else {
not_testable_error(cx, attr_sp, Some(&item));
return if is_stmt {
- vec![Annotatable::Stmt(P(ast::Stmt {
- id: ast::DUMMY_NODE_ID,
- span: item.span,
- kind: ast::StmtKind::Item(item),
- }))]
+ vec![Annotatable::Stmt(P(cx.stmt_item(item.span, item)))]
} else {
vec![Annotatable::Item(item)]
};
@@ -138,7 +134,11 @@ pub fn expand_test_or_bench(
if (!is_bench && !has_test_signature(cx, &item))
|| (is_bench && !has_bench_signature(cx, &item))
{
- return vec![Annotatable::Item(item)];
+ return if is_stmt {
+ vec![Annotatable::Stmt(P(cx.stmt_item(item.span, item)))]
+ } else {
+ vec![Annotatable::Item(item)]
+ };
}
let sp = cx.with_def_site_ctxt(item.span);
@@ -550,24 +550,21 @@ fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
return false;
}
- match (has_output, has_should_panic_attr) {
- (true, true) => {
- sd.span_err(i.span, "functions using `#[should_panic]` must return `()`");
- false
- }
- (true, false) => {
- if !generics.params.is_empty() {
- sd.span_err(
- i.span,
- "functions used as tests must have signature fn() -> ()",
- );
- false
- } else {
- true
- }
- }
- (false, _) => true,
+ if has_should_panic_attr && has_output {
+ sd.span_err(i.span, "functions using `#[should_panic]` must return `()`");
+ return false;
+ }
+
+ if generics.params.iter().any(|param| !matches!(param.kind, GenericParamKind::Lifetime))
+ {
+ sd.span_err(
+ i.span,
+ "functions used as tests can not have any non-lifetime generic parameters",
+ );
+ return false;
}
+
+ true
}
_ => {
// should be unreachable because `is_test_fn_item` should catch all non-fn items
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 5abb4644e1b09..ce10780f9de12 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -421,7 +421,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
target,
fn_span,
unwind: _,
- from_hir_call: _,
+ call_source: _,
} => {
fx.tcx.prof.generic_activity("codegen call").run(|| {
crate::abi::codegen_terminator_call(
diff --git a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs
index f751d8c179db5..13568b198db1b 100644
--- a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs
+++ b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs
@@ -22,8 +22,8 @@ pub(crate) fn maybe_codegen<'tcx>(
match bin_op {
BinOp::BitAnd | BinOp::BitOr | BinOp::BitXor => None,
- BinOp::Add | BinOp::Sub => None,
- BinOp::Mul => {
+ BinOp::Add | BinOp::AddUnchecked | BinOp::Sub | BinOp::SubUnchecked => None,
+ BinOp::Mul | BinOp::MulUnchecked => {
let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)];
let ret_val = fx.lib_call(
"__multi3",
@@ -69,7 +69,7 @@ pub(crate) fn maybe_codegen<'tcx>(
}
}
BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => None,
- BinOp::Shl | BinOp::Shr => None,
+ BinOp::Shl | BinOp::ShlUnchecked | BinOp::Shr | BinOp::ShrUnchecked => None,
}
}
@@ -131,9 +131,10 @@ pub(crate) fn maybe_codegen_checked<'tcx>(
fx.lib_call(name, param_types, vec![], &args);
Some(out_place.to_cvalue(fx))
}
+ BinOp::AddUnchecked | BinOp::SubUnchecked | BinOp::MulUnchecked => unreachable!(),
BinOp::Offset => unreachable!("offset should only be used on pointers, not 128bit ints"),
BinOp::Div | BinOp::Rem => unreachable!(),
BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => unreachable!(),
- BinOp::Shl | BinOp::Shr => unreachable!(),
+ BinOp::Shl | BinOp::ShlUnchecked | BinOp::Shr | BinOp::ShrUnchecked => unreachable!(),
}
}
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 1e83c30bd677a..5862f18299e90 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -472,25 +472,11 @@ fn codegen_regular_intrinsic_call<'tcx>(
ret.write_cvalue(fx, CValue::by_val(align, usize_layout));
}
- sym::unchecked_add
- | sym::unchecked_sub
- | sym::unchecked_mul
- | sym::exact_div
- | sym::unchecked_shl
- | sym::unchecked_shr => {
+ sym::exact_div => {
intrinsic_args!(fx, args => (x, y); intrinsic);
- // FIXME trap on overflow
- let bin_op = match intrinsic {
- sym::unchecked_add => BinOp::Add,
- sym::unchecked_sub => BinOp::Sub,
- sym::unchecked_mul => BinOp::Mul,
- sym::exact_div => BinOp::Div,
- sym::unchecked_shl => BinOp::Shl,
- sym::unchecked_shr => BinOp::Shr,
- _ => unreachable!(),
- };
- let res = crate::num::codegen_int_binop(fx, bin_op, x, y);
+ // FIXME trap on inexact
+ let res = crate::num::codegen_int_binop(fx, BinOp::Div, x, y);
ret.write_cvalue(fx, res);
}
sym::saturating_add | sym::saturating_sub => {
diff --git a/compiler/rustc_codegen_cranelift/src/num.rs b/compiler/rustc_codegen_cranelift/src/num.rs
index ba53e01c7a212..ac1a6cce096f4 100644
--- a/compiler/rustc_codegen_cranelift/src/num.rs
+++ b/compiler/rustc_codegen_cranelift/src/num.rs
@@ -128,10 +128,11 @@ pub(crate) fn codegen_int_binop<'tcx>(
let rhs = in_rhs.load_scalar(fx);
let b = fx.bcx.ins();
+ // FIXME trap on overflow for the Unchecked versions
let val = match bin_op {
- BinOp::Add => b.iadd(lhs, rhs),
- BinOp::Sub => b.isub(lhs, rhs),
- BinOp::Mul => b.imul(lhs, rhs),
+ BinOp::Add | BinOp::AddUnchecked => b.iadd(lhs, rhs),
+ BinOp::Sub | BinOp::SubUnchecked => b.isub(lhs, rhs),
+ BinOp::Mul | BinOp::MulUnchecked => b.imul(lhs, rhs),
BinOp::Div => {
if signed {
b.sdiv(lhs, rhs)
@@ -149,16 +150,19 @@ pub(crate) fn codegen_int_binop<'tcx>(
BinOp::BitXor => b.bxor(lhs, rhs),
BinOp::BitAnd => b.band(lhs, rhs),
BinOp::BitOr => b.bor(lhs, rhs),
- BinOp::Shl => b.ishl(lhs, rhs),
- BinOp::Shr => {
+ BinOp::Shl | BinOp::ShlUnchecked => b.ishl(lhs, rhs),
+ BinOp::Shr | BinOp::ShrUnchecked => {
if signed {
b.sshr(lhs, rhs)
} else {
b.ushr(lhs, rhs)
}
}
+ BinOp::Offset => unreachable!("Offset is not an integer operation"),
// Compare binops handles by `codegen_binop`.
- _ => unreachable!("{:?}({:?}, {:?})", bin_op, in_lhs.layout().ty, in_rhs.layout().ty),
+ BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge => {
+ unreachable!("{:?}({:?}, {:?})", bin_op, in_lhs.layout().ty, in_rhs.layout().ty);
+ }
};
CValue::by_val(val, in_lhs.layout())
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml b/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml
index 42fb35e738ffd..556c644483320 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml
@@ -20,9 +20,9 @@ jobs:
matrix:
libgccjit_version:
- { gcc: "libgccjit.so", artifacts_branch: "master" }
- commands: [
- "--test-successful-rustc --nb-parts 2 --current-part 0",
- "--test-successful-rustc --nb-parts 2 --current-part 1",
+ cargo_runner: [
+ "sde -future -rtm_mode full --",
+ "",
]
steps:
@@ -36,6 +36,20 @@ jobs:
- name: Install packages
run: sudo apt-get install ninja-build ripgrep
+ - name: Install Intel Software Development Emulator
+ if: ${{ matrix.cargo_runner }}
+ run: |
+ mkdir intel-sde
+ cd intel-sde
+ dir=sde-external-9.14.0-2022-10-25-lin
+ file=$dir.tar.xz
+ wget https://downloadmirror.intel.com/751535/$file
+ tar xvf $file
+ sudo mkdir /usr/share/intel-sde
+ sudo cp -r $dir/* /usr/share/intel-sde
+ sudo ln -s /usr/share/intel-sde/sde /usr/bin/sde
+ sudo ln -s /usr/share/intel-sde/sde64 /usr/bin/sde64
+
- name: Download artifact
uses: dawidd6/action-download-artifact@v2
with:
@@ -91,6 +105,10 @@ jobs:
./prepare_build.sh
./build.sh --release --release-sysroot
cargo test
+
+ - name: Clean
+ if: ${{ !matrix.cargo_runner }}
+ run: |
./clean_all.sh
- name: Prepare dependencies
@@ -107,10 +125,18 @@ jobs:
args: --release
- name: Run tests
+ if: ${{ !matrix.cargo_runner }}
run: |
./test.sh --release --clean --release-sysroot --build-sysroot --mini-tests --std-tests --test-libcore
- name: Run stdarch tests
+ if: ${{ !matrix.cargo_runner }}
run: |
cd build_sysroot/sysroot_src/library/stdarch/
CHANNEL=release TARGET=x86_64-unknown-linux-gnu ../../../../cargo.sh test
+
+ - name: Run stdarch tests
+ if: ${{ matrix.cargo_runner }}
+ run: |
+ cd build_sysroot/sysroot_src/library/stdarch/
+ STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu ../../../../cargo.sh test -- --skip rtm --skip tbm --skip sse4a
diff --git a/compiler/rustc_codegen_gcc/.gitignore b/compiler/rustc_codegen_gcc/.gitignore
index 12ed56675639c..c5ed7de200c24 100644
--- a/compiler/rustc_codegen_gcc/.gitignore
+++ b/compiler/rustc_codegen_gcc/.gitignore
@@ -23,3 +23,5 @@ benchmarks
tools/llvm-project
tools/llvmint
tools/llvmint-2
+# The `llvm` folder is generated by the `tools/generate_intrinsics.py` script to update intrinsics.
+llvm
diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock
index 0f2e152f8ce56..1c8754bf675ea 100644
--- a/compiler/rustc_codegen_gcc/Cargo.lock
+++ b/compiler/rustc_codegen_gcc/Cargo.lock
@@ -35,7 +35,7 @@ dependencies = [
[[package]]
name = "gccjit"
version = "1.0.0"
-source = "git+https://github.com/antoyo/gccjit.rs#fe242b7eb26980e6c78859d51c8d4cc1e43381a3"
+source = "git+https://github.com/antoyo/gccjit.rs#d6e52626cfc6f487094a5d5ac66302baf3439984"
dependencies = [
"gccjit_sys",
]
@@ -43,7 +43,7 @@ dependencies = [
[[package]]
name = "gccjit_sys"
version = "0.0.1"
-source = "git+https://github.com/antoyo/gccjit.rs#fe242b7eb26980e6c78859d51c8d4cc1e43381a3"
+source = "git+https://github.com/antoyo/gccjit.rs#d6e52626cfc6f487094a5d5ac66302baf3439984"
dependencies = [
"libc",
]
diff --git a/compiler/rustc_codegen_gcc/Readme.md b/compiler/rustc_codegen_gcc/Readme.md
index bb74194389254..a93637d9038dc 100644
--- a/compiler/rustc_codegen_gcc/Readme.md
+++ b/compiler/rustc_codegen_gcc/Readme.md
@@ -193,7 +193,7 @@ Using git-subtree with `rustc` requires a patched git to make it work.
The PR that is needed is [here](https://github.com/gitgitgadget/git/pull/493).
Use the following instructions to install it:
-```
+```bash
git clone git@github.com:tqc/git.git
cd git
git checkout tqc/subtree
@@ -204,6 +204,21 @@ make
cp git-subtree ~/bin
```
+Then, do a sync with this command:
+
+```bash
+PATH="$HOME/bin:$PATH" ~/bin/git-subtree push -P compiler/rustc_codegen_gcc/ ../rustc_codegen_gcc/ sync_branch_name
+cd ../rustc_codegen_gcc
+git checkout master
+git pull
+git checkout sync_branch_name
+git merge master
+```
+
+TODO: write a script that does the above.
+
+https://rust-lang.zulipchat.com/#narrow/stream/301329-t-devtools/topic/subtree.20madness/near/258877725
+
### How to use [mem-trace](https://github.com/antoyo/mem-trace)
`rustc` needs to be built without `jemalloc` so that `mem-trace` can overload `malloc` since `jemalloc` is linked statically, so a `LD_PRELOAD`-ed library won't a chance to intercept the calls to `malloc`.
diff --git a/compiler/rustc_codegen_gcc/build_sysroot/Cargo.toml b/compiler/rustc_codegen_gcc/build_sysroot/Cargo.toml
index cfadf47cc3f86..a84f86a821898 100644
--- a/compiler/rustc_codegen_gcc/build_sysroot/Cargo.toml
+++ b/compiler/rustc_codegen_gcc/build_sysroot/Cargo.toml
@@ -9,6 +9,7 @@ compiler_builtins = "0.1"
alloc = { path = "./sysroot_src/library/alloc" }
std = { path = "./sysroot_src/library/std", features = ["panic_unwind", "backtrace"] }
test = { path = "./sysroot_src/library/test" }
+proc_macro = { path = "./sysroot_src/library/proc_macro" }
[patch.crates-io]
rustc-std-workspace-core = { path = "./sysroot_src/library/rustc-std-workspace-core" }
diff --git a/compiler/rustc_codegen_gcc/build_sysroot/prepare_sysroot_src.sh b/compiler/rustc_codegen_gcc/build_sysroot/prepare_sysroot_src.sh
index 56768bbf1d015..71b3876bac2cf 100755
--- a/compiler/rustc_codegen_gcc/build_sysroot/prepare_sysroot_src.sh
+++ b/compiler/rustc_codegen_gcc/build_sysroot/prepare_sysroot_src.sh
@@ -29,10 +29,10 @@ git config user.name || git config user.name "None"
git commit -m "Initial commit" -q
for file in $(ls ../../patches/ | grep -v patcha); do
-echo "[GIT] apply" $file
-git apply ../../patches/$file
-git add -A
-git commit --no-gpg-sign -m "Patch $file"
+ echo "[GIT] apply" $file
+ git apply ../../patches/$file
+ git add -A
+ git commit --no-gpg-sign -m "Patch $file"
done
popd
diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs
index c27b610f2aba9..0cd7e6047c20a 100644
--- a/compiler/rustc_codegen_gcc/example/mini_core.rs
+++ b/compiler/rustc_codegen_gcc/example/mini_core.rs
@@ -451,6 +451,9 @@ pub unsafe fn drop_in_place(to_drop: *mut T) {
drop_in_place(to_drop);
}
+#[lang = "unpin"]
+pub auto trait Unpin {}
+
#[lang = "deref"]
pub trait Deref {
type Target: ?Sized;
@@ -488,10 +491,23 @@ pub struct Box(Unique, A);
impl, U: ?Sized, A: Allocator> CoerceUnsized> for Box {}
+impl Box {
+ pub fn new(val: T) -> Box {
+ unsafe {
+ let size = intrinsics::size_of::();
+ let ptr = libc::malloc(size);
+ intrinsics::copy(&val as *const T as *const u8, ptr, size);
+ Box(Unique { pointer: NonNull(ptr as *const T), _marker: PhantomData }, Global)
+ }
+ }
+}
+
impl Drop for Box {
fn drop(&mut self) {
- // inner value is dropped by compiler
- libc::free(self.pointer.0 as *mut u8);
+ // inner value is dropped by compiler.
+ unsafe {
+ libc::free(self.0.pointer.0 as *mut u8);
+ }
}
}
diff --git a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs
index cff26077740b0..b93d685970631 100644
--- a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs
+++ b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs
@@ -168,6 +168,9 @@ fn main() {
world as Box;
assert_eq!(intrinsics::bitreverse(0b10101000u8), 0b00010101u8);
+ assert_eq!(intrinsics::bitreverse(0xddccu16), 0x33bbu16);
+ assert_eq!(intrinsics::bitreverse(0xffee_ddccu32), 0x33bb77ffu32);
+ assert_eq!(intrinsics::bitreverse(0x1234_5678_ffee_ddccu64), 0x33bb77ff1e6a2c48u64);
assert_eq!(intrinsics::bswap(0xabu8), 0xabu8);
assert_eq!(intrinsics::bswap(0xddccu16), 0xccddu16);
diff --git a/compiler/rustc_codegen_gcc/example/std_example.rs b/compiler/rustc_codegen_gcc/example/std_example.rs
index 5c171c49fd194..18f2ddcde126b 100644
--- a/compiler/rustc_codegen_gcc/example/std_example.rs
+++ b/compiler/rustc_codegen_gcc/example/std_example.rs
@@ -58,6 +58,7 @@ fn main() {
assert_eq!(0b0000000000000000000000000010000010000000000000000000000000000000_0000000000100000000000000000000000001000000000000100000000000000u128.leading_zeros(), 26);
assert_eq!(0b0000000000000000000000000010000000000000000000000000000000000000_0000000000000000000000000000000000001000000000000000000010000000u128.trailing_zeros(), 7);
+ assert_eq!(0x1234_5678_ffee_ddcc_1234_5678_ffee_ddccu128.reverse_bits(), 0x33bb77ff1e6a2c4833bb77ff1e6a2c48u128);
let _d = 0i128.checked_div(2i128);
let _d = 0u128.checked_div(2u128);
diff --git a/compiler/rustc_codegen_gcc/failing-ui-tests.txt b/compiler/rustc_codegen_gcc/failing-ui-tests.txt
index 8539e27ea6a58..801464daae9a5 100644
--- a/compiler/rustc_codegen_gcc/failing-ui-tests.txt
+++ b/compiler/rustc_codegen_gcc/failing-ui-tests.txt
@@ -54,8 +54,8 @@ tests/ui/issues/issue-40883.rs
tests/ui/issues/issue-43853.rs
tests/ui/issues/issue-47364.rs
tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs
-tests/ui/rfc-2091-track-caller/std-panic-locations.rs
-tests/ui/rfcs/rfc1857-drop-order.rs
+tests/ui/rfcs/rfc-2091-track-caller/std-panic-locations.rs
+tests/ui/rfcs/rfc-1857-stabilize-drop-order/drop-order.rs
tests/ui/simd/issue-17170.rs
tests/ui/simd/issue-39720.rs
tests/ui/simd/issue-89193.rs
@@ -66,3 +66,5 @@ tests/ui/generator/panic-safe.rs
tests/ui/issues/issue-14875.rs
tests/ui/issues/issue-29948.rs
tests/ui/panic-while-printing.rs
+tests/ui/enum-discriminant/get_discr.rs
+tests/ui/panics/nested_panic_caught.rs
diff --git a/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch b/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch
deleted file mode 100644
index ee5ba449fb8e6..0000000000000
--- a/compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch
+++ /dev/null
@@ -1,49 +0,0 @@
-From dd82e95c9de212524e14fc60155de1ae40156dfc Mon Sep 17 00:00:00 2001
-From: bjorn3
-Date: Sun, 24 Nov 2019 15:34:06 +0100
-Subject: [PATCH] [core] Ignore failing tests
-
----
- library/core/tests/iter.rs | 4 ++++
- library/core/tests/num/bignum.rs | 10 ++++++++++
- library/core/tests/num/mod.rs | 5 +++--
- library/core/tests/time.rs | 1 +
- 4 files changed, 18 insertions(+), 2 deletions(-)
-
-diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs
-index 4bc44e9..8e3c7a4 100644
---- a/library/core/tests/array.rs
-+++ b/library/core/tests/array.rs
-@@ -242,6 +242,7 @@ fn iterator_drops() {
- assert_eq!(i.get(), 5);
- }
-
-+/*
- // This test does not work on targets without panic=unwind support.
- // To work around this problem, test is marked is should_panic, so it will
- // be automagically skipped on unsuitable targets, such as
-@@ -283,6 +284,7 @@ fn array_default_impl_avoids_leaks_on_panic() {
- assert_eq!(COUNTER.load(Relaxed), 0);
- panic!("test succeeded")
- }
-+*/
-
- #[test]
- fn empty_array_is_always_default() {
-@@ -304,6 +304,7 @@ fn array_map() {
- assert_eq!(b, [1, 2, 3]);
- }
-
-+/*
- // See note on above test for why `should_panic` is used.
- #[test]
- #[should_panic(expected = "test succeeded")]
-@@ -332,6 +333,7 @@ fn array_map_drop_safety() {
- assert_eq!(DROPPED.load(Ordering::SeqCst), num_to_create);
- panic!("test succeeded")
- }
-+*/
-
- #[test]
- fn cell_allows_array_cycle() {
--- 2.21.0 (Apple Git-122)
diff --git a/compiler/rustc_codegen_gcc/rust-toolchain b/compiler/rustc_codegen_gcc/rust-toolchain
index 933ecd45baadb..ebb04d0069cf5 100644
--- a/compiler/rustc_codegen_gcc/rust-toolchain
+++ b/compiler/rustc_codegen_gcc/rust-toolchain
@@ -1,3 +1,3 @@
[toolchain]
-channel = "nightly-2023-03-02"
+channel = "nightly-2023-06-19"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs
index 250aa79f8d609..4c3b7f5036ccb 100644
--- a/compiler/rustc_codegen_gcc/src/asm.rs
+++ b/compiler/rustc_codegen_gcc/src/asm.rs
@@ -518,7 +518,6 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
OperandValue::Immediate(op.tmp_var.to_rvalue()).store(self, place);
}
}
-
}
}
diff --git a/compiler/rustc_codegen_gcc/src/attributes.rs b/compiler/rustc_codegen_gcc/src/attributes.rs
index db841b1b52408..eb0cce19b85cb 100644
--- a/compiler/rustc_codegen_gcc/src/attributes.rs
+++ b/compiler/rustc_codegen_gcc/src/attributes.rs
@@ -2,9 +2,13 @@
use gccjit::FnAttribute;
use gccjit::Function;
use rustc_attr::InstructionSetAttr;
+#[cfg(feature="master")]
+use rustc_attr::InlineAttr;
use rustc_codegen_ssa::target_features::tied_target_features;
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::ty;
+#[cfg(feature="master")]
+use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_session::Session;
use rustc_span::symbol::sym;
use smallvec::{smallvec, SmallVec};
@@ -67,6 +71,24 @@ fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> {
}
}
+/// Get GCC attribute for the provided inline heuristic.
+#[cfg(feature="master")]
+#[inline]
+fn inline_attr<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, inline: InlineAttr) -> Option> {
+ match inline {
+ InlineAttr::Hint => Some(FnAttribute::Inline),
+ InlineAttr::Always => Some(FnAttribute::AlwaysInline),
+ InlineAttr::Never => {
+ if cx.sess().target.arch != "amdgpu" {
+ Some(FnAttribute::NoInline)
+ } else {
+ None
+ }
+ }
+ InlineAttr::None => None,
+ }
+}
+
/// Composite function which sets GCC attributes for function depending on its AST (`#[attribute]`)
/// attributes.
pub fn from_fn_attrs<'gcc, 'tcx>(
@@ -77,6 +99,23 @@ pub fn from_fn_attrs<'gcc, 'tcx>(
) {
let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(instance.def_id());
+ #[cfg(feature="master")]
+ {
+ let inline =
+ if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
+ InlineAttr::Never
+ }
+ else if codegen_fn_attrs.inline == InlineAttr::None && instance.def.requires_inline(cx.tcx) {
+ InlineAttr::Hint
+ }
+ else {
+ codegen_fn_attrs.inline
+ };
+ if let Some(attr) = inline_attr(cx, inline) {
+ func.add_attribute(attr);
+ }
+ }
+
let function_features =
codegen_fn_attrs.target_features.iter().map(|features| features.as_str()).collect::>();
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index f9ea0f004564b..43d0aafbd50bf 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -181,6 +181,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
})
.collect();
+ debug_assert_eq!(casted_args.len(), args.len());
+
Cow::Owned(casted_args)
}
@@ -207,7 +209,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
let func_name = format!("{:?}", func_ptr);
- let casted_args: Vec<_> = param_types
+ let mut casted_args: Vec<_> = param_types
.into_iter()
.zip(args.iter())
.enumerate()
@@ -237,6 +239,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
})
.collect();
+ // NOTE: to take into account variadic functions.
+ for i in casted_args.len()..args.len() {
+ casted_args.push(args[i]);
+ }
+
Cow::Owned(casted_args)
}
@@ -280,8 +287,17 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
}
}
- fn function_ptr_call(&mut self, func_ptr: RValue<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> {
- let gcc_func = func_ptr.get_type().dyncast_function_ptr_type().expect("function ptr");
+ fn function_ptr_call(&mut self, typ: Type<'gcc>, mut func_ptr: RValue<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> {
+ let gcc_func =
+ match func_ptr.get_type().dyncast_function_ptr_type() {
+ Some(func) => func,
+ None => {
+ // NOTE: due to opaque pointers now being used, we need to cast here.
+ let new_func_type = typ.dyncast_function_ptr_type().expect("function ptr");
+ func_ptr = self.context.new_cast(None, func_ptr, typ);
+ new_func_type
+ },
+ };
let func_name = format!("{:?}", func_ptr);
let previous_arg_count = args.len();
let orig_args = args;
@@ -424,16 +440,17 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
self.llbb().end_with_void_return(None)
}
- fn ret(&mut self, value: RValue<'gcc>) {
- let value =
- if self.structs_as_pointer.borrow().contains(&value) {
- // NOTE: hack to workaround a limitation of the rustc API: see comment on
- // CodegenCx.structs_as_pointer
- value.dereference(None).to_rvalue()
- }
- else {
- value
- };
+ fn ret(&mut self, mut value: RValue<'gcc>) {
+ if self.structs_as_pointer.borrow().contains(&value) {
+ // NOTE: hack to workaround a limitation of the rustc API: see comment on
+ // CodegenCx.structs_as_pointer
+ value = value.dereference(None).to_rvalue();
+ }
+ let expected_return_type = self.current_func().get_return_type();
+ if !expected_return_type.is_compatible_with(value.get_type()) {
+ // NOTE: due to opaque pointers now being used, we need to cast here.
+ value = self.context.new_cast(None, value, expected_return_type);
+ }
self.llbb().end_with_return(None, value);
}
@@ -719,17 +736,25 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
unimplemented!();
}
- fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, _align: Align) -> RValue<'gcc> {
+ fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
let block = self.llbb();
let function = block.get_function();
// NOTE: instead of returning the dereference here, we have to assign it to a variable in
// the current basic block. Otherwise, it could be used in another basic block, causing a
// dereference after a drop, for instance.
- // TODO(antoyo): handle align of the load instruction.
- let ptr = self.context.new_cast(None, ptr, pointee_ty.make_pointer());
+ // FIXME(antoyo): this check that we don't call get_aligned() a second time on a type.
+ // Ideally, we shouldn't need to do this check.
+ let aligned_type =
+ if pointee_ty == self.cx.u128_type || pointee_ty == self.cx.i128_type {
+ pointee_ty
+ }
+ else {
+ pointee_ty.get_aligned(align.bytes())
+ };
+ let ptr = self.context.new_cast(None, ptr, aligned_type.make_pointer());
let deref = ptr.dereference(None).to_rvalue();
unsafe { RETURN_VALUE_COUNT += 1 };
- let loaded_value = function.new_local(None, pointee_ty, &format!("loadedValue{}", unsafe { RETURN_VALUE_COUNT }));
+ let loaded_value = function.new_local(None, aligned_type, &format!("loadedValue{}", unsafe { RETURN_VALUE_COUNT }));
block.add_assignment(None, loaded_value, deref);
loaded_value.to_rvalue()
}
@@ -909,7 +934,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
self.context.new_bitcast(None, result, ptr_type)
}
- fn inbounds_gep(&mut self, _typ: Type<'gcc>, ptr: RValue<'gcc>, indices: &[RValue<'gcc>]) -> RValue<'gcc> {
+ fn inbounds_gep(&mut self, typ: Type<'gcc>, ptr: RValue<'gcc>, indices: &[RValue<'gcc>]) -> RValue<'gcc> {
+ // NOTE: due to opaque pointers now being used, we need to cast here.
+ let ptr = self.context.new_cast(None, ptr, typ.make_pointer());
// NOTE: array indexing is always considered in bounds in GCC (TODO(antoyo): to be verified).
let mut indices = indices.into_iter();
let index = indices.next().expect("first index in inbounds_gep");
@@ -938,6 +965,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
element.get_address(None)
}
else if let Some(struct_type) = value_type.is_struct() {
+ // NOTE: due to opaque pointers now being used, we need to bitcast here.
+ let ptr = self.bitcast_if_needed(ptr, value_type.make_pointer());
ptr.dereference_field(None, struct_type.get_field(idx as i32)).get_address(None)
}
else {
@@ -1356,7 +1385,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
fn call(
&mut self,
- _typ: Type<'gcc>,
+ typ: Type<'gcc>,
_fn_attrs: Option<&CodegenFnAttrs>,
fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
func: RValue<'gcc>,
@@ -1370,7 +1399,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
}
else {
// If it's a not function that was defined, it's a function pointer.
- self.function_ptr_call(func, args, funclet)
+ self.function_ptr_call(typ, func, args, funclet)
};
if let Some(_fn_abi) = fn_abi {
// TODO(bjorn3): Apply function attributes
@@ -1843,7 +1872,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
#[cfg(feature="master")]
let (cond, element_type) = {
- let then_val_vector_type = then_val.get_type().dyncast_vector().expect("vector type");
+ // TODO(antoyo): dyncast_vector should not require a call to unqualified.
+ let then_val_vector_type = then_val.get_type().unqualified().dyncast_vector().expect("vector type");
let then_val_element_type = then_val_vector_type.get_element_type();
let then_val_element_size = then_val_element_type.get_size();
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs
index 33e3b0baa9236..d8a1fd315c0a5 100644
--- a/compiler/rustc_codegen_gcc/src/consts.rs
+++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -1,5 +1,5 @@
#[cfg(feature = "master")]
-use gccjit::FnAttribute;
+use gccjit::{FnAttribute, VarAttribute, Visibility};
use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue};
use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods, DerivedTypeMethods, StaticMethods};
use rustc_middle::span_bug;
@@ -234,7 +234,8 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
);
if !self.tcx.is_reachable_non_generic(def_id) {
- // TODO(antoyo): set visibility.
+ #[cfg(feature = "master")]
+ global.add_attribute(VarAttribute::Visibility(Visibility::Hidden));
}
global
diff --git a/compiler/rustc_codegen_gcc/src/declare.rs b/compiler/rustc_codegen_gcc/src/declare.rs
index 4748e7e4be2a3..493626c3cf5de 100644
--- a/compiler/rustc_codegen_gcc/src/declare.rs
+++ b/compiler/rustc_codegen_gcc/src/declare.rs
@@ -132,7 +132,7 @@ fn declare_raw_fn<'gcc>(cx: &CodegenCx<'gcc, '_>, name: &str, _callconv: () /*ll
pub fn mangle_name(name: &str) -> String {
name.replace(|char: char| {
if !char.is_alphanumeric() && char != '_' {
- debug_assert!("$.".contains(char), "Unsupported char in function name: {}", char);
+ debug_assert!("$.*".contains(char), "Unsupported char in function name {}: {}", name, char);
true
}
else {
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs b/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs
index 8a4559355ea67..438eab78943af 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs
@@ -2967,10 +2967,6 @@ match name {
"llvm.nvvm.clz.ll" => "__nvvm_clz_ll",
"llvm.nvvm.cos.approx.f" => "__nvvm_cos_approx_f",
"llvm.nvvm.cos.approx.ftz.f" => "__nvvm_cos_approx_ftz_f",
- "llvm.nvvm.cp.async.ca.shared.global.16" => "__nvvm_cp_async_ca_shared_global_16",
- "llvm.nvvm.cp.async.ca.shared.global.4" => "__nvvm_cp_async_ca_shared_global_4",
- "llvm.nvvm.cp.async.ca.shared.global.8" => "__nvvm_cp_async_ca_shared_global_8",
- "llvm.nvvm.cp.async.cg.shared.global.16" => "__nvvm_cp_async_cg_shared_global_16",
"llvm.nvvm.cp.async.commit.group" => "__nvvm_cp_async_commit_group",
"llvm.nvvm.cp.async.mbarrier.arrive" => "__nvvm_cp_async_mbarrier_arrive",
"llvm.nvvm.cp.async.mbarrier.arrive.noinc" => "__nvvm_cp_async_mbarrier_arrive_noinc",
@@ -3086,18 +3082,8 @@ match name {
"llvm.nvvm.fma.rn.f16" => "__nvvm_fma_rn_f16",
"llvm.nvvm.fma.rn.f16x2" => "__nvvm_fma_rn_f16x2",
"llvm.nvvm.fma.rn.ftz.f" => "__nvvm_fma_rn_ftz_f",
- "llvm.nvvm.fma.rn.ftz.f16" => "__nvvm_fma_rn_ftz_f16",
- "llvm.nvvm.fma.rn.ftz.f16x2" => "__nvvm_fma_rn_ftz_f16x2",
- "llvm.nvvm.fma.rn.ftz.relu.f16" => "__nvvm_fma_rn_ftz_relu_f16",
- "llvm.nvvm.fma.rn.ftz.relu.f16x2" => "__nvvm_fma_rn_ftz_relu_f16x2",
- "llvm.nvvm.fma.rn.ftz.sat.f16" => "__nvvm_fma_rn_ftz_sat_f16",
- "llvm.nvvm.fma.rn.ftz.sat.f16x2" => "__nvvm_fma_rn_ftz_sat_f16x2",
"llvm.nvvm.fma.rn.relu.bf16" => "__nvvm_fma_rn_relu_bf16",
"llvm.nvvm.fma.rn.relu.bf16x2" => "__nvvm_fma_rn_relu_bf16x2",
- "llvm.nvvm.fma.rn.relu.f16" => "__nvvm_fma_rn_relu_f16",
- "llvm.nvvm.fma.rn.relu.f16x2" => "__nvvm_fma_rn_relu_f16x2",
- "llvm.nvvm.fma.rn.sat.f16" => "__nvvm_fma_rn_sat_f16",
- "llvm.nvvm.fma.rn.sat.f16x2" => "__nvvm_fma_rn_sat_f16x2",
"llvm.nvvm.fma.rp.d" => "__nvvm_fma_rp_d",
"llvm.nvvm.fma.rp.f" => "__nvvm_fma_rp_f",
"llvm.nvvm.fma.rp.ftz.f" => "__nvvm_fma_rp_ftz_f",
@@ -3111,32 +3097,18 @@ match name {
"llvm.nvvm.fmax.f16" => "__nvvm_fmax_f16",
"llvm.nvvm.fmax.f16x2" => "__nvvm_fmax_f16x2",
"llvm.nvvm.fmax.ftz.f" => "__nvvm_fmax_ftz_f",
- "llvm.nvvm.fmax.ftz.f16" => "__nvvm_fmax_ftz_f16",
- "llvm.nvvm.fmax.ftz.f16x2" => "__nvvm_fmax_ftz_f16x2",
"llvm.nvvm.fmax.ftz.nan.f" => "__nvvm_fmax_ftz_nan_f",
- "llvm.nvvm.fmax.ftz.nan.f16" => "__nvvm_fmax_ftz_nan_f16",
- "llvm.nvvm.fmax.ftz.nan.f16x2" => "__nvvm_fmax_ftz_nan_f16x2",
"llvm.nvvm.fmax.ftz.nan.xorsign.abs.f" => "__nvvm_fmax_ftz_nan_xorsign_abs_f",
- "llvm.nvvm.fmax.ftz.nan.xorsign.abs.f16" => "__nvvm_fmax_ftz_nan_xorsign_abs_f16",
- "llvm.nvvm.fmax.ftz.nan.xorsign.abs.f16x2" => "__nvvm_fmax_ftz_nan_xorsign_abs_f16x2",
"llvm.nvvm.fmax.ftz.xorsign.abs.f" => "__nvvm_fmax_ftz_xorsign_abs_f",
- "llvm.nvvm.fmax.ftz.xorsign.abs.f16" => "__nvvm_fmax_ftz_xorsign_abs_f16",
- "llvm.nvvm.fmax.ftz.xorsign.abs.f16x2" => "__nvvm_fmax_ftz_xorsign_abs_f16x2",
"llvm.nvvm.fmax.nan.bf16" => "__nvvm_fmax_nan_bf16",
"llvm.nvvm.fmax.nan.bf16x2" => "__nvvm_fmax_nan_bf16x2",
"llvm.nvvm.fmax.nan.f" => "__nvvm_fmax_nan_f",
- "llvm.nvvm.fmax.nan.f16" => "__nvvm_fmax_nan_f16",
- "llvm.nvvm.fmax.nan.f16x2" => "__nvvm_fmax_nan_f16x2",
"llvm.nvvm.fmax.nan.xorsign.abs.bf16" => "__nvvm_fmax_nan_xorsign_abs_bf16",
"llvm.nvvm.fmax.nan.xorsign.abs.bf16x2" => "__nvvm_fmax_nan_xorsign_abs_bf16x2",
"llvm.nvvm.fmax.nan.xorsign.abs.f" => "__nvvm_fmax_nan_xorsign_abs_f",
- "llvm.nvvm.fmax.nan.xorsign.abs.f16" => "__nvvm_fmax_nan_xorsign_abs_f16",
- "llvm.nvvm.fmax.nan.xorsign.abs.f16x2" => "__nvvm_fmax_nan_xorsign_abs_f16x2",
"llvm.nvvm.fmax.xorsign.abs.bf16" => "__nvvm_fmax_xorsign_abs_bf16",
"llvm.nvvm.fmax.xorsign.abs.bf16x2" => "__nvvm_fmax_xorsign_abs_bf16x2",
"llvm.nvvm.fmax.xorsign.abs.f" => "__nvvm_fmax_xorsign_abs_f",
- "llvm.nvvm.fmax.xorsign.abs.f16" => "__nvvm_fmax_xorsign_abs_f16",
- "llvm.nvvm.fmax.xorsign.abs.f16x2" => "__nvvm_fmax_xorsign_abs_f16x2",
"llvm.nvvm.fmin.bf16" => "__nvvm_fmin_bf16",
"llvm.nvvm.fmin.bf16x2" => "__nvvm_fmin_bf16x2",
"llvm.nvvm.fmin.d" => "__nvvm_fmin_d",
@@ -3144,32 +3116,18 @@ match name {
"llvm.nvvm.fmin.f16" => "__nvvm_fmin_f16",
"llvm.nvvm.fmin.f16x2" => "__nvvm_fmin_f16x2",
"llvm.nvvm.fmin.ftz.f" => "__nvvm_fmin_ftz_f",
- "llvm.nvvm.fmin.ftz.f16" => "__nvvm_fmin_ftz_f16",
- "llvm.nvvm.fmin.ftz.f16x2" => "__nvvm_fmin_ftz_f16x2",
"llvm.nvvm.fmin.ftz.nan.f" => "__nvvm_fmin_ftz_nan_f",
- "llvm.nvvm.fmin.ftz.nan.f16" => "__nvvm_fmin_ftz_nan_f16",
- "llvm.nvvm.fmin.ftz.nan.f16x2" => "__nvvm_fmin_ftz_nan_f16x2",
"llvm.nvvm.fmin.ftz.nan.xorsign.abs.f" => "__nvvm_fmin_ftz_nan_xorsign_abs_f",
- "llvm.nvvm.fmin.ftz.nan.xorsign.abs.f16" => "__nvvm_fmin_ftz_nan_xorsign_abs_f16",
- "llvm.nvvm.fmin.ftz.nan.xorsign.abs.f16x2" => "__nvvm_fmin_ftz_nan_xorsign_abs_f16x2",
"llvm.nvvm.fmin.ftz.xorsign.abs.f" => "__nvvm_fmin_ftz_xorsign_abs_f",
- "llvm.nvvm.fmin.ftz.xorsign.abs.f16" => "__nvvm_fmin_ftz_xorsign_abs_f16",
- "llvm.nvvm.fmin.ftz.xorsign.abs.f16x2" => "__nvvm_fmin_ftz_xorsign_abs_f16x2",
"llvm.nvvm.fmin.nan.bf16" => "__nvvm_fmin_nan_bf16",
"llvm.nvvm.fmin.nan.bf16x2" => "__nvvm_fmin_nan_bf16x2",
"llvm.nvvm.fmin.nan.f" => "__nvvm_fmin_nan_f",
- "llvm.nvvm.fmin.nan.f16" => "__nvvm_fmin_nan_f16",
- "llvm.nvvm.fmin.nan.f16x2" => "__nvvm_fmin_nan_f16x2",
"llvm.nvvm.fmin.nan.xorsign.abs.bf16" => "__nvvm_fmin_nan_xorsign_abs_bf16",
"llvm.nvvm.fmin.nan.xorsign.abs.bf16x2" => "__nvvm_fmin_nan_xorsign_abs_bf16x2",
"llvm.nvvm.fmin.nan.xorsign.abs.f" => "__nvvm_fmin_nan_xorsign_abs_f",
- "llvm.nvvm.fmin.nan.xorsign.abs.f16" => "__nvvm_fmin_nan_xorsign_abs_f16",
- "llvm.nvvm.fmin.nan.xorsign.abs.f16x2" => "__nvvm_fmin_nan_xorsign_abs_f16x2",
"llvm.nvvm.fmin.xorsign.abs.bf16" => "__nvvm_fmin_xorsign_abs_bf16",
"llvm.nvvm.fmin.xorsign.abs.bf16x2" => "__nvvm_fmin_xorsign_abs_bf16x2",
"llvm.nvvm.fmin.xorsign.abs.f" => "__nvvm_fmin_xorsign_abs_f",
- "llvm.nvvm.fmin.xorsign.abs.f16" => "__nvvm_fmin_xorsign_abs_f16",
- "llvm.nvvm.fmin.xorsign.abs.f16x2" => "__nvvm_fmin_xorsign_abs_f16x2",
"llvm.nvvm.fns" => "__nvvm_fns",
"llvm.nvvm.h2f" => "__nvvm_h2f",
"llvm.nvvm.i2d.rm" => "__nvvm_i2d_rm",
@@ -7895,6 +7853,10 @@ match name {
"llvm.x86.subborrow.u64" => "__builtin_ia32_subborrow_u64",
"llvm.x86.tbm.bextri.u32" => "__builtin_ia32_bextri_u32",
"llvm.x86.tbm.bextri.u64" => "__builtin_ia32_bextri_u64",
+ "llvm.x86.tcmmimfp16ps" => "__builtin_ia32_tcmmimfp16ps",
+ "llvm.x86.tcmmimfp16ps.internal" => "__builtin_ia32_tcmmimfp16ps_internal",
+ "llvm.x86.tcmmrlfp16ps" => "__builtin_ia32_tcmmrlfp16ps",
+ "llvm.x86.tcmmrlfp16ps.internal" => "__builtin_ia32_tcmmrlfp16ps_internal",
"llvm.x86.tdpbf16ps" => "__builtin_ia32_tdpbf16ps",
"llvm.x86.tdpbf16ps.internal" => "__builtin_ia32_tdpbf16ps_internal",
"llvm.x86.tdpbssd" => "__builtin_ia32_tdpbssd",
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs
index 0edec566be309..f28348380d7bc 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs
@@ -313,6 +313,13 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc
let new_args = args.to_vec();
args = vec![new_args[1], new_args[0], new_args[2], new_args[3], new_args[4]].into();
},
+ "__builtin_ia32_vpshrdv_v8di" | "__builtin_ia32_vpshrdv_v4di" | "__builtin_ia32_vpshrdv_v2di" |
+ "__builtin_ia32_vpshrdv_v16si" | "__builtin_ia32_vpshrdv_v8si" | "__builtin_ia32_vpshrdv_v4si" |
+ "__builtin_ia32_vpshrdv_v32hi" | "__builtin_ia32_vpshrdv_v16hi" | "__builtin_ia32_vpshrdv_v8hi" => {
+ // The first two arguments are reversed, compared to LLVM.
+ let new_args = args.to_vec();
+ args = vec![new_args[1], new_args[0], new_args[2]].into();
+ },
_ => (),
}
}
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index 6017687474726..a31fee3991884 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -551,141 +551,52 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
let context = &self.cx.context;
let result =
match width {
- 8 => {
- // First step.
- let left = self.and(value, context.new_rvalue_from_int(typ, 0xF0));
- let left = self.lshr(left, context.new_rvalue_from_int(typ, 4));
- let right = self.and(value, context.new_rvalue_from_int(typ, 0x0F));
- let right = self.shl(right, context.new_rvalue_from_int(typ, 4));
- let step1 = self.or(left, right);
-
- // Second step.
- let left = self.and(step1, context.new_rvalue_from_int(typ, 0xCC));
- let left = self.lshr(left, context.new_rvalue_from_int(typ, 2));
- let right = self.and(step1, context.new_rvalue_from_int(typ, 0x33));
- let right = self.shl(right, context.new_rvalue_from_int(typ, 2));
- let step2 = self.or(left, right);
-
- // Third step.
- let left = self.and(step2, context.new_rvalue_from_int(typ, 0xAA));
- let left = self.lshr(left, context.new_rvalue_from_int(typ, 1));
- let right = self.and(step2, context.new_rvalue_from_int(typ, 0x55));
- let right = self.shl(right, context.new_rvalue_from_int(typ, 1));
- let step3 = self.or(left, right);
-
- step3
- },
- 16 => {
- // First step.
- let left = self.and(value, context.new_rvalue_from_int(typ, 0x5555));
- let left = self.shl(left, context.new_rvalue_from_int(typ, 1));
- let right = self.and(value, context.new_rvalue_from_int(typ, 0xAAAA));
- let right = self.lshr(right, context.new_rvalue_from_int(typ, 1));
- let step1 = self.or(left, right);
-
- // Second step.
- let left = self.and(step1, context.new_rvalue_from_int(typ, 0x3333));
- let left = self.shl(left, context.new_rvalue_from_int(typ, 2));
- let right = self.and(step1, context.new_rvalue_from_int(typ, 0xCCCC));
- let right = self.lshr(right, context.new_rvalue_from_int(typ, 2));
- let step2 = self.or(left, right);
-
- // Third step.
- let left = self.and(step2, context.new_rvalue_from_int(typ, 0x0F0F));
- let left = self.shl(left, context.new_rvalue_from_int(typ, 4));
- let right = self.and(step2, context.new_rvalue_from_int(typ, 0xF0F0));
- let right = self.lshr(right, context.new_rvalue_from_int(typ, 4));
- let step3 = self.or(left, right);
-
- // Fourth step.
- let left = self.and(step3, context.new_rvalue_from_int(typ, 0x00FF));
- let left = self.shl(left, context.new_rvalue_from_int(typ, 8));
- let right = self.and(step3, context.new_rvalue_from_int(typ, 0xFF00));
- let right = self.lshr(right, context.new_rvalue_from_int(typ, 8));
- let step4 = self.or(left, right);
+ 8 | 16 | 32 | 64 => {
+ let mask = ((1u128 << width) - 1) as u64;
+ let (m0, m1, m2) = if width > 16 {
+ (
+ context.new_rvalue_from_long(typ, (0x5555555555555555u64 & mask) as i64),
+ context.new_rvalue_from_long(typ, (0x3333333333333333u64 & mask) as i64),
+ context.new_rvalue_from_long(typ, (0x0f0f0f0f0f0f0f0fu64 & mask) as i64),
+ )
+ } else {
+ (
+ context.new_rvalue_from_int(typ, (0x5555u64 & mask) as i32),
+ context.new_rvalue_from_int(typ, (0x3333u64 & mask) as i32),
+ context.new_rvalue_from_int(typ, (0x0f0fu64 & mask) as i32),
+ )
+ };
+ let one = context.new_rvalue_from_int(typ, 1);
+ let two = context.new_rvalue_from_int(typ, 2);
+ let four = context.new_rvalue_from_int(typ, 4);
- step4
- },
- 32 => {
- // TODO(antoyo): Refactor with other implementations.
// First step.
- let left = self.and(value, context.new_rvalue_from_long(typ, 0x55555555));
- let left = self.shl(left, context.new_rvalue_from_long(typ, 1));
- let right = self.and(value, context.new_rvalue_from_long(typ, 0xAAAAAAAA));
- let right = self.lshr(right, context.new_rvalue_from_long(typ, 1));
+ let left = self.lshr(value, one);
+ let left = self.and(left, m0);
+ let right = self.and(value, m0);
+ let right = self.shl(right, one);
let step1 = self.or(left, right);
// Second step.
- let left = self.and(step1, context.new_rvalue_from_long(typ, 0x33333333));
- let left = self.shl(left, context.new_rvalue_from_long(typ, 2));
- let right = self.and(step1, context.new_rvalue_from_long(typ, 0xCCCCCCCC));
- let right = self.lshr(right, context.new_rvalue_from_long(typ, 2));
+ let left = self.lshr(step1, two);
+ let left = self.and(left, m1);
+ let right = self.and(step1, m1);
+ let right = self.shl(right, two);
let step2 = self.or(left, right);
// Third step.
- let left = self.and(step2, context.new_rvalue_from_long(typ, 0x0F0F0F0F));
- let left = self.shl(left, context.new_rvalue_from_long(typ, 4));
- let right = self.and(step2, context.new_rvalue_from_long(typ, 0xF0F0F0F0));
- let right = self.lshr(right, context.new_rvalue_from_long(typ, 4));
+ let left = self.lshr(step2, four);
+ let left = self.and(left, m2);
+ let right = self.and(step2, m2);
+ let right = self.shl(right, four);
let step3 = self.or(left, right);
// Fourth step.
- let left = self.and(step3, context.new_rvalue_from_long(typ, 0x00FF00FF));
- let left = self.shl(left, context.new_rvalue_from_long(typ, 8));
- let right = self.and(step3, context.new_rvalue_from_long(typ, 0xFF00FF00));
- let right = self.lshr(right, context.new_rvalue_from_long(typ, 8));
- let step4 = self.or(left, right);
-
- // Fifth step.
- let left = self.and(step4, context.new_rvalue_from_long(typ, 0x0000FFFF));
- let left = self.shl(left, context.new_rvalue_from_long(typ, 16));
- let right = self.and(step4, context.new_rvalue_from_long(typ, 0xFFFF0000));
- let right = self.lshr(right, context.new_rvalue_from_long(typ, 16));
- let step5 = self.or(left, right);
-
- step5
- },
- 64 => {
- // First step.
- let left = self.shl(value, context.new_rvalue_from_long(typ, 32));
- let right = self.lshr(value, context.new_rvalue_from_long(typ, 32));
- let step1 = self.or(left, right);
-
- // Second step.
- let left = self.and(step1, context.new_rvalue_from_long(typ, 0x0001FFFF0001FFFF));
- let left = self.shl(left, context.new_rvalue_from_long(typ, 15));
- let right = self.and(step1, context.new_rvalue_from_long(typ, 0xFFFE0000FFFE0000u64 as i64)); // TODO(antoyo): transmute the number instead?
- let right = self.lshr(right, context.new_rvalue_from_long(typ, 17));
- let step2 = self.or(left, right);
-
- // Third step.
- let left = self.lshr(step2, context.new_rvalue_from_long(typ, 10));
- let left = self.xor(step2, left);
- let temp = self.and(left, context.new_rvalue_from_long(typ, 0x003F801F003F801F));
-
- let left = self.shl(temp, context.new_rvalue_from_long(typ, 10));
- let left = self.or(temp, left);
- let step3 = self.xor(left, step2);
-
- // Fourth step.
- let left = self.lshr(step3, context.new_rvalue_from_long(typ, 4));
- let left = self.xor(step3, left);
- let temp = self.and(left, context.new_rvalue_from_long(typ, 0x0E0384210E038421));
-
- let left = self.shl(temp, context.new_rvalue_from_long(typ, 4));
- let left = self.or(temp, left);
- let step4 = self.xor(left, step3);
-
- // Fifth step.
- let left = self.lshr(step4, context.new_rvalue_from_long(typ, 2));
- let left = self.xor(step4, left);
- let temp = self.and(left, context.new_rvalue_from_long(typ, 0x2248884222488842));
-
- let left = self.shl(temp, context.new_rvalue_from_long(typ, 2));
- let left = self.or(temp, left);
- let step5 = self.xor(left, step4);
-
- step5
+ if width == 8 {
+ step3
+ } else {
+ self.gcc_bswap(step3, width)
+ }
},
128 => {
// TODO(antoyo): find a more efficient implementation?
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
index b59c3a64f5728..9115cf971196e 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
@@ -165,10 +165,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
InvalidMonomorphizationReturnIntegerType { span, name, ret_ty, out_ty }
);
+ let arg1 = args[0].immediate();
+ // NOTE: we get different vector types for the same vector type and libgccjit doesn't
+ // compare them as equal, so bitcast.
+ // FIXME(antoyo): allow comparing vector types as equal in libgccjit.
+ let arg2 = bx.context.new_bitcast(None, args[1].immediate(), arg1.get_type());
return Ok(compare_simd_types(
bx,
- args[0].immediate(),
- args[1].immediate(),
+ arg1,
+ arg2,
in_elem,
llret_ty,
cmp_op,
@@ -341,7 +346,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
// endian and MSB-first for big endian.
let vector = args[0].immediate();
- let vector_type = vector.get_type().dyncast_vector().expect("vector type");
+ // TODO(antoyo): dyncast_vector should not require a call to unqualified.
+ let vector_type = vector.get_type().unqualified().dyncast_vector().expect("vector type");
let elem_type = vector_type.get_element_type();
let expected_int_bits = in_len.max(8);
@@ -848,7 +854,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
(true, true) => {
// Algorithm from: https://codereview.stackexchange.com/questions/115869/saturated-signed-addition
// TODO(antoyo): improve using conditional operators if possible.
- let arg_type = lhs.get_type();
+ // TODO(antoyo): dyncast_vector should not require a call to unqualified.
+ let arg_type = lhs.get_type().unqualified();
// TODO(antoyo): convert lhs and rhs to unsigned.
let sum = lhs + rhs;
let vector_type = arg_type.dyncast_vector().expect("vector type");
@@ -878,7 +885,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
res & cmp
},
(true, false) => {
- let arg_type = lhs.get_type();
+ // TODO(antoyo): dyncast_vector should not require a call to unqualified.
+ let arg_type = lhs.get_type().unqualified();
// TODO(antoyo): this uses the same algorithm from saturating add, but add the
// negative of the right operand. Find a proper subtraction algorithm.
let rhs = bx.context.new_unary_op(None, UnaryOp::Minus, arg_type, rhs);
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index ea013c4428cce..2a6b642782dfd 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -111,6 +111,8 @@ impl CodegenBackend for GccCodegenBackend {
}
fn init(&self, sess: &Session) {
+ #[cfg(feature="master")]
+ gccjit::set_global_personality_function_name(b"rust_eh_personality\0");
if sess.lto() != Lto::No {
sess.emit_warning(LTONotSupported {});
}
diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs
index 30a3fe67b8543..74f016cf90ae5 100644
--- a/compiler/rustc_codegen_gcc/src/type_of.rs
+++ b/compiler/rustc_codegen_gcc/src/type_of.rs
@@ -383,8 +383,8 @@ impl<'gcc, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
unimplemented!();
}
- fn fn_decl_backend_type(&self, _fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Type<'gcc> {
- // FIXME(antoyo): return correct type.
- self.type_void()
+ fn fn_decl_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Type<'gcc> {
+ let (return_type, param_types, variadic, _) = fn_abi.gcc_type(self);
+ self.context.new_function_pointer_type(None, return_type, ¶m_types, variadic)
}
}
diff --git a/compiler/rustc_codegen_gcc/test.sh b/compiler/rustc_codegen_gcc/test.sh
index 6139892aefca7..592997b8ab9da 100755
--- a/compiler/rustc_codegen_gcc/test.sh
+++ b/compiler/rustc_codegen_gcc/test.sh
@@ -214,12 +214,14 @@ function setup_rustc() {
rm config.toml || true
cat > config.toml < "{}",\n'.format(entry[0], entry[1]))
elif "_round_mask" in entry[1]:
out.write(' // [INVALID CONVERSION]: "{}" => "{}",\n'.format(entry[0], entry[1]))
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 1a8618e0c5577..4b88ab8a97a85 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -1031,7 +1031,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>(
build_field_di_node(
cx,
closure_or_generator_di_node,
- capture_name,
+ capture_name.as_str(),
cx.size_and_align_of(up_var_ty),
layout.fields.offset(index),
DIFlags::FlagZero,
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
index ecb0912d32881..b2765ffc93464 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
@@ -676,8 +676,7 @@ fn build_union_fields_for_direct_tag_generator<'ll, 'tcx>(
_ => unreachable!(),
};
- let (generator_layout, state_specific_upvar_names) =
- cx.tcx.generator_layout_and_saved_local_names(generator_def_id);
+ let generator_layout = cx.tcx.optimized_mir(generator_def_id).generator_layout().unwrap();
let common_upvar_names = cx.tcx.closure_saved_names_of_captured_variables(generator_def_id);
let variant_range = generator_substs.variant_range(generator_def_id, cx.tcx);
@@ -714,7 +713,6 @@ fn build_union_fields_for_direct_tag_generator<'ll, 'tcx>(
generator_type_and_layout,
generator_type_di_node,
generator_layout,
- &state_specific_upvar_names,
&common_upvar_names,
);
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
index 9e0e847a15565..8746ce0c5b137 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs
@@ -6,7 +6,7 @@ use rustc_hir::def::CtorKind;
use rustc_index::IndexSlice;
use rustc_middle::{
bug,
- mir::{GeneratorLayout, GeneratorSavedLocal},
+ mir::GeneratorLayout,
ty::{
self,
layout::{IntegerExt, LayoutOf, PrimitiveExt, TyAndLayout},
@@ -323,8 +323,7 @@ pub fn build_generator_variant_struct_type_di_node<'ll, 'tcx>(
generator_type_and_layout: TyAndLayout<'tcx>,
generator_type_di_node: &'ll DIType,
generator_layout: &GeneratorLayout<'tcx>,
- state_specific_upvar_names: &IndexSlice>,
- common_upvar_names: &[String],
+ common_upvar_names: &IndexSlice,
) -> &'ll DIType {
let variant_name = GeneratorSubsts::variant_name(variant_index);
let unique_type_id = UniqueTypeId::for_enum_variant_struct_type(
@@ -357,7 +356,7 @@ pub fn build_generator_variant_struct_type_di_node<'ll, 'tcx>(
.map(|field_index| {
let generator_saved_local = generator_layout.variant_fields[variant_index]
[FieldIdx::from_usize(field_index)];
- let field_name_maybe = state_specific_upvar_names[generator_saved_local];
+ let field_name_maybe = generator_layout.field_names[generator_saved_local];
let field_name = field_name_maybe
.as_ref()
.map(|s| Cow::from(s.as_str()))
@@ -380,12 +379,13 @@ pub fn build_generator_variant_struct_type_di_node<'ll, 'tcx>(
// Fields that are common to all states
let common_fields: SmallVec<_> = generator_substs
.prefix_tys()
+ .zip(common_upvar_names)
.enumerate()
- .map(|(index, upvar_ty)| {
+ .map(|(index, (upvar_ty, upvar_name))| {
build_field_di_node(
cx,
variant_struct_type_di_node,
- &common_upvar_names[index],
+ upvar_name.as_str(),
cx.size_and_align_of(upvar_ty),
generator_type_and_layout.fields.offset(index),
DIFlags::FlagZero,
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
index 666b9762f5a76..4d1cd64865f5e 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
@@ -155,8 +155,8 @@ pub(super) fn build_generator_di_node<'ll, 'tcx>(
DIFlags::FlagZero,
),
|cx, generator_type_di_node| {
- let (generator_layout, state_specific_upvar_names) =
- cx.tcx.generator_layout_and_saved_local_names(generator_def_id);
+ let generator_layout =
+ cx.tcx.optimized_mir(generator_def_id).generator_layout().unwrap();
let Variants::Multiple { tag_encoding: TagEncoding::Direct, ref variants, .. } = generator_type_and_layout.variants else {
bug!(
@@ -195,7 +195,6 @@ pub(super) fn build_generator_di_node<'ll, 'tcx>(
generator_type_and_layout,
generator_type_di_node,
generator_layout,
- &state_specific_upvar_names,
&common_upvar_names,
),
source_info,
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 109e9959aeac8..51ac441a7a425 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -11,9 +11,7 @@ use jobserver::{Acquired, Client};
use rustc_ast::attr;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_data_structures::memmap::Mmap;
-use rustc_data_structures::profiling::SelfProfilerRef;
-use rustc_data_structures::profiling::TimingGuard;
-use rustc_data_structures::profiling::VerboseTimingGuard;
+use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard};
use rustc_data_structures::sync::Lrc;
use rustc_errors::emitter::Emitter;
use rustc_errors::{translation::Translate, DiagnosticId, FatalError, Handler, Level};
@@ -322,7 +320,6 @@ pub type ExportedSymbols = FxHashMap {
// Resources needed when running LTO
- pub backend: B,
pub prof: SelfProfilerRef,
pub lto: Lto,
pub save_temps: bool,
@@ -340,14 +337,10 @@ pub struct CodegenContext {
pub msvc_imps_needed: bool,
pub is_pe_coff: bool,
pub target_can_use_split_dwarf: bool,
- pub target_pointer_width: u32,
pub target_arch: String,
- pub debuginfo: config::DebugInfo,
pub split_debuginfo: rustc_target::spec::SplitDebuginfo,
pub split_dwarf_kind: rustc_session::config::SplitDwarfKind,
- /// Number of cgus excluding the allocator/metadata modules
- pub total_cgus: usize,
/// Handler to use for diagnostics produced during codegen.
pub diag_emitter: SharedEmitter,
/// LLVM optimizations for which we want to print remarks.
@@ -443,7 +436,6 @@ pub fn start_async_codegen(
target_cpu: String,
metadata: EncodedMetadata,
metadata_module: Option,
- total_cgus: usize,
) -> OngoingCodegen {
let (coordinator_send, coordinator_receive) = channel();
let sess = tcx.sess;
@@ -471,7 +463,6 @@ pub fn start_async_codegen(
shared_emitter,
codegen_worker_send,
coordinator_receive,
- total_cgus,
sess.jobserver.clone(),
Arc::new(regular_config),
Arc::new(metadata_config),
@@ -687,7 +678,7 @@ fn produce_final_output_artifacts(
// These are used in linking steps and will be cleaned up afterward.
}
-pub enum WorkItem {
+pub(crate) enum WorkItem {
/// Optimize a newly codegened, totally unoptimized module.
Optimize(ModuleCodegen),
/// Copy the post-LTO artifacts from the incremental cache to the output
@@ -705,20 +696,6 @@ impl WorkItem {
}
}
- fn start_profiling<'a>(&self, cgcx: &'a CodegenContext) -> TimingGuard<'a> {
- match *self {
- WorkItem::Optimize(ref m) => {
- cgcx.prof.generic_activity_with_arg("codegen_module_optimize", &*m.name)
- }
- WorkItem::CopyPostLtoArtifacts(ref m) => cgcx
- .prof
- .generic_activity_with_arg("codegen_copy_artifacts_from_incr_cache", &*m.name),
- WorkItem::LTO(ref m) => {
- cgcx.prof.generic_activity_with_arg("codegen_module_perform_lto", m.name())
- }
- }
- }
-
/// Generate a short description of this work item suitable for use as a thread name.
fn short_description(&self) -> String {
// `pthread_setname()` on *nix is limited to 15 characters and longer names are ignored.
@@ -747,7 +724,8 @@ impl WorkItem {
}
}
-enum WorkItemResult {
+/// A result produced by the backend.
+pub(crate) enum WorkItemResult {
Compiled(CompiledModule),
NeedsLink(ModuleCodegen),
NeedsFatLTO(FatLTOInput),
@@ -759,21 +737,6 @@ pub enum FatLTOInput {
InMemory(ModuleCodegen),
}
-fn execute_work_item(
- cgcx: &CodegenContext,
- work_item: WorkItem,
-) -> Result, FatalError> {
- let module_config = cgcx.config(work_item.module_kind());
-
- match work_item {
- WorkItem::Optimize(module) => execute_optimize_work_item(cgcx, module, module_config),
- WorkItem::CopyPostLtoArtifacts(module) => {
- Ok(execute_copy_from_cache_work_item(cgcx, module, module_config))
- }
- WorkItem::LTO(module) => execute_lto_work_item(cgcx, module, module_config),
- }
-}
-
/// Actual LTO type we end up choosing based on multiple factors.
pub enum ComputedLtoType {
No,
@@ -954,38 +917,41 @@ fn finish_intra_module_work(
}
}
-pub enum Message {
+/// Messages sent to the coordinator.
+pub(crate) enum Message {
+ /// A jobserver token has become available. Sent from the jobserver helper
+ /// thread.
Token(io::Result),
- NeedsFatLTO {
- result: FatLTOInput,
- worker_id: usize,
- },
- NeedsThinLTO {
- name: String,
- thin_buffer: B::ThinBuffer,
- worker_id: usize,
- },
- NeedsLink {
- module: ModuleCodegen,
- worker_id: usize,
- },
- Done {
- result: Result>,
- worker_id: usize,
- },
- CodegenDone {
- llvm_work_item: WorkItem,
- cost: u64,
- },
+
+ /// The backend has finished processing a work item for a codegen unit.
+ /// Sent from a backend worker thread.
+ WorkItem { result: Result, Option>, worker_id: usize },
+
+ /// The frontend has finished generating something (backend IR or a
+ /// post-LTO artifact) for a codegen unit, and it should be passed to the
+ /// backend. Sent from the main thread.
+ CodegenDone { llvm_work_item: WorkItem, cost: u64 },
+
+ /// Similar to `CodegenDone`, but for reusing a pre-LTO artifact
+ /// Sent from the main thread.
AddImportOnlyModule {
module_data: SerializedModule,
work_product: WorkProduct,
},
+
+ /// The frontend has finished generating everything for all codegen units.
+ /// Sent from the main thread.
CodegenComplete,
- CodegenItem,
+
+ /// Some normal-ish compiler error occurred, and codegen should be wound
+ /// down. Sent from the main thread.
CodegenAborted,
}
+/// A message sent from the coordinator thread to the main thread telling it to
+/// process another codegen unit.
+pub struct CguMessage;
+
type DiagnosticArgName<'source> = Cow<'source, str>;
struct Diagnostic {
@@ -1007,9 +973,8 @@ fn start_executing_work(
tcx: TyCtxt<'_>,
crate_info: &CrateInfo,
shared_emitter: SharedEmitter,
- codegen_worker_send: Sender>,
+ codegen_worker_send: Sender,
coordinator_receive: Receiver>,
- total_cgus: usize,
jobserver: Client,
regular_config: Arc,
metadata_config: Arc,
@@ -1077,7 +1042,6 @@ fn start_executing_work(
};
let backend_features = tcx.global_backend_features(());
let cgcx = CodegenContext:: {
- backend: backend.clone(),
crate_types: sess.crate_types().to_vec(),
each_linked_rlib_for_lto,
lto: sess.lto(),
@@ -1098,13 +1062,10 @@ fn start_executing_work(
metadata_module_config: metadata_config,
allocator_module_config: allocator_config,
tm_factory: backend.target_machine_factory(tcx.sess, ol, backend_features),
- total_cgus,
msvc_imps_needed: msvc_imps_needed(tcx),
is_pe_coff: tcx.sess.target.is_like_windows,
target_can_use_split_dwarf: tcx.sess.target_can_use_split_dwarf(),
- target_pointer_width: tcx.sess.target.pointer_width,
target_arch: tcx.sess.target.arch.to_string(),
- debuginfo: tcx.sess.opts.debuginfo,
split_debuginfo: tcx.sess.split_debuginfo(),
split_dwarf_kind: tcx.sess.opts.unstable_opts.split_dwarf_kind,
};
@@ -1266,10 +1227,19 @@ fn start_executing_work(
let mut needs_thin_lto = Vec::new();
let mut lto_import_only_modules = Vec::new();
let mut started_lto = false;
- let mut codegen_aborted = false;
- // This flag tracks whether all items have gone through codegens
- let mut codegen_done = false;
+ /// Possible state transitions:
+ /// - Ongoing -> Completed
+ /// - Ongoing -> Aborted
+ /// - Completed -> Aborted
+ #[derive(Debug, PartialEq)]
+ enum CodegenState {
+ Ongoing,
+ Completed,
+ Aborted,
+ }
+ use CodegenState::*;
+ let mut codegen_state = Ongoing;
// This is the queue of LLVM work items that still need processing.
let mut work_items = Vec::<(WorkItem, u64)>::new();
@@ -1289,10 +1259,10 @@ fn start_executing_work(
// wait for all existing work to finish, so many of the conditions here
// only apply if codegen hasn't been aborted as they represent pending
// work to be done.
- while !codegen_done
+ while codegen_state == Ongoing
|| running > 0
|| main_thread_worker_state == MainThreadWorkerState::LLVMing
- || (!codegen_aborted
+ || (codegen_state == Completed
&& !(work_items.is_empty()
&& needs_fat_lto.is_empty()
&& needs_thin_lto.is_empty()
@@ -1302,7 +1272,7 @@ fn start_executing_work(
// While there are still CGUs to be codegened, the coordinator has
// to decide how to utilize the compiler processes implicit Token:
// For codegenning more CGU or for running them through LLVM.
- if !codegen_done {
+ if codegen_state == Ongoing {
if main_thread_worker_state == MainThreadWorkerState::Idle {
// Compute the number of workers that will be running once we've taken as many
// items from the work queue as we can, plus one for the main thread. It's not
@@ -1315,9 +1285,9 @@ fn start_executing_work(
let anticipated_running = running + additional_running + 1;
if !queue_full_enough(work_items.len(), anticipated_running) {
- // The queue is not full enough, codegen more items:
- if codegen_worker_send.send(Message::CodegenItem).is_err() {
- panic!("Could not send Message::CodegenItem to main thread")
+ // The queue is not full enough, process more codegen units:
+ if codegen_worker_send.send(CguMessage).is_err() {
+ panic!("Could not send CguMessage to main thread")
}
main_thread_worker_state = MainThreadWorkerState::Codegenning;
} else {
@@ -1339,10 +1309,7 @@ fn start_executing_work(
spawn_work(cgcx, item);
}
}
- } else if codegen_aborted {
- // don't queue up any more work if codegen was aborted, we're
- // just waiting for our existing children to finish
- } else {
+ } else if codegen_state == Completed {
// If we've finished everything related to normal codegen
// then it must be the case that we've got some LTO work to do.
// Perform the serial work here of figuring out what we're
@@ -1409,11 +1376,15 @@ fn start_executing_work(
// Already making good use of that token
}
}
+ } else {
+ // Don't queue up any more work if codegen was aborted, we're
+ // just waiting for our existing children to finish.
+ assert!(codegen_state == Aborted);
}
// Spin up what work we can, only doing this while we've got available
// parallelism slots and work left to spawn.
- while !codegen_aborted && !work_items.is_empty() && running < tokens.len() {
+ while codegen_state != Aborted && !work_items.is_empty() && running < tokens.len() {
let (item, _) = work_items.pop().unwrap();
maybe_start_llvm_timer(prof, cgcx.config(item.module_kind()), &mut llvm_start_time);
@@ -1465,8 +1436,7 @@ fn start_executing_work(
Err(e) => {
let msg = &format!("failed to acquire jobserver token: {}", e);
shared_emitter.fatal(msg);
- codegen_done = true;
- codegen_aborted = true;
+ codegen_state = Aborted;
}
}
}
@@ -1494,7 +1464,9 @@ fn start_executing_work(
}
Message::CodegenComplete => {
- codegen_done = true;
+ if codegen_state != Aborted {
+ codegen_state = Completed;
+ }
assert_eq!(main_thread_worker_state, MainThreadWorkerState::Codegenning);
main_thread_worker_state = MainThreadWorkerState::Idle;
}
@@ -1506,58 +1478,59 @@ fn start_executing_work(
// then conditions above will ensure no more work is spawned but
// we'll keep executing this loop until `running` hits 0.
Message::CodegenAborted => {
- codegen_done = true;
- codegen_aborted = true;
+ codegen_state = Aborted;
}
- Message::Done { result: Ok(compiled_module), worker_id } => {
+
+ Message::WorkItem { result, worker_id } => {
free_worker(worker_id);
- match compiled_module.kind {
- ModuleKind::Regular => {
- compiled_modules.push(compiled_module);
+
+ match result {
+ Ok(WorkItemResult::Compiled(compiled_module)) => {
+ match compiled_module.kind {
+ ModuleKind::Regular => {
+ compiled_modules.push(compiled_module);
+ }
+ ModuleKind::Allocator => {
+ assert!(compiled_allocator_module.is_none());
+ compiled_allocator_module = Some(compiled_module);
+ }
+ ModuleKind::Metadata => bug!("Should be handled separately"),
+ }
+ }
+ Ok(WorkItemResult::NeedsLink(module)) => {
+ needs_link.push(module);
+ }
+ Ok(WorkItemResult::NeedsFatLTO(fat_lto_input)) => {
+ assert!(!started_lto);
+ needs_fat_lto.push(fat_lto_input);
+ }
+ Ok(WorkItemResult::NeedsThinLTO(name, thin_buffer)) => {
+ assert!(!started_lto);
+ needs_thin_lto.push((name, thin_buffer));
}
- ModuleKind::Allocator => {
- assert!(compiled_allocator_module.is_none());
- compiled_allocator_module = Some(compiled_module);
+ Err(Some(WorkerFatalError)) => {
+ // Like `CodegenAborted`, wait for remaining work to finish.
+ codegen_state = Aborted;
+ }
+ Err(None) => {
+ // If the thread failed that means it panicked, so
+ // we abort immediately.
+ bug!("worker thread panicked");
}
- ModuleKind::Metadata => bug!("Should be handled separately"),
}
}
- Message::NeedsLink { module, worker_id } => {
- free_worker(worker_id);
- needs_link.push(module);
- }
- Message::NeedsFatLTO { result, worker_id } => {
- assert!(!started_lto);
- free_worker(worker_id);
- needs_fat_lto.push(result);
- }
- Message::NeedsThinLTO { name, thin_buffer, worker_id } => {
- assert!(!started_lto);
- free_worker(worker_id);
- needs_thin_lto.push((name, thin_buffer));
- }
+
Message::AddImportOnlyModule { module_data, work_product } => {
assert!(!started_lto);
- assert!(!codegen_done);
+ assert_eq!(codegen_state, Ongoing);
assert_eq!(main_thread_worker_state, MainThreadWorkerState::Codegenning);
lto_import_only_modules.push((module_data, work_product));
main_thread_worker_state = MainThreadWorkerState::Idle;
}
- // If the thread failed that means it panicked, so we abort immediately.
- Message::Done { result: Err(None), worker_id: _ } => {
- bug!("worker thread panicked");
- }
- Message::Done { result: Err(Some(WorkerFatalError)), worker_id } => {
- // Similar to CodegenAborted, wait for remaining work to finish.
- free_worker(worker_id);
- codegen_done = true;
- codegen_aborted = true;
- }
- Message::CodegenItem => bug!("the coordinator should not receive codegen requests"),
}
}
- if codegen_aborted {
+ if codegen_state == Aborted {
return Err(());
}
@@ -1672,22 +1645,11 @@ fn spawn_work(cgcx: CodegenContext, work: WorkItem
fn drop(&mut self) {
let worker_id = self.worker_id;
let msg = match self.result.take() {
- Some(Ok(WorkItemResult::Compiled(m))) => {
- Message::Done:: { result: Ok(m), worker_id }
- }
- Some(Ok(WorkItemResult::NeedsLink(m))) => {
- Message::NeedsLink:: { module: m, worker_id }
- }
- Some(Ok(WorkItemResult::NeedsFatLTO(m))) => {
- Message::NeedsFatLTO:: { result: m, worker_id }
- }
- Some(Ok(WorkItemResult::NeedsThinLTO(name, thin_buffer))) => {
- Message::NeedsThinLTO:: { name, thin_buffer, worker_id }
- }
+ Some(Ok(result)) => Message::WorkItem:: { result: Ok(result), worker_id },
Some(Err(FatalError)) => {
- Message::Done:: { result: Err(Some(WorkerFatalError)), worker_id }
+ Message::WorkItem:: { result: Err(Some(WorkerFatalError)), worker_id }
}
- None => Message::Done:: { result: Err(None), worker_id },
+ None => Message::WorkItem:: { result: Err(None), worker_id },
};
drop(self.coordinator_send.send(Box::new(msg)));
}
@@ -1706,8 +1668,27 @@ fn spawn_work(cgcx: CodegenContext, work: WorkItem
// as a diagnostic was already sent off to the main thread - just
// surface that there was an error in this worker.
bomb.result = {
- let _prof_timer = work.start_profiling(&cgcx);
- Some(execute_work_item(&cgcx, work))
+ let module_config = cgcx.config(work.module_kind());
+
+ Some(match work {
+ WorkItem::Optimize(m) => {
+ let _timer =
+ cgcx.prof.generic_activity_with_arg("codegen_module_optimize", &*m.name);
+ execute_optimize_work_item(&cgcx, m, module_config)
+ }
+ WorkItem::CopyPostLtoArtifacts(m) => {
+ let _timer = cgcx.prof.generic_activity_with_arg(
+ "codegen_copy_artifacts_from_incr_cache",
+ &*m.name,
+ );
+ Ok(execute_copy_from_cache_work_item(&cgcx, m, module_config))
+ }
+ WorkItem::LTO(m) => {
+ let _timer =
+ cgcx.prof.generic_activity_with_arg("codegen_module_perform_lto", m.name());
+ execute_lto_work_item(&cgcx, m, module_config)
+ }
+ })
};
})
.expect("failed to spawn thread");
@@ -1891,7 +1872,7 @@ pub struct OngoingCodegen {
pub metadata: EncodedMetadata,
pub metadata_module: Option,
pub crate_info: CrateInfo,
- pub codegen_worker_receive: Receiver>,
+ pub codegen_worker_receive: Receiver,
pub shared_emitter_main: SharedEmitterMain,
pub output_filenames: Arc,
pub coordinator: Coordinator,
@@ -1965,10 +1946,9 @@ impl OngoingCodegen {
pub fn wait_for_signal_to_codegen_item(&self) {
match self.codegen_worker_receive.recv() {
- Ok(Message::CodegenItem) => {
- // Nothing to do
+ Ok(CguMessage) => {
+ // Ok to proceed.
}
- Ok(_) => panic!("unexpected message"),
Err(_) => {
// One of the LLVM threads must have panicked, fall through so
// error handling can be reached.
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index dc4a28c866ff3..28f3c23364cf2 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -13,7 +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_ast::expand::allocator::{global_fn_name, AllocatorKind, ALLOCATOR_METHODS};
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};
@@ -580,7 +580,7 @@ pub fn codegen_crate(
) -> OngoingCodegen {
// Skip crate items and just output metadata in -Z no-codegen mode.
if tcx.sess.opts.unstable_opts.no_codegen || !tcx.sess.opts.output_types.should_codegen() {
- let ongoing_codegen = start_async_codegen(backend, tcx, target_cpu, metadata, None, 1);
+ let ongoing_codegen = start_async_codegen(backend, tcx, target_cpu, metadata, None);
ongoing_codegen.codegen_finished(tcx);
@@ -631,14 +631,8 @@ pub fn codegen_crate(
})
});
- let ongoing_codegen = start_async_codegen(
- backend.clone(),
- tcx,
- target_cpu,
- metadata,
- metadata_module,
- codegen_units.len(),
- );
+ let ongoing_codegen =
+ start_async_codegen(backend.clone(), tcx, target_cpu, metadata, metadata_module);
// Codegen an allocator shim, if necessary.
if let Some(kind) = allocator_kind_for_codegen(tcx) {
@@ -921,7 +915,21 @@ impl CrateInfo {
missing_weak_lang_items
.iter()
.map(|item| (format!("{prefix}{item}"), SymbolExportKind::Text)),
- )
+ );
+ if tcx.allocator_kind(()).is_some() {
+ // At least one crate needs a global allocator. This crate may be placed
+ // after the crate that defines it in the linker order, in which case some
+ // linkers return an error. By adding the global allocator shim methods to
+ // the linked_symbols list, linking the generated symbols.o will ensure that
+ // circular dependencies involving the global allocator don't lead to linker
+ // errors.
+ linked_symbols.extend(ALLOCATOR_METHODS.iter().map(|method| {
+ (
+ format!("{prefix}{}", global_fn_name(method.name).as_str()),
+ SymbolExportKind::Text,
+ )
+ }));
+ }
});
}
diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs
index e1abb73a504a3..5a68075991f16 100644
--- a/compiler/rustc_codegen_ssa/src/common.rs
+++ b/compiler/rustc_codegen_ssa/src/common.rs
@@ -132,7 +132,7 @@ pub fn build_langcall<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
// all shifts). For 32- and 64-bit types, this matches the semantics
// of Java. (See related discussion on #1877 and #10183.)
-pub fn build_unchecked_lshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
+pub fn build_masked_lshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
bx: &mut Bx,
lhs: Bx::Value,
rhs: Bx::Value,
@@ -143,7 +143,7 @@ pub fn build_unchecked_lshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
bx.shl(lhs, rhs)
}
-pub fn build_unchecked_rshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
+pub fn build_masked_rshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
bx: &mut Bx,
lhs_t: Ty<'tcx>,
lhs: Bx::Value,
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index a4a8aad87269d..0cec560ba4518 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -1280,7 +1280,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
destination,
target,
unwind,
- from_hir_call: _,
+ call_source: _,
fn_span,
} => self.codegen_call_terminator(
helper,
diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
index 9ac2424e76be0..8a65dd593b8c1 100644
--- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
@@ -211,52 +211,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
args[1].val.unaligned_volatile_store(bx, dst);
return;
}
- | sym::unchecked_shl
- | sym::unchecked_shr
- | sym::unchecked_add
- | sym::unchecked_sub
- | sym::unchecked_mul
- | sym::exact_div => {
+ sym::exact_div => {
let ty = arg_tys[0];
match int_type_width_signed(ty, bx.tcx()) {
- Some((_width, signed)) => match name {
- sym::exact_div => {
- if signed {
- bx.exactsdiv(args[0].immediate(), args[1].immediate())
- } else {
- bx.exactudiv(args[0].immediate(), args[1].immediate())
- }
- }
- sym::unchecked_shl => bx.shl(args[0].immediate(), args[1].immediate()),
- sym::unchecked_shr => {
- if signed {
- bx.ashr(args[0].immediate(), args[1].immediate())
- } else {
- bx.lshr(args[0].immediate(), args[1].immediate())
- }
- }
- sym::unchecked_add => {
- if signed {
- bx.unchecked_sadd(args[0].immediate(), args[1].immediate())
- } else {
- bx.unchecked_uadd(args[0].immediate(), args[1].immediate())
- }
- }
- sym::unchecked_sub => {
- if signed {
- bx.unchecked_ssub(args[0].immediate(), args[1].immediate())
- } else {
- bx.unchecked_usub(args[0].immediate(), args[1].immediate())
- }
- }
- sym::unchecked_mul => {
- if signed {
- bx.unchecked_smul(args[0].immediate(), args[1].immediate())
- } else {
- bx.unchecked_umul(args[0].immediate(), args[1].immediate())
- }
+ Some((_width, signed)) => {
+ if signed {
+ bx.exactsdiv(args[0].immediate(), args[1].immediate())
+ } else {
+ bx.exactudiv(args[0].immediate(), args[1].immediate())
}
- _ => bug!(),
},
None => {
bx.tcx().sess.emit_err(InvalidMonomorphization::BasicIntegerType { span, name, ty });
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 5241a5aee008e..2d3d0ec68b81c 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -798,6 +798,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
bx.add(lhs, rhs)
}
}
+ mir::BinOp::AddUnchecked => {
+ if is_signed {
+ bx.unchecked_sadd(lhs, rhs)
+ } else {
+ bx.unchecked_uadd(lhs, rhs)
+ }
+ }
mir::BinOp::Sub => {
if is_float {
bx.fsub(lhs, rhs)
@@ -805,6 +812,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
bx.sub(lhs, rhs)
}
}
+ mir::BinOp::SubUnchecked => {
+ if is_signed {
+ bx.unchecked_ssub(lhs, rhs)
+ } else {
+ bx.unchecked_usub(lhs, rhs)
+ }
+ }
mir::BinOp::Mul => {
if is_float {
bx.fmul(lhs, rhs)
@@ -812,6 +826,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
bx.mul(lhs, rhs)
}
}
+ mir::BinOp::MulUnchecked => {
+ if is_signed {
+ bx.unchecked_smul(lhs, rhs)
+ } else {
+ bx.unchecked_umul(lhs, rhs)
+ }
+ }
mir::BinOp::Div => {
if is_float {
bx.fdiv(lhs, rhs)
@@ -848,8 +869,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
bx.inbounds_gep(llty, lhs, &[rhs])
}
}
- mir::BinOp::Shl => common::build_unchecked_lshift(bx, lhs, rhs),
- mir::BinOp::Shr => common::build_unchecked_rshift(bx, input_ty, lhs, rhs),
+ mir::BinOp::Shl => common::build_masked_lshift(bx, lhs, rhs),
+ mir::BinOp::ShlUnchecked => {
+ let rhs = base::cast_shift_expr_rhs(bx, lhs, rhs);
+ bx.shl(lhs, rhs)
+ }
+ mir::BinOp::Shr => common::build_masked_rshift(bx, input_ty, lhs, rhs),
+ mir::BinOp::ShrUnchecked => {
+ let rhs = base::cast_shift_expr_rhs(bx, lhs, rhs);
+ if is_signed { bx.ashr(lhs, rhs) } else { bx.lshr(lhs, rhs) }
+ }
mir::BinOp::Ne
| mir::BinOp::Lt
| mir::BinOp::Gt
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index bf660c59cabda..e99005316b3fd 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -210,6 +210,9 @@ const_eval_long_running =
.label = the const evaluator is currently interpreting this expression
.help = the constant being evaluated
+const_eval_match_eq_non_const = cannot match on `{$ty}` in {const_eval_const_context}s
+ .note = `{$ty}` cannot be compared in compile-time, and therefore cannot be used in `match`es
+
const_eval_max_num_nodes_in_const = maximum number of nodes exceeded in constant {$global_const_id}
const_eval_memory_access_test = memory access failed
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index eed3091d481e3..ca38cce710e60 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -271,6 +271,18 @@ pub struct RawBytesNote {
pub bytes: String,
}
+// FIXME(fee1-dead) do not use stringly typed `ConstContext`
+
+#[derive(Diagnostic)]
+#[diag(const_eval_match_eq_non_const, code = "E0015")]
+#[note]
+pub struct NonConstMatchEq<'tcx> {
+ #[primary_span]
+ pub span: Span,
+ pub ty: Ty<'tcx>,
+ pub kind: ConstContext,
+}
+
#[derive(Diagnostic)]
#[diag(const_eval_for_loop_into_iter_non_const, code = "E0015")]
pub struct NonConstForLoopIntoIter<'tcx> {
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 7192bbc00d556..8f4cf23770e3d 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -234,37 +234,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let r = self.read_immediate(&args[1])?;
self.exact_div(&l, &r, dest)?;
}
- sym::unchecked_shl
- | sym::unchecked_shr
- | sym::unchecked_add
- | sym::unchecked_sub
- | sym::unchecked_mul => {
- let l = self.read_immediate(&args[0])?;
- let r = self.read_immediate(&args[1])?;
- let bin_op = match intrinsic_name {
- sym::unchecked_shl => BinOp::Shl,
- sym::unchecked_shr => BinOp::Shr,
- sym::unchecked_add => BinOp::Add,
- sym::unchecked_sub => BinOp::Sub,
- sym::unchecked_mul => BinOp::Mul,
- _ => bug!(),
- };
- let (val, overflowed, _ty) = self.overflowing_binary_op(bin_op, &l, &r)?;
- if overflowed {
- let layout = self.layout_of(substs.type_at(0))?;
- let r_val = r.to_scalar().to_bits(layout.size)?;
- if let sym::unchecked_shl | sym::unchecked_shr = intrinsic_name {
- throw_ub_custom!(
- fluent::const_eval_overflow_shift,
- val = r_val,
- name = intrinsic_name
- );
- } else {
- throw_ub_custom!(fluent::const_eval_overflow, name = intrinsic_name);
- }
- }
- self.write_scalar(val, dest)?;
- }
sym::rotate_left | sym::rotate_right => {
// rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW))
// rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs
index 7186148daf0ba..7bca7efdf5a83 100644
--- a/compiler/rustc_const_eval/src/interpret/operator.rs
+++ b/compiler/rustc_const_eval/src/interpret/operator.rs
@@ -3,10 +3,13 @@ use rustc_middle::mir;
use rustc_middle::mir::interpret::{InterpResult, Scalar};
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, FloatTy, Ty};
+use rustc_span::symbol::sym;
use rustc_target::abi::Abi;
use super::{ImmTy, Immediate, InterpCx, Machine, PlaceTy};
+use crate::fluent_generated as fluent;
+
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// Applies the binary operation `op` to the two operands and writes a tuple of the result
/// and a boolean signifying the potential overflow to the destination.
@@ -139,8 +142,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> {
use rustc_middle::mir::BinOp::*;
+ let throw_ub_on_overflow = match bin_op {
+ AddUnchecked => Some(sym::unchecked_add),
+ SubUnchecked => Some(sym::unchecked_sub),
+ MulUnchecked => Some(sym::unchecked_mul),
+ ShlUnchecked => Some(sym::unchecked_shl),
+ ShrUnchecked => Some(sym::unchecked_shr),
+ _ => None,
+ };
+
// Shift ops can have an RHS with a different numeric type.
- if bin_op == Shl || bin_op == Shr {
+ if matches!(bin_op, Shl | ShlUnchecked | Shr | ShrUnchecked) {
let size = u128::from(left_layout.size.bits());
// Even if `r` is signed, we treat it as if it was unsigned (i.e., we use its
// zero-extended form). This matches the codegen backend:
@@ -155,6 +167,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// integers are maximally 128bits wide, so negative shifts *always* overflow and we have
// consistent results for the same value represented at different bit widths.
assert!(size <= 128);
+ let original_r = r;
let overflow = r >= size;
// The shift offset is implicitly masked to the type size, to make sure this operation
// is always defined. This is the one MIR operator that does *not* directly map to a
@@ -166,19 +179,28 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let result = if left_layout.abi.is_signed() {
let l = self.sign_extend(l, left_layout) as i128;
let result = match bin_op {
- Shl => l.checked_shl(r).unwrap(),
- Shr => l.checked_shr(r).unwrap(),
+ Shl | ShlUnchecked => l.checked_shl(r).unwrap(),
+ Shr | ShrUnchecked => l.checked_shr(r).unwrap(),
_ => bug!(),
};
result as u128
} else {
match bin_op {
- Shl => l.checked_shl(r).unwrap(),
- Shr => l.checked_shr(r).unwrap(),
+ Shl | ShlUnchecked => l.checked_shl(r).unwrap(),
+ Shr | ShrUnchecked => l.checked_shr(r).unwrap(),
_ => bug!(),
}
};
let truncated = self.truncate(result, left_layout);
+
+ if overflow && let Some(intrinsic_name) = throw_ub_on_overflow {
+ throw_ub_custom!(
+ fluent::const_eval_overflow_shift,
+ val = original_r,
+ name = intrinsic_name
+ );
+ }
+
return Ok((Scalar::from_uint(truncated, left_layout.size), overflow, left_layout.ty));
}
@@ -216,9 +238,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Rem if r == 0 => throw_ub!(RemainderByZero),
Div => Some(i128::overflowing_div),
Rem => Some(i128::overflowing_rem),
- Add => Some(i128::overflowing_add),
- Sub => Some(i128::overflowing_sub),
- Mul => Some(i128::overflowing_mul),
+ Add | AddUnchecked => Some(i128::overflowing_add),
+ Sub | SubUnchecked => Some(i128::overflowing_sub),
+ Mul | MulUnchecked => Some(i128::overflowing_mul),
_ => None,
};
if let Some(op) = op {
@@ -242,11 +264,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// If that truncation loses any information, we have an overflow.
let result = result as u128;
let truncated = self.truncate(result, left_layout);
- return Ok((
- Scalar::from_uint(truncated, size),
- oflo || self.sign_extend(truncated, left_layout) != result,
- left_layout.ty,
- ));
+ let overflow = oflo || self.sign_extend(truncated, left_layout) != result;
+ if overflow && let Some(intrinsic_name) = throw_ub_on_overflow {
+ throw_ub_custom!(fluent::const_eval_overflow, name = intrinsic_name);
+ }
+ return Ok((Scalar::from_uint(truncated, size), overflow, left_layout.ty));
}
}
@@ -263,12 +285,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
BitAnd => (Scalar::from_uint(l & r, size), left_layout.ty),
BitXor => (Scalar::from_uint(l ^ r, size), left_layout.ty),
- Add | Sub | Mul | Rem | Div => {
+ Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Rem | Div => {
assert!(!left_layout.abi.is_signed());
let op: fn(u128, u128) -> (u128, bool) = match bin_op {
- Add => u128::overflowing_add,
- Sub => u128::overflowing_sub,
- Mul => u128::overflowing_mul,
+ Add | AddUnchecked => u128::overflowing_add,
+ Sub | SubUnchecked => u128::overflowing_sub,
+ Mul | MulUnchecked => u128::overflowing_mul,
Div if r == 0 => throw_ub!(DivisionByZero),
Rem if r == 0 => throw_ub!(RemainderByZero),
Div => u128::overflowing_div,
@@ -279,11 +301,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// Truncate to target type.
// If that truncation loses any information, we have an overflow.
let truncated = self.truncate(result, left_layout);
- return Ok((
- Scalar::from_uint(truncated, size),
- oflo || truncated != result,
- left_layout.ty,
- ));
+ let overflow = oflo || truncated != result;
+ if overflow && let Some(intrinsic_name) = throw_ub_on_overflow {
+ throw_ub_custom!(fluent::const_eval_overflow, name = intrinsic_name);
+ }
+ return Ok((Scalar::from_uint(truncated, size), overflow, left_layout.ty));
}
_ => span_bug!(
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index 1e60a1e72ea07..619da8abb7d22 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -9,27 +9,7 @@ use rustc_middle::mir::interpret::{InterpResult, Scalar};
use rustc_middle::ty::layout::LayoutOf;
use super::{ImmTy, InterpCx, Machine};
-
-/// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
-/// same type as the result.
-#[inline]
-fn binop_left_homogeneous(op: mir::BinOp) -> bool {
- use rustc_middle::mir::BinOp::*;
- match op {
- Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr | Offset | Shl | Shr => true,
- Eq | Ne | Lt | Le | Gt | Ge => false,
- }
-}
-/// Classify whether an operator is "right-homogeneous", i.e., the RHS has the
-/// same type as the LHS.
-#[inline]
-fn binop_right_homogeneous(op: mir::BinOp) -> bool {
- use rustc_middle::mir::BinOp::*;
- match op {
- Add | Sub | Mul | Div | Rem | BitXor | BitAnd | BitOr | Eq | Ne | Lt | Le | Gt | Ge => true,
- Offset | Shl | Shr => false,
- }
-}
+use crate::util;
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// Returns `true` as long as there are more things to do.
@@ -179,9 +159,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
BinaryOp(bin_op, box (ref left, ref right)) => {
- let layout = binop_left_homogeneous(bin_op).then_some(dest.layout);
+ let layout = util::binop_left_homogeneous(bin_op).then_some(dest.layout);
let left = self.read_immediate(&self.eval_operand(left, layout)?)?;
- let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
+ let layout = util::binop_right_homogeneous(bin_op).then_some(left.layout);
let right = self.read_immediate(&self.eval_operand(right, layout)?)?;
self.binop_ignore_overflow(bin_op, &left, &right, &dest)?;
}
@@ -189,7 +169,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
CheckedBinaryOp(bin_op, box (ref left, ref right)) => {
// Due to the extra boolean in the result, we can never reuse the `dest.layout`.
let left = self.read_immediate(&self.eval_operand(left, None)?)?;
- let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
+ let layout = util::binop_right_homogeneous(bin_op).then_some(left.layout);
let right = self.read_immediate(&self.eval_operand(right, layout)?)?;
self.binop_with_overflow(bin_op, &left, &right, &dest)?;
}
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 7269ff8d53cdf..719d8a14b4134 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -62,7 +62,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
destination,
target,
unwind,
- from_hir_call: _,
+ call_source: _,
fn_span: _,
} => {
let old_stack = self.frame_idx();
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 106cf1114749a..33c79ad7e5535 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -412,7 +412,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
BorrowKind::Shallow => {
PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow)
}
- BorrowKind::Unique => PlaceContext::MutatingUse(MutatingUseContext::Borrow),
BorrowKind::Mut { .. } => {
PlaceContext::MutatingUse(MutatingUseContext::Borrow)
}
@@ -457,7 +456,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
}
}
- Rvalue::Ref(_, kind @ (BorrowKind::Mut { .. } | BorrowKind::Unique), place) => {
+ Rvalue::Ref(_, BorrowKind::Mut { .. }, place) => {
let ty = place.ty(self.body, self.tcx).ty;
let is_allowed = match ty.kind() {
// Inside a `static mut`, `&mut [...]` is allowed.
@@ -478,11 +477,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
};
if !is_allowed {
- if let BorrowKind::Mut { .. } = kind {
- self.check_mut_borrow(place.local, hir::BorrowKind::Ref)
- } else {
- self.check_op(ops::CellBorrow);
- }
+ self.check_mut_borrow(place.local, hir::BorrowKind::Ref)
}
}
@@ -702,7 +697,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
self.super_terminator(terminator, location);
match &terminator.kind {
- TerminatorKind::Call { func, args, fn_span, from_hir_call, .. } => {
+ TerminatorKind::Call { func, args, fn_span, call_source, .. } => {
let ConstCx { tcx, body, param_env, .. } = *self.ccx;
let caller = self.def_id();
@@ -755,7 +750,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
callee,
substs,
span: *fn_span,
- from_hir_call: *from_hir_call,
+ call_source: *call_source,
feature: Some(sym::const_trait_impl),
});
return;
@@ -797,7 +792,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
callee,
substs,
span: *fn_span,
- from_hir_call: *from_hir_call,
+ call_source: *call_source,
feature: None,
});
@@ -823,7 +818,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
callee,
substs,
span: *fn_span,
- from_hir_call: *from_hir_call,
+ call_source: *call_source,
feature: None,
});
return;
@@ -866,7 +861,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
callee,
substs,
span: *fn_span,
- from_hir_call: *from_hir_call,
+ call_source: *call_source,
feature: None,
});
return;
@@ -926,7 +921,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
callee,
substs,
span: *fn_span,
- from_hir_call: *from_hir_call,
+ call_source: *call_source,
feature: None,
});
return;
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index 236e43bdfcc71..32bd9cda6f2b4 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -7,7 +7,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
-use rustc_middle::mir;
+use rustc_middle::mir::{self, CallSource};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
use rustc_middle::ty::{suggest_constraining_type_param, Adt, Closure, FnDef, FnPtr, Param, Ty};
@@ -100,7 +100,7 @@ pub struct FnCallNonConst<'tcx> {
pub callee: DefId,
pub substs: SubstsRef<'tcx>,
pub span: Span,
- pub from_hir_call: bool,
+ pub call_source: CallSource,
pub feature: Option,
}
@@ -110,7 +110,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
ccx: &ConstCx<'_, 'tcx>,
_: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- let FnCallNonConst { caller, callee, substs, span, from_hir_call, feature } = *self;
+ let FnCallNonConst { caller, callee, substs, span, call_source, feature } = *self;
let ConstCx { tcx, param_env, .. } = *ccx;
let diag_trait = |err, self_ty: Ty<'_>, trait_id| {
@@ -157,7 +157,8 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
}
};
- let call_kind = call_kind(tcx, ccx.param_env, callee, substs, span, from_hir_call, None);
+ let call_kind =
+ call_kind(tcx, ccx.param_env, callee, substs, span, call_source.from_hir_call(), None);
debug!(?call_kind);
@@ -219,48 +220,59 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
err
}
CallKind::Operator { trait_id, self_ty, .. } => {
- let mut sugg = None;
-
- if Some(trait_id) == ccx.tcx.lang_items().eq_trait() {
- match (substs[0].unpack(), substs[1].unpack()) {
- (GenericArgKind::Type(self_ty), GenericArgKind::Type(rhs_ty))
- if self_ty == rhs_ty
- && self_ty.is_ref()
- && self_ty.peel_refs().is_primitive() =>
- {
- let mut num_refs = 0;
- let mut tmp_ty = self_ty;
- while let rustc_middle::ty::Ref(_, inner_ty, _) = tmp_ty.kind() {
- num_refs += 1;
- tmp_ty = *inner_ty;
- }
- let deref = "*".repeat(num_refs);
-
- if let Ok(call_str) = ccx.tcx.sess.source_map().span_to_snippet(span) {
- if let Some(eq_idx) = call_str.find("==") {
- if let Some(rhs_idx) =
- call_str[(eq_idx + 2)..].find(|c: char| !c.is_whitespace())
- {
- let rhs_pos =
- span.lo() + BytePos::from_usize(eq_idx + 2 + rhs_idx);
- let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos);
- sugg = Some(errors::ConsiderDereferencing {
- deref,
- span: span.shrink_to_lo(),
- rhs_span,
- });
+ let mut err = if let CallSource::MatchCmp = call_source {
+ tcx.sess.create_err(errors::NonConstMatchEq {
+ span,
+ kind: ccx.const_kind(),
+ ty: self_ty,
+ })
+ } else {
+ let mut sugg = None;
+
+ if Some(trait_id) == ccx.tcx.lang_items().eq_trait() {
+ match (substs[0].unpack(), substs[1].unpack()) {
+ (GenericArgKind::Type(self_ty), GenericArgKind::Type(rhs_ty))
+ if self_ty == rhs_ty
+ && self_ty.is_ref()
+ && self_ty.peel_refs().is_primitive() =>
+ {
+ let mut num_refs = 0;
+ let mut tmp_ty = self_ty;
+ while let rustc_middle::ty::Ref(_, inner_ty, _) = tmp_ty.kind() {
+ num_refs += 1;
+ tmp_ty = *inner_ty;
+ }
+ let deref = "*".repeat(num_refs);
+
+ if let Ok(call_str) =
+ ccx.tcx.sess.source_map().span_to_snippet(span)
+ {
+ if let Some(eq_idx) = call_str.find("==") {
+ if let Some(rhs_idx) = call_str[(eq_idx + 2)..]
+ .find(|c: char| !c.is_whitespace())
+ {
+ let rhs_pos = span.lo()
+ + BytePos::from_usize(eq_idx + 2 + rhs_idx);
+ let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos);
+ sugg = Some(errors::ConsiderDereferencing {
+ deref,
+ span: span.shrink_to_lo(),
+ rhs_span,
+ });
+ }
}
}
}
+ _ => {}
}
- _ => {}
}
- }
- let mut err = tcx.sess.create_err(errors::NonConstOperator {
- span,
- kind: ccx.const_kind(),
- sugg,
- });
+ tcx.sess.create_err(errors::NonConstOperator {
+ span,
+ kind: ccx.const_kind(),
+ sugg,
+ })
+ };
+
diag_trait(&mut err, self_ty, trait_id);
err
}
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs
index 65fe164f8ec76..3a869f7f54721 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs
@@ -103,7 +103,7 @@ where
fn ref_allows_mutation(&self, kind: mir::BorrowKind, place: mir::Place<'tcx>) -> bool {
match kind {
mir::BorrowKind::Mut { .. } => true,
- mir::BorrowKind::Shared | mir::BorrowKind::Shallow | mir::BorrowKind::Unique => {
+ mir::BorrowKind::Shared | mir::BorrowKind::Shallow => {
self.shared_borrow_allows_mutation(place)
}
}
diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs
index 44b143c77f36e..dd80f745c2f0a 100644
--- a/compiler/rustc_const_eval/src/transform/promote_consts.rs
+++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs
@@ -454,7 +454,9 @@ impl<'tcx> Validator<'_, 'tcx> {
match kind {
// Reject these borrow types just to be safe.
// FIXME(RalfJung): could we allow them? Should we? No point in it until we have a usecase.
- BorrowKind::Shallow | BorrowKind::Unique => return Err(Unpromotable),
+ BorrowKind::Shallow | BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture } => {
+ return Err(Unpromotable);
+ }
BorrowKind::Shared => {
let has_mut_interior = self.qualif_local::(place.local);
@@ -463,7 +465,9 @@ impl<'tcx> Validator<'_, 'tcx> {
}
}
- BorrowKind::Mut { .. } => {
+ // FIXME: consider changing this to only promote &mut [] for default borrows,
+ // also forbidding two phase borrows
+ BorrowKind::Mut { kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow } => {
let ty = place.ty(self.body, self.tcx).ty;
// In theory, any zero-sized value could be borrowed
@@ -569,13 +573,18 @@ impl<'tcx> Validator<'_, 'tcx> {
| BinOp::Gt
| BinOp::Offset
| BinOp::Add
+ | BinOp::AddUnchecked
| BinOp::Sub
+ | BinOp::SubUnchecked
| BinOp::Mul
+ | BinOp::MulUnchecked
| BinOp::BitXor
| BinOp::BitAnd
| BinOp::BitOr
| BinOp::Shl
- | BinOp::Shr => {}
+ | BinOp::ShlUnchecked
+ | BinOp::Shr
+ | BinOp::ShrUnchecked => {}
}
self.validate_operand(lhs)?;
@@ -792,7 +801,9 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
};
match terminator.kind {
- TerminatorKind::Call { mut func, mut args, from_hir_call, fn_span, .. } => {
+ TerminatorKind::Call {
+ mut func, mut args, call_source: desugar, fn_span, ..
+ } => {
self.visit_operand(&mut func, loc);
for arg in &mut args {
self.visit_operand(arg, loc);
@@ -808,7 +819,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
unwind: UnwindAction::Continue,
destination: Place::from(new_temp),
target: Some(new_target),
- from_hir_call,
+ call_source: desugar,
fn_span,
},
source_info: SourceInfo::outermost(terminator.source_info.span),
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 3c350e25ba6ec..f197541da5bea 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -498,8 +498,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
macro_rules! check_kinds {
- ($t:expr, $text:literal, $($patterns:tt)*) => {
- if !matches!(($t).kind(), $($patterns)*) {
+ ($t:expr, $text:literal, $typat:pat) => {
+ if !matches!(($t).kind(), $typat) {
self.fail(location, format!($text, $t));
}
};
@@ -527,6 +527,25 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
use BinOp::*;
let a = vals.0.ty(&self.body.local_decls, self.tcx);
let b = vals.1.ty(&self.body.local_decls, self.tcx);
+ if crate::util::binop_right_homogeneous(*op) {
+ if let Eq | Lt | Le | Ne | Ge | Gt = op {
+ // The function pointer types can have lifetimes
+ if !self.mir_assign_valid_types(a, b) {
+ self.fail(
+ location,
+ format!("Cannot {op:?} compare incompatible types {a:?} and {b:?}"),
+ );
+ }
+ } else if a != b {
+ self.fail(
+ location,
+ format!(
+ "Cannot perform binary op {op:?} on unequal types {a:?} and {b:?}"
+ ),
+ );
+ }
+ }
+
match op {
Offset => {
check_kinds!(a, "Cannot offset non-pointer type {:?}", ty::RawPtr(..));
@@ -538,7 +557,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
for x in [a, b] {
check_kinds!(
x,
- "Cannot compare type {:?}",
+ "Cannot {op:?} compare type {:?}",
ty::Bool
| ty::Char
| ty::Int(..)
@@ -548,19 +567,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
| ty::FnPtr(..)
)
}
- // The function pointer types can have lifetimes
- if !self.mir_assign_valid_types(a, b) {
- self.fail(
- location,
- format!("Cannot compare unequal types {:?} and {:?}", a, b),
- );
- }
}
- Shl | Shr => {
+ AddUnchecked | SubUnchecked | MulUnchecked | Shl | ShlUnchecked | Shr
+ | ShrUnchecked => {
for x in [a, b] {
check_kinds!(
x,
- "Cannot shift non-integer type {:?}",
+ "Cannot {op:?} non-integer type {:?}",
ty::Uint(..) | ty::Int(..)
)
}
@@ -569,37 +582,19 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
for x in [a, b] {
check_kinds!(
x,
- "Cannot perform bitwise op on type {:?}",
+ "Cannot perform bitwise op {op:?} on type {:?}",
ty::Uint(..) | ty::Int(..) | ty::Bool
)
}
- if a != b {
- self.fail(
- location,
- format!(
- "Cannot perform bitwise op on unequal types {:?} and {:?}",
- a, b
- ),
- );
- }
}
Add | Sub | Mul | Div | Rem => {
for x in [a, b] {
check_kinds!(
x,
- "Cannot perform arithmetic on type {:?}",
+ "Cannot perform arithmetic {op:?} on type {:?}",
ty::Uint(..) | ty::Int(..) | ty::Float(..)
)
}
- if a != b {
- self.fail(
- location,
- format!(
- "Cannot perform arithmetic on unequal types {:?} and {:?}",
- a, b
- ),
- );
- }
}
}
}
diff --git a/compiler/rustc_const_eval/src/util/mod.rs b/compiler/rustc_const_eval/src/util/mod.rs
index 7641f560714d4..289e342259547 100644
--- a/compiler/rustc_const_eval/src/util/mod.rs
+++ b/compiler/rustc_const_eval/src/util/mod.rs
@@ -1,3 +1,5 @@
+use rustc_middle::mir;
+
mod alignment;
mod check_validity_requirement;
mod compare_types;
@@ -7,3 +9,27 @@ pub use self::alignment::is_disaligned;
pub use self::check_validity_requirement::check_validity_requirement;
pub use self::compare_types::{is_equal_up_to_subtyping, is_subtype};
pub use self::type_name::type_name;
+
+/// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
+/// same type as the result.
+#[inline]
+pub(crate) fn binop_left_homogeneous(op: mir::BinOp) -> bool {
+ use rustc_middle::mir::BinOp::*;
+ match op {
+ Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Div | Rem | BitXor
+ | BitAnd | BitOr | Offset | Shl | ShlUnchecked | Shr | ShrUnchecked => true,
+ Eq | Ne | Lt | Le | Gt | Ge => false,
+ }
+}
+
+/// Classify whether an operator is "right-homogeneous", i.e., the RHS has the
+/// same type as the LHS.
+#[inline]
+pub(crate) fn binop_right_homogeneous(op: mir::BinOp) -> bool {
+ use rustc_middle::mir::BinOp::*;
+ match op {
+ Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Div | Rem | BitXor
+ | BitAnd | BitOr | Eq | Ne | Lt | Le | Gt | Ge => true,
+ Offset | Shl | ShlUnchecked | Shr | ShrUnchecked => false,
+ }
+}
diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs
index 0c1fb7518fa3b..6d75b0fb8a0ca 100644
--- a/compiler/rustc_data_structures/src/stable_hasher.rs
+++ b/compiler/rustc_data_structures/src/stable_hasher.rs
@@ -1,6 +1,6 @@
use crate::sip128::SipHasher128;
use rustc_index::bit_set::{self, BitSet};
-use rustc_index::{Idx, IndexVec};
+use rustc_index::{Idx, IndexSlice, IndexVec};
use smallvec::SmallVec;
use std::fmt;
use std::hash::{BuildHasher, Hash, Hasher};
@@ -597,6 +597,18 @@ where
}
}
+impl HashStable for IndexSlice
+where
+ T: HashStable,
+{
+ fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
+ self.len().hash_stable(ctx, hasher);
+ for v in &self.raw {
+ v.hash_stable(ctx, hasher);
+ }
+ }
+}
+
impl HashStable for IndexVec
where
T: HashStable,
diff --git a/compiler/rustc_data_structures/src/unord.rs b/compiler/rustc_data_structures/src/unord.rs
index e18c7b415f6cf..2b21815b687d5 100644
--- a/compiler/rustc_data_structures/src/unord.rs
+++ b/compiler/rustc_data_structures/src/unord.rs
@@ -107,6 +107,10 @@ impl> UnordItems {
{
UnordItems(self.0.flat_map(f))
}
+
+ pub fn collect>>(self) -> C {
+ self.into()
+ }
}
impl UnordItems> {
@@ -161,10 +165,6 @@ impl> UnordItems {
items.sort_by_cached_key(|x| x.to_stable_hash_key(hcx));
items
}
-
- pub fn collect>>(self) -> C {
- self.into()
- }
}
/// This is a set collection type that tries very hard to not expose
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 2f1c78197275d..984cc1557a49b 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -97,6 +97,7 @@ pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[
rustc_codegen_ssa::DEFAULT_LOCALE_RESOURCE,
rustc_const_eval::DEFAULT_LOCALE_RESOURCE,
rustc_error_messages::DEFAULT_LOCALE_RESOURCE,
+ rustc_errors::DEFAULT_LOCALE_RESOURCE,
rustc_expand::DEFAULT_LOCALE_RESOURCE,
rustc_hir_analysis::DEFAULT_LOCALE_RESOURCE,
rustc_hir_typeck::DEFAULT_LOCALE_RESOURCE,
@@ -329,7 +330,7 @@ fn run_compiler(
return;
}
let should_stop =
- print_crate_info(&***compiler.codegen_backend(), compiler.session(), false);
+ print_crate_info(&**compiler.codegen_backend(), compiler.session(), false);
if should_stop == Compilation::Stop {
return;
@@ -351,7 +352,7 @@ fn run_compiler(
interface::run_compiler(config, |compiler| {
let sess = compiler.session();
- let should_stop = print_crate_info(&***compiler.codegen_backend(), sess, true)
+ let should_stop = print_crate_info(&**compiler.codegen_backend(), sess, true)
.and_then(|| list_metadata(sess, &*compiler.codegen_backend().metadata_loader()))
.and_then(|| try_process_rlink(sess, compiler));
@@ -424,7 +425,7 @@ fn run_compiler(
return early_exit();
}
- queries.ongoing_codegen()?;
+ let ongoing_codegen = queries.ongoing_codegen()?;
if sess.opts.unstable_opts.print_type_sizes {
sess.code_stats.print_type_sizes();
@@ -437,7 +438,7 @@ fn run_compiler(
sess.code_stats.print_vtable_sizes(crate_name);
}
- let linker = queries.linker()?;
+ let linker = queries.linker(ongoing_codegen)?;
Ok(Some(linker))
})?;
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index ee9616a0f0a9d..4a8a14994ff11 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -535,7 +535,7 @@ pub fn compile_declarative_macro(
.pop()
.unwrap();
}
- sess.parse_sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs")
+ sess.parse_sess.span_diagnostic.span_bug(def.span, "wrong-structured rhs")
})
.collect::>(),
_ => sess.parse_sess.span_diagnostic.span_bug(def.span, "wrong-structured rhs"),
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 4c53f9d8369fd..93f968aa851d3 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -395,6 +395,8 @@ declare_features! (
(active, exclusive_range_pattern, "1.11.0", Some(37854), None),
/// Allows exhaustive pattern matching on types that contain uninhabited types.
(active, exhaustive_patterns, "1.13.0", Some(51085), None),
+ /// Allows explicit tail calls via `become` expression.
+ (incomplete, explicit_tail_calls, "CURRENT_RUSTC_VERSION", Some(112788), None),
/// Allows using `efiapi`, `sysv64` and `win64` as calling convention
/// for functions with varargs.
(active, extended_varargs_abi_support, "1.65.0", Some(100189), None),
@@ -440,6 +442,8 @@ declare_features! (
(active, intra_doc_pointers, "1.51.0", Some(80896), None),
// Allows setting the threshold for the `large_assignments` lint.
(active, large_assignments, "1.52.0", Some(83518), None),
+ /// Allow to have type alias types for inter-crate use.
+ (active, lazy_type_alias, "CURRENT_RUSTC_VERSION", Some(112792), None),
/// Allows `if/while p && let q = r && ...` chains.
(active, let_chains, "1.37.0", Some(53667), None),
/// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check.
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 9be28c338f64b..3c5bff3812a94 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -705,7 +705,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
"#[rustc_allow_incoherent_impl] has to be added to all impl items of an incoherent inherent impl."
),
rustc_attr!(
- rustc_deny_explicit_impl, AttributeType::Normal, template!(Word), ErrorFollowing, @only_local: false,
+ rustc_deny_explicit_impl,
+ AttributeType::Normal,
+ template!(List: "implement_via_object = (true|false)"),
+ ErrorFollowing,
+ @only_local: true,
"#[rustc_deny_explicit_impl] enforces that a trait can have no user-provided impls"
),
rustc_attr!(
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 70fc66947df99..5e5001bc8b450 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -3743,6 +3743,29 @@ impl<'hir> Node<'hir> {
}
}
+ /// Get the type for constants, assoc types, type aliases and statics.
+ pub fn ty(self) -> Option<&'hir Ty<'hir>> {
+ match self {
+ Node::Item(it) => match it.kind {
+ ItemKind::TyAlias(ty, _) | ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _) => {
+ Some(ty)
+ }
+ _ => None,
+ },
+ Node::TraitItem(it) => match it.kind {
+ TraitItemKind::Const(ty, _) => Some(ty),
+ TraitItemKind::Type(_, ty) => ty,
+ _ => None,
+ },
+ Node::ImplItem(it) => match it.kind {
+ ImplItemKind::Const(ty, _) => Some(ty),
+ ImplItemKind::Type(ty) => Some(ty),
+ _ => None,
+ },
+ _ => None,
+ }
+ }
+
pub fn alias_ty(self) -> Option<&'hir Ty<'hir>> {
match self {
Node::Item(Item { kind: ItemKind::TyAlias(ty, ..), .. }) => Some(ty),
diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
index e4eb0e6abd435..d29601e9008c3 100644
--- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
@@ -412,7 +412,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
// an RPITIT (return-position impl trait in trait) or AFIT (async fn in trait).
let output = tcx.fn_sig(assoc_item.def_id).skip_binder().output();
let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind()
- && tcx.def_kind(alias_ty.def_id) == DefKind::ImplTraitPlaceholder
+ && tcx.is_impl_trait_in_trait(alias_ty.def_id)
{
alias_ty
} else {
diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs
index 7b922f5d52599..dc17ef7048d01 100644
--- a/compiler/rustc_hir_analysis/src/astconv/errors.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs
@@ -122,9 +122,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let all_candidate_names: Vec<_> = all_candidates()
.flat_map(|r| self.tcx().associated_items(r.def_id()).in_definition_order())
- .filter_map(
- |item| if item.kind == ty::AssocKind::Type { Some(item.name) } else { None },
- )
+ .filter_map(|item| {
+ if item.opt_rpitit_info.is_none() && item.kind == ty::AssocKind::Type {
+ Some(item.name)
+ } else {
+ None
+ }
+ })
.collect();
if let (Some(suggested_name), true) = (
@@ -159,9 +163,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.flat_map(|trait_def_id| {
self.tcx().associated_items(*trait_def_id).in_definition_order()
})
- .filter_map(
- |item| if item.kind == ty::AssocKind::Type { Some(item.name) } else { None },
- )
+ .filter_map(|item| {
+ if item.opt_rpitit_info.is_none() && item.kind == ty::AssocKind::Type {
+ Some(item.name)
+ } else {
+ None
+ }
+ })
.collect();
if let (Some(suggested_name), true) = (
@@ -343,7 +351,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let format_pred = |pred: ty::Predicate<'tcx>| {
let bound_predicate = pred.kind();
match bound_predicate.skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
let pred = bound_predicate.rebind(pred);
// `::Item = String`.
let projection_ty = pred.skip_binder().projection_ty;
@@ -364,7 +372,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
Some((obligation, projection_ty.self_ty()))
}
- ty::PredicateKind::Clause(ty::Clause::Trait(poly_trait_ref)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(poly_trait_ref)) => {
let p = poly_trait_ref.trait_ref;
let self_ty = p.self_ty();
let path = p.print_only_trait_path();
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 621569ab3215d..41a6d94b27885 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -896,7 +896,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let ty = self.tcx().at(span).type_of(did);
if matches!(self.tcx().def_kind(did), DefKind::TyAlias)
- && ty.skip_binder().has_opaque_types()
+ && (ty.skip_binder().has_opaque_types() || self.tcx().features().lazy_type_alias)
{
// Type aliases referring to types that contain opaque types (but aren't just directly
// referencing a single opaque type) get encoded as a type alias that normalization will
@@ -945,12 +945,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let mut trait_bounds = vec![];
let mut projection_bounds = vec![];
- for (clause, span) in bounds.predicates() {
- let pred: ty::Predicate<'tcx> = clause.to_predicate(tcx);
+ for (clause, span) in bounds.clauses() {
+ let pred: ty::Predicate<'tcx> = clause.as_predicate();
let bound_pred = pred.kind();
match bound_pred.skip_binder() {
ty::PredicateKind::Clause(clause) => match clause {
- ty::Clause::Trait(trait_pred) => {
+ ty::ClauseKind::Trait(trait_pred) => {
assert_eq!(trait_pred.polarity, ty::ImplPolarity::Positive);
trait_bounds.push((
bound_pred.rebind(trait_pred.trait_ref),
@@ -958,16 +958,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
trait_pred.constness,
));
}
- ty::Clause::Projection(proj) => {
+ ty::ClauseKind::Projection(proj) => {
projection_bounds.push((bound_pred.rebind(proj), span));
}
- ty::Clause::TypeOutlives(_) => {
+ ty::ClauseKind::TypeOutlives(_) => {
// Do nothing, we deal with regions separately
}
- ty::Clause::RegionOutlives(_)
- | ty::Clause::ConstArgHasType(..)
- | ty::Clause::WellFormed(_)
- | ty::Clause::ConstEvaluatable(_) => bug!(),
+ ty::ClauseKind::RegionOutlives(_)
+ | ty::ClauseKind::ConstArgHasType(..)
+ | ty::ClauseKind::WellFormed(_)
+ | ty::ClauseKind::ConstEvaluatable(_) => {
+ bug!()
+ }
},
ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::ObjectSafe(_)
@@ -1064,7 +1066,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let bound_predicate = pred.kind();
match bound_predicate.skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
let pred = bound_predicate.rebind(pred);
associated_types.entry(span).or_default().extend(
tcx.associated_items(pred.def_id())
@@ -1074,7 +1076,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.map(|item| item.def_id),
);
}
- ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
let pred = bound_predicate.rebind(pred);
// A `Self` within the original bound will be substituted with a
// `trait_object_dummy_self`, so check for that.
diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs
index 8a318e984d7ae..531100e1fe61b 100644
--- a/compiler/rustc_hir_analysis/src/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/bounds.rs
@@ -2,7 +2,6 @@
//! `ty` form from the HIR.
use rustc_hir::LangItem;
-use rustc_middle::ty::Binder;
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
use rustc_span::Span;
@@ -24,58 +23,58 @@ use rustc_span::Span;
/// include the self type (e.g., `trait_bounds`) but in others we do not
#[derive(Default, PartialEq, Eq, Clone, Debug)]
pub struct Bounds<'tcx> {
- pub predicates: Vec<(Binder<'tcx, ty::Clause<'tcx>>, Span)>,
+ pub clauses: Vec<(ty::Clause<'tcx>, Span)>,
}
impl<'tcx> Bounds<'tcx> {
pub fn push_region_bound(
&mut self,
- _tcx: TyCtxt<'tcx>,
+ tcx: TyCtxt<'tcx>,
region: ty::PolyTypeOutlivesPredicate<'tcx>,
span: Span,
) {
- self.predicates.push((region.map_bound(|p| ty::Clause::TypeOutlives(p)), span));
+ self.clauses
+ .push((region.map_bound(|p| ty::ClauseKind::TypeOutlives(p)).to_predicate(tcx), span));
}
pub fn push_trait_bound(
&mut self,
- _tcx: TyCtxt<'tcx>,
+ tcx: TyCtxt<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
span: Span,
constness: ty::BoundConstness,
polarity: ty::ImplPolarity,
) {
- self.predicates.push((
- trait_ref.map_bound(|trait_ref| {
- ty::Clause::Trait(ty::TraitPredicate { trait_ref, constness, polarity })
- }),
+ self.clauses.push((
+ trait_ref
+ .map_bound(|trait_ref| {
+ ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, constness, polarity })
+ })
+ .to_predicate(tcx),
span,
));
}
pub fn push_projection_bound(
&mut self,
- _tcx: TyCtxt<'tcx>,
+ tcx: TyCtxt<'tcx>,
projection: ty::PolyProjectionPredicate<'tcx>,
span: Span,
) {
- self.predicates.push((projection.map_bound(|proj| ty::Clause::Projection(proj)), span));
+ self.clauses.push((
+ projection.map_bound(|proj| ty::ClauseKind::Projection(proj)).to_predicate(tcx),
+ span,
+ ));
}
pub fn push_sized(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) {
let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span));
let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [ty]);
// Preferable to put this obligation first, since we report better errors for sized ambiguity.
- self.predicates.insert(
- 0,
- (
- ty::Binder::dummy(ty::Clause::Trait(trait_ref.without_const().to_predicate(tcx))),
- span,
- ),
- );
+ self.clauses.insert(0, (trait_ref.to_predicate(tcx), span));
}
- pub fn predicates(&self) -> impl Iterator- >, Span)> + '_ {
- self.predicates.iter().cloned()
+ pub fn clauses(&self) -> impl Iterator
- , Span)> + '_ {
+ self.clauses.iter().cloned()
}
}
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index c09734d6e6983..a7e81f41c6996 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -440,7 +440,7 @@ fn check_opaque_meets_bounds<'tcx>(
// Defining use functions may have more bounds than the opaque type, which is ok, as long as the
// hidden type is well formed even without those bounds.
let predicate =
- ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::WellFormed(hidden_ty.into())));
+ ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(hidden_ty.into())));
ocx.register_obligation(Obligation::new(tcx, misc_cause, param_env, predicate));
// Check that all obligations are satisfied by the implementation's
@@ -563,8 +563,8 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
check_union(tcx, id.owner_id.def_id);
}
DefKind::OpaqueTy => {
- let opaque = tcx.hir().expect_item(id.owner_id.def_id).expect_opaque_ty();
- if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = opaque.origin
+ let origin = tcx.opaque_type_origin(id.owner_id.def_id);
+ if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = origin
&& let hir::Node::TraitItem(trait_item) = tcx.hir().get_by_def_id(fn_def_id)
&& let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn()
{
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 838b212ef8782..b2ba566f60c74 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -321,7 +321,7 @@ fn compare_method_predicate_entailment<'tcx>(
infcx.tcx,
ObligationCause::dummy(),
param_env,
- ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::WellFormed(
+ ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
unnormalized_impl_fty.into(),
))),
));
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index c9e74896ac08e..596c5518086d6 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -304,7 +304,7 @@ fn bounds_from_generic_predicates<'tcx>(
debug!("predicate {:?}", predicate);
let bound_predicate = predicate.kind();
match bound_predicate.skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {
let entry = types.entry(trait_predicate.self_ty()).or_default();
let def_id = trait_predicate.def_id();
if Some(def_id) != tcx.lang_items().sized_trait() {
@@ -313,7 +313,7 @@ fn bounds_from_generic_predicates<'tcx>(
entry.push(trait_predicate.def_id());
}
}
- ty::PredicateKind::Clause(ty::Clause::Projection(projection_pred)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::Projection(projection_pred)) => {
projections.push(bound_predicate.rebind(projection_pred));
}
_ => {}
@@ -403,7 +403,30 @@ fn fn_sig_suggestion<'tcx>(
.flatten()
.collect::>()
.join(", ");
- let output = sig.output();
+ let mut output = sig.output();
+
+ let asyncness = if tcx.asyncness(assoc.def_id).is_async() {
+ output = if let ty::Alias(_, alias_ty) = *output.kind() {
+ tcx.explicit_item_bounds(alias_ty.def_id)
+ .subst_iter_copied(tcx, alias_ty.substs)
+ .find_map(|(bound, _)| bound.as_projection_clause()?.no_bound_vars()?.term.ty())
+ .unwrap_or_else(|| {
+ span_bug!(
+ ident.span,
+ "expected async fn to have `impl Future` output, but it returns {output}"
+ )
+ })
+ } else {
+ span_bug!(
+ ident.span,
+ "expected async fn to have `impl Future` output, but it returns {output}"
+ )
+ };
+ "async "
+ } else {
+ ""
+ };
+
let output = if !output.is_unit() { format!(" -> {output}") } else { String::new() };
let unsafety = sig.unsafety.prefix_str();
@@ -414,7 +437,9 @@ fn fn_sig_suggestion<'tcx>(
// lifetimes between the `impl` and the `trait`, but this should be good enough to
// fill in a significant portion of the missing code, and other subsequent
// suggestions can help the user fix the code.
- format!("{unsafety}fn {ident}{generics}({args}){output}{where_clauses} {{ todo!() }}")
+ format!(
+ "{unsafety}{asyncness}fn {ident}{generics}({args}){output}{where_clauses} {{ todo!() }}"
+ )
}
pub fn ty_kind_suggestion(ty: Ty<'_>) -> Option<&'static str> {
@@ -443,19 +468,16 @@ fn suggestion_signature<'tcx>(
);
match assoc.kind {
- ty::AssocKind::Fn => {
- // We skip the binder here because the binder would deanonymize all
- // late-bound regions, and we don't want method signatures to show up
- // `as for<'r> fn(&'r MyType)`. Pretty-printing handles late-bound
- // regions just fine, showing `fn(&MyType)`.
- fn_sig_suggestion(
- tcx,
- tcx.fn_sig(assoc.def_id).subst(tcx, substs).skip_binder(),
- assoc.ident(tcx),
- tcx.predicates_of(assoc.def_id).instantiate_own(tcx, substs),
- assoc,
- )
- }
+ ty::AssocKind::Fn => fn_sig_suggestion(
+ tcx,
+ tcx.liberate_late_bound_regions(
+ assoc.def_id,
+ tcx.fn_sig(assoc.def_id).subst(tcx, substs),
+ ),
+ assoc.ident(tcx),
+ tcx.predicates_of(assoc.def_id).instantiate_own(tcx, substs),
+ assoc,
+ ),
ty::AssocKind::Type => {
let (generics, where_clauses) = bounds_from_generic_predicates(
tcx,
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 73a7ba005b330..744eb03693358 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -81,7 +81,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
self.tcx(),
cause,
param_env,
- ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::WellFormed(arg))),
+ ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg))),
));
}
}
@@ -419,10 +419,9 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
let mut unsatisfied_bounds: Vec<_> = required_bounds
.into_iter()
.filter(|clause| match clause.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::RegionOutlives(ty::OutlivesPredicate(
- a,
- b,
- ))) => !region_known_to_outlive(
+ ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(
+ ty::OutlivesPredicate(a, b),
+ )) => !region_known_to_outlive(
tcx,
gat_def_id.def_id,
param_env,
@@ -430,7 +429,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
a,
b,
),
- ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
+ ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
a,
b,
))) => !ty_known_to_outlive(
@@ -574,7 +573,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable>>(
);
// The predicate we expect to see. (In our example,
// `Self: 'me`.)
- let clause = ty::PredicateKind::Clause(ty::Clause::TypeOutlives(
+ let clause = ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(
ty::OutlivesPredicate(ty_param, region_param),
));
let clause = tcx.mk_predicate(ty::Binder::dummy(clause));
@@ -623,7 +622,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable>>(
},
);
// The predicate we expect to see.
- let clause = ty::PredicateKind::Clause(ty::Clause::RegionOutlives(
+ let clause = ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(
ty::OutlivesPredicate(region_a_param, region_b_param),
));
let clause = tcx.mk_predicate(ty::Binder::dummy(clause));
@@ -1032,7 +1031,7 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
tcx,
cause,
wfcx.param_env,
- ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(
+ ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(
ty::Const::from_anon_const(tcx, discr_def_id.expect_local()),
))),
));
@@ -1087,7 +1086,7 @@ fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocIt
wfcx.infcx,
wfcx.param_env,
wfcx.body_def_id,
- normalized_bound,
+ normalized_bound.as_predicate(),
bound_span,
)
});
@@ -1544,8 +1543,8 @@ impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> {
if let ty::Alias(ty::Opaque, unshifted_opaque_ty) = *ty.kind()
&& self.seen.insert(unshifted_opaque_ty.def_id)
&& let Some(opaque_def_id) = unshifted_opaque_ty.def_id.as_local()
- && let opaque = tcx.hir().expect_item(opaque_def_id).expect_opaque_ty()
- && let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin
+ && let origin = tcx.opaque_type_origin(opaque_def_id)
+ && let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = origin
&& source == self.fn_def_id
{
let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, _depth| {
@@ -1563,7 +1562,7 @@ impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> {
self.wfcx.infcx,
self.wfcx.param_env,
self.wfcx.body_def_id,
- bound,
+ bound.as_predicate(),
bound_span,
));
// Set the debruijn index back to innermost here, since we already eagerly
@@ -1876,7 +1875,8 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
// We lower empty bounds like `Vec:` as
// `WellFormed(Vec)`, which will later get checked by
// regular WF checking
- if let ty::PredicateKind::Clause(ty::Clause::WellFormed(..)) = pred.kind().skip_binder()
+ if let ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) =
+ pred.kind().skip_binder()
{
continue;
}
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index a98d8e17153d8..2441c8667d49a 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -571,7 +571,7 @@ fn infringing_fields_error(
.or_default()
.push(error.obligation.cause.span);
}
- if let ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate {
+ if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
trait_ref,
polarity: ty::ImplPolarity::Positive,
..
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index 4524b87a418aa..5097f43607e85 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -10,7 +10,6 @@ use rustc_errors::{error_code, struct_span_err};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
-use rustc_span::sym;
use rustc_trait_selection::traits;
mod builtin;
@@ -44,7 +43,7 @@ fn enforce_trait_manually_implementable(
let impl_header_span = tcx.def_span(impl_def_id);
// Disallow *all* explicit impls of traits marked `#[rustc_deny_explicit_impl]`
- if tcx.has_attr(trait_def_id, sym::rustc_deny_explicit_impl) {
+ if tcx.trait_def(trait_def_id).deny_explicit_impl {
let trait_name = tcx.item_name(trait_def_id);
let mut err = struct_span_err!(
tcx.sess,
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 8b5c1791fc139..eba943e0072c5 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -991,6 +991,50 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
no_dups.then_some(list)
});
+ let mut deny_explicit_impl = false;
+ let mut implement_via_object = true;
+ if let Some(attr) = tcx.get_attr(def_id, sym::rustc_deny_explicit_impl) {
+ deny_explicit_impl = true;
+ let mut seen_attr = false;
+ for meta in attr.meta_item_list().iter().flatten() {
+ if let Some(meta) = meta.meta_item()
+ && meta.name_or_empty() == sym::implement_via_object
+ && let Some(lit) = meta.name_value_literal()
+ {
+ if seen_attr {
+ tcx.sess.span_err(
+ meta.span,
+ "duplicated `implement_via_object` meta item",
+ );
+ }
+ seen_attr = true;
+
+ match lit.symbol {
+ kw::True => {
+ implement_via_object = true;
+ }
+ kw::False => {
+ implement_via_object = false;
+ }
+ _ => {
+ tcx.sess.span_err(
+ meta.span,
+ format!("unknown literal passed to `implement_via_object` attribute: {}", lit.symbol),
+ );
+ }
+ }
+ } else {
+ tcx.sess.span_err(
+ meta.span(),
+ format!("unknown meta item passed to `rustc_deny_explicit_impl` {:?}", meta),
+ );
+ }
+ }
+ if !seen_attr {
+ tcx.sess.span_err(attr.span, "missing `implement_via_object` meta item");
+ }
+ }
+
ty::TraitDef {
def_id: def_id.to_def_id(),
unsafety,
@@ -1001,6 +1045,8 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
skip_array_during_method_dispatch,
specialization_kind,
must_implement_one_of,
+ implement_via_object,
+ deny_explicit_impl,
}
}
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 0479efceaad90..958313fee6fb7 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -3,7 +3,6 @@ use crate::astconv::{AstConv, OnlySelfBounds};
use rustc_hir as hir;
use rustc_infer::traits::util;
use rustc_middle::ty::subst::InternalSubsts;
-use rustc_middle::ty::ToPredicate;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::Span;
@@ -20,7 +19,7 @@ fn associated_type_bounds<'tcx>(
assoc_item_def_id: LocalDefId,
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
span: Span,
-) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
+) -> &'tcx [(ty::Clause<'tcx>, Span)] {
let item_ty = tcx.mk_projection(
assoc_item_def_id.to_def_id(),
InternalSubsts::identity_for_item(tcx, assoc_item_def_id),
@@ -34,23 +33,23 @@ fn associated_type_bounds<'tcx>(
let trait_def_id = tcx.local_parent(assoc_item_def_id);
let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id);
- let bounds_from_parent = trait_predicates.predicates.iter().copied().filter(|(pred, _)| {
- match pred.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(tr)) => tr.self_ty() == item_ty,
- ty::PredicateKind::Clause(ty::Clause::Projection(proj)) => {
+ let bounds_from_parent = trait_predicates
+ .predicates
+ .iter()
+ .copied()
+ .filter(|(pred, _)| match pred.kind().skip_binder() {
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr)) => tr.self_ty() == item_ty,
+ ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) => {
proj.projection_ty.self_ty() == item_ty
}
- ty::PredicateKind::Clause(ty::Clause::TypeOutlives(outlives)) => outlives.0 == item_ty,
+ ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(outlives)) => {
+ outlives.0 == item_ty
+ }
_ => false,
- }
- });
+ })
+ .map(|(pred, span)| (pred.expect_clause(), span));
- let all_bounds = tcx.arena.alloc_from_iter(
- bounds
- .predicates()
- .map(|(clause, span)| (clause.to_predicate(tcx), span))
- .chain(bounds_from_parent),
- );
+ let all_bounds = tcx.arena.alloc_from_iter(bounds.clauses().chain(bounds_from_parent));
debug!(
"associated_type_bounds({}) = {:?}",
tcx.def_path_str(assoc_item_def_id.to_def_id()),
@@ -70,7 +69,7 @@ fn opaque_type_bounds<'tcx>(
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
item_ty: Ty<'tcx>,
span: Span,
-) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
+) -> &'tcx [(ty::Clause<'tcx>, Span)] {
ty::print::with_no_queries!({
let icx = ItemCtxt::new(tcx, opaque_def_id);
let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, OnlySelfBounds(false));
@@ -78,16 +77,14 @@ fn opaque_type_bounds<'tcx>(
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
debug!(?bounds);
- tcx.arena.alloc_from_iter(
- bounds.predicates().map(|(clause, span)| (clause.to_predicate(tcx), span)),
- )
+ tcx.arena.alloc_from_iter(bounds.clauses())
})
}
pub(super) fn explicit_item_bounds(
tcx: TyCtxt<'_>,
def_id: LocalDefId,
-) -> ty::EarlyBinder<&'_ [(ty::Predicate<'_>, Span)]> {
+) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> {
match tcx.opt_rpitit_info(def_id.to_def_id()) {
// RPITIT's bounds are the same as opaque type bounds, but with
// a projection self type.
@@ -139,11 +136,8 @@ pub(super) fn explicit_item_bounds(
pub(super) fn item_bounds(
tcx: TyCtxt<'_>,
def_id: DefId,
-) -> ty::EarlyBinder<&'_ ty::List>> {
+) -> ty::EarlyBinder<&'_ ty::List>> {
tcx.explicit_item_bounds(def_id).map_bound(|bounds| {
- tcx.mk_predicates_from_iter(util::elaborate(
- tcx,
- bounds.iter().map(|&(bound, _span)| bound),
- ))
+ tcx.mk_clauses_from_iter(util::elaborate(tcx, bounds.iter().map(|&(bound, _span)| bound)))
})
}
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index c905db0617409..3081f0c386a27 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -126,8 +126,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
predicates.extend(
icx.astconv()
.compute_bounds(tcx.types.self_param, self_bounds, OnlySelfBounds(false))
- .predicates()
- .map(|(clause, span)| (clause.to_predicate(tcx), span)),
+ .clauses()
+ .map(|(clause, span)| (clause.as_predicate(), span)),
);
}
@@ -176,9 +176,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
param.span,
);
trace!(?bounds);
- predicates.extend(
- bounds.predicates().map(|(clause, span)| (clause.to_predicate(tcx), span)),
- );
+ predicates
+ .extend(bounds.clauses().map(|(clause, span)| (clause.as_predicate(), span)));
trace!(?predicates);
}
GenericParamKind::Const { .. } => {
@@ -190,7 +189,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
let ct = tcx.mk_const(param_const, ct_ty);
let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(
- ty::Clause::ConstArgHasType(ct, ct_ty),
+ ty::ClauseKind::ConstArgHasType(ct, ct_ty),
))
.to_predicate(tcx);
predicates.insert((predicate, param.span));
@@ -222,7 +221,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
} else {
let span = bound_pred.bounded_ty.span;
let predicate = ty::Binder::bind_with_vars(
- ty::PredicateKind::Clause(ty::Clause::WellFormed(ty.into())),
+ ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(ty.into())),
bound_vars,
);
predicates.insert((predicate.to_predicate(tcx), span));
@@ -237,9 +236,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
bound_vars,
OnlySelfBounds(false),
);
- predicates.extend(
- bounds.predicates().map(|(clause, span)| (clause.to_predicate(tcx), span)),
- );
+ predicates
+ .extend(bounds.clauses().map(|(clause, span)| (clause.as_predicate(), span)));
}
hir::WherePredicate::RegionPredicate(region_pred) => {
@@ -252,7 +250,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
_ => bug!(),
};
let pred = ty::Binder::dummy(ty::PredicateKind::Clause(
- ty::Clause::RegionOutlives(ty::OutlivesPredicate(r1, r2)),
+ ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)),
))
.to_predicate(icx.tcx);
@@ -320,14 +318,14 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
},
);
predicates.push((
- ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::RegionOutlives(
+ ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(
ty::OutlivesPredicate(orig_region, dup_region),
)))
.to_predicate(icx.tcx),
duplicate.span,
));
predicates.push((
- ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::RegionOutlives(
+ ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(
ty::OutlivesPredicate(dup_region, orig_region),
)))
.to_predicate(icx.tcx),
@@ -358,8 +356,10 @@ fn const_evaluatable_predicates_of(
if let ty::ConstKind::Unevaluated(_) = ct.kind() {
let span = self.tcx.def_span(c.def_id);
self.preds.insert((
- ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(ct)))
- .to_predicate(self.tcx),
+ ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(
+ ct,
+ )))
+ .to_predicate(self.tcx),
span,
));
}
@@ -449,11 +449,13 @@ pub(super) fn explicit_predicates_of<'tcx>(
.iter()
.copied()
.filter(|(pred, _)| match pred.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(tr)) => !is_assoc_item_ty(tr.self_ty()),
- ty::PredicateKind::Clause(ty::Clause::Projection(proj)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr)) => {
+ !is_assoc_item_ty(tr.self_ty())
+ }
+ ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) => {
!is_assoc_item_ty(proj.projection_ty.self_ty())
}
- ty::PredicateKind::Clause(ty::Clause::TypeOutlives(outlives)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(outlives)) => {
!is_assoc_item_ty(outlives.0)
}
_ => true,
@@ -496,7 +498,7 @@ pub(super) fn explicit_predicates_of<'tcx>(
.predicates
.into_iter()
.filter(|(pred, _)| {
- if let ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, _)) =
+ if let ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, _)) =
pred.kind().skip_binder()
{
match ct.kind() {
@@ -665,8 +667,8 @@ pub(super) fn implied_predicates_with_filter(
// Combine the two lists to form the complete set of superbounds:
let implied_bounds = &*tcx.arena.alloc_from_iter(
superbounds
- .predicates()
- .map(|(clause, span)| (clause.to_predicate(tcx), span))
+ .clauses()
+ .map(|(clause, span)| (clause.as_predicate(), span))
.chain(where_bounds_that_match),
);
debug!(?implied_bounds);
@@ -677,7 +679,7 @@ pub(super) fn implied_predicates_with_filter(
if matches!(filter, PredicateFilter::SelfOnly) {
for &(pred, span) in implied_bounds {
debug!("superbound: {:?}", pred);
- if let ty::PredicateKind::Clause(ty::Clause::Trait(bound)) = pred.kind().skip_binder()
+ if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(bound)) = pred.kind().skip_binder()
&& bound.polarity == ty::ImplPolarity::Positive
{
tcx.at(span).super_predicates_of(bound.def_id());
@@ -774,7 +776,9 @@ pub(super) fn type_param_predicates(
)
.into_iter()
.filter(|(predicate, _)| match predicate.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(data)) => data.self_ty().is_param(index),
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
+ data.self_ty().is_param(index)
+ }
_ => false,
}),
);
@@ -825,7 +829,7 @@ impl<'tcx> ItemCtxt<'tcx> {
);
}
- bounds.predicates().map(|(clause, span)| (clause.to_predicate(self.tcx), span)).collect()
+ bounds.clauses().map(|(clause, span)| (clause.as_predicate(), span)).collect()
}
#[instrument(level = "trace", skip(self))]
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 794812a5ce7d9..d20f39e9b05b9 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -1761,7 +1761,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| {
let bound_predicate = pred.kind();
match bound_predicate.skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(data)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
// The order here needs to match what we would get from `subst_supertrait`
let pred_bound_vars = bound_predicate.bound_vars();
let mut all_bound_vars = bound_vars.clone();
diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
index 9200c2aecf55c..6aecb95b484a1 100644
--- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
+++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
@@ -187,7 +187,7 @@ pub fn setup_constraining_predicates<'tcx>(
for j in i..predicates.len() {
// Note that we don't have to care about binders here,
// as the impl trait ref never contains any late-bound regions.
- if let ty::PredicateKind::Clause(ty::Clause::Projection(projection)) =
+ if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(projection)) =
predicates[j].0.kind().skip_binder()
{
// Special case: watch out for some kind of sneaky attempt
diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
index f2618b3daf147..f1765174d79de 100644
--- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
@@ -79,7 +79,7 @@ fn diagnostic_hir_wf_check<'tcx>(
self.tcx,
cause,
self.param_env,
- ty::PredicateKind::Clause(ty::Clause::WellFormed(tcx_ty.into())),
+ ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(tcx_ty.into())),
));
for error in ocx.select_all_or_error() {
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
index 201cb94f0b319..97813a291da62 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
@@ -236,7 +236,7 @@ fn unconstrained_parent_impl_substs<'tcx>(
// the functions in `cgp` add the constrained parameters to a list of
// unconstrained parameters.
for (predicate, _) in impl_generic_predicates.predicates.iter() {
- if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) =
+ if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) =
predicate.kind().skip_binder()
{
let projection_ty = proj.projection_ty;
@@ -438,8 +438,8 @@ fn trait_predicates_eq<'tcx>(
let pred2_kind = predicate2.kind().skip_binder();
let (trait_pred1, trait_pred2) = match (pred1_kind, pred2_kind) {
(
- ty::PredicateKind::Clause(ty::Clause::Trait(pred1)),
- ty::PredicateKind::Clause(ty::Clause::Trait(pred2)),
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred1)),
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred2)),
) => (pred1, pred2),
// Just use plain syntactic equivalence if either of the predicates aren't
// trait predicates or have bound vars.
@@ -478,7 +478,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
_ if predicate.is_global() => (),
// We allow specializing on explicitly marked traits with no associated
// items.
- ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate {
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
trait_ref,
constness: _,
polarity: _,
@@ -498,7 +498,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
.emit();
}
}
- ty::PredicateKind::Clause(ty::Clause::Projection(ty::ProjectionPredicate {
+ ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate {
projection_ty,
term,
})) => {
@@ -509,7 +509,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
)
.emit();
}
- ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) => {
// FIXME(min_specialization), FIXME(const_generics):
// It probably isn't right to allow _every_ `ConstArgHasType` but I am somewhat unsure
// about the actual rules that would be sound. Can't just always error here because otherwise
@@ -532,22 +532,22 @@ fn trait_predicate_kind<'tcx>(
predicate: ty::Predicate<'tcx>,
) -> Option {
match predicate.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate {
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
trait_ref,
constness: _,
polarity: _,
})) => Some(tcx.trait_def(trait_ref.def_id).specialization_kind),
- ty::PredicateKind::Clause(ty::Clause::RegionOutlives(_))
- | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(_))
- | ty::PredicateKind::Clause(ty::Clause::Projection(_))
- | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
+ ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(_))
+ | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(_))
+ | ty::PredicateKind::Clause(ty::ClauseKind::Projection(_))
+ | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
| ty::PredicateKind::AliasRelate(..)
- | ty::PredicateKind::Clause(ty::Clause::WellFormed(_))
+ | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_))
| ty::PredicateKind::Subtype(_)
| ty::PredicateKind::Coerce(_)
| ty::PredicateKind::ObjectSafe(_)
| ty::PredicateKind::ClosureKind(..)
- | ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(..))
+ | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::Ambiguous
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs
index 79c56490f3c1a..e63549998d2ac 100644
--- a/compiler/rustc_hir_analysis/src/outlives/explicit.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs
@@ -30,7 +30,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
// process predicates and convert to `RequiredPredicates` entry, see below
for &(predicate, span) in predicates.predicates {
match predicate.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::TypeOutlives(OutlivesPredicate(
+ ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(OutlivesPredicate(
ty,
reg,
))) => insert_outlives_predicate(
@@ -41,10 +41,9 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
&mut required_predicates,
),
- ty::PredicateKind::Clause(ty::Clause::RegionOutlives(OutlivesPredicate(
- reg1,
- reg2,
- ))) => insert_outlives_predicate(
+ ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(
+ OutlivesPredicate(reg1, reg2),
+ )) => insert_outlives_predicate(
tcx,
reg1.into(),
reg2,
@@ -52,16 +51,16 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
&mut required_predicates,
),
- ty::PredicateKind::Clause(ty::Clause::Trait(..))
- | ty::PredicateKind::Clause(ty::Clause::Projection(..))
- | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
- | ty::PredicateKind::Clause(ty::Clause::WellFormed(..))
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(..))
+ | ty::PredicateKind::Clause(ty::ClauseKind::Projection(..))
+ | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
+ | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..))
| ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::Coerce(..)
- | ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(..))
+ | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::Ambiguous
| ty::PredicateKind::TypeWellFormedFromEnv(..) => (),
diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs
index fdbb890ce3d47..48624cefe4d02 100644
--- a/compiler/rustc_hir_analysis/src/outlives/mod.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs
@@ -3,7 +3,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::query::Providers;
use rustc_middle::ty::subst::GenericArgKind;
-use rustc_middle::ty::{self, CratePredicatesMap, TyCtxt};
+use rustc_middle::ty::{self, CratePredicatesMap, ToPredicate, TyCtxt};
use rustc_span::symbol::sym;
use rustc_span::Span;
@@ -52,9 +52,9 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clau
if tcx.has_attr(item_def_id, sym::rustc_outlives) {
let mut pred: Vec = predicates
.iter()
- .map(|(out_pred, _)| match out_pred {
- ty::Clause::RegionOutlives(p) => p.to_string(),
- ty::Clause::TypeOutlives(p) => p.to_string(),
+ .map(|(out_pred, _)| match out_pred.kind().skip_binder() {
+ ty::ClauseKind::RegionOutlives(p) => p.to_string(),
+ ty::ClauseKind::TypeOutlives(p) => p.to_string(),
err => bug!("unexpected clause {:?}", err),
})
.collect();
@@ -104,13 +104,15 @@ fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> {
|(ty::OutlivesPredicate(kind1, region2), &span)| {
match kind1.unpack() {
GenericArgKind::Type(ty1) => Some((
- ty::Clause::TypeOutlives(ty::OutlivesPredicate(ty1, *region2)),
+ ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty1, *region2))
+ .to_predicate(tcx),
span,
)),
GenericArgKind::Lifetime(region1) => Some((
- ty::Clause::RegionOutlives(ty::OutlivesPredicate(
+ ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(
region1, *region2,
- )),
+ ))
+ .to_predicate(tcx),
span,
)),
GenericArgKind::Const(_) => {
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 3ebd9e134bfa2..23d8da88a454b 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -162,28 +162,25 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
// which thus mentions `'a` and should thus accept hidden types that borrow 'a
// instead of requiring an additional `+ 'a`.
match pred.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate {
+ ty::ClauseKind::Trait(ty::TraitPredicate {
trait_ref: ty::TraitRef { def_id: _, substs, .. },
constness: _,
polarity: _,
- })) => {
+ }) => {
for subst in &substs[1..] {
subst.visit_with(&mut collector);
}
}
- ty::PredicateKind::Clause(ty::Clause::Projection(ty::ProjectionPredicate {
+ ty::ClauseKind::Projection(ty::ProjectionPredicate {
projection_ty: ty::AliasTy { substs, .. },
term,
- })) => {
+ }) => {
for subst in &substs[1..] {
subst.visit_with(&mut collector);
}
term.visit_with(&mut collector);
}
- ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
- _,
- region,
- ))) => {
+ ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(_, region)) => {
region.visit_with(&mut collector);
}
_ => {
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index 444ff90595c23..c7fa27da1acfe 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -536,31 +536,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
for ty in [first_ty, second_ty] {
- for (pred, _) in self
+ for (clause, _) in self
.tcx
.explicit_item_bounds(rpit_def_id)
.subst_iter_copied(self.tcx, substs)
{
- let pred = pred.kind().rebind(match pred.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => {
+ let pred = clause.kind().rebind(match clause.kind().skip_binder() {
+ ty::ClauseKind::Trait(trait_pred) => {
// FIXME(rpitit): This will need to be fixed when we move to associated types
assert!(matches!(
*trait_pred.trait_ref.self_ty().kind(),
ty::Alias(_, ty::AliasTy { def_id, substs: alias_substs, .. })
if def_id == rpit_def_id && substs == alias_substs
));
- ty::PredicateKind::Clause(ty::Clause::Trait(
- trait_pred.with_self_ty(self.tcx, ty),
- ))
+ ty::ClauseKind::Trait(trait_pred.with_self_ty(self.tcx, ty))
}
- ty::PredicateKind::Clause(ty::Clause::Projection(mut proj_pred)) => {
+ ty::ClauseKind::Projection(mut proj_pred) => {
assert!(matches!(
*proj_pred.projection_ty.self_ty().kind(),
ty::Alias(_, ty::AliasTy { def_id, substs: alias_substs, .. })
if def_id == rpit_def_id && substs == alias_substs
));
proj_pred = proj_pred.with_self_ty(self.tcx, ty);
- ty::PredicateKind::Clause(ty::Clause::Projection(proj_pred))
+ ty::ClauseKind::Projection(proj_pred)
}
_ => continue,
});
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index 69ccbf0b58ff3..0a1b639af5157 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -92,10 +92,7 @@ pub(super) fn check_fn<'a, 'tcx>(
fcx.check_pat_top(¶m.pat, param_ty, ty_span, None);
// Check that argument is Sized.
- // The check for a non-trivial pattern is a hack to avoid duplicate warnings
- // for simple cases like `fn foo(x: Trait)`,
- // where we would error once on the parameter as a whole, and once on the binding `x`.
- if param.pat.simple_ident().is_none() && !params_can_be_unsized {
+ if !params_can_be_unsized {
fcx.require_type_is_sized(
param_ty,
param.pat.span,
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index dce426ca2db6a..c64b64e925a45 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -174,7 +174,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => self
.deduce_closure_signature_from_predicates(
expected_ty,
- self.tcx.explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs),
+ self.tcx
+ .explicit_item_bounds(def_id)
+ .subst_iter_copied(self.tcx, substs)
+ .map(|(c, s)| (c.as_predicate(), s)),
),
ty::Dynamic(ref object_type, ..) => {
let sig = object_type.projection_bounds().find_map(|pb| {
@@ -222,7 +225,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Given a Projection predicate, we can potentially infer
// the complete signature.
if expected_sig.is_none()
- && let ty::PredicateKind::Clause(ty::Clause::Projection(proj_predicate)) = bound_predicate.skip_binder()
+ && let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj_predicate)) = bound_predicate.skip_binder()
{
let inferred_sig = self.normalize(
span,
@@ -258,10 +261,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// like `F : Fn`. Note that due to subtyping we could encounter
// many viable options, so pick the most restrictive.
let trait_def_id = match bound_predicate.skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Projection(data)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {
Some(data.projection_ty.trait_def_id(self.tcx))
}
- ty::PredicateKind::Clause(ty::Clause::Trait(data)) => Some(data.def_id()),
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => Some(data.def_id()),
_ => None,
};
if let Some(closure_kind) =
@@ -695,7 +698,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// where R is the return type we are expecting. This type `T`
// will be our output.
let bound_predicate = predicate.kind();
- if let ty::PredicateKind::Clause(ty::Clause::Projection(proj_predicate)) =
+ if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj_predicate)) =
bound_predicate.skip_binder()
{
self.deduce_future_output_from_projection(
@@ -717,13 +720,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.tcx
.explicit_item_bounds(def_id)
.subst_iter_copied(self.tcx, substs)
- .find_map(|(p, s)| get_future_output(p, s))?,
+ .find_map(|(p, s)| get_future_output(p.as_predicate(), s))?,
ty::Error(_) => return None,
ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => self
.tcx
.explicit_item_bounds(proj.def_id)
.subst_iter_copied(self.tcx, proj.substs)
- .find_map(|(p, s)| get_future_output(p, s))?,
+ .find_map(|(p, s)| get_future_output(p.as_predicate(), s))?,
_ => span_bug!(
self.tcx.def_span(expr_def_id),
"async fn generator return type not an inference variable: {ret_ty}"
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 79157eae7ed6d..c0c839b1f1862 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -631,7 +631,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
debug!("coerce_unsized resolve step: {:?}", obligation);
let bound_predicate = obligation.predicate.kind();
let trait_pred = match bound_predicate.skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred))
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred))
if traits.contains(&trait_pred.def_id()) =>
{
if unsize_did == trait_pred.def_id() {
@@ -767,7 +767,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
self.tcx,
self.cause.clone(),
self.param_env,
- ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::TypeOutlives(
+ ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(
ty::OutlivesPredicate(a, b_region),
))),
),
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index b62f689ec6b89..9ce03060e0fe9 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -370,13 +370,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Fudge the receiver, so we can do new inference on it.
let possible_rcvr_ty = possible_rcvr_ty.fold_with(&mut fudger);
let method = self
- .lookup_method(
+ .lookup_method_for_diagnostic(
possible_rcvr_ty,
segment,
DUMMY_SP,
call_expr,
binding,
- args,
)
.ok()?;
// Unify the method signature with our incompatible arg, to
@@ -435,14 +434,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let Some(rcvr_ty) = self.node_ty_opt(rcvr.hir_id) else { continue; };
let rcvr_ty = rcvr_ty.fold_with(&mut fudger);
let Ok(method) =
- self.lookup_method(rcvr_ty, segment, DUMMY_SP, parent_expr, rcvr, args)
+ self.lookup_method_for_diagnostic(rcvr_ty, segment, DUMMY_SP, parent_expr, rcvr)
else {
continue;
};
let ideal_rcvr_ty = rcvr_ty.fold_with(&mut fudger);
let ideal_method = self
- .lookup_method(ideal_rcvr_ty, segment, DUMMY_SP, parent_expr, rcvr, args)
+ .lookup_method_for_diagnostic(ideal_rcvr_ty, segment, DUMMY_SP, parent_expr, rcvr)
.ok()
.and_then(|method| {
let _ = self.at(&ObligationCause::dummy(), self.param_env)
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 3f6847be91b65..e250e68a7f176 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -2983,7 +2983,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
for error in errors {
match error.obligation.predicate.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(predicate))
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate))
if self.tcx.is_diagnostic_item(sym::SliceIndex, predicate.trait_ref.def_id) => {
}
_ => continue,
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index e14e8ac2ce000..82d9f03b1451e 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -443,7 +443,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
if matches!((lhs, wild, rhs), (&[], Some(_), &[]))
// Arrays have a statically known size, so
// there is no need to read their length
- || discr_place.place.base_ty.is_array()
+ || place.place.ty().peel_refs().is_array()
{
} else {
needs_to_be_read = true;
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 34f98f4310ee4..b44c51ba94588 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -483,7 +483,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx,
cause,
self.param_env,
- ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::WellFormed(arg))),
+ ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg))),
));
}
@@ -647,7 +647,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.fulfillment_cx.borrow().pending_obligations().into_iter().filter_map(
move |obligation| match &obligation.predicate.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Projection(data))
+ ty::PredicateKind::Clause(ty::ClauseKind::Projection(data))
if self.self_type_matches_expected_vid(
data.projection_ty.self_ty(),
ty_var_root,
@@ -655,23 +655,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{
Some(obligation)
}
- ty::PredicateKind::Clause(ty::Clause::Trait(data))
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(data))
if self.self_type_matches_expected_vid(data.self_ty(), ty_var_root) =>
{
Some(obligation)
}
- ty::PredicateKind::Clause(ty::Clause::Trait(..))
- | ty::PredicateKind::Clause(ty::Clause::Projection(..))
- | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(..))
+ | ty::PredicateKind::Clause(ty::ClauseKind::Projection(..))
+ | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::Coerce(..)
- | ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
- | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..))
- | ty::PredicateKind::Clause(ty::Clause::WellFormed(..))
+ | ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..))
+ | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..))
+ | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..))
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::AliasRelate(..)
- | ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(..))
+ | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
| ty::PredicateKind::ConstEquate(..)
// N.B., this predicate is created by breaking down a
// `ClosureType: FnFoo()` predicate, where
@@ -692,7 +692,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let sized_did = self.tcx.lang_items().sized_trait();
self.obligations_for_self_ty(self_ty).any(|obligation| {
match obligation.predicate.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(data)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
Some(data.def_id()) == sized_did
}
_ => false,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
index 2135643cbeb93..880437023c8b5 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
@@ -25,14 +25,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let generics = self.tcx.generics_of(def_id);
let predicate_substs = match unsubstituted_pred.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => pred.trait_ref.substs.to_vec(),
- ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
+ pred.trait_ref.substs.to_vec()
+ }
+ ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
pred.projection_ty.substs.to_vec()
}
- ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(arg, ty)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(arg, ty)) => {
vec![ty.into(), arg.into()]
}
- ty::PredicateKind::Clause(ty::Clause::ConstEvaluatable(e)) => vec![e.into()],
+ ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(e)) => vec![e.into()],
_ => return false,
};
@@ -514,7 +516,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
impl_predicates.predicates[impl_predicate_index].0.kind().skip_binder();
match relevant_broken_predicate {
- ty::PredicateKind::Clause(ty::Clause::Trait(broken_trait)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(broken_trait)) => {
// ...
self.blame_specific_part_of_expr_corresponding_to_generic_param(
broken_trait.trait_ref.self_ty().into(),
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs
index d45e3d395e430..7aadb95d9393e 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs
@@ -1,7 +1,7 @@
-use std::cmp;
-
+use core::cmp::Ordering;
use rustc_index::IndexVec;
use rustc_middle::ty::error::TypeError;
+use std::cmp;
rustc_index::newtype_index! {
#[debug_format = "ExpectedIdx({})"]
@@ -34,14 +34,14 @@ enum Issue {
Permutation(Vec