about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2018-12-20 16:52:52 -0800
committerEsteban Küber <esteban@kuber.com.ar>2018-12-20 16:52:52 -0800
commitcdbccf50a7746a07c44a404c270f188f64c5abf2 (patch)
treea126c7fd7b5bb65c30df5cf574c9c0f6363e0ec6
parent59f643fc5f7f9de0896680ec41fc64087311bead (diff)
downloadrust-cdbccf50a7746a07c44a404c270f188f64c5abf2.tar.gz
rust-cdbccf50a7746a07c44a404c270f188f64c5abf2.zip
Point at coercion source on type errors for fn returning `impl Trait`
-rw-r--r--src/librustc_typeck/check/coercion.rs15
-rw-r--r--src/librustc_typeck/check/mod.rs4
-rw-r--r--src/libsyntax_pos/lib.rs7
-rw-r--r--src/test/ui/impl-trait/equality.stderr3
4 files changed, 29 insertions, 0 deletions
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 0b99a30b67d..c7adf298227 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -1183,6 +1183,11 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
                     (self.final_ty.unwrap_or(self.expected_ty), expression_ty)
                 };
 
+                let reason_label = if label_expression_as_expected {
+                    "found because of this statement"
+                } else {
+                    "expected because of this statement"
+                };
                 let mut db;
                 match cause.code {
                     ObligationCauseCode::ReturnNoExpression => {
@@ -1207,9 +1212,19 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
                             cause.span,
                             blk_id,
                         );
+                        if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() {
+                            if !sp.overlaps(cause.span) {
+                                db.span_label(*sp, reason_label);
+                            }
+                        }
                     }
                     _ => {
                         db = fcx.report_mismatched_types(cause, expected, found, err);
+                        if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() {
+                            if !sp.overlaps(cause.span) {
+                                db.span_label(*sp, reason_label);
+                            }
+                        }
                     }
                 }
 
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index d40afbbc302..50cf5ef1655 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -535,6 +535,7 @@ pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     err_count_on_creation: usize,
 
     ret_coercion: Option<RefCell<DynamicCoerceMany<'gcx, 'tcx>>>,
+    ret_coercion_span: RefCell<Option<Span>>,
 
     yield_ty: Option<Ty<'tcx>>,
 
@@ -1984,6 +1985,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             param_env,
             err_count_on_creation: inh.tcx.sess.err_count(),
             ret_coercion: None,
+            ret_coercion_span: RefCell::new(None),
             yield_ty: None,
             ps: RefCell::new(UnsafetyState::function(hir::Unsafety::Normal,
                                                      ast::CRATE_NODE_ID)),
@@ -4099,9 +4101,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     struct_span_err!(self.tcx.sess, expr.span, E0572,
                                      "return statement outside of function body").emit();
                 } else if let Some(ref e) = *expr_opt {
+                    *self.ret_coercion_span.borrow_mut() = Some(e.span);
                     self.check_return_expr(e);
                 } else {
                     let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut();
+                    *self.ret_coercion_span.borrow_mut() = Some(expr.span);
                     let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression);
                     if let Some((fn_decl, _)) = self.get_fn_decl(expr.id) {
                         coercion.coerce_forced_unit(
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index 8b7ffa499cd..514dea7fb17 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -331,6 +331,13 @@ impl Span {
         span.lo <= other.lo && other.hi <= span.hi
     }
 
+    /// Return `true` if `self` touches `other`.
+    pub fn overlaps(self, other: Span) -> bool {
+        let span = self.data();
+        let other = other.data();
+        span.lo < other.hi && other.lo < span.hi
+    }
+
     /// Return true if the spans are equal with regards to the source text.
     ///
     /// Use this instead of `==` when either span could be generated code,
diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr
index e277d4e28cb..f1d2071bbdb 100644
--- a/src/test/ui/impl-trait/equality.stderr
+++ b/src/test/ui/impl-trait/equality.stderr
@@ -1,6 +1,9 @@
 error[E0308]: mismatched types
   --> $DIR/equality.rs:25:5
    |
+LL |         return 1_i32;
+   |                ----- expected because of this statement
+LL |     }
 LL |     0_u32
    |     ^^^^^ expected i32, found u32
    |