summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_borrowck/src/diagnostics
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_borrowck/src/diagnostics')
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs52
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs111
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs64
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs187
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/move_errors.rs11
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs162
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs8
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs41
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs110
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/var_name.rs9
10 files changed, 513 insertions, 242 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index cfcf31fce..924e68fa9 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -10,6 +10,8 @@ use rustc_infer::infer::RegionVariableOrigin;
use rustc_infer::infer::{InferCtxt, RegionResolutionError, SubregionOrigin, TyCtxtInferExt as _};
use rustc_infer::traits::ObligationCause;
use rustc_middle::ty::error::TypeError;
+use rustc_middle::ty::RePlaceholder;
+use rustc_middle::ty::Region;
use rustc_middle::ty::RegionVid;
use rustc_middle::ty::UniverseIndex;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
@@ -205,6 +207,8 @@ trait TypeOpInfo<'tcx> {
let span = cause.span;
let nice_error = self.nice_error(mbcx, cause, placeholder_region, error_region);
+ debug!(?nice_error);
+
if let Some(nice_error) = nice_error {
mbcx.buffer_error(nice_error);
} else {
@@ -381,7 +385,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
// We generally shouldn't have errors here because the query was
- // already run, but there's no point using `delay_span_bug`
+ // already run, but there's no point using `span_delayed_bug`
// when we're going to emit an error here anyway.
let _errors = ocx.select_all_or_error();
let region_constraints = ocx.infcx.with_region_constraints(|r| r.clone());
@@ -404,19 +408,41 @@ fn try_extract_error_from_region_constraints<'tcx>(
mut region_var_origin: impl FnMut(RegionVid) -> RegionVariableOrigin,
mut universe_of_region: impl FnMut(RegionVid) -> UniverseIndex,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
- let (sub_region, cause) =
- region_constraints.constraints.iter().find_map(|(constraint, cause)| {
- match *constraint {
- Constraint::RegSubReg(sub, sup) if sup == placeholder_region && sup != sub => {
- Some((sub, cause.clone()))
- }
- // FIXME: Should this check the universe of the var?
- Constraint::VarSubReg(vid, sup) if sup == placeholder_region => {
- Some((ty::Region::new_var(infcx.tcx, vid), cause.clone()))
- }
- _ => None,
+ let matches =
+ |a_region: Region<'tcx>, b_region: Region<'tcx>| match (a_region.kind(), b_region.kind()) {
+ (RePlaceholder(a_p), RePlaceholder(b_p)) => a_p.bound == b_p.bound,
+ _ => a_region == b_region,
+ };
+ let check = |constraint: &Constraint<'tcx>, cause: &SubregionOrigin<'tcx>, exact| {
+ match *constraint {
+ Constraint::RegSubReg(sub, sup)
+ if ((exact && sup == placeholder_region)
+ || (!exact && matches(sup, placeholder_region)))
+ && sup != sub =>
+ {
+ Some((sub, cause.clone()))
+ }
+ // FIXME: Should this check the universe of the var?
+ Constraint::VarSubReg(vid, sup)
+ if ((exact && sup == placeholder_region)
+ || (!exact && matches(sup, placeholder_region))) =>
+ {
+ Some((ty::Region::new_var(infcx.tcx, vid), cause.clone()))
}
- })?;
+ _ => None,
+ }
+ };
+ let mut info = region_constraints
+ .constraints
+ .iter()
+ .find_map(|(constraint, cause)| check(constraint, cause, true));
+ if info.is_none() {
+ info = region_constraints
+ .constraints
+ .iter()
+ .find_map(|(constraint, cause)| check(constraint, cause, false));
+ }
+ let (sub_region, cause) = info?;
debug!(?sub_region, "cause = {:#?}", cause);
let error = match (error_region, *sub_region) {
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 9a8f1c97e..db0f4559a 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -18,7 +18,7 @@ use rustc_middle::mir::{
PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
VarBindingForm,
};
-use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty};
+use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty, TyCtxt};
use rustc_middle::util::CallKind;
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
use rustc_span::def_id::LocalDefId;
@@ -398,7 +398,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
let typeck = self.infcx.tcx.typeck(self.mir_def_id());
let hir_id = hir.parent_id(expr.hir_id);
- if let Some(parent) = hir.find(hir_id) {
+ if let Some(parent) = self.infcx.tcx.opt_hir_node(hir_id) {
let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent
&& let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind
&& let Some(def_id) = typeck.type_dependent_def_id(parent_expr.hir_id)
@@ -413,7 +413,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
(None, &[][..], 0)
};
if let Some(def_id) = def_id
- && let Some(node) = hir.find(hir.local_def_id_to_hir_id(def_id))
+ && let Some(node) = self
+ .infcx
+ .tcx
+ .opt_hir_node(self.infcx.tcx.local_def_id_to_hir_id(def_id))
&& let Some(fn_sig) = node.fn_sig()
&& let Some(ident) = node.ident()
&& let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id)
@@ -445,7 +448,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
&& let hir::ExprKind::Path(hir::QPath::LangItem(
LangItem::IntoIterIntoIter,
_,
- _,
)) = call_expr.kind
{
// Do not suggest `.clone()` in a `for` loop, we already suggest borrowing.
@@ -490,7 +492,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let mut spans = vec![];
for init_idx in inits {
let init = &self.move_data.inits[*init_idx];
- let span = init.span(&self.body);
+ let span = init.span(self.body);
if !span.is_dummy() {
spans.push(span);
}
@@ -518,7 +520,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let body = map.body(body_id);
let mut visitor = ConditionVisitor { spans: &spans, name: &name, errors: vec![] };
- visitor.visit_body(&body);
+ visitor.visit_body(body);
let mut show_assign_sugg = false;
let isnt_initialized = if let InitializationRequiringAction::PartialAssignment
@@ -614,7 +616,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
let mut visitor = LetVisitor { decl_span, sugg_span: None };
- visitor.visit_body(&body);
+ visitor.visit_body(body);
if let Some(span) = visitor.sugg_span {
self.suggest_assign_value(&mut err, moved_place, span);
}
@@ -779,7 +781,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
return;
};
// Try to find predicates on *generic params* that would allow copying `ty`
- let ocx = ObligationCtxt::new(&self.infcx);
+ let ocx = ObligationCtxt::new(self.infcx);
let copy_did = tcx.require_lang_item(LangItem::Copy, Some(span));
let cause = ObligationCause::misc(span, self.mir_def_id());
@@ -856,7 +858,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
self.explain_why_borrow_contains_point(location, borrow, None)
.add_explanation_to_diagnostic(
self.infcx.tcx,
- &self.body,
+ self.body,
&self.local_names,
&mut err,
"",
@@ -903,7 +905,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
self.explain_why_borrow_contains_point(location, borrow, None)
.add_explanation_to_diagnostic(
self.infcx.tcx,
- &self.body,
+ self.body,
&self.local_names,
&mut err,
"",
@@ -1136,7 +1138,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
});
} else {
issued_spans.var_subdiag(
- Some(&self.infcx.tcx.sess.parse_sess.span_diagnostic),
+ Some(self.infcx.tcx.sess.dcx()),
&mut err,
Some(issued_borrow.kind),
|kind, var_span| {
@@ -1153,7 +1155,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
borrow_spans.var_subdiag(
- Some(&self.infcx.tcx.sess.parse_sess.span_diagnostic),
+ Some(self.infcx.tcx.sess.dcx()),
&mut err,
Some(gen_borrow_kind),
|kind, var_span| {
@@ -1174,7 +1176,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
explanation.add_explanation_to_diagnostic(
self.infcx.tcx,
- &self.body,
+ self.body,
&self.local_names,
&mut err,
first_borrow_desc,
@@ -1318,7 +1320,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let tcx = self.infcx.tcx;
let hir = tcx.hir();
- let Some(body_id) = hir.get(self.mir_hir_id()).body_id() else { return };
+ let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else { return };
let typeck_results = tcx.typeck(self.mir_def_id());
struct ExprFinder<'hir> {
@@ -1346,11 +1348,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// };
// corresponding to the desugaring of a for loop `for <pat> in <head> { <body> }`.
if let hir::ExprKind::Call(path, [arg]) = ex.kind
- && let hir::ExprKind::Path(hir::QPath::LangItem(
- LangItem::IntoIterIntoIter,
- _,
- _,
- )) = path.kind
+ && let hir::ExprKind::Path(hir::QPath::LangItem(LangItem::IntoIterIntoIter, _)) =
+ path.kind
&& arg.span.contains(self.issue_span)
{
// Find `IntoIterator::into_iter(<head>)`
@@ -1368,10 +1367,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
..
}) = stmt.kind
&& let hir::ExprKind::Call(path, _args) = call.kind
- && let hir::ExprKind::Path(hir::QPath::LangItem(LangItem::IteratorNext, _, _)) =
+ && 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, pat_span, _) = path
+ && let hir::QPath::LangItem(LangItem::OptionSome, pat_span) = path
&& call.span.contains(self.issue_span)
{
// Find `<pat>` and the span for the whole `for` loop.
@@ -1513,7 +1512,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let local_ty = self.body.local_decls[local].ty;
// Get the body the error happens in
- let Some(body_id) = hir.get(self.mir_hir_id()).body_id() else { return };
+ let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else { return };
let body_expr = hir.body(body_id).value;
@@ -1562,7 +1561,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// Check that the parent of the closure is a method call,
// with receiver matching with local's type (modulo refs)
let parent = hir.parent_id(closure_expr.hir_id);
- if let hir::Node::Expr(parent) = hir.get(parent) {
+ if let hir::Node::Expr(parent) = tcx.hir_node(parent) {
if let hir::ExprKind::MethodCall(_, recv, ..) = parent.kind {
let recv_ty = typeck_results.expr_ty(recv);
@@ -1578,8 +1577,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
return;
};
let sig = args.as_closure().sig();
- let tupled_params =
- tcx.erase_late_bound_regions(sig.inputs().iter().next().unwrap().map_bound(|&b| b));
+ let tupled_params = tcx.instantiate_bound_regions_with_erased(
+ sig.inputs().iter().next().unwrap().map_bound(|&b| b),
+ );
let ty::Tuple(params) = tupled_params.kind() else { return };
// Find the first argument with a matching type, get its name
@@ -1638,15 +1638,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
issued_spans: &UseSpans<'tcx>,
) {
let UseSpans::ClosureUse { capture_kind_span, .. } = issued_spans else { return };
- let hir = self.infcx.tcx.hir();
- struct ExpressionFinder<'hir> {
+ struct ExpressionFinder<'tcx> {
capture_span: Span,
closure_change_spans: Vec<Span>,
closure_arg_span: Option<Span>,
in_closure: bool,
suggest_arg: String,
- hir: rustc_middle::hir::map::Map<'hir>,
+ tcx: TyCtxt<'tcx>,
closure_local_id: Option<hir::HirId>,
closure_call_changes: Vec<(Span, String)>,
}
@@ -1660,7 +1659,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
fn_decl: hir::FnDecl { inputs, .. },
..
}) = e.kind
- && let Some(hir::Node::Expr(body)) = self.hir.find(body.hir_id)
+ && let Some(hir::Node::Expr(body)) = self.tcx.opt_hir_node(body.hir_id)
{
self.suggest_arg = "this: &Self".to_string();
if inputs.len() > 0 {
@@ -1725,8 +1724,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if let Some(hir::Node::ImplItem(hir::ImplItem {
kind: hir::ImplItemKind::Fn(_fn_sig, body_id),
..
- })) = hir.find(self.mir_hir_id())
- && let Some(hir::Node::Expr(expr)) = hir.find(body_id.hir_id)
+ })) = self.infcx.tcx.opt_hir_node(self.mir_hir_id())
+ && let Some(hir::Node::Expr(expr)) = self.infcx.tcx.opt_hir_node(body_id.hir_id)
{
let mut finder = ExpressionFinder {
capture_span: *capture_kind_span,
@@ -1736,7 +1735,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
suggest_arg: String::new(),
closure_local_id: None,
closure_call_changes: vec![],
- hir,
+ tcx: self.infcx.tcx,
};
finder.visit_expr(expr);
@@ -1931,7 +1930,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let place_desc = self.describe_place(borrow.borrowed_place.as_ref());
let kind_place = kind.filter(|_| place_desc.is_some()).map(|k| (k, place_span.0));
- let explanation = self.explain_why_borrow_contains_point(location, &borrow, kind_place);
+ let explanation = self.explain_why_borrow_contains_point(location, borrow, kind_place);
debug!(?place_desc, ?explanation);
@@ -2000,14 +1999,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
(Some(name), explanation) => self.report_local_value_does_not_live_long_enough(
location,
&name,
- &borrow,
+ borrow,
drop_span,
borrow_spans,
explanation,
),
(None, explanation) => self.report_temporary_value_does_not_live_long_enough(
location,
- &borrow,
+ borrow,
drop_span,
borrow_spans,
proper_span,
@@ -2075,8 +2074,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
.map(|name| format!("function `{name}`"))
.unwrap_or_else(|| {
match &self.infcx.tcx.def_kind(self.mir_def_id()) {
+ DefKind::Closure
+ if self
+ .infcx
+ .tcx
+ .is_coroutine(self.mir_def_id().to_def_id()) =>
+ {
+ "enclosing coroutine"
+ }
DefKind::Closure => "enclosing closure",
- DefKind::Coroutine => "enclosing coroutine",
kind => bug!("expected closure or coroutine, found {:?}", kind),
}
.to_string()
@@ -2097,7 +2103,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} else {
explanation.add_explanation_to_diagnostic(
self.infcx.tcx,
- &self.body,
+ self.body,
&self.local_names,
&mut err,
"",
@@ -2118,7 +2124,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
explanation.add_explanation_to_diagnostic(
self.infcx.tcx,
- &self.body,
+ self.body,
&self.local_names,
&mut err,
"",
@@ -2179,7 +2185,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
explanation.add_explanation_to_diagnostic(
self.infcx.tcx,
- &self.body,
+ self.body,
&self.local_names,
&mut err,
"",
@@ -2290,7 +2296,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let proper_span = proper_span.source_callsite();
if let Some(scope) = self.body.source_scopes.get(source_info.scope)
&& let ClearCrossCrate::Set(scope_data) = &scope.local_data
- && let Some(node) = self.infcx.tcx.hir().find(scope_data.lint_root)
+ && let Some(node) = self.infcx.tcx.opt_hir_node(scope_data.lint_root)
&& let Some(id) = node.body_id()
&& let hir::ExprKind::Block(block, _) = self.infcx.tcx.hir().body(id).value.kind
{
@@ -2348,7 +2354,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
Applicability::MaybeIncorrect,
);
} else {
- err.note("the result of `format_args!` can only be assigned directly if no placeholders in it's arguments are used");
+ err.note("the result of `format_args!` can only be assigned directly if no placeholders in its arguments are used");
err.note("to learn more, visit <https://doc.rust-lang.org/std/macro.format_args.html>");
}
suggested = true;
@@ -2364,7 +2370,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
explanation.add_explanation_to_diagnostic(
self.infcx.tcx,
- &self.body,
+ self.body,
&self.local_names,
&mut err,
"",
@@ -2513,12 +2519,23 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
CoroutineKind::Gen(kind) => match kind {
CoroutineSource::Block => "gen block",
CoroutineSource::Closure => "gen closure",
- _ => bug!("gen block/closure expected, but gen function found."),
+ CoroutineSource::Fn => {
+ bug!("gen block/closure expected, but gen function found.")
+ }
+ },
+ CoroutineKind::AsyncGen(kind) => match kind {
+ CoroutineSource::Block => "async gen block",
+ CoroutineSource::Closure => "async gen closure",
+ CoroutineSource::Fn => {
+ bug!("gen block/closure expected, but gen function found.")
+ }
},
CoroutineKind::Async(async_kind) => match async_kind {
CoroutineSource::Block => "async block",
CoroutineSource::Closure => "async closure",
- _ => bug!("async block/closure expected, but async function found."),
+ CoroutineSource::Fn => {
+ bug!("async block/closure expected, but async function found.")
+ }
},
CoroutineKind::Coroutine => "coroutine",
},
@@ -2841,7 +2858,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
self.explain_why_borrow_contains_point(location, loan, None).add_explanation_to_diagnostic(
self.infcx.tcx,
- &self.body,
+ self.body,
&self.local_names,
&mut err,
"",
@@ -3019,7 +3036,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}
let mut visitor = FakeReadCauseFinder { place, cause: None };
- visitor.visit_body(&self.body);
+ visitor.visit_body(self.body);
match visitor.cause {
Some(FakeReadCause::ForMatchGuard) => Some("match guard"),
Some(FakeReadCause::ForIndex) => Some("indexing expression"),
@@ -3246,7 +3263,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
) -> Option<AnnotatedBorrowFnSignature<'tcx>> {
debug!("annotate_fn_sig: did={:?} sig={:?}", did, sig);
let is_closure = self.infcx.tcx.is_closure(did.to_def_id());
- let fn_hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(did);
+ let fn_hir_id = self.infcx.tcx.local_def_id_to_hir_id(did);
let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(fn_hir_id)?;
// We need to work out which arguments to highlight. We do this by looking
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 8a930ca59..f1e712d81 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -5,12 +5,13 @@ use rustc_hir as hir;
use rustc_hir::intravisit::Visitor;
use rustc_index::IndexSlice;
use rustc_infer::infer::NllRegionVariableOrigin;
+use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
use rustc_middle::mir::{
Body, CallSource, CastKind, ConstraintCategory, FakeReadCause, Local, LocalInfo, Location,
Operand, Place, Rvalue, Statement, StatementKind, TerminatorKind,
};
use rustc_middle::ty::adjustment::PointerCoercion;
-use rustc_middle::ty::{self, RegionVid, TyCtxt};
+use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt};
use rustc_span::symbol::{kw, Symbol};
use rustc_span::{sym, DesugaringKind, Span};
use rustc_trait_selection::traits::error_reporting::FindExprBySpan;
@@ -86,7 +87,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
if let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind
&& let [hir::PathSegment { ident, args: None, .. }] = p.segments
&& let hir::def::Res::Local(hir_id) = p.res
- && let Some(hir::Node::Pat(pat)) = tcx.hir().find(hir_id)
+ && let Some(hir::Node::Pat(pat)) = tcx.opt_hir_node(hir_id)
{
err.span_label(pat.span, format!("binding `{ident}` declared here"));
}
@@ -290,12 +291,69 @@ impl<'tcx> BorrowExplanation<'tcx> {
}
}
+ if let ConstraintCategory::Cast { unsize_to: Some(unsize_ty) } = category {
+ self.add_object_lifetime_default_note(tcx, err, unsize_ty);
+ }
self.add_lifetime_bound_suggestion_to_diagnostic(err, &category, span, region_name);
}
_ => {}
}
}
+ fn add_object_lifetime_default_note(
+ &self,
+ tcx: TyCtxt<'tcx>,
+ err: &mut Diagnostic,
+ unsize_ty: Ty<'tcx>,
+ ) {
+ if let ty::Adt(def, args) = unsize_ty.kind() {
+ // We try to elaborate the object lifetime defaults and present those to the user. This should
+ // make it clear where the region constraint is coming from.
+ let generics = tcx.generics_of(def.did());
+
+ let mut has_dyn = false;
+ let mut failed = false;
+
+ let elaborated_args = std::iter::zip(*args, &generics.params).map(|(arg, param)| {
+ if let Some(ty::Dynamic(obj, _, ty::DynKind::Dyn)) = arg.as_type().map(Ty::kind) {
+ let default = tcx.object_lifetime_default(param.def_id);
+
+ let re_static = tcx.lifetimes.re_static;
+
+ let implied_region = match default {
+ // This is not entirely precise.
+ ObjectLifetimeDefault::Empty => re_static,
+ ObjectLifetimeDefault::Ambiguous => {
+ failed = true;
+ re_static
+ }
+ ObjectLifetimeDefault::Param(param_def_id) => {
+ let index = generics.param_def_id_to_index[&param_def_id] as usize;
+ args.get(index).and_then(|arg| arg.as_region()).unwrap_or_else(|| {
+ failed = true;
+ re_static
+ })
+ }
+ ObjectLifetimeDefault::Static => re_static,
+ };
+
+ has_dyn = true;
+
+ Ty::new_dynamic(tcx, obj, implied_region, ty::DynKind::Dyn).into()
+ } else {
+ arg
+ }
+ });
+ let elaborated_ty = Ty::new_adt(tcx, *def, tcx.mk_args_from_iter(elaborated_args));
+
+ if has_dyn && !failed {
+ err.note(format!(
+ "due to object lifetime defaults, `{unsize_ty}` actually means `{elaborated_ty}`"
+ ));
+ }
+ }
+ }
+
fn add_lifetime_bound_suggestion_to_diagnostic(
&self,
err: &mut Diagnostic,
@@ -364,7 +422,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
kind_place: Option<(WriteKind, Place<'tcx>)>,
) -> BorrowExplanation<'tcx> {
let regioncx = &self.regioncx;
- let body: &Body<'_> = &self.body;
+ let body: &Body<'_> = self.body;
let tcx = self.infcx.tcx;
let borrow_region_vid = borrow.region;
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index c4323fef9..ee3213654 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -10,7 +10,8 @@ use rustc_hir as hir;
use rustc_hir::def::{CtorKind, Namespace};
use rustc_hir::CoroutineKind;
use rustc_index::IndexSlice;
-use rustc_infer::infer::LateBoundRegionConversionTime;
+use rustc_infer::infer::BoundRegionConversionTime;
+use rustc_infer::traits::{FulfillmentErrorCode, SelectionError};
use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::{
AggregateKind, CallSource, ConstOperand, FakeReadCause, Local, LocalInfo, LocalKind, Location,
@@ -24,10 +25,9 @@ use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult};
use rustc_span::def_id::LocalDefId;
use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
use rustc_target::abi::{FieldIdx, VariantIdx};
-use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
-use rustc_trait_selection::traits::{
- type_known_to_meet_bound_modulo_regions, Obligation, ObligationCause,
-};
+use rustc_trait_selection::infer::InferCtxtExt;
+use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _;
+use rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions;
use super::borrow_set::BorrowData;
use super::MirBorrowckCtxt;
@@ -124,7 +124,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let did = did.expect_local();
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
diag.eager_subdiagnostic(
- &self.infcx.tcx.sess.parse_sess.span_diagnostic,
+ self.infcx.tcx.sess.dcx(),
OnClosureNote::InvokedTwice {
place_name: &ty::place_to_string_for_capture(
self.infcx.tcx,
@@ -146,7 +146,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let did = did.expect_local();
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
diag.eager_subdiagnostic(
- &self.infcx.tcx.sess.parse_sess.span_diagnostic,
+ self.infcx.tcx.sess.dcx(),
OnClosureNote::MovedTwice {
place_name: &ty::place_to_string_for_capture(self.infcx.tcx, hir_place),
span: *span,
@@ -217,9 +217,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
projection: place.projection.split_at(index + 1).0,
}) {
let var_index = field.index();
- buf = self.upvars[var_index].place.to_string(self.infcx.tcx);
+ buf = self.upvars[var_index].to_string(self.infcx.tcx);
ok = Ok(());
- if !self.upvars[var_index].by_ref {
+ if !self.upvars[var_index].is_by_ref() {
buf.insert(0, '*');
}
} else {
@@ -250,7 +250,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
local,
projection: place.projection.split_at(index + 1).0,
}) {
- buf = self.upvars[field.index()].place.to_string(self.infcx.tcx);
+ buf = self.upvars[field.index()].to_string(self.infcx.tcx);
ok = Ok(());
} else {
let field_name = self.describe_field(
@@ -354,7 +354,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
ty::Adt(def, _) => {
let variant = if let Some(idx) = variant_index {
assert!(def.is_enum());
- &def.variant(idx)
+ def.variant(idx)
} else {
def.non_enum_variant()
};
@@ -462,7 +462,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// lifetimes without names with the value `'0`.
if let ty::Ref(region, ..) = ty.kind() {
match **region {
- ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
+ ty::ReBound(_, ty::BoundRegion { kind: br, .. })
| ty::RePlaceholder(ty::PlaceholderRegion {
bound: ty::BoundRegion { kind: br, .. },
..
@@ -482,7 +482,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let region = if let ty::Ref(region, ..) = ty.kind() {
match **region {
- ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
+ ty::ReBound(_, ty::BoundRegion { kind: br, .. })
| ty::RePlaceholder(ty::PlaceholderRegion {
bound: ty::BoundRegion { kind: br, .. },
..
@@ -624,7 +624,7 @@ impl UseSpans<'_> {
/// Add a subdiagnostic to the use of the captured variable, if it exists.
pub(super) fn var_subdiag(
self,
- handler: Option<&rustc_errors::Handler>,
+ dcx: Option<&rustc_errors::DiagCtxt>,
err: &mut Diagnostic,
kind: Option<rustc_middle::mir::BorrowKind>,
f: impl FnOnce(Option<CoroutineKind>, Span) -> CaptureVarCause,
@@ -646,7 +646,7 @@ impl UseSpans<'_> {
});
};
let diag = f(coroutine_kind, path_span);
- match handler {
+ match dcx {
Some(hd) => err.eager_subdiagnostic(hd, diag),
None => err.subdiagnostic(diag),
};
@@ -851,7 +851,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
{
let Some((method_did, method_args)) = rustc_middle::util::find_self_call(
self.infcx.tcx,
- &self.body,
+ self.body,
target_temp,
location.block,
) else {
@@ -958,7 +958,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
"closure_span: def_id={:?} target_place={:?} places={:?}",
def_id, target_place, places
);
- let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(def_id);
+ let hir_id = self.infcx.tcx.local_def_id_to_hir_id(def_id);
let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind;
debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
if let hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }) = expr {
@@ -1043,12 +1043,43 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
CallKind::Normal { self_arg, desugaring, method_did, method_args } => {
let self_arg = self_arg.unwrap();
+ let mut has_sugg = false;
let tcx = self.infcx.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,
+ place_name: place_name.clone(),
+ span: self_arg.span,
+ });
+ }
+ let parent_did = tcx.parent(method_did);
+ let parent_self_ty =
+ matches!(tcx.def_kind(parent_did), rustc_hir::def::DefKind::Impl { .. })
+ .then_some(parent_did)
+ .and_then(|did| match tcx.type_of(did).instantiate_identity().kind() {
+ ty::Adt(def, ..) => Some(def.did()),
+ _ => None,
+ });
+ let is_option_or_result = parent_self_ty.is_some_and(|def_id| {
+ matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
+ });
+ if is_option_or_result && maybe_reinitialized_locations_is_empty {
+ err.subdiagnostic(CaptureReasonLabel::BorrowContent { var_span });
+ }
if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring {
let ty = moved_place.ty(self.body, tcx).ty;
let suggest = match tcx.get_diagnostic_item(sym::IntoIterator) {
Some(def_id) => type_known_to_meet_bound_modulo_regions(
- &self.infcx,
+ self.infcx,
self.param_env,
Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, ty),
def_id,
@@ -1108,72 +1139,92 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// Erase and shadow everything that could be passed to the new infcx.
let ty = moved_place.ty(self.body, tcx).ty;
- if let ty::Adt(def, args) = ty.kind()
+ if let ty::Adt(def, args) = ty.peel_refs().kind()
&& Some(def.did()) == tcx.lang_items().pin_type()
&& let ty::Ref(_, _, hir::Mutability::Mut) = args.type_at(0).kind()
&& let self_ty = self.infcx.instantiate_binder_with_fresh_vars(
fn_call_span,
- LateBoundRegionConversionTime::FnCall,
+ BoundRegionConversionTime::FnCall,
tcx.fn_sig(method_did).instantiate(tcx, method_args).input(0),
)
&& self.infcx.can_eq(self.param_env, ty, self_ty)
{
err.eager_subdiagnostic(
- &self.infcx.tcx.sess.parse_sess.span_diagnostic,
+ self.infcx.tcx.sess.dcx(),
CaptureReasonSuggest::FreshReborrow {
span: move_span.shrink_to_hi(),
},
);
+ has_sugg = true;
}
- if let Some(clone_trait) = tcx.lang_items().clone_trait()
- && let trait_ref = ty::TraitRef::new(tcx, clone_trait, [ty])
- && let o = Obligation::new(
- tcx,
- ObligationCause::dummy(),
- self.param_env,
- ty::Binder::dummy(trait_ref),
- )
- && self.infcx.predicate_must_hold_modulo_regions(&o)
- {
- err.span_suggestion_verbose(
- move_span.shrink_to_hi(),
- "you can `clone` the value and consume it, but this might not be \
- your desired behavior",
- ".clone()".to_string(),
- Applicability::MaybeIncorrect,
- );
+ if let Some(clone_trait) = tcx.lang_items().clone_trait() {
+ let sugg = if moved_place
+ .iter_projections()
+ .any(|(_, elem)| matches!(elem, ProjectionElem::Deref))
+ {
+ vec![
+ // We use the fully-qualified path because `.clone()` can
+ // sometimes choose `<&T as Clone>` instead of `<T as Clone>`
+ // when going through auto-deref, so this ensures that doesn't
+ // happen, causing suggestions for `.clone().clone()`.
+ (move_span.shrink_to_lo(), format!("<{ty} as Clone>::clone(&")),
+ (move_span.shrink_to_hi(), ")".to_string()),
+ ]
+ } else {
+ vec![(move_span.shrink_to_hi(), ".clone()".to_string())]
+ };
+ if let Some(errors) =
+ self.infcx.could_impl_trait(clone_trait, ty, self.param_env)
+ && !has_sugg
+ {
+ let msg = match &errors[..] {
+ [] => "you can `clone` the value and consume it, but this \
+ might not be your desired behavior"
+ .to_string(),
+ [error] => {
+ format!(
+ "you could `clone` the value and consume it, if \
+ the `{}` trait bound could be satisfied",
+ error.obligation.predicate,
+ )
+ }
+ [errors @ .., last] => {
+ format!(
+ "you could `clone` the value and consume it, if \
+ the following trait bounds could be satisfied: {} \
+ and `{}`",
+ errors
+ .iter()
+ .map(|e| format!("`{}`", e.obligation.predicate))
+ .collect::<Vec<_>>()
+ .join(", "),
+ last.obligation.predicate,
+ )
+ }
+ };
+ err.multipart_suggestion_verbose(
+ msg,
+ sugg,
+ Applicability::MaybeIncorrect,
+ );
+ for error in errors {
+ if let FulfillmentErrorCode::CodeSelectionError(
+ SelectionError::Unimplemented,
+ ) = error.code
+ && let ty::PredicateKind::Clause(ty::ClauseKind::Trait(
+ pred,
+ )) = error.obligation.predicate.kind().skip_binder()
+ {
+ self.infcx.err_ctxt().suggest_derive(
+ &error.obligation,
+ err,
+ error.obligation.predicate.kind().rebind(pred),
+ );
+ }
+ }
+ }
}
}
- // 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,
- place_name,
- span: self_arg.span,
- });
- }
- let parent_did = tcx.parent(method_did);
- let parent_self_ty =
- matches!(tcx.def_kind(parent_did), rustc_hir::def::DefKind::Impl { .. })
- .then_some(parent_did)
- .and_then(|did| match tcx.type_of(did).instantiate_identity().kind() {
- ty::Adt(def, ..) => Some(def.did()),
- _ => None,
- });
- let is_option_or_result = parent_self_ty.is_some_and(|def_id| {
- matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
- });
- if is_option_or_result && maybe_reinitialized_locations_is_empty {
- err.subdiagnostic(CaptureReasonLabel::BorrowContent { var_span });
- }
}
// Other desugarings takes &self, which cannot cause a move
_ => {}
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 41d6b98d7..43487b85a 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -321,7 +321,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let deref_base = match deref_target_place.projection.as_ref() {
[proj_base @ .., ProjectionElem::Deref] => {
- PlaceRef { local: deref_target_place.local, projection: &proj_base }
+ PlaceRef { local: deref_target_place.local, projection: proj_base }
}
_ => bug!("deref_target_place is not a deref projection"),
};
@@ -363,8 +363,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
format!("captured variable in an `{closure_kind}` closure");
let upvar = &self.upvars[upvar_field.unwrap().index()];
- let upvar_hir_id = upvar.place.get_root_variable();
- let upvar_name = upvar.place.to_string(self.infcx.tcx);
+ let upvar_hir_id = upvar.get_root_variable();
+ let upvar_name = upvar.to_string(self.infcx.tcx);
let upvar_span = self.infcx.tcx.hir().span(upvar_hir_id);
let place_name = self.describe_any_place(move_place.as_ref());
@@ -583,7 +583,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
is_partial_move: false,
ty: bind_to.ty,
- place: &place_desc,
+ place: place_desc,
span: binding_span,
});
}
@@ -607,7 +607,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if let Some(adt) = local_ty.ty_adt_def()
&& adt.repr().packed()
- && let ExpnKind::Macro(MacroKind::Derive, name) = self.body.span.ctxt().outer_expn_data().kind
+ && let ExpnKind::Macro(MacroKind::Derive, name) =
+ self.body.span.ctxt().outer_expn_data().kind
{
err.note(format!("`#[derive({name})]` triggers a move because taking references to the fields of a packed struct is undefined behaviour"));
}
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index dde46eef6..c3c1f1293 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -3,8 +3,9 @@ use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed
use rustc_hir as hir;
use rustc_hir::intravisit::Visitor;
use rustc_hir::Node;
+use rustc_infer::traits;
use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem};
-use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt};
+use rustc_middle::ty::{self, InstanceDef, ToPredicate, Ty, TyCtxt};
use rustc_middle::{
hir::place::PlaceBase,
mir::{self, BindingForm, Local, LocalDecl, LocalInfo, LocalKind, Location},
@@ -12,6 +13,8 @@ use rustc_middle::{
use rustc_span::symbol::{kw, Symbol};
use rustc_span::{sym, BytePos, DesugaringKind, Span};
use rustc_target::abi::FieldIdx;
+use rustc_trait_selection::infer::InferCtxtExt;
+use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
use crate::diagnostics::BorrowedContentSource;
use crate::util::FindAssignments;
@@ -67,7 +70,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let imm_borrow_derefed = self.upvars[upvar_index.index()]
.place
- .place
.deref_tys()
.any(|ty| matches!(ty.kind(), ty::Ref(.., hir::Mutability::Not)));
@@ -85,7 +87,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if self.is_upvar_field_projection(access_place.as_ref()).is_some() {
reason = ", as it is not declared as mutable".to_string();
} else {
- let name = self.upvars[upvar_index.index()].place.to_string(self.infcx.tcx);
+ let name = self.upvars[upvar_index.index()].to_string(self.infcx.tcx);
reason = format!(", as `{name}` is not declared as mutable");
}
}
@@ -388,13 +390,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty
));
- let captured_place = &self.upvars[upvar_index.index()].place;
+ let captured_place = self.upvars[upvar_index.index()];
err.span_label(span, format!("cannot {act}"));
let upvar_hir_id = captured_place.get_root_variable();
- if let Some(Node::Pat(pat)) = self.infcx.tcx.hir().find(upvar_hir_id)
+ if let Some(Node::Pat(pat)) = self.infcx.tcx.opt_hir_node(upvar_hir_id)
&& let hir::PatKind::Binding(hir::BindingAnnotation::NONE, _, upvar_ident, _) =
pat.kind
{
@@ -659,9 +661,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if self.body.local_kind(local) != LocalKind::Arg {
return (false, None);
}
- let hir_map = self.infcx.tcx.hir();
let my_def = self.body.source.def_id();
- let my_hir = hir_map.local_def_id_to_hir_id(my_def.as_local().unwrap());
+ let my_hir = self.infcx.tcx.local_def_id_to_hir_id(my_def.as_local().unwrap());
let Some(td) =
self.infcx.tcx.impl_of_method(my_def).and_then(|x| self.infcx.tcx.trait_id_of_impl(x))
else {
@@ -669,7 +670,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
};
(
true,
- td.as_local().and_then(|tld| match hir_map.find_by_def_id(tld) {
+ td.as_local().and_then(|tld| match self.infcx.tcx.opt_hir_node_by_def_id(tld) {
Some(Node::Item(hir::Item {
kind: hir::ItemKind::Trait(_, _, _, _, items),
..
@@ -680,25 +681,27 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if !matches!(k, hir::AssocItemKind::Fn { .. }) {
continue;
}
- if hir_map.name(hi) != hir_map.name(my_hir) {
+ if self.infcx.tcx.hir().name(hi) != self.infcx.tcx.hir().name(my_hir) {
continue;
}
f_in_trait_opt = Some(hi);
break;
}
- f_in_trait_opt.and_then(|f_in_trait| match hir_map.find(f_in_trait) {
- Some(Node::TraitItem(hir::TraitItem {
- kind:
- hir::TraitItemKind::Fn(
- hir::FnSig { decl: hir::FnDecl { inputs, .. }, .. },
- _,
- ),
- ..
- })) => {
- let hir::Ty { span, .. } = inputs[local.index() - 1];
- Some(span)
+ f_in_trait_opt.and_then(|f_in_trait| {
+ match self.infcx.tcx.opt_hir_node(f_in_trait) {
+ Some(Node::TraitItem(hir::TraitItem {
+ kind:
+ hir::TraitItemKind::Fn(
+ hir::FnSig { decl: hir::FnDecl { inputs, .. }, .. },
+ _,
+ ),
+ ..
+ })) => {
+ let hir::Ty { span, .. } = inputs[local.index() - 1];
+ Some(span)
+ }
+ _ => None,
}
- _ => None,
})
}
_ => None,
@@ -739,12 +742,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
}
- let hir_map = self.infcx.tcx.hir();
let def_id = self.body.source.def_id();
let hir_id = if let Some(local_def_id) = def_id.as_local()
- && let Some(body_id) = hir_map.maybe_body_owned_by(local_def_id)
+ && let Some(body_id) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id)
{
- let body = hir_map.body(body_id);
+ let body = self.infcx.tcx.hir().body(body_id);
let mut v = BindingFinder { span: pat_span, hir_id: None };
v.visit_body(body);
v.hir_id
@@ -760,7 +762,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
&& let Some(hir::Node::Local(hir::Local {
pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. },
..
- })) = hir_map.find(hir_id)
+ })) = self.infcx.tcx.opt_hir_node(hir_id)
&& let Ok(name) =
self.infcx.tcx.sess.source_map().span_to_snippet(local_decl.source_info.span)
{
@@ -940,7 +942,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let closure_id = self.mir_hir_id();
let closure_span = self.infcx.tcx.def_span(self.mir_def_id());
let fn_call_id = hir.parent_id(closure_id);
- let node = hir.get(fn_call_id);
+ let node = self.infcx.tcx.hir_node(fn_call_id);
let def_id = hir.enclosing_body_owner(fn_call_id);
let mut look_at_return = true;
// If we can detect the expression to be an `fn` call where the closure was an argument,
@@ -999,7 +1001,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if look_at_return && hir.get_return_block(closure_id).is_some() {
// ...otherwise we are probably in the tail expression of the function, point at the
// return type.
- match hir.get_by_def_id(hir.get_parent_item(fn_call_id).def_id) {
+ match self.infcx.tcx.hir_node_by_def_id(hir.get_parent_item(fn_call_id).def_id) {
hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(sig, ..), .. })
| hir::Node::TraitItem(hir::TraitItem {
ident,
@@ -1197,12 +1199,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
hir::intravisit::walk_stmt(self, s);
}
}
- let hir_map = self.infcx.tcx.hir();
let def_id = self.body.source.def_id();
let hir_id = if let Some(local_def_id) = def_id.as_local()
- && let Some(body_id) = hir_map.maybe_body_owned_by(local_def_id)
+ && let Some(body_id) = self.infcx.tcx.hir().maybe_body_owned_by(local_def_id)
{
- let body = hir_map.body(body_id);
+ let body = self.infcx.tcx.hir().body(body_id);
let mut v = BindingFinder { span: err_label_span, hir_id: None };
v.visit_body(body);
v.hir_id
@@ -1211,8 +1212,105 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
};
if let Some(hir_id) = hir_id
- && let Some(hir::Node::Local(local)) = hir_map.find(hir_id)
+ && let Some(hir::Node::Local(local)) = self.infcx.tcx.opt_hir_node(hir_id)
{
+ let tables = self.infcx.tcx.typeck(def_id.as_local().unwrap());
+ if let Some(clone_trait) = self.infcx.tcx.lang_items().clone_trait()
+ && let Some(expr) = local.init
+ && let ty = tables.node_type_opt(expr.hir_id)
+ && let Some(ty) = ty
+ && let ty::Ref(..) = ty.kind()
+ {
+ match self
+ .infcx
+ .could_impl_trait(clone_trait, ty.peel_refs(), self.param_env)
+ .as_deref()
+ {
+ Some([]) => {
+ // The type implements Clone.
+ err.span_help(
+ expr.span,
+ format!(
+ "you can `clone` the `{}` value and consume it, but this \
+ might not be your desired behavior",
+ ty.peel_refs(),
+ ),
+ );
+ }
+ None => {
+ if let hir::ExprKind::MethodCall(segment, _rcvr, [], span) =
+ expr.kind
+ && segment.ident.name == sym::clone
+ {
+ err.span_help(
+ span,
+ format!(
+ "`{}` doesn't implement `Clone`, so this call clones \
+ the reference `{ty}`",
+ ty.peel_refs(),
+ ),
+ );
+ }
+ // The type doesn't implement Clone.
+ let trait_ref = ty::Binder::dummy(ty::TraitRef::new(
+ self.infcx.tcx,
+ clone_trait,
+ [ty.peel_refs()],
+ ));
+ let obligation = traits::Obligation::new(
+ self.infcx.tcx,
+ traits::ObligationCause::dummy(),
+ self.param_env,
+ trait_ref,
+ );
+ self.infcx.err_ctxt().suggest_derive(
+ &obligation,
+ err,
+ trait_ref.to_predicate(self.infcx.tcx),
+ );
+ }
+ Some(errors) => {
+ if let hir::ExprKind::MethodCall(segment, _rcvr, [], span) =
+ expr.kind
+ && segment.ident.name == sym::clone
+ {
+ err.span_help(
+ span,
+ format!(
+ "`{}` doesn't implement `Clone` because its \
+ implementations trait bounds could not be met, so \
+ this call clones the reference `{ty}`",
+ ty.peel_refs(),
+ ),
+ );
+ err.note(format!(
+ "the following trait bounds weren't met: {}",
+ errors
+ .iter()
+ .map(|e| e.obligation.predicate.to_string())
+ .collect::<Vec<_>>()
+ .join("\n"),
+ ));
+ }
+ // The type doesn't implement Clone because of unmet obligations.
+ for error in errors {
+ if let traits::FulfillmentErrorCode::CodeSelectionError(
+ traits::SelectionError::Unimplemented,
+ ) = error.code
+ && let ty::PredicateKind::Clause(ty::ClauseKind::Trait(
+ pred,
+ )) = error.obligation.predicate.kind().skip_binder()
+ {
+ self.infcx.err_ctxt().suggest_derive(
+ &error.obligation,
+ err,
+ error.obligation.predicate.kind().rebind(pred),
+ );
+ }
+ }
+ }
+ }
+ }
let (changing, span, sugg) = match local.ty {
Some(ty) => ("changing", ty.span, message),
None => {
@@ -1397,7 +1495,7 @@ fn get_mut_span_in_struct_field<'tcx>(
&& let ty::Adt(def, _) = ty.kind()
&& let field = def.all_fields().nth(field.index())?
// Use the HIR types to construct the diagnostic message.
- && let node = tcx.hir().find_by_def_id(field.did.as_local()?)?
+ && let node = tcx.opt_hir_node_by_def_id(field.did.as_local()?)?
// Now we're dealing with the actual struct that we're going to suggest a change to,
// we can expect a field that is an immutable reference to a type.
&& let hir::Node::Field(field) = node
diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
index b6eb9ae98..66275888c 100644
--- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
@@ -50,8 +50,8 @@ impl OutlivesSuggestionBuilder {
// naming the `'self` lifetime in methods, etc.
fn region_name_is_suggestable(name: &RegionName) -> bool {
match name.source {
- RegionNameSource::NamedEarlyBoundRegion(..)
- | RegionNameSource::NamedFreeRegion(..)
+ RegionNameSource::NamedEarlyParamRegion(..)
+ | RegionNameSource::NamedLateParamRegion(..)
| RegionNameSource::Static => true,
// Don't give suggestions for upvars, closure return types, or other unnameable
@@ -206,7 +206,7 @@ impl OutlivesSuggestionBuilder {
// If there is exactly one suggestable constraints, then just suggest it. Otherwise, emit a
// list of diagnostics.
let mut diag = if suggested.len() == 1 {
- mbcx.infcx.tcx.sess.diagnostic().struct_help(match suggested.last().unwrap() {
+ mbcx.infcx.tcx.sess.dcx().struct_help(match suggested.last().unwrap() {
SuggestedConstraint::Outlives(a, bs) => {
let bs: SmallVec<[String; 2]> = bs.iter().map(|r| r.to_string()).collect();
format!("add bound `{a}: {}`", bs.join(" + "))
@@ -223,7 +223,7 @@ impl OutlivesSuggestionBuilder {
.infcx
.tcx
.sess
- .diagnostic()
+ .dcx()
.struct_help("the following changes may resolve your lifetime errors");
// Add suggestions.
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index a0a809123..759f5e910 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -35,7 +35,7 @@ use crate::session_diagnostics::{
LifetimeReturnCategoryErr, RequireStaticErr, VarHereDenote,
};
-use super::{OutlivesSuggestionBuilder, RegionName};
+use super::{OutlivesSuggestionBuilder, RegionName, RegionNameSource};
use crate::region_infer::{BlameConstraint, ExtraConstraintInfo};
use crate::{
nll::ConstraintDescription,
@@ -53,7 +53,7 @@ impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> {
ConstraintCategory::Yield => "yielding this value ",
ConstraintCategory::UseAsConst => "using this value as a constant ",
ConstraintCategory::UseAsStatic => "using this value as a static ",
- ConstraintCategory::Cast => "cast ",
+ ConstraintCategory::Cast { .. } => "cast ",
ConstraintCategory::CallArgument(_) => "argument ",
ConstraintCategory::TypeAnnotation => "type annotation ",
ConstraintCategory::ClosureBounds => "closure body ",
@@ -84,7 +84,7 @@ impl<'tcx> RegionErrors<'tcx> {
#[track_caller]
pub fn push(&mut self, val: impl Into<RegionErrorKind<'tcx>>) {
let val = val.into();
- self.1.sess.delay_span_bug(DUMMY_SP, format!("{val:?}"));
+ self.1.sess.span_delayed_bug(DUMMY_SP, format!("{val:?}"));
self.0.push(val);
}
pub fn is_empty(&self) -> bool {
@@ -95,6 +95,12 @@ impl<'tcx> RegionErrors<'tcx> {
}
}
+impl std::fmt::Debug for RegionErrors<'_> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_tuple("RegionErrors").field(&self.0).finish()
+ }
+}
+
#[derive(Clone, Debug)]
pub(crate) enum RegionErrorKind<'tcx> {
/// A generic bound failure for a type test (`T: 'a`).
@@ -181,8 +187,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
/// Returns `true` if a closure is inferred to be an `FnMut` closure.
fn is_closure_fn_mut(&self, fr: RegionVid) -> bool {
- if let Some(ty::ReFree(free_region)) = self.to_error_region(fr).as_deref()
- && let ty::BoundRegionKind::BrEnv = free_region.bound_region
+ if let Some(ty::ReLateParam(late_param)) = self.to_error_region(fr).as_deref()
+ && let ty::BoundRegionKind::BrEnv = late_param.bound_region
&& let DefiningTy::Closure(_, args) = self.regioncx.universal_regions().defining_ty
{
return args.as_closure().kind() == ty::ClosureKind::FnMut;
@@ -209,7 +215,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
.map(|placeholder| {
if let Some(id) = placeholder.bound.kind.get_id()
&& let Some(placeholder_id) = id.as_local()
- && let gat_hir_id = hir.local_def_id_to_hir_id(placeholder_id)
+ && let gat_hir_id = self.infcx.tcx.local_def_id_to_hir_id(placeholder_id)
&& let Some(generics_impl) = hir.get_parent(gat_hir_id).generics()
{
Some((gat_hir_id, generics_impl))
@@ -230,7 +236,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
};
if bound_generic_params
.iter()
- .rfind(|bgp| hir.local_def_id_to_hir_id(bgp.def_id) == *gat_hir_id)
+ .rfind(|bgp| self.infcx.tcx.local_def_id_to_hir_id(bgp.def_id) == *gat_hir_id)
.is_some()
{
for bound in *bounds {
@@ -599,7 +605,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
};
let captured_place = &self.upvars[upvar_field.index()].place;
- let defined_hir = match captured_place.place.base {
+ let defined_hir = match captured_place.base {
PlaceBase::Local(hirid) => Some(hirid),
PlaceBase::Upvar(upvar) => Some(upvar.var_path.hir_id),
_ => None,
@@ -644,14 +650,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let fr_name_and_span = self.regioncx.get_var_name_and_span_for_region(
self.infcx.tcx,
- &self.body,
+ self.body,
&self.local_names,
&self.upvars,
errci.fr,
);
let outlived_fr_name_and_span = self.regioncx.get_var_name_and_span_for_region(
self.infcx.tcx,
- &self.body,
+ self.body,
&self.local_names,
&self.upvars,
errci.outlived_fr,
@@ -757,7 +763,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let err = LifetimeOutliveErr { span: *span };
let mut diag = self.infcx.tcx.sess.create_err(err);
- let fr_name = self.give_region_a_name(*fr).unwrap();
+ // In certain scenarios, such as the one described in issue #118021,
+ // we might encounter a lifetime that cannot be named.
+ // These situations are bound to result in errors.
+ // To prevent an immediate ICE, we opt to create a dummy name instead.
+ let fr_name = self.give_region_a_name(*fr).unwrap_or(RegionName {
+ name: kw::UnderscoreLifetime,
+ source: RegionNameSource::Static,
+ });
fr_name.highlight_region_name(&mut diag);
let outlived_fr_name = self.give_region_a_name(*outlived_fr).unwrap();
outlived_fr_name.highlight_region_name(&mut diag);
@@ -958,7 +971,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
for found_did in found_dids {
let mut traits = vec![];
let mut hir_v = HirTraitObjectVisitor(&mut traits, *found_did);
- hir_v.visit_ty(&self_ty);
+ hir_v.visit_ty(self_ty);
debug!("trait spans found: {:?}", traits);
for span in &traits {
let mut multi_span: MultiSpan = vec![*span].into();
@@ -995,7 +1008,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
.infcx
.tcx
.is_suitable_region(sub)
- .and_then(|anon_reg| find_anon_type(self.infcx.tcx, sub, &anon_reg.boundregion))
+ .and_then(|anon_reg| find_anon_type(self.infcx.tcx, sub, &anon_reg.bound_region))
else {
return;
};
@@ -1004,7 +1017,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
.infcx
.tcx
.is_suitable_region(sup)
- .and_then(|anon_reg| find_anon_type(self.infcx.tcx, sup, &anon_reg.boundregion))
+ .and_then(|anon_reg| find_anon_type(self.infcx.tcx, sup, &anon_reg.bound_region))
else {
return;
};
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index d38cfbc54..8441dfaa7 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -23,14 +23,14 @@ pub(crate) struct RegionName {
}
/// Denotes the source of a region that is named by a `RegionName`. For example, a free region that
-/// was named by the user would get `NamedFreeRegion` and `'static` lifetime would get `Static`.
+/// was named by the user would get `NamedLateParamRegion` and `'static` lifetime would get `Static`.
/// This helps to print the right kinds of diagnostics.
#[derive(Debug, Clone)]
pub(crate) enum RegionNameSource {
/// A bound (not free) region that was instantiated at the def site (not an HRTB).
- NamedEarlyBoundRegion(Span),
+ NamedEarlyParamRegion(Span),
/// A free region that the user has a name (`'a`) for.
- NamedFreeRegion(Span),
+ NamedLateParamRegion(Span),
/// The `'static` region.
Static,
/// The free region corresponding to the environment of a closure.
@@ -69,8 +69,8 @@ pub(crate) enum RegionNameHighlight {
impl RegionName {
pub(crate) fn was_named(&self) -> bool {
match self.source {
- RegionNameSource::NamedEarlyBoundRegion(..)
- | RegionNameSource::NamedFreeRegion(..)
+ RegionNameSource::NamedEarlyParamRegion(..)
+ | RegionNameSource::NamedLateParamRegion(..)
| RegionNameSource::Static => true,
RegionNameSource::SynthesizedFreeEnvRegion(..)
| RegionNameSource::AnonRegionFromArgument(..)
@@ -85,8 +85,8 @@ impl RegionName {
pub(crate) fn span(&self) -> Option<Span> {
match self.source {
RegionNameSource::Static => None,
- RegionNameSource::NamedEarlyBoundRegion(span)
- | RegionNameSource::NamedFreeRegion(span)
+ RegionNameSource::NamedEarlyParamRegion(span)
+ | RegionNameSource::NamedLateParamRegion(span)
| RegionNameSource::SynthesizedFreeEnvRegion(span, _)
| RegionNameSource::AnonRegionFromUpvar(span, _)
| RegionNameSource::AnonRegionFromYieldTy(span, _)
@@ -104,8 +104,8 @@ impl RegionName {
pub(crate) fn highlight_region_name(&self, diag: &mut Diagnostic) {
match &self.source {
- RegionNameSource::NamedFreeRegion(span)
- | RegionNameSource::NamedEarlyBoundRegion(span) => {
+ RegionNameSource::NamedLateParamRegion(span)
+ | RegionNameSource::NamedEarlyParamRegion(span) => {
diag.span_label(*span, format!("lifetime `{self}` defined here"));
}
RegionNameSource::SynthesizedFreeEnvRegion(span, note) => {
@@ -199,7 +199,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
}
pub(crate) fn mir_hir_id(&self) -> hir::HirId {
- self.infcx.tcx.hir().local_def_id_to_hir_id(self.mir_def_id())
+ self.infcx.tcx.local_def_id_to_hir_id(self.mir_def_id())
}
/// Generate a synthetic region named `'N`, where `N` is the next value of the counter. Then,
@@ -280,28 +280,31 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
debug!("give_region_a_name: error_region = {:?}", error_region);
match *error_region {
- ty::ReEarlyBound(ebr) => ebr.has_name().then(|| {
+ ty::ReEarlyParam(ebr) => ebr.has_name().then(|| {
let span = tcx.hir().span_if_local(ebr.def_id).unwrap_or(DUMMY_SP);
- RegionName { name: ebr.name, source: RegionNameSource::NamedEarlyBoundRegion(span) }
+ RegionName { name: ebr.name, source: RegionNameSource::NamedEarlyParamRegion(span) }
}),
ty::ReStatic => {
Some(RegionName { name: kw::StaticLifetime, source: RegionNameSource::Static })
}
- ty::ReFree(free_region) => match free_region.bound_region {
+ ty::ReLateParam(late_param) => match late_param.bound_region {
ty::BoundRegionKind::BrNamed(region_def_id, name) => {
// Get the span to point to, even if we don't use the name.
let span = tcx.hir().span_if_local(region_def_id).unwrap_or(DUMMY_SP);
debug!(
"bound region named: {:?}, is_named: {:?}",
name,
- free_region.bound_region.is_named()
+ late_param.bound_region.is_named()
);
- if free_region.bound_region.is_named() {
+ if late_param.bound_region.is_named() {
// A named region that is actually named.
- Some(RegionName { name, source: RegionNameSource::NamedFreeRegion(span) })
+ Some(RegionName {
+ name,
+ source: RegionNameSource::NamedLateParamRegion(span),
+ })
} else if tcx.asyncness(self.mir_hir_id().owner).is_async() {
// If we spuriously thought that the region is named, we should let the
// system generate a true name for error messages. Currently this can
@@ -357,7 +360,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
ty::BoundRegionKind::BrAnon => None,
},
- ty::ReLateBound(..)
+ ty::ReBound(..)
| ty::ReVar(..)
| ty::RePlaceholder(..)
| ty::ReErased
@@ -384,7 +387,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
let arg_ty = self.regioncx.universal_regions().unnormalized_input_tys
[implicit_inputs + argument_index];
let (_, span) = self.regioncx.get_argument_name_and_span_for_region(
- &self.body,
+ self.body,
&self.local_names,
argument_index,
);
@@ -616,8 +619,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
_,
) => {
// HIR lowering sometimes doesn't catch this in erroneous
- // programs, so we need to use delay_span_bug here. See #82126.
- self.infcx.tcx.sess.delay_span_bug(
+ // programs, so we need to use span_delayed_bug here. See #82126.
+ self.infcx.tcx.sess.span_delayed_bug(
hir_arg.span(),
format!("unmatched arg and hir arg: found {kind:?} vs {hir_arg:?}"),
);
@@ -669,7 +672,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
let mir_hir_id = self.mir_hir_id();
- let (return_span, mir_description, hir_ty) = match hir.get(mir_hir_id) {
+ let (return_span, mir_description, hir_ty) = match tcx.hir_node(mir_hir_id) {
hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure(&hir::Closure { fn_decl, body, fn_decl_span, .. }),
..
@@ -681,12 +684,12 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
hir::FnRetTy::Return(hir_ty) => (fn_decl.output.span(), Some(hir_ty)),
};
let mir_description = match hir.body(body).coroutine_kind {
- Some(hir::CoroutineKind::Async(gen)) => match gen {
+ Some(hir::CoroutineKind::Async(src)) => match src {
hir::CoroutineSource::Block => " of async block",
hir::CoroutineSource::Closure => " of async closure",
hir::CoroutineSource::Fn => {
let parent_item =
- hir.get_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
+ tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
let output = &parent_item
.fn_decl()
.expect("coroutine lowered from async fn should be in fn")
@@ -698,12 +701,12 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
" of async function"
}
},
- Some(hir::CoroutineKind::Gen(gen)) => match gen {
+ Some(hir::CoroutineKind::Gen(src)) => match src {
hir::CoroutineSource::Block => " of gen block",
hir::CoroutineSource::Closure => " of gen closure",
hir::CoroutineSource::Fn => {
let parent_item =
- hir.get_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
+ tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
let output = &parent_item
.fn_decl()
.expect("coroutine lowered from gen fn should be in fn")
@@ -712,6 +715,21 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
" of gen function"
}
},
+
+ Some(hir::CoroutineKind::AsyncGen(src)) => match src {
+ hir::CoroutineSource::Block => " of async gen block",
+ hir::CoroutineSource::Closure => " of async gen closure",
+ hir::CoroutineSource::Fn => {
+ let parent_item =
+ tcx.hir_node_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
+ let output = &parent_item
+ .fn_decl()
+ .expect("coroutine lowered from async gen fn should be in fn")
+ .output;
+ span = output.span();
+ " of async gen function"
+ }
+ },
Some(hir::CoroutineKind::Coroutine) => " of coroutine",
None => " of closure",
};
@@ -770,28 +788,18 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
};
let opaque_ty = hir.item(id);
if let hir::ItemKind::OpaqueTy(hir::OpaqueTy {
- bounds:
- [
- hir::GenericBound::LangItemTrait(
- hir::LangItem::Future,
- _,
- _,
- hir::GenericArgs {
- bindings:
- [
- hir::TypeBinding {
- ident: Ident { name: sym::Output, .. },
- kind:
- hir::TypeBindingKind::Equality { term: hir::Term::Ty(ty) },
- ..
- },
- ],
- ..
- },
- ),
- ],
+ bounds: [hir::GenericBound::Trait(trait_ref, _)],
..
}) = opaque_ty.kind
+ && let Some(segment) = trait_ref.trait_ref.path.segments.last()
+ && let Some(args) = segment.args
+ && let [
+ hir::TypeBinding {
+ ident: Ident { name: sym::Output, .. },
+ kind: hir::TypeBindingKind::Equality { term: hir::Term::Ty(ty) },
+ ..
+ },
+ ] = args.bindings
{
ty
} else {
@@ -823,7 +831,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
let type_name =
self.infcx.extract_inference_diagnostics_data(yield_ty.into(), Some(highlight)).name;
- let yield_span = match tcx.hir().get(self.mir_hir_id()) {
+ let yield_span = match tcx.hir_node(self.mir_hir_id()) {
hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }),
..
@@ -847,7 +855,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
&self,
fr: RegionVid,
) -> Option<RegionName> {
- let ty::ReEarlyBound(region) = *self.to_error_region(fr)? else {
+ let ty::ReEarlyParam(region) = *self.to_error_region(fr)? else {
return None;
};
if region.has_name() {
@@ -862,7 +870,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
let found = tcx
.any_free_region_meets(&tcx.type_of(region_parent).instantiate_identity(), |r| {
- *r == ty::ReEarlyBound(region)
+ *r == ty::ReEarlyParam(region)
});
Some(RegionName {
@@ -881,7 +889,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
&self,
fr: RegionVid,
) -> Option<RegionName> {
- let ty::ReEarlyBound(region) = *self.to_error_region(fr)? else {
+ let ty::ReEarlyParam(region) = *self.to_error_region(fr)? else {
return None;
};
if region.has_name() {
@@ -943,7 +951,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
&self,
clauses: &[ty::Clause<'tcx>],
ty: Ty<'tcx>,
- region: ty::EarlyBoundRegion,
+ region: ty::EarlyParamRegion,
) -> bool {
let tcx = self.infcx.tcx;
ty.walk().any(|arg| {
@@ -956,7 +964,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
ty::ClauseKind::Projection(data) if data.projection_ty.self_ty() == ty => {}
_ => return false,
}
- tcx.any_free_region_meets(pred, |r| *r == ty::ReEarlyBound(region))
+ tcx.any_free_region_meets(pred, |r| *r == ty::ReEarlyParam(region))
})
} else {
false
diff --git a/compiler/rustc_borrowck/src/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs
index 3a104c524..28e07f2a8 100644
--- a/compiler/rustc_borrowck/src/diagnostics/var_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs
@@ -2,10 +2,9 @@
#![deny(rustc::diagnostic_outside_of_impl)]
use crate::region_infer::RegionInferenceContext;
-use crate::Upvar;
use rustc_index::IndexSlice;
use rustc_middle::mir::{Body, Local};
-use rustc_middle::ty::{RegionVid, TyCtxt};
+use rustc_middle::ty::{self, RegionVid, TyCtxt};
use rustc_span::symbol::Symbol;
use rustc_span::Span;
@@ -15,7 +14,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
local_names: &IndexSlice<Local, Option<Symbol>>,
- upvars: &[Upvar<'tcx>],
+ upvars: &[&ty::CapturedPlace<'tcx>],
fr: RegionVid,
) -> Option<(Option<Symbol>, Span)> {
debug!("get_var_name_and_span_for_region(fr={fr:?})");
@@ -66,10 +65,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
pub(crate) fn get_upvar_name_and_span_for_region(
&self,
tcx: TyCtxt<'tcx>,
- upvars: &[Upvar<'tcx>],
+ upvars: &[&ty::CapturedPlace<'tcx>],
upvar_index: usize,
) -> (Symbol, Span) {
- let upvar_hir_id = upvars[upvar_index].place.get_root_variable();
+ let upvar_hir_id = upvars[upvar_index].get_root_variable();
debug!("get_upvar_name_and_span_for_region: upvar_hir_id={upvar_hir_id:?}");
let upvar_name = tcx.hir().name(upvar_hir_id);