Skip to content

Commit cdbccf5

Browse files
committed
Point at coercion source on type errors for fn returning impl Trait
1 parent 59f643f commit cdbccf5

File tree

4 files changed

+29
-0
lines changed

4 files changed

+29
-0
lines changed

src/librustc_typeck/check/coercion.rs

+15
Original file line numberDiff line numberDiff line change
@@ -1183,6 +1183,11 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
11831183
(self.final_ty.unwrap_or(self.expected_ty), expression_ty)
11841184
};
11851185

1186+
let reason_label = if label_expression_as_expected {
1187+
"found because of this statement"
1188+
} else {
1189+
"expected because of this statement"
1190+
};
11861191
let mut db;
11871192
match cause.code {
11881193
ObligationCauseCode::ReturnNoExpression => {
@@ -1207,9 +1212,19 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
12071212
cause.span,
12081213
blk_id,
12091214
);
1215+
if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() {
1216+
if !sp.overlaps(cause.span) {
1217+
db.span_label(*sp, reason_label);
1218+
}
1219+
}
12101220
}
12111221
_ => {
12121222
db = fcx.report_mismatched_types(cause, expected, found, err);
1223+
if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() {
1224+
if !sp.overlaps(cause.span) {
1225+
db.span_label(*sp, reason_label);
1226+
}
1227+
}
12131228
}
12141229
}
12151230

src/librustc_typeck/check/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,7 @@ pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
535535
err_count_on_creation: usize,
536536

537537
ret_coercion: Option<RefCell<DynamicCoerceMany<'gcx, 'tcx>>>,
538+
ret_coercion_span: RefCell<Option<Span>>,
538539

539540
yield_ty: Option<Ty<'tcx>>,
540541

@@ -1984,6 +1985,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
19841985
param_env,
19851986
err_count_on_creation: inh.tcx.sess.err_count(),
19861987
ret_coercion: None,
1988+
ret_coercion_span: RefCell::new(None),
19871989
yield_ty: None,
19881990
ps: RefCell::new(UnsafetyState::function(hir::Unsafety::Normal,
19891991
ast::CRATE_NODE_ID)),
@@ -4099,9 +4101,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
40994101
struct_span_err!(self.tcx.sess, expr.span, E0572,
41004102
"return statement outside of function body").emit();
41014103
} else if let Some(ref e) = *expr_opt {
4104+
*self.ret_coercion_span.borrow_mut() = Some(e.span);
41024105
self.check_return_expr(e);
41034106
} else {
41044107
let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut();
4108+
*self.ret_coercion_span.borrow_mut() = Some(expr.span);
41054109
let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression);
41064110
if let Some((fn_decl, _)) = self.get_fn_decl(expr.id) {
41074111
coercion.coerce_forced_unit(

src/libsyntax_pos/lib.rs

+7
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,13 @@ impl Span {
331331
span.lo <= other.lo && other.hi <= span.hi
332332
}
333333

334+
/// Return `true` if `self` touches `other`.
335+
pub fn overlaps(self, other: Span) -> bool {
336+
let span = self.data();
337+
let other = other.data();
338+
span.lo < other.hi && other.lo < span.hi
339+
}
340+
334341
/// Return true if the spans are equal with regards to the source text.
335342
///
336343
/// Use this instead of `==` when either span could be generated code,

src/test/ui/impl-trait/equality.stderr

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
error[E0308]: mismatched types
22
--> $DIR/equality.rs:25:5
33
|
4+
LL | return 1_i32;
5+
| ----- expected because of this statement
6+
LL | }
47
LL | 0_u32
58
| ^^^^^ expected i32, found u32
69
|

0 commit comments

Comments
 (0)