-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rollup merge of #105443 - compiler-errors:move-more, r=oli-obk
Move some queries and methods Each commit's title should be self-explanatory. Motivated to break up some large, general files and move queries into leaf crates.
- Loading branch information
Showing
13 changed files
with
1,756 additions
and
1,095 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
427 changes: 427 additions & 0 deletions
427
compiler/rustc_infer/src/infer/error_reporting/note_region.rs
Large diffs are not rendered by default.
Oops, something went wrong.
672 changes: 672 additions & 0 deletions
672
compiler/rustc_infer/src/infer/error_reporting/suggest.rs
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,203 @@ | ||
impl<'tcx> TypeErrCtxt<'_, 'tcx> { | ||
fn note_error_origin( | ||
&self, | ||
err: &mut Diagnostic, | ||
cause: &ObligationCause<'tcx>, | ||
exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>, | ||
terr: TypeError<'tcx>, | ||
) { | ||
match *cause.code() { | ||
ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => { | ||
let ty = self.resolve_vars_if_possible(root_ty); | ||
if !matches!(ty.kind(), ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_))) | ||
{ | ||
// don't show type `_` | ||
if span.desugaring_kind() == Some(DesugaringKind::ForLoop) | ||
&& let ty::Adt(def, substs) = ty.kind() | ||
&& Some(def.did()) == self.tcx.get_diagnostic_item(sym::Option) | ||
{ | ||
err.span_label(span, format!("this is an iterator with items of type `{}`", substs.type_at(0))); | ||
} else { | ||
err.span_label(span, format!("this expression has type `{}`", ty)); | ||
} | ||
} | ||
if let Some(ty::error::ExpectedFound { found, .. }) = exp_found | ||
&& ty.is_box() && ty.boxed_ty() == found | ||
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) | ||
{ | ||
err.span_suggestion( | ||
span, | ||
"consider dereferencing the boxed value", | ||
format!("*{}", snippet), | ||
Applicability::MachineApplicable, | ||
); | ||
} | ||
} | ||
ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => { | ||
err.span_label(span, "expected due to this"); | ||
} | ||
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { | ||
arm_block_id, | ||
arm_span, | ||
arm_ty, | ||
prior_arm_block_id, | ||
prior_arm_span, | ||
prior_arm_ty, | ||
source, | ||
ref prior_arms, | ||
scrut_hir_id, | ||
opt_suggest_box_span, | ||
scrut_span, | ||
.. | ||
}) => match source { | ||
hir::MatchSource::TryDesugar => { | ||
if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found { | ||
let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id); | ||
let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind { | ||
let arg_expr = args.first().expect("try desugaring call w/out arg"); | ||
self.typeck_results.as_ref().and_then(|typeck_results| { | ||
typeck_results.expr_ty_opt(arg_expr) | ||
}) | ||
} else { | ||
bug!("try desugaring w/out call expr as scrutinee"); | ||
}; | ||
|
||
match scrut_ty { | ||
Some(ty) if expected == ty => { | ||
let source_map = self.tcx.sess.source_map(); | ||
err.span_suggestion( | ||
source_map.end_point(cause.span), | ||
"try removing this `?`", | ||
"", | ||
Applicability::MachineApplicable, | ||
); | ||
} | ||
_ => {} | ||
} | ||
} | ||
} | ||
_ => { | ||
// `prior_arm_ty` can be `!`, `expected` will have better info when present. | ||
let t = self.resolve_vars_if_possible(match exp_found { | ||
Some(ty::error::ExpectedFound { expected, .. }) => expected, | ||
_ => prior_arm_ty, | ||
}); | ||
let source_map = self.tcx.sess.source_map(); | ||
let mut any_multiline_arm = source_map.is_multiline(arm_span); | ||
if prior_arms.len() <= 4 { | ||
for sp in prior_arms { | ||
any_multiline_arm |= source_map.is_multiline(*sp); | ||
err.span_label(*sp, format!("this is found to be of type `{}`", t)); | ||
} | ||
} else if let Some(sp) = prior_arms.last() { | ||
any_multiline_arm |= source_map.is_multiline(*sp); | ||
err.span_label( | ||
*sp, | ||
format!("this and all prior arms are found to be of type `{}`", t), | ||
); | ||
} | ||
let outer_error_span = if any_multiline_arm { | ||
// Cover just `match` and the scrutinee expression, not | ||
// the entire match body, to reduce diagram noise. | ||
cause.span.shrink_to_lo().to(scrut_span) | ||
} else { | ||
cause.span | ||
}; | ||
let msg = "`match` arms have incompatible types"; | ||
err.span_label(outer_error_span, msg); | ||
self.suggest_remove_semi_or_return_binding( | ||
err, | ||
prior_arm_block_id, | ||
prior_arm_ty, | ||
prior_arm_span, | ||
arm_block_id, | ||
arm_ty, | ||
arm_span, | ||
); | ||
if let Some(ret_sp) = opt_suggest_box_span { | ||
// Get return type span and point to it. | ||
self.suggest_boxing_for_return_impl_trait( | ||
err, | ||
ret_sp, | ||
prior_arms.iter().chain(std::iter::once(&arm_span)).map(|s| *s), | ||
); | ||
} | ||
} | ||
}, | ||
ObligationCauseCode::IfExpression(box IfExpressionCause { | ||
then_id, | ||
else_id, | ||
then_ty, | ||
else_ty, | ||
outer_span, | ||
opt_suggest_box_span, | ||
}) => { | ||
let then_span = self.find_block_span_from_hir_id(then_id); | ||
let else_span = self.find_block_span_from_hir_id(else_id); | ||
err.span_label(then_span, "expected because of this"); | ||
if let Some(sp) = outer_span { | ||
err.span_label(sp, "`if` and `else` have incompatible types"); | ||
} | ||
self.suggest_remove_semi_or_return_binding( | ||
err, | ||
Some(then_id), | ||
then_ty, | ||
then_span, | ||
Some(else_id), | ||
else_ty, | ||
else_span, | ||
); | ||
if let Some(ret_sp) = opt_suggest_box_span { | ||
self.suggest_boxing_for_return_impl_trait( | ||
err, | ||
ret_sp, | ||
[then_span, else_span].into_iter(), | ||
); | ||
} | ||
} | ||
ObligationCauseCode::LetElse => { | ||
err.help("try adding a diverging expression, such as `return` or `panic!(..)`"); | ||
err.help("...or use `match` instead of `let...else`"); | ||
} | ||
_ => { | ||
if let ObligationCauseCode::BindingObligation(_, span) | ||
| ObligationCauseCode::ExprBindingObligation(_, span, ..) | ||
= cause.code().peel_derives() | ||
&& let TypeError::RegionsPlaceholderMismatch = terr | ||
{ | ||
err.span_note( * span, | ||
"the lifetime requirement is introduced here"); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
impl<'tcx> InferCtxt<'tcx> { | ||
/// Given a [`hir::Block`], get the span of its last expression or | ||
/// statement, peeling off any inner blocks. | ||
pub fn find_block_span(&self, block: &'tcx hir::Block<'tcx>) -> Span { | ||
let block = block.innermost_block(); | ||
if let Some(expr) = &block.expr { | ||
expr.span | ||
} else if let Some(stmt) = block.stmts.last() { | ||
// possibly incorrect trailing `;` in the else arm | ||
stmt.span | ||
} else { | ||
// empty block; point at its entirety | ||
block.span | ||
} | ||
} | ||
|
||
/// Given a [`hir::HirId`] for a block, get the span of its last expression | ||
/// or statement, peeling off any inner blocks. | ||
pub fn find_block_span_from_hir_id(&self, hir_id: hir::HirId) -> Span { | ||
match self.tcx.hir().get(hir_id) { | ||
hir::Node::Block(blk) => self.find_block_span(blk), | ||
// The parser was in a weird state if either of these happen, but | ||
// it's better not to panic. | ||
hir::Node::Expr(e) => e.span, | ||
_ => rustc_span::DUMMY_SP, | ||
} | ||
} | ||
} |
Oops, something went wrong.