summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_typeck/src/fn_ctxt
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_hir_typeck/src/fn_ctxt')
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs61
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs123
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs237
6 files changed, 252 insertions, 187 deletions
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 750ed2c34..4bc237c23 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -72,7 +72,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
orig_span,
custom_note
.unwrap_or("any code following this expression is unreachable"),
- )
+ );
},
)
}
@@ -83,7 +83,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// version (resolve_vars_if_possible), this version will
/// also select obligations if it seems useful, in an effort
/// to get more type information.
- // FIXME(-Ztrait-solver=next): A lot of the calls to this method should
+ // FIXME(-Znext-solver): A lot of the calls to this method should
// probably be `try_structurally_resolve_type` or `structurally_resolve_type` instead.
#[instrument(skip(self), level = "debug", ret)]
pub(in super::super) fn resolve_vars_with_obligations(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
@@ -159,7 +159,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
#[instrument(level = "debug", skip(self))]
- pub fn write_method_call(&self, hir_id: hir::HirId, method: MethodCallee<'tcx>) {
+ pub fn write_method_call_and_enforce_effects(
+ &self,
+ hir_id: hir::HirId,
+ span: Span,
+ method: MethodCallee<'tcx>,
+ ) {
+ self.enforce_context_effects(span, method.def_id, method.args);
self.write_resolution(hir_id, Ok((DefKind::AssocFn, method.def_id)));
self.write_args(hir_id, method.args);
}
@@ -271,7 +277,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// FIXME: currently we never try to compose autoderefs
// and ReifyFnPointer/UnsafeFnPointer, but we could.
_ => {
- self.tcx.sess.delay_span_bug(
+ self.tcx.sess.span_delayed_bug(
expr.span,
format!(
"while adjusting {:?}, can't compose {:?} and {:?}",
@@ -505,7 +511,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub(in super::super) fn resolve_rvalue_scopes(&self, def_id: DefId) {
let scope_tree = self.tcx.region_scope_tree(def_id);
- let rvalue_scopes = { rvalue_scopes::resolve_rvalue_scopes(self, &scope_tree, def_id) };
+ let rvalue_scopes = { rvalue_scopes::resolve_rvalue_scopes(self, scope_tree, def_id) };
let mut typeck_results = self.inh.typeck_results.borrow_mut();
typeck_results.rvalue_scopes = rvalue_scopes;
}
@@ -651,20 +657,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
| ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..))
| ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..))
| ty::PredicateKind::ObjectSafe(..)
+ | ty::PredicateKind::NormalizesTo(..)
| ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
| ty::PredicateKind::ConstEquate(..)
- // N.B., this predicate is created by breaking down a
- // `ClosureType: FnFoo()` predicate, where
- // `ClosureType` represents some `Closure`. It can't
- // possibly be referring to the current closure,
- // because we haven't produced the `Closure` for
- // this closure yet; this is exactly why the other
- // code is looking for a self type of an unresolved
- // inference variable.
- | ty::PredicateKind::ClosureKind(..)
- | ty::PredicateKind::Ambiguous
- => None,
+ | ty::PredicateKind::Ambiguous => None,
},
)
}
@@ -754,7 +751,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
lang_item: hir::LangItem,
span: Span,
hir_id: hir::HirId,
- expr_hir_id: Option<hir::HirId>,
) -> (Res, Ty<'tcx>) {
let def_id = self.tcx.require_lang_item(lang_item, Some(span));
let def_kind = self.tcx.def_kind(def_id);
@@ -767,11 +763,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let args = self.fresh_args_for_item(span, def_id);
let ty = item_ty.instantiate(self.tcx, args);
+ self.write_args(hir_id, args);
self.write_resolution(hir_id, Ok((def_kind, def_id)));
let code = match lang_item {
hir::LangItem::IntoFutureIntoFuture => {
- Some(ObligationCauseCode::AwaitableExpr(expr_hir_id))
+ if let hir::Node::Expr(into_future_call) = self.tcx.hir().get_parent(hir_id)
+ && let hir::ExprKind::Call(_, [arg0]) = &into_future_call.kind
+ {
+ Some(ObligationCauseCode::AwaitableExpr(arg0.hir_id))
+ } else {
+ None
+ }
}
hir::LangItem::IteratorNext | hir::LangItem::IntoIterIntoIter => {
Some(ObligationCauseCode::ForLoopIterator)
@@ -804,7 +807,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
qpath, hir_id, span
);
let (ty, qself, item_segment) = match *qpath {
- QPath::Resolved(ref opt_qself, ref path) => {
+ QPath::Resolved(ref opt_qself, path) => {
return (
path.res,
opt_qself.as_ref().map(|qself| self.to_ty(qself)),
@@ -845,7 +848,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& let Some(mut diag) = self
.tcx
.sess
- .diagnostic()
+ .dcx()
.steal_diagnostic(qself.span, StashKey::TraitMissingMethod)
{
diag.emit();
@@ -856,7 +859,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let guar = self
.tcx
.sess
- .delay_span_bug(span, "method resolution should've emitted an error");
+ .span_delayed_bug(span, "method resolution should've emitted an error");
let result = match error {
method::MethodError::PrivateMatch(kind, def_id, _) => Ok((kind, def_id)),
_ => Err(guar),
@@ -881,7 +884,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& let Some(mut diag) = self
.tcx
.sess
- .diagnostic()
+ .dcx()
.steal_diagnostic(qself.span, StashKey::TraitMissingMethod)
{
if trait_missing_method {
@@ -991,7 +994,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or
// `while` before reaching it, as block tail returns are not available in them.
self.tcx.hir().get_return_block(blk_id).and_then(|blk_id| {
- let parent = self.tcx.hir().get(blk_id);
+ let parent = self.tcx.hir_node(blk_id);
self.get_node_fn_decl(parent)
.map(|(fn_id, fn_decl, _, is_main)| (fn_id, fn_decl, is_main))
})
@@ -1186,7 +1189,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
tcx,
span,
def_id,
- &generics,
+ generics,
seg,
IsMethodCall::No,
);
@@ -1278,7 +1281,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// going to infer the arguments for better error messages.
if !self.infer_args_for_err.contains(&index) {
// Check whether the user has provided generic arguments.
- if let Some(ref data) = self.segments[index].args {
+ if let Some(data) = self.segments[index].args {
return (Some(data), self.segments[index].infer_args);
}
}
@@ -1406,7 +1409,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Normalize only after registering type annotations.
let args = self.normalize(span, args_raw);
- self.add_required_obligations_for_hir(span, def_id, &args, hir_id);
+ self.add_required_obligations_for_hir(span, def_id, args, hir_id);
// Substitute the values for the type parameters into the type of
// the referenced item.
@@ -1430,7 +1433,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
Ok(ok) => self.register_infer_ok_obligations(ok),
Err(_) => {
- self.tcx.sess.delay_span_bug(
+ self.tcx.sess.span_delayed_bug(
span,
format!(
"instantiate_value_path: (UFCS) {self_ty:?} was a subtype of {impl_ty:?} but now is not?",
@@ -1473,7 +1476,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
let param_env = self.param_env;
- let bounds = self.instantiate_bounds(span, def_id, &args);
+ let bounds = self.instantiate_bounds(span, def_id, args);
for obligation in traits::predicates_for_generics(
|idx, predicate_span| {
@@ -1495,7 +1498,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ty = self.resolve_vars_with_obligations(ty);
if self.next_trait_solver()
- && let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, _) = ty.kind()
+ && let ty::Alias(..) = ty.kind()
{
match self
.at(&self.misc(sp), self.param_env)
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
index facbeb8ba..76360239c 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
@@ -4,7 +4,7 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_infer::{infer::type_variable::TypeVariableOriginKind, traits::ObligationCauseCode};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
-use rustc_span::{self, symbol::kw, Span};
+use rustc_span::{symbol::kw, Span};
use rustc_trait_selection::traits;
use std::ops::ControlFlow;
@@ -94,7 +94,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
let hir = self.tcx.hir();
- let (expr, qpath) = match hir.get(hir_id) {
+ let (expr, qpath) = match self.tcx.hir_node(hir_id) {
hir::Node::Expr(expr) => {
if self.closure_span_overlaps_error(error, expr.span) {
return false;
@@ -454,7 +454,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.find_ancestor_in_same_ctxt(error.obligation.cause.span)
.unwrap_or(arg.span);
- if let hir::Node::Expr(arg_expr) = self.tcx.hir().get(arg.hir_id) {
+ if let hir::Node::Expr(arg_expr) = self.tcx.hir_node(arg.hir_id) {
// This is more specific than pointing at the entire argument.
self.blame_specific_expr_if_possible(error, arg_expr)
}
@@ -495,7 +495,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Whether it succeeded or failed, it likely made some amount of progress.
// In the very worst case, it's just the same `expr` we originally passed in.
let expr = match self.blame_specific_expr_if_possible_for_obligation_cause_code(
- &error.obligation.cause.code(),
+ error.obligation.cause.code(),
expr,
) {
Ok(expr) => expr,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs
index 7aadb95d9..566d407d2 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs
@@ -4,11 +4,13 @@ use rustc_middle::ty::error::TypeError;
use std::cmp;
rustc_index::newtype_index! {
+ #[orderable]
#[debug_format = "ExpectedIdx({})"]
pub(crate) struct ExpectedIdx {}
}
rustc_index::newtype_index! {
+ #[orderable]
#[debug_format = "ProvidedIdx({})"]
pub(crate) struct ProvidedIdx {}
}
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 33dfa16a6..4caa0df58 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -33,7 +33,7 @@ use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt};
use rustc_session::Session;
use rustc_span::symbol::{kw, Ident};
-use rustc_span::{self, sym, BytePos, Span};
+use rustc_span::{sym, BytePos, Span};
use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext};
use std::iter;
@@ -230,11 +230,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let minimum_input_count = expected_input_tys.len();
let provided_arg_count = provided_args.len();
- let is_const_eval_select = matches!(fn_def_id, Some(def_id) if
- self.tcx.def_kind(def_id) == hir::def::DefKind::Fn
- && self.tcx.is_intrinsic(def_id)
- && self.tcx.item_name(def_id) == sym::const_eval_select);
-
// We introduce a helper function to demand that a given argument satisfy a given input
// This is more complicated than just checking type equality, as arguments could be coerced
// This version writes those types back so further type checking uses the narrowed types
@@ -269,35 +264,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return Compatibility::Incompatible(coerce_error);
}
- // Check that second and third argument of `const_eval_select` must be `FnDef`, and additionally that
- // the second argument must be `const fn`. The first argument must be a tuple, but this is already expressed
- // in the function signature (`F: FnOnce<ARG>`), so I did not bother to add another check here.
- //
- // This check is here because there is currently no way to express a trait bound for `FnDef` types only.
- if is_const_eval_select && (1..=2).contains(&idx) {
- if let ty::FnDef(def_id, args) = *checked_ty.kind() {
- if idx == 1 {
- if !self.tcx.is_const_fn_raw(def_id) {
- self.tcx.sess.emit_err(errors::ConstSelectMustBeConst {
- span: provided_arg.span,
- });
- } else {
- self.enforce_context_effects(
- provided_arg.hir_id,
- provided_arg.span,
- def_id,
- args,
- )
- }
- }
- } else {
- self.tcx.sess.emit_err(errors::ConstSelectMustBeFn {
- span: provided_arg.span,
- ty: checked_ty,
- });
- }
- }
-
// 3. Check if the formal type is a supertype of the checked one
// and register any such obligations for future type checks
let supertype_error = self.at(&self.misc(provided_arg.span), self.param_env).sup(
@@ -397,7 +363,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
for arg in provided_args.iter().skip(minimum_input_count) {
// Make sure we've checked this expr at least once.
- let arg_ty = self.check_expr(&arg);
+ let arg_ty = self.check_expr(arg);
// If the function is c-style variadic, we skipped a bunch of arguments
// so we need to check those, and write out the types
@@ -522,7 +488,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let tcx = self.tcx;
// FIXME: taint after emitting errors and pass through an `ErrorGuaranteed`
self.set_tainted_by_errors(
- tcx.sess.delay_span_bug(call_span, "no errors reported for args"),
+ tcx.sess.span_delayed_bug(call_span, "no errors reported for args"),
);
// Get the argument span in the context of the call span so that
@@ -796,7 +762,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut err = self.err_ctxt().report_and_explain_type_error(trace, *err);
self.emit_coerce_suggestions(
&mut err,
- &provided_args[*provided_idx],
+ provided_args[*provided_idx],
provided_ty,
Expectation::rvalue_hint(self, expected_ty)
.only_has_type(self)
@@ -925,7 +891,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.emit_coerce_suggestions(
&mut err,
- &provided_args[provided_idx],
+ provided_args[provided_idx],
provided_ty,
Expectation::rvalue_hint(self, expected_ty)
.only_has_type(self)
@@ -998,7 +964,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}) {
match e {
Error::Missing(expected_idx) => missing_idxs.push(expected_idx),
- _ => unreachable!(),
+ _ => unreachable!(
+ "control flow ensures that we should always get an `Error::Missing`"
+ ),
}
}
@@ -1366,7 +1334,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let variant = match def {
Res::Err => {
let guar =
- self.tcx.sess.delay_span_bug(path_span, "`Res::Err` but no error emitted");
+ self.tcx.sess.span_delayed_bug(path_span, "`Res::Err` but no error emitted");
self.set_tainted_by_errors(guar);
return Err(guar);
}
@@ -1469,7 +1437,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Type check the initializer.
if let Some(ref init) = decl.init {
- let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, &init);
+ let init_ty = self.check_decl_initializer(decl.hir_id, decl.pat, init);
self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, init_ty);
}
@@ -1483,7 +1451,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
// Type check the pattern. Override if necessary to avoid knock-on errors.
- self.check_pat_top(&decl.pat, decl_ty, ty_span, origin_expr, Some(decl.origin));
+ self.check_pat_top(decl.pat, decl_ty, ty_span, origin_expr, Some(decl.origin));
let pat_ty = self.node_ty(decl.pat.hir_id);
self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, pat_ty);
@@ -1525,13 +1493,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::StmtKind::Item(_) => {}
hir::StmtKind::Expr(ref expr) => {
// Check with expected type of `()`.
- self.check_expr_has_type_or_error(&expr, Ty::new_unit(self.tcx), |err| {
+ self.check_expr_has_type_or_error(expr, Ty::new_unit(self.tcx), |err| {
if expr.can_have_side_effects() {
self.suggest_semicolon_at_end(expr.span, err);
}
});
}
- hir::StmtKind::Semi(ref expr) => {
+ hir::StmtKind::Semi(expr) => {
self.check_expr(expr);
}
}
@@ -1739,7 +1707,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
fn parent_item_span(&self, id: hir::HirId) -> Option<Span> {
- let node = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(id).def_id);
+ let node = self.tcx.hir_node_by_def_id(self.tcx.hir().get_parent_item(id).def_id);
match node {
Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })
| Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => {
@@ -1755,7 +1723,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Given a function block's `HirId`, returns its `FnDecl` if it exists, or `None` otherwise.
fn get_parent_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident)> {
- let parent = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(blk_id).def_id);
+ let parent = self.tcx.hir_node_by_def_id(self.tcx.hir().get_parent_item(blk_id).def_id);
self.get_node_fn_decl(parent).map(|(_, fn_decl, ident, _)| (fn_decl, ident))
}
@@ -1820,12 +1788,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir_id: hir::HirId,
) -> (Res, RawTy<'tcx>) {
match *qpath {
- QPath::Resolved(ref maybe_qself, ref path) => {
+ QPath::Resolved(ref maybe_qself, path) => {
let self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself).raw);
let ty = self.astconv().res_to_ty(self_ty, path, hir_id, true);
(path.res, self.handle_raw_ty(path_span, ty))
}
- QPath::TypeRelative(ref qself, ref segment) => {
+ QPath::TypeRelative(qself, segment) => {
let ty = self.to_ty(qself);
let result = self
@@ -1842,8 +1810,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)), ty)
}
- QPath::LangItem(lang_item, span, id) => {
- let (res, ty) = self.resolve_lang_item_path(lang_item, span, hir_id, id);
+ QPath::LangItem(lang_item, span) => {
+ let (res, ty) = self.resolve_lang_item_path(lang_item, span, hir_id);
(res, self.handle_raw_ty(path_span, ty))
}
}
@@ -1855,7 +1823,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
for (span, code) in errors_causecode {
let Some(mut diag) =
- self.tcx.sess.diagnostic().steal_diagnostic(span, StashKey::MaybeForgetReturn)
+ self.tcx.sess.dcx().steal_diagnostic(span, StashKey::MaybeForgetReturn)
else {
continue;
};
@@ -1864,35 +1832,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& let ExprBindingObligation(_, _, hir_id, ..) = code
&& !fn_sig.output().is_unit()
{
- let mut block_num = 0;
- let mut found_semi = false;
- for (_, node) in self.tcx.hir().parent_iter(hir_id) {
- match node {
- hir::Node::Stmt(stmt) => if let hir::StmtKind::Semi(ref expr) = stmt.kind {
+ let mut block_num = 0;
+ let mut found_semi = false;
+ for (_, node) in self.tcx.hir().parent_iter(hir_id) {
+ match node {
+ hir::Node::Stmt(stmt) => {
+ if let hir::StmtKind::Semi(expr) = stmt.kind {
let expr_ty = self.typeck_results.borrow().expr_ty(expr);
let return_ty = fn_sig.output();
- if !matches!(expr.kind, hir::ExprKind::Ret(..)) &&
- self.can_coerce(expr_ty, return_ty) {
+ if !matches!(expr.kind, hir::ExprKind::Ret(..))
+ && self.can_coerce(expr_ty, return_ty)
+ {
found_semi = true;
}
- },
- hir::Node::Block(_block) => if found_semi {
+ }
+ }
+ hir::Node::Block(_block) => {
+ if found_semi {
block_num += 1;
}
- hir::Node::Item(item) => if let hir::ItemKind::Fn(..) = item.kind {
+ }
+ hir::Node::Item(item) => {
+ if let hir::ItemKind::Fn(..) = item.kind {
break;
}
- _ => {}
}
+ _ => {}
}
- if block_num > 1 && found_semi {
- diag.span_suggestion_verbose(
- span.shrink_to_lo(),
- "you might have meant to return this to infer its type parameters",
- "return ",
- Applicability::MaybeIncorrect,
- );
- }
+ }
+ if block_num > 1 && found_semi {
+ diag.span_suggestion_verbose(
+ span.shrink_to_lo(),
+ "you might have meant to return this to infer its type parameters",
+ "return ",
+ Applicability::MaybeIncorrect,
+ );
+ }
}
diag.emit();
}
@@ -2016,7 +1991,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let new_def_id = self.probe(|_| {
let trait_ref = ty::TraitRef::new(
self.tcx,
- call_kind.to_def_id(self.tcx),
+ self.tcx.fn_trait_kind_to_def_id(call_kind)?,
[
callee_ty,
self.next_ty_var(TypeVariableOrigin {
@@ -2031,7 +2006,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.param_env,
trait_ref,
);
- match SelectionContext::new(&self).select(&obligation) {
+ match SelectionContext::new(self).select(&obligation) {
Ok(Some(traits::ImplSource::UserDefined(impl_source))) => {
Some(impl_source.impl_def_id)
}
@@ -2082,7 +2057,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let node = self
.tcx
.opt_local_def_id_to_hir_id(self.tcx.hir().get_parent_item(call_expr.hir_id))
- .and_then(|hir_id| self.tcx.hir().find(hir_id));
+ .and_then(|hir_id| self.tcx.opt_hir_node(hir_id));
match node {
Some(hir::Node::Item(item)) => call_finder.visit_item(item),
Some(hir::Node::TraitItem(item)) => call_finder.visit_trait_item(item),
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index e93d180fc..072df1343 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -143,7 +143,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
pub fn sess(&self) -> &Session {
- &self.tcx.sess
+ self.tcx.sess
}
/// Creates an `TypeErrCtxt` with a reference to the in-progress
@@ -196,7 +196,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> {
type Target = Inherited<'tcx>;
fn deref(&self) -> &Self::Target {
- &self.inh
+ self.inh
}
}
@@ -238,7 +238,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
fn re_infer(&self, def: Option<&ty::GenericParamDef>, span: Span) -> Option<ty::Region<'tcx>> {
let v = match def {
- Some(def) => infer::EarlyBoundRegion(span, def.name),
+ Some(def) => infer::RegionParameterDefinition(span, def.name),
None => infer::MiscVariable(span),
};
Some(self.next_region_var(v))
@@ -289,7 +289,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
) -> Ty<'tcx> {
let trait_ref = self.instantiate_binder_with_fresh_vars(
span,
- infer::LateBoundRegionConversionTime::AssocTypeProjection(item_def_id),
+ infer::BoundRegionConversionTime::AssocTypeProjection(item_def_id),
poly_trait_ref,
);
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index c43d4932f..668e54757 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -43,7 +43,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.typeck_results
.borrow()
.liberated_fn_sigs()
- .get(self.tcx.hir().local_def_id_to_hir_id(self.body_id))
+ .get(self.tcx.local_def_id_to_hir_id(self.body_id))
.copied()
}
@@ -72,23 +72,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
blk_id: hir::HirId,
) -> bool {
let expr = expr.peel_drop_temps();
- self.suggest_missing_semicolon(err, expr, expected, false);
let mut pointing_at_return_type = false;
if let hir::ExprKind::Break(..) = expr.kind {
// `break` type mismatches provide better context for tail `loop` expressions.
return false;
}
if let Some((fn_id, fn_decl, can_suggest)) = self.get_fn_decl(blk_id) {
- pointing_at_return_type = self.suggest_missing_return_type(
- err,
- &fn_decl,
- expected,
- found,
- can_suggest,
- fn_id,
- );
+ pointing_at_return_type =
+ self.suggest_missing_return_type(err, fn_decl, expected, found, can_suggest, fn_id);
self.suggest_missing_break_or_return_expr(
- err, expr, &fn_decl, expected, found, blk_id, fn_id,
+ err, expr, fn_decl, expected, found, blk_id, fn_id,
);
}
pointing_at_return_type
@@ -449,12 +442,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected,
)
});
+
+ let prefix_wrap = |sugg: &str| {
+ if let Some(name) = self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
+ format!(": {}{}", name, sugg)
+ } else {
+ sugg.to_string()
+ }
+ };
+
// FIXME: This could/should be extended to suggest `as_mut` and `as_deref_mut`,
// but those checks need to be a bit more delicate and the benefit is diminishing.
if self.can_eq(self.param_env, found_ty_inner, peeled) && error_tys_equate_as_ref {
+ let sugg = prefix_wrap(".as_ref()");
err.subdiagnostic(errors::SuggestConvertViaMethod {
span: expr.span.shrink_to_hi(),
- sugg: ".as_ref()",
+ sugg,
expected,
found,
borrow_removal_span,
@@ -465,9 +468,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& self.can_eq(self.param_env, deref_ty, peeled)
&& error_tys_equate_as_ref
{
+ let sugg = prefix_wrap(".as_deref()");
err.subdiagnostic(errors::SuggestConvertViaMethod {
span: expr.span.shrink_to_hi(),
- sugg: ".as_deref()",
+ sugg,
expected,
found,
borrow_removal_span,
@@ -481,10 +485,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.can_eq(self.param_env, found, expected)
})
{
+ let sugg = prefix_wrap(".map(|x| x.as_str())");
err.span_suggestion_verbose(
expr.span.shrink_to_hi(),
fluent::hir_typeck_convert_to_str,
- ".map(|x| x.as_str())",
+ sugg,
Applicability::MachineApplicable,
);
return true;
@@ -615,7 +620,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return false;
}
let pin_did = self.tcx.lang_items().pin_type();
- // This guards the `unwrap` and `mk_box` below.
+ // This guards the `new_box` below.
if pin_did.is_none() || self.tcx.lang_items().owned_box().is_none() {
return false;
}
@@ -635,12 +640,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.help("use `Box::pin`");
}
_ => {
+ let prefix = if let Some(name) =
+ self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr)
+ {
+ format!("{}: ", name)
+ } else {
+ String::new()
+ };
+ let suggestion = vec![
+ (expr.span.shrink_to_lo(), format!("{prefix}Box::pin(")),
+ (expr.span.shrink_to_hi(), ")".to_string()),
+ ];
err.multipart_suggestion(
"you need to pin and box this expression",
- vec![
- (expr.span.shrink_to_lo(), "Box::pin(".to_string()),
- (expr.span.shrink_to_hi(), ")".to_string()),
- ],
+ suggestion,
Applicability::MaybeIncorrect,
);
}
@@ -664,7 +677,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// can suggest Box::pin.
let parent = self.tcx.hir().parent_id(expr.hir_id);
let Some(Node::Expr(Expr { kind: ExprKind::Call(fn_name, _), .. })) =
- self.tcx.hir().find(parent)
+ self.tcx.opt_hir_node(parent)
else {
return false;
};
@@ -811,10 +824,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let hir::TyKind::OpaqueDef(item_id, ..) = hir_ty.kind
&& let hir::Node::Item(hir::Item {
kind: hir::ItemKind::OpaqueTy(op_ty), ..
- }) = self.tcx.hir().get(item_id.hir_id())
- && let [
- hir::GenericBound::LangItemTrait(hir::LangItem::Future, _, _, generic_args),
- ] = op_ty.bounds
+ }) = self.tcx.hir_node(item_id.hir_id())
+ && let [hir::GenericBound::Trait(trait_ref, _)] = op_ty.bounds
+ && let Some(hir::PathSegment { args: Some(generic_args), .. }) =
+ trait_ref.trait_ref.path.segments.last()
&& let hir::GenericArgs { bindings: [ty_binding], .. } = generic_args
&& let hir::TypeBindingKind::Equality { term: hir::Term::Ty(term) } =
ty_binding.kind
@@ -846,7 +859,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let bound_vars = self.tcx.late_bound_vars(hir_ty.hir_id.owner.into());
let ty = Binder::bind_with_vars(ty, bound_vars);
let ty = self.normalize(hir_ty.span, ty);
- let ty = self.tcx.erase_late_bound_regions(ty);
+ let ty = self.tcx.instantiate_bound_regions_with_erased(ty);
if self.can_coerce(expected, ty) {
err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other {
span: hir_ty.span,
@@ -889,7 +902,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ty::Param(expected_ty_as_param) = expected.kind() else { return };
- let fn_node = self.tcx.hir().find(fn_id);
+ let fn_node = self.tcx.opt_hir_node(fn_id);
let Some(hir::Node::Item(hir::Item {
kind:
@@ -1023,7 +1036,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let hir::FnRetTy::Return(ty) = fn_decl.output {
let ty = self.astconv().ast_ty_to_ty(ty);
let bound_vars = self.tcx.late_bound_vars(fn_id);
- let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars));
+ let ty = self
+ .tcx
+ .instantiate_bound_regions_with_erased(Binder::bind_with_vars(ty, bound_vars));
let ty = match self.tcx.asyncness(fn_id.owner) {
ty::Asyncness::Yes => self.get_impl_future_output_ty(ty).unwrap_or_else(|| {
span_bug!(fn_decl.output.span(), "failed to get output type of async function")
@@ -1032,7 +1047,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
let ty = self.normalize(expr.span, ty);
if self.can_coerce(found, ty) {
- if let Some(node) = self.tcx.hir().find(fn_id)
+ if let Some(node) = self.tcx.opt_hir_node(fn_id)
&& let Some(owner_node) = node.as_owner()
&& let Some(span) = expr.span.find_ancestor_inside(owner_node.span())
{
@@ -1219,7 +1234,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span = parent_callsite;
}
- let sugg = if expr.precedence().order() >= PREC_POSTFIX {
+ let mut sugg = if expr.precedence().order() >= PREC_POSTFIX {
vec![(span.shrink_to_hi(), ".into()".to_owned())]
} else {
vec![
@@ -1227,6 +1242,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(span.shrink_to_hi(), ").into()".to_owned()),
]
};
+ if let Some(name) = self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
+ sugg.insert(0, (expr.span.shrink_to_lo(), format!("{}: ", name)));
+ }
diag.multipart_suggestion(
format!("call `Into::into` on this expression to convert `{expr_ty}` into `{expected_ty}`"),
sugg,
@@ -1527,12 +1545,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
fn is_loop(&self, id: hir::HirId) -> bool {
- let node = self.tcx.hir().get(id);
+ let node = self.tcx.hir_node(id);
matches!(node, Node::Expr(Expr { kind: ExprKind::Loop(..), .. }))
}
fn is_local_statement(&self, id: hir::HirId) -> bool {
- let node = self.tcx.hir().get(id);
+ let node = self.tcx.hir_node(id);
matches!(node, Node::Stmt(Stmt { kind: StmtKind::Local(..), .. }))
}
@@ -1601,6 +1619,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
None,
);
} else {
+ if let Some(errors) =
+ self.could_impl_trait(clone_trait_did, expected_ty, self.param_env)
+ {
+ match &errors[..] {
+ [] => {}
+ [error] => {
+ diag.help(format!(
+ "`Clone` is not implemented because the trait bound `{}` is \
+ not satisfied",
+ error.obligation.predicate,
+ ));
+ }
+ [errors @ .., last] => {
+ diag.help(format!(
+ "`Clone` is not implemented because the following trait bounds \
+ could not be satisfied: {} and `{}`",
+ errors
+ .iter()
+ .map(|e| format!("`{}`", e.obligation.predicate))
+ .collect::<Vec<_>>()
+ .join(", "),
+ last.obligation.predicate,
+ ));
+ }
+ }
+ 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,
+ diag,
+ error.obligation.predicate.kind().rebind(pred),
+ );
+ }
+ }
+ }
self.suggest_derive(diag, &[(trait_ref.to_predicate(self.tcx), None, None)]);
}
}
@@ -1619,11 +1677,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
None,
hir::Path { segments: [_], res: crate::Res::Local(binding), .. },
)) => {
- let Some(hir::Node::Pat(hir::Pat { hir_id, .. })) = self.tcx.hir().find(*binding)
+ let Some(hir::Node::Pat(hir::Pat { hir_id, .. })) = self.tcx.opt_hir_node(*binding)
else {
return expr;
};
- let Some(parent) = self.tcx.hir().find(self.tcx.hir().parent_id(*hir_id)) else {
+ let Some(parent) = self.tcx.opt_hir_node(self.tcx.hir().parent_id(*hir_id)) else {
return expr;
};
@@ -1639,7 +1697,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
..
}) => {
let Some(hir::Node::Local(hir::Local { init: Some(init), .. })) =
- self.tcx.hir().find(self.tcx.hir().parent_id(*pat_hir_id))
+ self.tcx.opt_hir_node(self.tcx.hir().parent_id(*pat_hir_id))
else {
return expr;
};
@@ -1672,8 +1730,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&& let hir::Path { segments: [_], res: crate::Res::Local(binding), .. } =
call_expr_path
&& let Some(hir::Node::Pat(hir::Pat { hir_id, .. })) =
- self.tcx.hir().find(*binding)
- && let Some(closure) = self.tcx.hir().find(self.tcx.hir().parent_id(*hir_id))
+ self.tcx.opt_hir_node(*binding)
+ && let Some(closure) = self.tcx.opt_hir_node(self.tcx.hir().parent_id(*hir_id))
&& let hir::Node::Local(hir::Local { init: Some(init), .. }) = closure
&& let Expr {
kind: hir::ExprKind::Closure(hir::Closure { body: body_id, .. }),
@@ -1816,6 +1874,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
".expect(\"REASON\")",
)
};
+
+ let sugg = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
+ Some(ident) => format!(": {ident}{sugg}"),
+ None => sugg.to_string(),
+ };
+
err.span_suggestion_verbose(
expr.span.shrink_to_hi(),
msg,
@@ -1921,7 +1985,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some(hir::Node::Block(&hir::Block {
span: block_span, expr: Some(e), ..
- })) = self.tcx.hir().find(parent)
+ })) = self.tcx.opt_hir_node(parent)
{
if e.hir_id == id {
if let Some(span) = expr.span.find_ancestor_inside(block_span) {
@@ -2008,8 +2072,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Some(CtorKind::Fn) => ("(".to_owned(), ")"),
None => (format!(" {{ {field_name}: "), " }"),
- // unit variants don't have fields
- Some(CtorKind::Const) => unreachable!(),
+ Some(CtorKind::Const) => unreachable!("unit variants don't have fields"),
};
// Suggest constructor as deep into the block tree as possible.
@@ -2137,7 +2200,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// opt.map(|param| { takes_ref(param) });
/// ```
fn can_use_as_ref(&self, expr: &hir::Expr<'_>) -> Option<(Vec<(Span, String)>, &'static str)> {
- let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = expr.kind else {
+ let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind else {
return None;
};
@@ -2147,7 +2210,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let local_parent = self.tcx.hir().parent_id(local_id);
let Some(Node::Param(hir::Param { hir_id: param_hir_id, .. })) =
- self.tcx.hir().find(local_parent)
+ self.tcx.opt_hir_node(local_parent)
else {
return None;
};
@@ -2157,13 +2220,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir_id: expr_hir_id,
kind: hir::ExprKind::Closure(hir::Closure { fn_decl: closure_fn_decl, .. }),
..
- })) = self.tcx.hir().find(param_parent)
+ })) = self.tcx.opt_hir_node(param_parent)
else {
return None;
};
let expr_parent = self.tcx.hir().parent_id(*expr_hir_id);
- let hir = self.tcx.hir().find(expr_parent);
+ let hir = self.tcx.opt_hir_node(expr_parent);
let closure_params_len = closure_fn_decl.inputs.len();
let (
Some(Node::Expr(hir::Expr {
@@ -2293,16 +2356,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
if self.can_coerce(ref_ty, expected) {
let mut sugg_sp = sp;
- if let hir::ExprKind::MethodCall(ref segment, receiver, args, _) = expr.kind {
+ if let hir::ExprKind::MethodCall(segment, receiver, args, _) = expr.kind {
let clone_trait =
self.tcx.require_lang_item(LangItem::Clone, Some(segment.ident.span));
if args.is_empty()
- && self.typeck_results.borrow().type_dependent_def_id(expr.hir_id).map(
- |did| {
+ && self
+ .typeck_results
+ .borrow()
+ .type_dependent_def_id(expr.hir_id)
+ .is_some_and(|did| {
let ai = self.tcx.associated_item(did);
ai.trait_container(self.tcx) == Some(clone_trait)
- },
- ) == Some(true)
+ })
&& segment.ident.name == sym::clone
{
// If this expression had a clone call when suggesting borrowing
@@ -2311,7 +2376,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
- if let hir::ExprKind::Unary(hir::UnOp::Deref, ref inner) = expr.kind
+ if let hir::ExprKind::Unary(hir::UnOp::Deref, inner) = expr.kind
&& let Some(1) = self.deref_steps(expected, checked_ty)
{
// We have `*&T`, check if what was expected was `&T`.
@@ -2326,14 +2391,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
));
}
- let needs_parens = match expr.kind {
- // parenthesize if needed (Issue #46756)
- hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
- // parenthesize borrows of range literals (Issue #54505)
- _ if is_range_literal(expr) => true,
- _ => false,
- };
-
if let Some((sugg, msg)) = self.can_use_as_ref(expr) {
return Some((
sugg,
@@ -2361,18 +2418,48 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
- let sugg = mutability.ref_prefix_str();
- let (sugg, verbose) = if needs_parens {
- (
- vec![
- (sp.shrink_to_lo(), format!("{prefix}{sugg}(")),
- (sp.shrink_to_hi(), ")".to_string()),
- ],
- false,
- )
- } else {
- (vec![(sp.shrink_to_lo(), format!("{prefix}{sugg}"))], true)
+ let make_sugg = |expr: &Expr<'_>, span: Span, sugg: &str| {
+ let needs_parens = match expr.kind {
+ // parenthesize if needed (Issue #46756)
+ hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true,
+ // parenthesize borrows of range literals (Issue #54505)
+ _ if is_range_literal(expr) => true,
+ _ => false,
+ };
+
+ if needs_parens {
+ (
+ vec![
+ (span.shrink_to_lo(), format!("{prefix}{sugg}(")),
+ (span.shrink_to_hi(), ")".to_string()),
+ ],
+ false,
+ )
+ } else {
+ (vec![(span.shrink_to_lo(), format!("{prefix}{sugg}"))], true)
+ }
};
+
+ // Suggest dereferencing the lhs for expressions such as `&T == T`
+ if let Some(hir::Node::Expr(hir::Expr {
+ kind: hir::ExprKind::Binary(_, lhs, ..),
+ ..
+ })) = self.tcx.hir().find_parent(expr.hir_id)
+ && let &ty::Ref(..) = self.check_expr(lhs).kind()
+ {
+ let (sugg, verbose) = make_sugg(lhs, lhs.span, "*");
+
+ return Some((
+ sugg,
+ "consider dereferencing the borrow".to_string(),
+ Applicability::MachineApplicable,
+ verbose,
+ false,
+ ));
+ }
+
+ let sugg = mutability.ref_prefix_str();
+ let (sugg, verbose) = make_sugg(expr, sp, sugg);
return Some((
sugg,
format!("consider {}borrowing here", mutability.mutably_str()),
@@ -2382,11 +2469,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
));
}
}
- (
- hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, ref expr),
- _,
- &ty::Ref(_, checked, _),
- ) if self.can_sub(self.param_env, checked, expected) => {
+ (hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, expr), _, &ty::Ref(_, checked, _))
+ if self.can_sub(self.param_env, checked, expected) =>
+ {
let make_sugg = |start: Span, end: BytePos| {
// skip `(` for tuples such as `(c) = (&123)`.
// make sure we won't suggest like `(c) = 123)` which is incorrect.
@@ -2581,7 +2666,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some(Node::Expr(hir::Expr {
kind: hir::ExprKind::If(_, _, Some(else_expr)),
..
- })) = self.tcx.hir().find(parent_id)
+ })) = self.tcx.opt_hir_node(parent_id)
{
return else_expr.hir_id == expr.hir_id;
}
@@ -2971,7 +3056,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return;
};
let parent = self.tcx.hir().parent_id(expr.hir_id);
- if let Some(hir::Node::ExprField(_)) = self.tcx.hir().find(parent) {
+ if let Some(hir::Node::ExprField(_)) = self.tcx.opt_hir_node(parent) {
// Ignore `Foo { field: a..Default::default() }`
return;
}
@@ -3050,7 +3135,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let hir::def::Res::Local(hir_id) = path.res else {
return;
};
- let Some(hir::Node::Pat(pat)) = self.tcx.hir().find(hir_id) else {
+ let Some(hir::Node::Pat(pat)) = self.tcx.opt_hir_node(hir_id) else {
return;
};
let Some(hir::Node::Local(hir::Local { ty: None, init: Some(init), .. })) =