|  | 
| 10 | 10 | 
 | 
| 11 | 11 | 
 | 
| 12 | 12 | use check::FnCtxt; | 
| 13 |  | -use rustc::ty::Ty; | 
| 14 |  | -use rustc::infer::{InferOk}; | 
|  | 13 | +use hir::map::Node; | 
|  | 14 | +use rustc::infer::{InferOk, TypeTrace}; | 
| 15 | 15 | use rustc::traits::ObligationCause; | 
|  | 16 | +use rustc::ty::Ty; | 
|  | 17 | +use rustc::ty::error::TypeError; | 
| 16 | 18 | 
 | 
| 17 | 19 | use syntax_pos::Span; | 
| 18 | 20 | use rustc::hir; | 
| @@ -57,7 +59,47 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { | 
| 57 | 59 |         if let Err(e) = self.try_coerce(expr, checked_ty, expected) { | 
| 58 | 60 |             let cause = self.misc(expr.span); | 
| 59 | 61 |             let expr_ty = self.resolve_type_vars_with_obligations(checked_ty); | 
| 60 |  | -            self.report_mismatched_types(&cause, expected, expr_ty, e); | 
|  | 62 | +            let trace = TypeTrace::types(&cause, true, expected, expr_ty); | 
|  | 63 | +            let mut diag = self.report_and_explain_type_error(trace, &e); | 
|  | 64 | + | 
|  | 65 | +            if let Node::NodeBlock(block) = self.tcx.map | 
|  | 66 | +                .get(self.tcx.map.get_parent_node(expr.id)) | 
|  | 67 | +            { | 
|  | 68 | +                if let TypeError::Sorts(ref values) = e { | 
|  | 69 | +                    if values.expected.is_nil() { | 
|  | 70 | +                        // An implicit return to a method with return type `()` | 
|  | 71 | +                        diag.span_label(expr.span, | 
|  | 72 | +                                        &"possibly missing `;` here?"); | 
|  | 73 | +                        // Get the current node's method definition | 
|  | 74 | +                        if let Node::NodeExpr(item) = self.tcx.map | 
|  | 75 | +                            .get(self.tcx.map.get_parent_node(block.id)) | 
|  | 76 | +                        { | 
|  | 77 | +                            // The fn has a default return type of () | 
|  | 78 | +                            if let Node::NodeItem(&hir::Item { | 
|  | 79 | +                                name, | 
|  | 80 | +                                node: hir::ItemFn(ref decl, ..), | 
|  | 81 | +                                .. | 
|  | 82 | +                            }) = self.tcx.map.get(self.tcx.map.get_parent_node(item.id)) { | 
|  | 83 | +                                // `main` *must* have return type () | 
|  | 84 | +                                if name.as_str() != "main" { | 
|  | 85 | +                                    decl.clone().and_then(|decl| { | 
|  | 86 | +                                        if let hir::FnDecl { | 
|  | 87 | +                                            output: hir::FunctionRetTy::DefaultReturn(span), | 
|  | 88 | +                                            .. | 
|  | 89 | +                                        } = decl { | 
|  | 90 | +                                            diag.span_label(span, | 
|  | 91 | +                                                            &format!("possibly return type `{}` \ | 
|  | 92 | +                                                                      missing in this fn?", | 
|  | 93 | +                                                                     values.found)); | 
|  | 94 | +                                        } | 
|  | 95 | +                                    }); | 
|  | 96 | +                                } | 
|  | 97 | +                            } | 
|  | 98 | +                        } | 
|  | 99 | +                    } | 
|  | 100 | +                } | 
|  | 101 | +            }; | 
|  | 102 | +            diag.emit(); | 
| 61 | 103 |         } | 
| 62 | 104 |     } | 
| 63 | 105 | } | 
0 commit comments