Skip to content

Commit 6111a73

Browse files
authored
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.
2 parents 441669c + 3b9daac commit 6111a73

File tree

13 files changed

+1756
-1095
lines changed

13 files changed

+1756
-1095
lines changed

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+2-660
Large diffs are not rendered by default.

compiler/rustc_infer/src/infer/error_reporting/note_region.rs

+427
Large diffs are not rendered by default.

compiler/rustc_infer/src/infer/error_reporting/suggest.rs

+672
Large diffs are not rendered by default.
+203
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
2+
fn note_error_origin(
3+
&self,
4+
err: &mut Diagnostic,
5+
cause: &ObligationCause<'tcx>,
6+
exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
7+
terr: TypeError<'tcx>,
8+
) {
9+
match *cause.code() {
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(_)))
13+
{
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)
18+
{
19+
err.span_label(span, format!("this is an iterator with items of type `{}`", substs.type_at(0)));
20+
} else {
21+
err.span_label(span, format!("this expression has type `{}`", ty));
22+
}
23+
}
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)
27+
{
28+
err.span_suggestion(
29+
span,
30+
"consider dereferencing the boxed value",
31+
format!("*{}", snippet),
32+
Applicability::MachineApplicable,
33+
);
34+
}
35+
}
36+
ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => {
37+
err.span_label(span, "expected due to this");
38+
}
39+
ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
40+
arm_block_id,
41+
arm_span,
42+
arm_ty,
43+
prior_arm_block_id,
44+
prior_arm_span,
45+
prior_arm_ty,
46+
source,
47+
ref prior_arms,
48+
scrut_hir_id,
49+
opt_suggest_box_span,
50+
scrut_span,
51+
..
52+
}) => match source {
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)
60+
})
61+
} else {
62+
bug!("try desugaring w/out call expr as scrutinee");
63+
};
64+
65+
match scrut_ty {
66+
Some(ty) if expected == ty => {
67+
let source_map = self.tcx.sess.source_map();
68+
err.span_suggestion(
69+
source_map.end_point(cause.span),
70+
"try removing this `?`",
71+
"",
72+
Applicability::MachineApplicable,
73+
);
74+
}
75+
_ => {}
76+
}
77+
}
78+
}
79+
_ => {
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,
83+
_ => prior_arm_ty,
84+
});
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));
91+
}
92+
} else if let Some(sp) = prior_arms.last() {
93+
any_multiline_arm |= source_map.is_multiline(*sp);
94+
err.span_label(
95+
*sp,
96+
format!("this and all prior arms are found to be of type `{}`", t),
97+
);
98+
}
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)
103+
} else {
104+
cause.span
105+
};
106+
let msg = "`match` arms have incompatible types";
107+
err.span_label(outer_error_span, msg);
108+
self.suggest_remove_semi_or_return_binding(
109+
err,
110+
prior_arm_block_id,
111+
prior_arm_ty,
112+
prior_arm_span,
113+
arm_block_id,
114+
arm_ty,
115+
arm_span,
116+
);
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(
120+
err,
121+
ret_sp,
122+
prior_arms.iter().chain(std::iter::once(&arm_span)).map(|s| *s),
123+
);
124+
}
125+
}
126+
},
127+
ObligationCauseCode::IfExpression(box IfExpressionCause {
128+
then_id,
129+
else_id,
130+
then_ty,
131+
else_ty,
132+
outer_span,
133+
opt_suggest_box_span,
134+
}) => {
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");
140+
}
141+
self.suggest_remove_semi_or_return_binding(
142+
err,
143+
Some(then_id),
144+
then_ty,
145+
then_span,
146+
Some(else_id),
147+
else_ty,
148+
else_span,
149+
);
150+
if let Some(ret_sp) = opt_suggest_box_span {
151+
self.suggest_boxing_for_return_impl_trait(
152+
err,
153+
ret_sp,
154+
[then_span, else_span].into_iter(),
155+
);
156+
}
157+
}
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`");
161+
}
162+
_ => {
163+
if let ObligationCauseCode::BindingObligation(_, span)
164+
| ObligationCauseCode::ExprBindingObligation(_, span, ..)
165+
= cause.code().peel_derives()
166+
&& let TypeError::RegionsPlaceholderMismatch = terr
167+
{
168+
err.span_note( * span,
169+
"the lifetime requirement is introduced here");
170+
}
171+
}
172+
}
173+
}
174+
}
175+
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 {
182+
expr.span
183+
} else if let Some(stmt) = block.stmts.last() {
184+
// possibly incorrect trailing `;` in the else arm
185+
stmt.span
186+
} else {
187+
// empty block; point at its entirety
188+
block.span
189+
}
190+
}
191+
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,
201+
}
202+
}
203+
}

0 commit comments

Comments
 (0)