summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_borrowck
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_borrowck')
-rw-r--r--compiler/rustc_borrowck/src/borrow_set.rs7
-rw-r--r--compiler/rustc_borrowck/src/borrowck_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/constraint_generation.rs8
-rw-r--r--compiler/rustc_borrowck/src/dataflow.rs112
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs41
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs165
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs14
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs27
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs40
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs8
-rw-r--r--compiler/rustc_borrowck/src/invalidation.rs15
-rw-r--r--compiler/rustc_borrowck/src/lib.rs58
-rw-r--r--compiler/rustc_borrowck/src/nll.rs2
-rw-r--r--compiler/rustc_borrowck/src/place_ext.rs6
-rw-r--r--compiler/rustc_borrowck/src/places_conflict.rs33
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs8
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs149
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs12
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs16
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs117
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs13
23 files changed, 476 insertions, 381 deletions
diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs
index 6be20b097..0b44beeb0 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 acca1a147..a4e0e773a 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/constraint_generation.rs b/compiler/rustc_borrowck/src/constraint_generation.rs
index 2aa09a3f2..743d117e0 100644
--- a/compiler/rustc_borrowck/src/constraint_generation.rs
+++ b/compiler/rustc_borrowck/src/constraint_generation.rs
@@ -4,8 +4,8 @@ use rustc_infer::infer::InferCtxt;
use rustc_middle::mir::visit::TyContext;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{
- BasicBlock, BasicBlockData, Body, Local, Location, Place, PlaceRef, ProjectionElem, Rvalue,
- SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UserTypeProjection,
+ Body, Local, Location, Place, PlaceRef, ProjectionElem, Rvalue, SourceInfo, Statement,
+ StatementKind, Terminator, TerminatorKind, UserTypeProjection,
};
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::visit::TypeVisitable;
@@ -49,10 +49,6 @@ struct ConstraintGeneration<'cg, 'tcx> {
}
impl<'cg, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'tcx> {
- fn visit_basic_block_data(&mut self, bb: BasicBlock, data: &BasicBlockData<'tcx>) {
- self.super_basic_block_data(bb, data);
- }
-
/// We sometimes have `substs` within an rvalue, or within a
/// call. Make them live at the location where they appear.
fn visit_substs(&mut self, substs: &SubstsRef<'tcx>, location: Location) {
diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs
index 2daa82aef..1064b44d2 100644
--- a/compiler/rustc_borrowck/src/dataflow.rs
+++ b/compiler/rustc_borrowck/src/dataflow.rs
@@ -59,7 +59,7 @@ macro_rules! impl_visitable {
}
fn reconstruct_before_statement_effect(
- &self,
+ &mut self,
state: &mut Self::FlowState,
stmt: &mir::Statement<'tcx>,
loc: Location,
@@ -69,7 +69,7 @@ macro_rules! impl_visitable {
}
fn reconstruct_statement_effect(
- &self,
+ &mut self,
state: &mut Self::FlowState,
stmt: &mir::Statement<'tcx>,
loc: Location,
@@ -79,7 +79,7 @@ macro_rules! impl_visitable {
}
fn reconstruct_before_terminator_effect(
- &self,
+ &mut self,
state: &mut Self::FlowState,
term: &mir::Terminator<'tcx>,
loc: Location,
@@ -89,7 +89,7 @@ macro_rules! impl_visitable {
}
fn reconstruct_terminator_effect(
- &self,
+ &mut self,
state: &mut Self::FlowState,
term: &mir::Terminator<'tcx>,
loc: Location,
@@ -125,15 +125,9 @@ pub struct Borrows<'a, 'tcx> {
borrows_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>,
}
-struct StackEntry {
- bb: mir::BasicBlock,
- lo: usize,
- hi: usize,
-}
-
struct OutOfScopePrecomputer<'a, 'tcx> {
visited: BitSet<mir::BasicBlock>,
- visit_stack: Vec<StackEntry>,
+ visit_stack: Vec<mir::BasicBlock>,
body: &'a Body<'tcx>,
regioncx: &'a RegionInferenceContext<'tcx>,
borrows_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>,
@@ -158,29 +152,50 @@ impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> {
borrow_region: RegionVid,
first_location: Location,
) {
- // We visit one BB at a time. The complication is that we may start in the
- // middle of the first BB visited (the one containing `first_location`), in which
- // case we may have to later on process the first part of that BB if there
- // is a path back to its start.
-
- // For visited BBs, we record the index of the first statement processed.
- // (In fully processed BBs this index is 0.) Note also that we add BBs to
- // `visited` once they are added to `stack`, before they are actually
- // processed, because this avoids the need to look them up again on
- // completion.
- self.visited.insert(first_location.block);
-
let first_block = first_location.block;
- let mut first_lo = first_location.statement_index;
- let first_hi = self.body[first_block].statements.len();
+ let first_bb_data = &self.body.basic_blocks[first_block];
+
+ // This is the first block, we only want to visit it from the creation of the borrow at
+ // `first_location`.
+ let first_lo = first_location.statement_index;
+ let first_hi = first_bb_data.statements.len();
+
+ if let Some(kill_stmt) = self.regioncx.first_non_contained_inclusive(
+ borrow_region,
+ first_block,
+ first_lo,
+ first_hi,
+ ) {
+ let kill_location = Location { block: first_block, statement_index: kill_stmt };
+ // If region does not contain a point at the location, then add to list and skip
+ // successor locations.
+ debug!("borrow {:?} gets killed at {:?}", borrow_index, kill_location);
+ self.borrows_out_of_scope_at_location
+ .entry(kill_location)
+ .or_default()
+ .push(borrow_index);
+
+ // The borrow is already dead, there is no need to visit other blocks.
+ return;
+ }
- self.visit_stack.push(StackEntry { bb: first_block, lo: first_lo, hi: first_hi });
+ // The borrow is not dead. Add successor BBs to the work list, if necessary.
+ for succ_bb in first_bb_data.terminator().successors() {
+ if self.visited.insert(succ_bb) {
+ self.visit_stack.push(succ_bb);
+ }
+ }
- 'preorder: while let Some(StackEntry { bb, lo, hi }) = self.visit_stack.pop() {
+ // We may end up visiting `first_block` again. This is not an issue: we know at this point
+ // that it does not kill the borrow in the `first_lo..=first_hi` range, so checking the
+ // `0..first_lo` range and the `0..first_hi` range give the same result.
+ while let Some(block) = self.visit_stack.pop() {
+ let bb_data = &self.body[block];
+ let num_stmts = bb_data.statements.len();
if let Some(kill_stmt) =
- self.regioncx.first_non_contained_inclusive(borrow_region, bb, lo, hi)
+ self.regioncx.first_non_contained_inclusive(borrow_region, block, 0, num_stmts)
{
- let kill_location = Location { block: bb, statement_index: kill_stmt };
+ let kill_location = Location { block, statement_index: kill_stmt };
// If region does not contain a point at the location, then add to list and skip
// successor locations.
debug!("borrow {:?} gets killed at {:?}", borrow_index, kill_location);
@@ -188,38 +203,15 @@ impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> {
.entry(kill_location)
.or_default()
.push(borrow_index);
- continue 'preorder;
- }
- // If we process the first part of the first basic block (i.e. we encounter that block
- // for the second time), we no longer have to visit its successors again.
- if bb == first_block && hi != first_hi {
+ // We killed the borrow, so we do not visit this block's successors.
continue;
}
// Add successor BBs to the work list, if necessary.
- let bb_data = &self.body[bb];
- debug_assert!(hi == bb_data.statements.len());
for succ_bb in bb_data.terminator().successors() {
- if !self.visited.insert(succ_bb) {
- if succ_bb == first_block && first_lo > 0 {
- // `succ_bb` has been seen before. If it wasn't
- // fully processed, add its first part to `stack`
- // for processing.
- self.visit_stack.push(StackEntry { bb: succ_bb, lo: 0, hi: first_lo - 1 });
-
- // And update this entry with 0, to represent the
- // whole BB being processed.
- first_lo = 0;
- }
- } else {
- // succ_bb hasn't been seen before. Add it to
- // `stack` for processing.
- self.visit_stack.push(StackEntry {
- bb: succ_bb,
- lo: 0,
- hi: self.body[succ_bb].statements.len(),
- });
+ if self.visited.insert(succ_bb) {
+ self.visit_stack.push(succ_bb);
}
}
}
@@ -343,7 +335,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
type Idx = BorrowIndex;
fn before_statement_effect(
- &self,
+ &mut self,
trans: &mut impl GenKill<Self::Idx>,
_statement: &mir::Statement<'tcx>,
location: Location,
@@ -352,7 +344,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
}
fn statement_effect(
- &self,
+ &mut self,
trans: &mut impl GenKill<Self::Idx>,
stmt: &mir::Statement<'tcx>,
location: Location,
@@ -400,7 +392,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
}
fn before_terminator_effect(
- &self,
+ &mut self,
trans: &mut impl GenKill<Self::Idx>,
_terminator: &mir::Terminator<'tcx>,
location: Location,
@@ -409,7 +401,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
}
fn terminator_effect(
- &self,
+ &mut self,
trans: &mut impl GenKill<Self::Idx>,
terminator: &mir::Terminator<'tcx>,
_location: Location,
@@ -426,7 +418,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
}
fn call_return_effect(
- &self,
+ &mut self,
_trans: &mut impl GenKill<Self::Idx>,
_block: mir::BasicBlock,
_return_places: CallReturnPlaces<'_, 'tcx>,
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index f41795d60..cfcf31fce 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -180,24 +180,25 @@ trait TypeOpInfo<'tcx> {
return;
};
- let placeholder_region = tcx.mk_re_placeholder(ty::Placeholder {
- universe: adjusted_universe.into(),
- bound: placeholder.bound,
- });
-
- let error_region =
- if let RegionElement::PlaceholderRegion(error_placeholder) = error_element {
- let adjusted_universe =
- error_placeholder.universe.as_u32().checked_sub(base_universe.as_u32());
- adjusted_universe.map(|adjusted| {
- tcx.mk_re_placeholder(ty::Placeholder {
- universe: adjusted.into(),
- bound: error_placeholder.bound,
- })
- })
- } else {
- None
- };
+ let placeholder_region = ty::Region::new_placeholder(
+ tcx,
+ ty::Placeholder { universe: adjusted_universe.into(), bound: placeholder.bound },
+ );
+
+ let error_region = if let RegionElement::PlaceholderRegion(error_placeholder) =
+ error_element
+ {
+ let adjusted_universe =
+ error_placeholder.universe.as_u32().checked_sub(base_universe.as_u32());
+ adjusted_universe.map(|adjusted| {
+ ty::Region::new_placeholder(
+ tcx,
+ ty::Placeholder { universe: adjusted.into(), bound: error_placeholder.bound },
+ )
+ })
+ } else {
+ None
+ };
debug!(?placeholder_region);
@@ -390,7 +391,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
error_region,
&region_constraints,
|vid| ocx.infcx.region_var_origin(vid),
- |vid| ocx.infcx.universe_of_region(ocx.infcx.tcx.mk_re_var(vid)),
+ |vid| ocx.infcx.universe_of_region(ty::Region::new_var(ocx.infcx.tcx, vid)),
)
}
@@ -411,7 +412,7 @@ fn try_extract_error_from_region_constraints<'tcx>(
}
// FIXME: Should this check the universe of the var?
Constraint::VarSubReg(vid, sup) if sup == placeholder_region => {
- Some((infcx.tcx.mk_re_var(vid), cause.clone()))
+ Some((ty::Region::new_var(infcx.tcx, vid), cause.clone()))
}
_ => None,
}
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 15d73ed73..c8c8b72b3 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1,6 +1,5 @@
-use std::iter;
-
use either::Either;
+use hir::PatField;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::{
@@ -14,9 +13,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;
@@ -27,6 +27,7 @@ use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{BytePos, Span, Symbol};
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::ObligationCtxt;
+use std::iter;
use crate::borrow_set::TwoPhaseActivation;
use crate::borrowck_errors;
@@ -677,8 +678,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let tcx = self.infcx.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()
+ let find_fn_kind_from_did = |(pred, _): (ty::Clause<'tcx>, _)| {
+ if let 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, 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<Vec<_>, _> = 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,
@@ -972,7 +982,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
&msg_borrow,
None,
);
- self.suggest_split_at_mut_if_applicable(
+ self.suggest_slice_method_if_applicable(
&mut err,
place,
issued_borrow.borrowed_place,
@@ -982,15 +992,23 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
issued_borrow.borrowed_place,
&issued_spans,
);
+ self.explain_iterator_advancement_in_for_loop_if_applicable(
+ &mut err,
+ span,
+ &issued_spans,
+ );
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 +1022,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 +1056,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 +1070,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 +1085,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 +1103,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!(),
};
@@ -1252,7 +1267,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
}
- fn suggest_split_at_mut_if_applicable(
+ fn suggest_slice_method_if_applicable(
&self,
err: &mut Diagnostic,
place: Place<'tcx>,
@@ -1264,7 +1279,75 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
err.help(
"consider using `.split_at_mut(position)` or similar method to obtain \
two mutable non-overlapping sub-slices",
- );
+ )
+ .help("consider using `.swap(index_1, index_2)` to swap elements at the specified indices");
+ }
+ }
+
+ /// Suggest using `while let` for call `next` on an iterator in a for loop.
+ ///
+ /// For example:
+ /// ```ignore (illustrative)
+ ///
+ /// for x in iter {
+ /// ...
+ /// iter.next()
+ /// }
+ /// ```
+ pub(crate) fn explain_iterator_advancement_in_for_loop_if_applicable(
+ &self,
+ err: &mut Diagnostic,
+ span: Span,
+ issued_spans: &UseSpans<'tcx>,
+ ) {
+ let issue_span = issued_spans.args_or_use();
+ let tcx = self.infcx.tcx;
+ let hir = tcx.hir();
+
+ let Some(body_id) = hir.get(self.mir_hir_id()).body_id() else { return };
+ let typeck_results = tcx.typeck(self.mir_def_id());
+
+ struct ExprFinder<'hir> {
+ issue_span: Span,
+ expr_span: Span,
+ body_expr: Option<&'hir hir::Expr<'hir>>,
+ loop_bind: Option<Symbol>,
+ }
+ impl<'hir> Visitor<'hir> for ExprFinder<'hir> {
+ fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
+ if let hir::ExprKind::Loop(hir::Block{ stmts: [stmt, ..], ..}, _, hir::LoopSource::ForLoop, _) = ex.kind &&
+ let hir::StmtKind::Expr(hir::Expr{ kind: hir::ExprKind::Match(call, [_, bind, ..], _), ..}) = stmt.kind &&
+ let hir::ExprKind::Call(path, _args) = call.kind &&
+ let hir::ExprKind::Path(hir::QPath::LangItem(LangItem::IteratorNext, _, _, )) = path.kind &&
+ let hir::PatKind::Struct(path, [field, ..], _) = bind.pat.kind &&
+ let hir::QPath::LangItem(LangItem::OptionSome, _, _) = path &&
+ let PatField { pat: hir::Pat{ kind: hir::PatKind::Binding(_, _, ident, ..), .. }, ..} = field &&
+ self.issue_span.source_equal(call.span) {
+ self.loop_bind = Some(ident.name);
+ }
+
+ if let hir::ExprKind::MethodCall(body_call, _recv, ..) = ex.kind &&
+ body_call.ident.name == sym::next && ex.span.source_equal(self.expr_span) {
+ self.body_expr = Some(ex);
+ }
+
+ hir::intravisit::walk_expr(self, ex);
+ }
+ }
+ let mut finder =
+ ExprFinder { expr_span: span, issue_span, loop_bind: None, body_expr: None };
+ finder.visit_expr(hir.body(body_id).value);
+
+ if let Some(loop_bind) = finder.loop_bind &&
+ let Some(body_expr) = finder.body_expr &&
+ let Some(def_id) = typeck_results.type_dependent_def_id(body_expr.hir_id) &&
+ let Some(trait_did) = tcx.trait_of_item(def_id) &&
+ tcx.is_diagnostic_item(sym::Iterator, trait_did) {
+ err.note(format!(
+ "a for loop advances the iterator for you, the result is stored in `{}`.",
+ loop_bind
+ ));
+ err.help("if you want to call `next` on a iterator within the loop, consider using `while let`.");
}
}
@@ -1720,18 +1803,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
(
Some(name),
BorrowExplanation::UsedLater(LaterUseKind::ClosureCapture, var_or_use_span, _),
- ) => self.report_escaping_closure_capture(
- borrow_spans,
- borrow_span,
- &RegionName {
- name: self.synthesize_region_name(),
- source: RegionNameSource::Static,
- },
- ConstraintCategory::CallArgument(None),
- var_or_use_span,
- &format!("`{}`", name),
- "block",
- ),
+ ) if borrow_spans.for_generator() || borrow_spans.for_closure() => self
+ .report_escaping_closure_capture(
+ borrow_spans,
+ borrow_span,
+ &RegionName {
+ name: self.synthesize_region_name(),
+ source: RegionNameSource::Static,
+ },
+ ConstraintCategory::CallArgument(None),
+ var_or_use_span,
+ &format!("`{}`", name),
+ "block",
+ ),
(
Some(name),
BorrowExplanation::MustBeValidFor {
@@ -1744,7 +1828,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
span,
..
},
- ) if borrow_spans.for_generator() | borrow_spans.for_closure() => self
+ ) if borrow_spans.for_generator() || borrow_spans.for_closure() => self
.report_escaping_closure_capture(
borrow_spans,
borrow_span,
@@ -2579,7 +2663,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 1d430a93a..225c38efb 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -6,10 +6,10 @@ 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::adjustment::PointerCoercion;
use rustc_middle::ty::{self, RegionVid, TyCtxt};
use rustc_span::symbol::{kw, Symbol};
use rustc_span::{sym, DesugaringKind, Span};
@@ -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.
@@ -584,7 +584,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
},
// If we see an unsized cast, then if it is our data we should check
// whether it is being cast to a trait object.
- Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), operand, ty) => {
+ Rvalue::Cast(
+ CastKind::PointerCoercion(PointerCoercion::Unsize),
+ operand,
+ ty,
+ ) => {
match operand {
Operand::Copy(place) | Operand::Move(place) => {
if let Some(from) = place.as_local() {
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 20370e4c6..d292611e6 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]),
);
@@ -1045,7 +1050,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
Some(def_id) => type_known_to_meet_bound_modulo_regions(
&self.infcx,
self.param_env,
- tcx.mk_imm_ref(tcx.lifetimes.re_erased, ty),
+ Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, ty),
def_id,
),
_ => false,
@@ -1141,6 +1146,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// Avoid pointing to the same function in multiple different
// error messages.
if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) {
+ self.explain_iterator_advancement_in_for_loop_if_applicable(
+ err,
+ span,
+ &move_spans,
+ );
+
let func = tcx.def_path_str(method_did);
err.subdiagnostic(CaptureReasonNote::FuncTakeSelf {
func,
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index d0e17bf5a..1f2fefadf 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -123,13 +123,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
item_msg = access_place_desc;
debug_assert!(self.body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty.is_ref());
debug_assert!(is_closure_or_generator(
- Place::ty_from(
- the_place_err.local,
- the_place_err.projection,
- self.body,
- self.infcx.tcx
- )
- .ty
+ the_place_err.ty(self.body, self.infcx.tcx).ty
));
reason = if self.is_upvar_field_projection(access_place.as_ref()).is_some() {
@@ -234,7 +228,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 +294,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 },
_,
),
)),
@@ -416,12 +410,28 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
_,
) = pat.kind
{
- err.span_suggestion(
- upvar_ident.span,
- "consider changing this to be mutable",
- format!("mut {}", upvar_ident.name),
- Applicability::MachineApplicable,
- );
+ if upvar_ident.name == kw::SelfLower {
+ for (_, node) in self.infcx.tcx.hir().parent_iter(upvar_hir_id) {
+ if let Some(fn_decl) = node.fn_decl() {
+ if !matches!(fn_decl.implicit_self, hir::ImplicitSelfKind::ImmRef | hir::ImplicitSelfKind::MutRef) {
+ err.span_suggestion(
+ upvar_ident.span,
+ "consider changing this to be mutable",
+ format!("mut {}", upvar_ident.name),
+ Applicability::MachineApplicable,
+ );
+ break;
+ }
+ }
+ }
+ } else {
+ err.span_suggestion(
+ upvar_ident.span,
+ "consider changing this to be mutable",
+ format!("mut {}", upvar_ident.name),
+ Applicability::MachineApplicable,
+ );
+ }
}
let tcx = self.infcx.tcx;
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 8ec872e20..617c85174 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -508,7 +508,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let generic_arg = substs[param_index as usize];
let identity_substs =
InternalSubsts::identity_for_item(self.infcx.tcx, adt.did());
- let base_ty = self.infcx.tcx.mk_adt(*adt, identity_substs);
+ let base_ty = Ty::new_adt(self.infcx.tcx, *adt, identity_substs);
let base_generic_arg = identity_substs[param_index as usize];
let adt_desc = adt.descr();
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index f38e1605f..074f37bed 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -928,7 +928,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
fn any_param_predicate_mentions(
&self,
- predicates: &[ty::Predicate<'tcx>],
+ clauses: &[ty::Clause<'tcx>],
ty: Ty<'tcx>,
region: ty::EarlyBoundRegion,
) -> bool {
@@ -937,10 +937,10 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
if let ty::GenericArgKind::Type(ty) = arg.unpack()
&& let ty::Param(_) = ty.kind()
{
- predicates.iter().any(|pred| {
+ clauses.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::ClauseKind::Trait(data) if data.self_ty() == ty => {}
+ 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 b2ff25ecb..0152d89eb 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 a53ea100c..97d15cb53 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};
@@ -222,7 +222,7 @@ fn do_mir_borrowck<'tcx>(
let (move_data, move_errors): (MoveData<'tcx>, Vec<(Place<'tcx>, MoveError<'tcx>)>) =
match MoveData::gather_moves(&body, tcx, param_env) {
- Ok((_, move_data)) => (move_data, Vec::new()),
+ Ok(move_data) => (move_data, Vec::new()),
Err((move_data, move_errors)) => (move_data, move_errors),
};
let promoted_errors = promoted
@@ -368,7 +368,7 @@ fn do_mir_borrowck<'tcx>(
// Compute and report region errors, if any.
mbcx.report_region_errors(nll_errors);
- let results = BorrowckResults {
+ let mut results = BorrowckResults {
ever_inits: flow_ever_inits,
uninits: flow_uninits,
borrows: flow_borrows,
@@ -379,7 +379,7 @@ fn do_mir_borrowck<'tcx>(
rustc_mir_dataflow::visit_results(
body,
traversal::reverse_postorder(body).map(|(bb, _)| bb),
- &results,
+ &mut results,
&mut mbcx,
);
@@ -598,11 +598,12 @@ struct MirBorrowckCtxt<'cx, 'tcx> {
// 2. loans made in overlapping scopes do not conflict
// 3. assignments do not affect things loaned out as immutable
// 4. moves do not affect things loaned out in any way
-impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx> {
+impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorrowckCtxt<'cx, 'tcx> {
type FlowState = Flows<'cx, 'tcx>;
fn visit_statement_before_primary_effect(
&mut self,
+ _results: &R,
flow_state: &Flows<'cx, 'tcx>,
stmt: &'cx Statement<'tcx>,
location: Location,
@@ -672,6 +673,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
fn visit_terminator_before_primary_effect(
&mut self,
+ _results: &R,
flow_state: &Flows<'cx, 'tcx>,
term: &'cx Terminator<'tcx>,
loc: Location,
@@ -708,7 +710,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
destination,
target: _,
unwind: _,
- from_hir_call: _,
+ call_source: _,
fn_span: _,
} => {
self.consume_operand(loc, (func, span), flow_state);
@@ -782,6 +784,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
fn visit_terminator_after_primary_effect(
&mut self,
+ _results: &R,
flow_state: &Flows<'cx, 'tcx>,
term: &'cx Terminator<'tcx>,
loc: Location,
@@ -1068,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
@@ -1084,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));
@@ -1191,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))
@@ -1228,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))),
@@ -1562,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(
@@ -1956,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) => {
@@ -2028,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/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 889acb3ac..b5014a3f4 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -441,7 +441,7 @@ fn for_each_region_constraint<'tcx>(
let subject = match req.subject {
ClosureOutlivesSubject::Region(subject) => format!("{:?}", subject),
ClosureOutlivesSubject::Ty(ty) => {
- format!("{:?}", ty.instantiate(tcx, |vid| tcx.mk_re_var(vid)))
+ format!("{:?}", ty.instantiate(tcx, |vid| ty::Region::new_var(tcx, vid)))
}
};
with_msg(format!("where {}: {:?}", subject, req.outlived_free_region,))?;
diff --git a/compiler/rustc_borrowck/src/place_ext.rs b/compiler/rustc_borrowck/src/place_ext.rs
index d521d0db2..3d7e8c6eb 100644
--- a/compiler/rustc_borrowck/src/place_ext.rs
+++ b/compiler/rustc_borrowck/src/place_ext.rs
@@ -46,11 +46,9 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
}
}
- for (i, elem) in self.projection.iter().enumerate() {
- let proj_base = &self.projection[..i];
-
+ for (i, (proj_base, elem)) in self.iter_projections().enumerate() {
if elem == ProjectionElem::Deref {
- let ty = Place::ty_from(self.local, proj_base, body, tcx).ty;
+ let ty = proj_base.ty(body, tcx).ty;
match ty.kind() {
ty::Ref(_, _, hir::Mutability::Not) if i == 0 => {
// For references to thread-local statics, we do need
diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs
index 25c485b81..1217dcb9c 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,
@@ -135,13 +137,11 @@ fn place_components_conflict<'tcx>(
}
// loop invariant: borrow_c is always either equal to access_c or disjoint from it.
- for (i, (borrow_c, &access_c)) in
- iter::zip(borrow_place.projection, access_place.projection).enumerate()
+ for ((borrow_place, borrow_c), &access_c) in
+ iter::zip(borrow_place.iter_projections(), access_place.projection)
{
debug!(?borrow_c, ?access_c);
- let borrow_proj_base = &borrow_place.projection[..i];
-
// Borrow and access path both have more components.
//
// Examples:
@@ -154,15 +154,7 @@ fn place_components_conflict<'tcx>(
// check whether the components being borrowed vs
// accessed are disjoint (as in the second example,
// but not the first).
- match place_projection_conflict(
- tcx,
- body,
- borrow_local,
- borrow_proj_base,
- borrow_c,
- access_c,
- bias,
- ) {
+ match place_projection_conflict(tcx, body, borrow_place, borrow_c, access_c, bias) {
Overlap::Arbitrary => {
// We have encountered different fields of potentially
// the same union - the borrow now partially overlaps.
@@ -193,8 +185,7 @@ fn place_components_conflict<'tcx>(
}
if borrow_place.projection.len() > access_place.projection.len() {
- for (i, elem) in borrow_place.projection[access_place.projection.len()..].iter().enumerate()
- {
+ for (base, elem) in borrow_place.iter_projections().skip(access_place.projection.len()) {
// Borrow path is longer than the access path. Examples:
//
// - borrow of `a.b.c`, access to `a.b`
@@ -203,8 +194,7 @@ fn place_components_conflict<'tcx>(
// our place. This is a conflict if that is a part our
// access cares about.
- let proj_base = &borrow_place.projection[..access_place.projection.len() + i];
- let base_ty = Place::ty_from(borrow_local, proj_base, body, tcx).ty;
+ let base_ty = base.ty(body, tcx).ty;
match (elem, &base_ty.kind(), access) {
(_, _, Shallow(Some(ArtificialField::ArrayLength)))
@@ -308,8 +298,7 @@ fn place_base_conflict(l1: Local, l2: Local) -> Overlap {
fn place_projection_conflict<'tcx>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
- pi1_local: Local,
- pi1_proj_base: &[PlaceElem<'tcx>],
+ pi1: PlaceRef<'tcx>,
pi1_elem: PlaceElem<'tcx>,
pi2_elem: PlaceElem<'tcx>,
bias: PlaceConflictBias,
@@ -331,7 +320,7 @@ fn place_projection_conflict<'tcx>(
debug!("place_element_conflict: DISJOINT-OR-EQ-FIELD");
Overlap::EqualOrDisjoint
} else {
- let ty = Place::ty_from(pi1_local, pi1_proj_base, body, tcx).ty;
+ let ty = pi1.ty(body, tcx).ty;
if ty.is_union() {
// Different fields of a union, we are basically stuck.
debug!("place_element_conflict: STUCK-UNION");
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 50b246b14..e45d3a2c8 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -1139,7 +1139,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
_ => arg.fold_with(self),
}
});
- tcx.mk_opaque(def_id, tcx.mk_substs_from_iter(substs))
+ Ty::new_opaque(tcx, def_id, tcx.mk_substs_from_iter(substs))
}
}
@@ -1158,7 +1158,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
.universal_regions_outlived_by(r_scc)
.filter(|&u_r| !self.universal_regions.is_local_free_region(u_r))
.find(|&u_r| self.eval_equal(u_r, r_vid))
- .map(|u_r| tcx.mk_re_var(u_r))
+ .map(|u_r| ty::Region::new_var(tcx, u_r))
// In the case of a failure, use `ReErased`. We will eventually
// return `None` in this case.
.unwrap_or(tcx.lifetimes.re_erased)
@@ -1355,7 +1355,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let vid = self.to_region_vid(r);
let scc = self.constraint_sccs.scc(vid);
let repr = self.scc_representatives[scc];
- tcx.mk_re_var(repr)
+ ty::Region::new_var(tcx, repr)
})
}
@@ -1779,7 +1779,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}
// If not, report an error.
- let member_region = infcx.tcx.mk_re_var(member_region_vid);
+ let member_region = ty::Region::new_var(infcx.tcx, member_region_vid);
errors_buffer.push(RegionErrorKind::UnexpectedHiddenRegion {
span: m_c.definition_span,
hidden_ty: m_c.hidden_ty,
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 7fc89e89a..1a227f2d1 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -61,7 +61,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
pub(crate) fn infer_opaque_types(
&self,
infcx: &InferCtxt<'tcx>,
- opaque_ty_decls: FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>,
+ opaque_ty_decls: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
) -> FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> {
let mut result: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> = FxIndexMap::default();
@@ -72,7 +72,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
.collect();
debug!(?member_constraints);
- for (opaque_type_key, (concrete_type, origin)) in opaque_ty_decls {
+ for (opaque_type_key, concrete_type) in opaque_ty_decls {
let substs = opaque_type_key.substs;
debug!(?concrete_type, ?substs);
@@ -92,7 +92,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}
None => {
subst_regions.push(vid);
- infcx.tcx.mk_re_error_with_message(
+ ty::Region::new_error_with_message(
+ infcx.tcx,
concrete_type.span,
"opaque type with non-universal region substs",
)
@@ -142,7 +143,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let ty = infcx.infer_opaque_definition_from_instantiation(
opaque_type_key,
universal_concrete_type,
- origin,
);
// Sometimes two opaque types are the same only after we remap the generic parameters
// back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to `(X, Y)`
@@ -158,7 +158,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
)
.emit()
});
- prev.ty = infcx.tcx.ty_error(guar);
+ prev.ty = Ty::new_error(infcx.tcx, guar);
}
// Pick a better span if there is one.
// FIXME(oli-obk): collect multiple spans for better diagnostics down the road.
@@ -214,7 +214,6 @@ pub trait InferCtxtExt<'tcx> {
&self,
opaque_type_key: OpaqueTypeKey<'tcx>,
instantiated_ty: OpaqueHiddenType<'tcx>,
- origin: OpaqueTyOrigin,
) -> Ty<'tcx>;
}
@@ -247,99 +246,117 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
&self,
opaque_type_key: OpaqueTypeKey<'tcx>,
instantiated_ty: OpaqueHiddenType<'tcx>,
- origin: OpaqueTyOrigin,
) -> Ty<'tcx> {
if let Some(e) = self.tainted_by_errors() {
- return self.tcx.ty_error(e);
+ return Ty::new_error(self.tcx, e);
+ }
+
+ if let Err(guar) =
+ check_opaque_type_parameter_valid(self.tcx, opaque_type_key, instantiated_ty.span)
+ {
+ return Ty::new_error(self.tcx, guar);
}
let definition_ty = instantiated_ty
.remap_generic_params_to_declaration_params(opaque_type_key, self.tcx, false)
.ty;
- if let Err(guar) = check_opaque_type_parameter_valid(
+ // `definition_ty` does not live in of the current inference context,
+ // so lets make sure that we don't accidentally misuse our current `infcx`.
+ match check_opaque_type_well_formed(
self.tcx,
- opaque_type_key,
- origin,
+ self.next_trait_solver(),
+ opaque_type_key.def_id,
instantiated_ty.span,
+ definition_ty,
) {
- return self.tcx.ty_error(guar);
+ Ok(hidden_ty) => hidden_ty,
+ Err(guar) => Ty::new_error(self.tcx, guar),
}
+ }
+}
- // Only check this for TAIT. RPIT already supports `tests/ui/impl-trait/nested-return-type2.rs`
- // on stable and we'd break that.
- let OpaqueTyOrigin::TyAlias { .. } = origin else {
- return definition_ty;
- };
- let def_id = opaque_type_key.def_id;
- // This logic duplicates most of `check_opaque_meets_bounds`.
- // FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely.
- let param_env = self.tcx.param_env(def_id);
- // HACK This bubble is required for this tests to pass:
- // nested-return-type2-tait2.rs
- // nested-return-type2-tait3.rs
- let infcx =
- self.tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build();
- let ocx = ObligationCtxt::new(&infcx);
- // 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::WellFormed(definition_ty.into()));
-
- let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id);
+/// This logic duplicates most of `check_opaque_meets_bounds`.
+/// FIXME(oli-obk): Also do region checks here and then consider removing
+/// `check_opaque_meets_bounds` entirely.
+fn check_opaque_type_well_formed<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ next_trait_solver: bool,
+ def_id: LocalDefId,
+ definition_span: Span,
+ definition_ty: Ty<'tcx>,
+) -> Result<Ty<'tcx>, ErrorGuaranteed> {
+ // Only check this for TAIT. RPIT already supports `tests/ui/impl-trait/nested-return-type2.rs`
+ // on stable and we'd break that.
+ let opaque_ty_hir = tcx.hir().expect_item(def_id);
+ let OpaqueTyOrigin::TyAlias { .. } = opaque_ty_hir.expect_opaque_ty().origin else {
+ return Ok(definition_ty);
+ };
+ let param_env = tcx.param_env(def_id);
+ // HACK This bubble is required for this tests to pass:
+ // nested-return-type2-tait2.rs
+ // nested-return-type2-tait3.rs
+ // FIXME(-Ztrait-solver=next): We probably should use `DefiningAnchor::Error`
+ // and prepopulate this `InferCtxt` with known opaque values, rather than
+ // using the `Bind` anchor here. For now it's fine.
+ let infcx = tcx
+ .infer_ctxt()
+ .with_next_trait_solver(next_trait_solver)
+ .with_opaque_type_inference(if next_trait_solver {
+ DefiningAnchor::Bind(def_id)
+ } else {
+ DefiningAnchor::Bubble
+ })
+ .build();
+ let ocx = ObligationCtxt::new(&infcx);
+ let identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
- // Require that the hidden type actually fulfills all the bounds of the opaque type, even without
- // the bounds that the function supplies.
- let opaque_ty = self.tcx.mk_opaque(def_id.to_def_id(), id_substs);
- if let Err(err) = ocx.eq(
- &ObligationCause::misc(instantiated_ty.span, def_id),
- param_env,
- opaque_ty,
- definition_ty,
- ) {
+ // Require that the hidden type actually fulfills all the bounds of the opaque type, even without
+ // the bounds that the function supplies.
+ let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), identity_substs);
+ ocx.eq(&ObligationCause::misc(definition_span, def_id), param_env, opaque_ty, definition_ty)
+ .map_err(|err| {
infcx
.err_ctxt()
.report_mismatched_types(
- &ObligationCause::misc(instantiated_ty.span, def_id),
+ &ObligationCause::misc(definition_span, def_id),
opaque_ty,
definition_ty,
err,
)
- .emit();
- }
+ .emit()
+ })?;
- ocx.register_obligation(Obligation::misc(
- infcx.tcx,
- instantiated_ty.span,
- def_id,
- param_env,
- predicate,
- ));
+ // 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::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
- // version.
- let errors = ocx.select_all_or_error();
+ // Check that all obligations are satisfied by the implementation's
+ // version.
+ let errors = ocx.select_all_or_error();
- // This is still required for many(half of the tests in ui/type-alias-impl-trait)
- // tests to pass
- let _ = infcx.take_opaque_types();
+ // This is still required for many(half of the tests in ui/type-alias-impl-trait)
+ // tests to pass
+ let _ = infcx.take_opaque_types();
- if errors.is_empty() {
- definition_ty
- } else {
- let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
- self.tcx.ty_error(reported)
- }
+ if errors.is_empty() {
+ Ok(definition_ty)
+ } else {
+ Err(infcx.err_ctxt().report_fulfillment_errors(&errors))
}
}
fn check_opaque_type_parameter_valid(
tcx: TyCtxt<'_>,
opaque_type_key: OpaqueTypeKey<'_>,
- origin: OpaqueTyOrigin,
span: Span,
) -> Result<(), ErrorGuaranteed> {
- match origin {
+ let opaque_ty_hir = tcx.hir().expect_item(opaque_type_key.def_id);
+ match opaque_ty_hir.expect_opaque_ty().origin {
// No need to check return position impl trait (RPIT)
// because for type and const parameters they are correct
// by construction: we convert
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index f527eee7b..c19fbf20c 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/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index c8ec1257d..f22851d76 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -245,7 +245,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
.and(type_op::normalize::Normalize::new(ty))
.fully_perform(self.infcx, span)
.unwrap_or_else(|guar| TypeOpOutput {
- output: self.infcx.tcx.ty_error(guar),
+ output: Ty::new_error(self.infcx.tcx, guar),
constraints: None,
error_info: None,
});
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index a06d4bcc6..eec886b7b 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -124,21 +124,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// Return types are a bit more complex. They may contain opaque `impl Trait` types.
let mir_output_ty = body.local_decls[RETURN_PLACE].ty;
let output_span = body.local_decls[RETURN_PLACE].source_info.span;
- if let Err(terr) = self.eq_types(
- normalized_output_ty,
- mir_output_ty,
- Locations::All(output_span),
- ConstraintCategory::BoringNoLocation,
- ) {
- span_mirbug!(
- self,
- Location::START,
- "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
- normalized_output_ty,
- mir_output_ty,
- terr
- );
- };
+ self.equate_normalized_input_or_output(normalized_output_ty, mir_output_ty, output_span);
}
#[instrument(skip(self), level = "debug")]
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index dc5121e1a..a15e1065c 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -7,7 +7,6 @@ use std::{fmt, iter, mem};
use either::Either;
-use hir::OpaqueTyOrigin;
use rustc_data_structures::frozen::Frozen;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_errors::ErrorGuaranteed;
@@ -28,7 +27,8 @@ use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::AssertKind;
use rustc_middle::mir::*;
use rustc_middle::traits::query::NoSolution;
-use rustc_middle::ty::adjustment::PointerCast;
+use rustc_middle::traits::ObligationCause;
+use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::cast::CastTy;
use rustc_middle::ty::subst::{SubstsRef, UserSubsts};
use rustc_middle::ty::visit::TypeVisitableExt;
@@ -50,7 +50,6 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
use rustc_mir_dataflow::move_paths::MoveData;
use rustc_mir_dataflow::ResultsCursor;
-use crate::renumber::RegionCtxt;
use crate::session_diagnostics::MoveUnsized;
use crate::{
borrow_set::BorrowSet,
@@ -139,7 +138,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
upvars: &[Upvar<'tcx>],
use_polonius: bool,
) -> MirTypeckResults<'tcx> {
- let implicit_region_bound = infcx.tcx.mk_re_var(universal_regions.fr_fn_body);
+ let implicit_region_bound = ty::Region::new_var(infcx.tcx, universal_regions.fr_fn_body);
let mut constraints = MirTypeckRegionConstraints {
placeholder_indices: PlaceholderIndices::default(),
placeholder_index_to_region: IndexVec::default(),
@@ -188,10 +187,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
// FIXME(-Ztrait-solver=next): A bit dubious that we're only registering
// predefined opaques in the typeck root.
- // FIXME(-Ztrait-solver=next): This is also totally wrong for TAITs, since
- // the HIR typeck map defining usages back to their definition params,
- // they won't actually match up with the usages in this body...
- if infcx.tcx.trait_solver_next() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
+ if infcx.next_trait_solver() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
checker.register_predefined_opaques_in_new_solver();
}
@@ -241,10 +237,10 @@ pub(crate) fn type_check<'mir, 'tcx>(
decl.hidden_type.span,
format!("could not resolve {:#?}", hidden_type.ty.kind()),
);
- hidden_type.ty = infcx.tcx.ty_error(reported);
+ hidden_type.ty = Ty::new_error(infcx.tcx, reported);
}
- (opaque_type_key, (hidden_type, decl.origin))
+ (opaque_type_key, hidden_type)
})
.collect();
@@ -480,9 +476,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
fn visit_body(&mut self, body: &Body<'tcx>) {
self.sanitize_type(&"return type", body.return_ty());
- for local_decl in &body.local_decls {
- self.sanitize_type(local_decl, local_decl.ty);
- }
+ // The types of local_decls are checked above which is called in super_body.
self.super_body(body);
}
}
@@ -526,7 +520,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
for elem in place.projection.iter() {
if place_ty.variant_index.is_none() {
if let Err(guar) = place_ty.ty.error_reported() {
- return PlaceTy::from_ty(self.tcx().ty_error(guar));
+ return PlaceTy::from_ty(Ty::new_error(self.tcx(), guar));
}
}
place_ty = self.sanitize_projection(place_ty, elem, place, location, context);
@@ -662,7 +656,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
PlaceTy::from_ty(match base_ty.kind() {
ty::Array(inner, _) => {
assert!(!from_end, "array subslices should not use from_end");
- tcx.mk_array(*inner, to - from)
+ Ty::new_array(tcx, *inner, to - from)
}
ty::Slice(..) => {
assert!(from_end, "slice subslices should use from_end");
@@ -755,7 +749,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
}
fn error(&mut self) -> Ty<'tcx> {
- self.tcx().ty_error_misc()
+ Ty::new_misc_error(self.tcx())
}
fn get_ambient_variance(&self, context: PlaceContext) -> ty::Variance {
@@ -883,8 +877,7 @@ struct BorrowCheckContext<'a, 'tcx> {
pub(crate) struct MirTypeckResults<'tcx> {
pub(crate) constraints: MirTypeckRegionConstraints<'tcx>,
pub(crate) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
- pub(crate) opaque_type_values:
- FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>,
+ pub(crate) opaque_type_values: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
}
/// A collection of region constraints that must be satisfied for the
@@ -1042,16 +1035,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
.typeck(self.body.source.def_id().expect_local())
.concrete_opaque_types
.iter()
- .map(|(&def_id, &hidden_ty)| {
- let substs = ty::InternalSubsts::identity_for_item(self.infcx.tcx, def_id);
- (ty::OpaqueTypeKey { def_id, substs }, hidden_ty)
- })
+ .map(|(k, v)| (*k, *v))
.collect();
let renumbered_opaques = self.infcx.tcx.fold_regions(opaques, |_, _| {
- self.infcx.next_nll_region_var(
+ self.infcx.next_nll_region_var_in_universe(
NllRegionVariableOrigin::Existential { from_forall: false },
- || RegionCtxt::Unknown,
+ ty::UniverseIndex::ROOT,
)
});
@@ -1061,15 +1051,29 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
ConstraintCategory::OpaqueType,
CustomTypeOp::new(
|ocx| {
- for (key, hidden_ty) in renumbered_opaques {
- ocx.register_infer_ok_obligations(
- ocx.infcx.register_hidden_type_in_new_solver(
- key,
- param_env,
- hidden_ty.ty,
- )?,
+ let mut obligations = Vec::new();
+ for (opaque_type_key, hidden_ty) in renumbered_opaques {
+ let cause = ObligationCause::dummy();
+ ocx.infcx.insert_hidden_type(
+ opaque_type_key,
+ &cause,
+ param_env,
+ hidden_ty.ty,
+ true,
+ &mut obligations,
+ )?;
+
+ ocx.infcx.add_item_bounds_for_hidden_type(
+ opaque_type_key.def_id.to_def_id(),
+ opaque_type_key.substs,
+ cause,
+ param_env,
+ hidden_ty.ty,
+ &mut obligations,
);
}
+
+ ocx.register_obligations(obligations);
Ok(())
},
"register pre-defined opaques",
@@ -1366,7 +1370,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);
@@ -1415,9 +1419,11 @@ 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::WellFormed(ty.into()))),
+ sig.inputs_and_output.iter().map(|ty| {
+ ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
+ ty.into(),
+ )))
+ }),
term_location.to_locations(),
ConstraintCategory::Boring,
);
@@ -1440,7 +1446,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);
@@ -1567,7 +1573,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) {
@@ -1585,7 +1591,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
@@ -1846,7 +1852,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let array_ty = rvalue.ty(body.local_decls(), tcx);
self.prove_predicate(
- ty::PredicateKind::WellFormed(array_ty.into()),
+ ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(array_ty.into())),
Locations::Single(location),
ConstraintCategory::Boring,
);
@@ -1902,7 +1908,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
self.check_operand(op, location);
match cast_kind {
- CastKind::Pointer(PointerCast::ReifyFnPointer) => {
+ CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => {
let fn_sig = op.ty(body, tcx).fn_sig(tcx);
// The type that we see in the fcx is like
@@ -1912,7 +1918,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// and hence may contain unnormalized results.
let fn_sig = self.normalize(fn_sig, location);
- let ty_fn_ptr_from = tcx.mk_fn_ptr(fn_sig);
+ let ty_fn_ptr_from = Ty::new_fn_ptr(tcx, fn_sig);
if let Err(terr) = self.eq_types(
*ty,
@@ -1931,12 +1937,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}
- CastKind::Pointer(PointerCast::ClosureFnPointer(unsafety)) => {
+ CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(unsafety)) => {
let sig = match op.ty(body, tcx).kind() {
ty::Closure(_, substs) => substs.as_closure().sig(),
_ => bug!(),
};
- let ty_fn_ptr_from = tcx.mk_fn_ptr(tcx.signature_unclosure(sig, *unsafety));
+ let ty_fn_ptr_from =
+ Ty::new_fn_ptr(tcx, tcx.signature_unclosure(sig, *unsafety));
if let Err(terr) = self.eq_types(
*ty,
@@ -1955,7 +1962,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}
- CastKind::Pointer(PointerCast::UnsafeFnPointer) => {
+ CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer) => {
let fn_sig = op.ty(body, tcx).fn_sig(tcx);
// The type that we see in the fcx is like
@@ -1984,7 +1991,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}
- CastKind::Pointer(PointerCast::Unsize) => {
+ CastKind::PointerCoercion(PointerCoercion::Unsize) => {
let &ty = ty;
let trait_ref = ty::TraitRef::from_lang_item(
tcx,
@@ -2019,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(),
@@ -2030,7 +2038,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
);
}
- CastKind::Pointer(PointerCast::MutToConstPointer) => {
+ CastKind::PointerCoercion(PointerCoercion::MutToConstPointer) => {
let ty::RawPtr(ty::TypeAndMut {
ty: ty_from,
mutbl: hir::Mutability::Mut,
@@ -2072,7 +2080,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}
- CastKind::Pointer(PointerCast::ArrayToPointer) => {
+ CastKind::PointerCoercion(PointerCoercion::ArrayToPointer) => {
let ty_from = op.ty(body, tcx);
let opt_ty_elem_mut = match ty_from.kind() {
@@ -2495,7 +2503,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
location, borrow_region, borrowed_place
);
- let mut cursor = borrowed_place.projection.as_ref();
let tcx = self.infcx.tcx;
let field = path_utils::is_upvar_field_projection(
tcx,
@@ -2509,14 +2516,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
ConstraintCategory::Boring
};
- while let [proj_base @ .., elem] = cursor {
- cursor = proj_base;
-
+ for (base, elem) in borrowed_place.as_ref().iter_projections().rev() {
debug!("add_reborrow_constraint - iteration {:?}", elem);
match elem {
ProjectionElem::Deref => {
- let base_ty = Place::ty_from(borrowed_place.local, proj_base, body, tcx).ty;
+ let base_ty = base.ty(body, tcx).ty;
debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
match base_ty.kind() {
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 56f078f2d..7821b82bf 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -500,7 +500,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
.next_nll_region_var(FR, || RegionCtxt::Free(Symbol::intern("c-variadic")))
.as_var();
- let region = self.infcx.tcx.mk_re_var(reg_vid);
+ let region = ty::Region::new_var(self.infcx.tcx, reg_vid);
let va_list_ty =
self.infcx.tcx.type_of(va_list_did).subst(self.infcx.tcx, &[region.into()]);
@@ -660,7 +660,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
kind: ty::BrEnv,
};
- let env_region = tcx.mk_re_late_bound(ty::INNERMOST, br);
+ let env_region = ty::Region::new_late_bound(tcx, ty::INNERMOST, br);
let closure_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap();
// The "inputs" of the closure in the
@@ -685,7 +685,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
assert_eq!(self.mir_def.to_def_id(), def_id);
let resume_ty = substs.as_generator().resume_ty();
let output = substs.as_generator().return_ty();
- let generator_ty = tcx.mk_generator(def_id, substs, movability);
+ let generator_ty = Ty::new_generator(tcx, def_id, substs, movability);
let inputs_and_output =
self.infcx.tcx.mk_type_list(&[generator_ty, resume_ty, output]);
ty::Binder::dummy(inputs_and_output)
@@ -778,7 +778,8 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> {
{
let (value, _map) = self.tcx.replace_late_bound_regions(value, |br| {
debug!(?br);
- let liberated_region = self.tcx.mk_re_free(all_outlive_scope.to_def_id(), br.kind);
+ let liberated_region =
+ ty::Region::new_free(self.tcx, all_outlive_scope.to_def_id(), br.kind);
let region_vid = {
let name = match br.kind.get_name() {
Some(name) => name,
@@ -889,7 +890,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
- tcx.fold_regions(value, |region, _| tcx.mk_re_var(self.to_region_vid(region)))
+ tcx.fold_regions(value, |region, _| ty::Region::new_var(tcx, self.to_region_vid(region)))
}
}
@@ -929,7 +930,7 @@ fn for_each_late_bound_region_in_item<'tcx>(
for bound_var in tcx.late_bound_vars(tcx.hir().local_def_id_to_hir_id(mir_def_id)) {
let ty::BoundVariableKind::Region(bound_region) = bound_var else { continue; };
- let liberated_region = tcx.mk_re_free(mir_def_id.to_def_id(), bound_region);
+ let liberated_region = ty::Region::new_free(tcx, mir_def_id.to_def_id(), bound_region);
f(liberated_region);
}
}