1 impl<'tcx> TypeErrCtxt<'_, 'tcx> {
5 cause: &ObligationCause<'tcx>,
6 exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
10 ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => {
11 let ty = self.resolve_vars_if_possible(root_ty);
12 if !matches!(ty.kind(), ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_)))
14 // don't show type `_`
15 if span.desugaring_kind() == Some(DesugaringKind::ForLoop)
16 && let ty::Adt(def, substs) = ty.kind()
17 && Some(def.did()) == self.tcx.get_diagnostic_item(sym::Option)
19 err.span_label(span, format!("this is an iterator with items of type `{}`", substs.type_at(0)));
21 err.span_label(span, format!("this expression has type `{}`", ty));
24 if let Some(ty::error::ExpectedFound { found, .. }) = exp_found
25 && ty.is_box() && ty.boxed_ty() == found
26 && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
30 "consider dereferencing the boxed value",
31 format!("*{}", snippet),
32 Applicability::MachineApplicable,
36 ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => {
37 err.span_label(span, "expected due to this");
39 ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
53 hir::MatchSource::TryDesugar => {
54 if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found {
55 let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id);
56 let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind {
57 let arg_expr = args.first().expect("try desugaring call w/out arg");
58 self.typeck_results.as_ref().and_then(|typeck_results| {
59 typeck_results.expr_ty_opt(arg_expr)
62 bug!("try desugaring w/out call expr as scrutinee");
66 Some(ty) if expected == ty => {
67 let source_map = self.tcx.sess.source_map();
69 source_map.end_point(cause.span),
70 "try removing this `?`",
72 Applicability::MachineApplicable,
80 // `prior_arm_ty` can be `!`, `expected` will have better info when present.
81 let t = self.resolve_vars_if_possible(match exp_found {
82 Some(ty::error::ExpectedFound { expected, .. }) => expected,
85 let source_map = self.tcx.sess.source_map();
86 let mut any_multiline_arm = source_map.is_multiline(arm_span);
87 if prior_arms.len() <= 4 {
88 for sp in prior_arms {
89 any_multiline_arm |= source_map.is_multiline(*sp);
90 err.span_label(*sp, format!("this is found to be of type `{}`", t));
92 } else if let Some(sp) = prior_arms.last() {
93 any_multiline_arm |= source_map.is_multiline(*sp);
96 format!("this and all prior arms are found to be of type `{}`", t),
99 let outer_error_span = if any_multiline_arm {
100 // Cover just `match` and the scrutinee expression, not
101 // the entire match body, to reduce diagram noise.
102 cause.span.shrink_to_lo().to(scrut_span)
106 let msg = "`match` arms have incompatible types";
107 err.span_label(outer_error_span, msg);
108 self.suggest_remove_semi_or_return_binding(
117 if let Some(ret_sp) = opt_suggest_box_span {
118 // Get return type span and point to it.
119 self.suggest_boxing_for_return_impl_trait(
122 prior_arms.iter().chain(std::iter::once(&arm_span)).map(|s| *s),
127 ObligationCauseCode::IfExpression(box IfExpressionCause {
133 opt_suggest_box_span,
135 let then_span = self.find_block_span_from_hir_id(then_id);
136 let else_span = self.find_block_span_from_hir_id(else_id);
137 err.span_label(then_span, "expected because of this");
138 if let Some(sp) = outer_span {
139 err.span_label(sp, "`if` and `else` have incompatible types");
141 self.suggest_remove_semi_or_return_binding(
150 if let Some(ret_sp) = opt_suggest_box_span {
151 self.suggest_boxing_for_return_impl_trait(
154 [then_span, else_span].into_iter(),
158 ObligationCauseCode::LetElse => {
159 err.help("try adding a diverging expression, such as `return` or `panic!(..)`");
160 err.help("...or use `match` instead of `let...else`");
163 if let ObligationCauseCode::BindingObligation(_, span)
164 | ObligationCauseCode::ExprBindingObligation(_, span, ..)
165 = cause.code().peel_derives()
166 && let TypeError::RegionsPlaceholderMismatch = terr
168 err.span_note( * span,
169 "the lifetime requirement is introduced here");
176 impl<'tcx> InferCtxt<'tcx> {
177 /// Given a [`hir::Block`], get the span of its last expression or
178 /// statement, peeling off any inner blocks.
179 pub fn find_block_span(&self, block: &'tcx hir::Block<'tcx>) -> Span {
180 let block = block.innermost_block();
181 if let Some(expr) = &block.expr {
183 } else if let Some(stmt) = block.stmts.last() {
184 // possibly incorrect trailing `;` in the else arm
187 // empty block; point at its entirety
192 /// Given a [`hir::HirId`] for a block, get the span of its last expression
193 /// or statement, peeling off any inner blocks.
194 pub fn find_block_span_from_hir_id(&self, hir_id: hir::HirId) -> Span {
195 match self.tcx.hir().get(hir_id) {
196 hir::Node::Block(blk) => self.find_block_span(blk),
197 // The parser was in a weird state if either of these happen, but
198 // it's better not to panic.
199 hir::Node::Expr(e) => e.span,
200 _ => rustc_span::DUMMY_SP,