use rustc_middle::ty::adjustment::AllowTwoPhase;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut};
+use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut};
use rustc_span::symbol::{sym, Symbol};
use rustc_span::{BytePos, Span};
///
/// N.B., this code relies on `self.diverges` to be accurate. In particular, assignments to `!`
/// will be permitted if the diverges flag is currently "always".
+ #[tracing::instrument(level = "debug", skip(self, expr, expected_ty_expr, allow_two_phase))]
pub fn demand_coerce_diag(
&self,
expr: &hir::Expr<'tcx>,
let expr_ty = self.resolve_vars_with_obligations(checked_ty);
let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e.clone());
- self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr, Some(e));
+ let is_insufficiently_polymorphic =
+ matches!(e, TypeError::RegionsInsufficientlyPolymorphic(..));
+
+ // FIXME(#73154): For now, we do leak check when coercing function
+ // pointers in typeck, instead of only during borrowck. This can lead
+ // to these `RegionsInsufficientlyPolymorphic` errors that aren't helpful.
+ if !is_insufficiently_polymorphic {
+ self.emit_coerce_suggestions(
+ &mut err,
+ expr,
+ expr_ty,
+ expected,
+ expected_ty_expr,
+ Some(e),
+ );
+ }
(expected, Some(err))
}
let param_parent = self.tcx.hir().get_parent_node(*param_hir_id);
let Some(Node::Expr(hir::Expr {
hir_id: expr_hir_id,
- kind: hir::ExprKind::Closure(_, closure_fn_decl, ..),
+ kind: hir::ExprKind::Closure { fn_decl: closure_fn_decl, .. },
..
})) = self.tcx.hir().find(param_parent) else {
return None;
}
}
- crate fn maybe_get_struct_pattern_shorthand_field(
+ pub(crate) fn maybe_get_struct_pattern_shorthand_field(
&self,
expr: &hir::Expr<'_>,
) -> Option<Symbol> {
}
/// If the given `HirId` corresponds to a block with a trailing expression, return that expression
- crate fn maybe_get_block_expr(&self, expr: &hir::Expr<'tcx>) -> Option<&'tcx hir::Expr<'tcx>> {
+ pub(crate) fn maybe_get_block_expr(
+ &self,
+ expr: &hir::Expr<'tcx>,
+ ) -> Option<&'tcx hir::Expr<'tcx>> {
match expr {
hir::Expr { kind: hir::ExprKind::Block(block, ..), .. } => block.expr,
_ => None,
}
/// Returns whether the given expression is an `else if`.
- crate fn is_else_if_block(&self, expr: &hir::Expr<'_>) -> bool {
+ pub(crate) fn is_else_if_block(&self, expr: &hir::Expr<'_>) -> bool {
if let hir::ExprKind::If(..) = expr.kind {
let parent_id = self.tcx.hir().get_parent_node(expr.hir_id);
if let Some(Node::Expr(hir::Expr {
};
if let Some(hir::Node::Expr(hir::Expr {
- kind: hir::ExprKind::Assign(left_expr, ..),
+ kind: hir::ExprKind::Assign(..),
..
})) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id))
{
if mutability == hir::Mutability::Mut {
- // Found the following case:
- // fn foo(opt: &mut Option<String>){ opt = None }
- // --- ^^^^
- // | |
- // consider dereferencing here: `*opt` |
- // expected mutable reference, found enum `Option`
- if sm.span_to_snippet(left_expr.span).is_ok() {
- return Some((
- left_expr.span.shrink_to_lo(),
- "consider dereferencing here to assign to the mutable \
- borrowed piece of memory"
- .to_string(),
- "*".to_string(),
- Applicability::MachineApplicable,
- true,
- ));
- }
+ // Suppressing this diagnostic, we'll properly print it in `check_expr_assign`
+ return None;
}
}