about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2016-10-27 00:43:00 +0200
committerGuillaume Gomez <guillaume1.gomez@gmail.com>2016-12-20 11:37:15 +0100
commit07a3ede5f2ee2db963b73453f43126a71f5092bd (patch)
treee356a617086291c1492ed79adc08eaeb859dfb10
parent021d97d1c5e053176961970ccbcad9f2802e9c91 (diff)
downloadrust-07a3ede5f2ee2db963b73453f43126a71f5092bd.tar.gz
rust-07a3ede5f2ee2db963b73453f43126a71f5092bd.zip
Return DiagnosticBuilder to add help suggestions
-rw-r--r--src/librustc/infer/error_reporting.rs154
-rw-r--r--src/librustc/infer/mod.rs4
-rw-r--r--src/librustc_typeck/check/_match.rs2
-rw-r--r--src/librustc_typeck/check/demand.rs65
-rw-r--r--src/librustc_typeck/check/mod.rs4
-rw-r--r--src/librustc_typeck/coherence/mod.rs2
-rw-r--r--src/librustc_typeck/lib.rs2
7 files changed, 50 insertions, 183 deletions
diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs
index 8fed2a82095..a67af1d5dcc 100644
--- a/src/librustc/infer/error_reporting.rs
+++ b/src/librustc/infer/error_reporting.rs
@@ -90,7 +90,6 @@ use ty::error::TypeError;
 use std::cell::{Cell, RefCell};
 use std::char::from_u32;
 use std::fmt;
-//use std::rc::Rc;
 use syntax::ast;
 use syntax::ptr::P;
 use syntax::symbol::Symbol;
@@ -234,22 +233,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     }
 }
 
-/*struct MethodInfo<'tcx> {
-    ast: Option<ast::Attribute>,
-    id: DefId,
-    item: Rc<ImplOrTraitItem<'tcx>>,
-}
-
-impl<'tcx> MethodInfo<'tcx> {
-    fn new(ast: Option<ast::Attribute>, id: DefId, item: Rc<ImplOrTraitItem<'tcx>>) -> MethodInfo {
-        MethodInfo {
-            ast: ast,
-            id: id,
-            item: item,
-        }
-    }
-}*/
-
 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     pub fn report_region_errors(&self,
                                 errors: &Vec<RegionResolutionError<'tcx>>) {
@@ -599,54 +582,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                     diag.note_expected_found(&"type", &expected, &found);
                 }
             }
-
-            //if let Some((found, (expected_ty, expected))) = self.get_ids(values) {
-                // look for expected with found id
-                /*self.tcx.populate_inherent_implementations_for_type_if_necessary(found);
-                if let Some(impl_infos) = self.tcx.inherent_impls.borrow().get(&found) {
-                    let mut methods: Vec<MethodInfo> = Vec::new();
-                    for impl_ in impl_infos {
-                        methods.append(&mut self.tcx
-                                                .impl_or_trait_items(*impl_)
-                                                .iter()
-                                                .map(|&did| MethodInfo::new(None, did, Rc::new(self.tcx.impl_or_trait_item(did))))
-                                                .filter(|ref x| {
-                                                    self.matches_return_type(&*x.item, &expected_ty)
-                                                })
-                                                .collect());
-                    }
-                    for did in self.tcx.sess.cstore.implementations_of_trait(None) {
-                        if did == found {
-                            methods.append(
-                                self.tcx.sess.cstore.impl_or_trait_items(did)
-                                                    .iter()
-                                                    .map(|&did| MethodInfo::new(None, did, Rc::new(self.tcx.impl_or_trait_item(did))))
-                                                    .filter(|ref x| {
-                                                        self.matches_return_type(&*x.item, &expected_ty)
-                                                    })
-                                                    .collect());
-                            ;
-                        }
-                    }
-                    let safe_suggestions: Vec<_> =
-                        methods.iter()
-                               .map(|ref x| MethodInfo::new(self.find_attr(x.id, "safe_suggestion"), x.id, x.item.clone()))
-                               .filter(|ref x| x.ast.is_some())
-                               .collect();
-                    if safe_suggestions.len() > 0 {
-                        println!("safe");
-                        self.get_best_match(&safe_suggestions);
-                    } else {
-                        println!("not safe");
-                        self.get_best_match(&methods);
-                    }*/
-                    /*let mode = probe::Mode::MethodCall;
-                    if let Ok(ret) = self.probe_return(DUMMY_SP, mode, expected, found,                               DUMMY_NODE_ID) {
-                        println!("got it");
-                    } else {
-                        println!("sad...");
-                    }*/
-            //}
         }
 
         diag.span_label(span, &terr);
@@ -659,32 +594,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         self.tcx.note_and_explain_type_err(diag, terr, span);
     }
 
-    /*fn get_best_match(&self, methods: &[MethodInfo<'tcx>]) -> String {
-        let no_argument_methods: Vec<&MethodInfo> =
-            methods.iter()
-                   .filter(|ref x| self.has_not_input_arg(&*x.item))
-                   .collect();
-        if no_argument_methods.len() > 0 {
-            for ref method in no_argument_methods {
-                println!("best match ==> {:?}", method.item.name());
-            }
-        } else {
-            for ref method in methods.iter() {
-                println!("not best ==> {:?}", method.item.name());
-            }
-        }
-        String::new()
-    }
-
-    fn find_attr(&self, def_id: DefId, attr_name: &str) -> Option<ast::Attribute> {
-        for item in self.tcx.get_attrs(def_id).iter() {
-            if item.check_name(attr_name) {
-                return Some(item.clone());
-            }
-        }
-        None
-    }*/
-
     pub fn report_and_explain_type_error(&self,
                                          trace: TypeTrace<'tcx>,
                                          terr: &TypeError<'tcx>)
@@ -713,69 +622,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
-    /*fn has_not_input_arg(&self, method: &ImplOrTraitItem<'tcx>) -> bool {
-        match *method {
-            ImplOrTraitItem::MethodTraitItem(ref x) => {
-                x.fty.sig.skip_binder().inputs.len() == 1
-            }
-            _ => false,
-        }
-    }
-
-    fn matches_return_type(&self, method: &ImplOrTraitItem<'tcx>, expected: &ty::Ty<'tcx>) -> bool {
-        match *method {
-            ImplOrTraitItem::MethodTraitItem(ref x) => {
-                self.can_sub_types(x.fty.sig.skip_binder().output, expected).is_ok()
-            }
-            _ => false,
-        }
-    }
-
-    fn get_id(&self, ty: Ty<'tcx>) -> Option<DefId> {
-        match ty.sty {
-            ty::TyTrait(box ref data) => Some(data.principal.def_id()),
-            ty::TyAdt(def, _) => Some(def.did),
-            ty::TyBox(ref ty) => self.get_id(*ty), // since we don't want box's methods by type's
-            ty::TyChar => self.tcx.lang_items.char_impl(),
-            ty::TyStr => self.tcx.lang_items.str_impl(),
-            ty::TySlice(_) => self.tcx.lang_items.slice_impl(),
-            ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
-                self.tcx.lang_items.const_ptr_impl()
-            }
-            ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
-                self.tcx.lang_items.mut_ptr_impl()
-            }
-            ty::TyInt(ast::IntTy::I8) => self.tcx.lang_items.i8_impl(),
-            ty::TyInt(ast::IntTy::I16) => self.tcx.lang_items.i16_impl(),
-            ty::TyInt(ast::IntTy::I32) => self.tcx.lang_items.i32_impl(),
-            ty::TyInt(ast::IntTy::I64) => self.tcx.lang_items.i64_impl(),
-            ty::TyInt(ast::IntTy::Is) => self.tcx.lang_items.isize_impl(),
-            ty::TyUint(ast::UintTy::U8) => self.tcx.lang_items.u8_impl(),
-            ty::TyUint(ast::UintTy::U16) => self.tcx.lang_items.u16_impl(),
-            ty::TyUint(ast::UintTy::U32) => self.tcx.lang_items.u32_impl(),
-            ty::TyUint(ast::UintTy::U64) => self.tcx.lang_items.u64_impl(),
-            ty::TyUint(ast::UintTy::Us) => self.tcx.lang_items.usize_impl(),
-            ty::TyFloat(ast::FloatTy::F32) => self.tcx.lang_items.f32_impl(),
-            ty::TyFloat(ast::FloatTy::F64) => self.tcx.lang_items.f64_impl(),
-            _ => None,
-        }
-    }
-
-    // Yep, returned value super ugly. it'll certainly become `Option<(DefId, ty::Ty<'tcx>)>`
-    // in a close future. Or maybe a struct?
-    fn get_ids(&self, values: Option<ValuePairs<'tcx>>) -> Option<(DefId, (ty::Ty<'tcx>, DefId))> {
-        match values {
-            // for now, only handling non trait types
-            Some(infer::Types(ref exp_found)) => {
-                match (self.get_id(exp_found.found), self.get_id(exp_found.expected)) {
-                    (Some(found), Some(expected)) => Some((found, (exp_found.expected, expected))),
-                    _ => None,
-                }
-            }
-            _ => None,
-        }
-    }*/
-
     fn expected_found_str<T: fmt::Display + TypeFoldable<'tcx>>(
         &self,
         exp_found: &ty::error::ExpectedFound<T>)
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 9b58334e658..6bbe40950b7 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -1367,9 +1367,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                    cause: &ObligationCause<'tcx>,
                                    expected: Ty<'tcx>,
                                    actual: Ty<'tcx>,
-                                   err: TypeError<'tcx>) {
+                                   err: TypeError<'tcx>) -> DiagnosticBuilder<'tcx> {
         let trace = TypeTrace::types(cause, true, expected, actual);
-        self.report_and_explain_type_error(trace, &err).emit();
+        self.report_and_explain_type_error(trace, &err)
     }
 
     pub fn report_conflicting_default_types(&self,
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 624201eaab6..ff50ee11b39 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -481,7 +481,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     } else {
                         (result_ty, arm_ty)
                     };
-                    self.report_mismatched_types(&cause, expected, found, e);
+                    self.report_mismatched_types(&cause, expected, found, e).emit();
                     self.tcx.types.err
                 }
             };
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index db711e4a31d..01a961949bc 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -51,7 +51,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 self.register_predicates(obligations);
             },
             Err(e) => {
+<<<<<<< HEAD
                 self.report_mismatched_types(&cause, expected, actual, e);
+=======
+                self.report_mismatched_types(origin, expected, actual, e).emit();
+>>>>>>> Return DiagnosticBuilder to add help suggestions
             }
         }
     }
@@ -70,7 +74,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 self.register_predicates(obligations);
             },
             Err(e) => {
-                self.report_mismatched_types(cause, expected, actual, e);
+                self.report_mismatched_types(cause, expected, actual, e).emit();
             }
         }
     }
@@ -82,7 +86,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             let cause = self.misc(expr.span);
             let expr_ty = self.resolve_type_vars_with_obligations(checked_ty);
             let mode = probe::Mode::MethodCall;
-            if let Ok(methods) = self.probe_return(syntax_pos::DUMMY_SP, mode, expected,
+            let suggestions = 
+                if let Ok(methods) = self.probe_return(syntax_pos::DUMMY_SP, mode, expected,
                                                    checked_ty, ast::DUMMY_NODE_ID) {
                 let suggestions: Vec<_> =
                     methods.iter()
@@ -93,43 +98,59 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                 None
                             }})
                            .collect();
-                let safe_suggestions: Vec<_> =
-                    suggestions.iter()
-                               .map(|ref x| MethodInfo::new(
-                                                self.find_attr(x.id, "safe_suggestion"),
-                                                               x.id,
-                                                               x.item.clone()))
-                               .filter(|ref x| x.ast.is_some())
-                               .collect();
-                if safe_suggestions.len() > 0 {
-                    self.get_best_match(&safe_suggestions);
+                if suggestions.len() > 0 {
+                    let safe_suggestions: Vec<_> =
+                        suggestions.iter()
+                                   .map(|ref x| MethodInfo::new(
+                                                    self.find_attr(x.id, "safe_suggestion"),
+                                                                   x.id,
+                                                                   x.item.clone()))
+                                   .filter(|ref x| x.ast.is_some())
+                                   .collect();
+                    Some(if safe_suggestions.len() > 0 {
+                        self.get_best_match(&safe_suggestions)
+                    } else {
+                        format!("no safe suggestion found, here are functions which match your \
+                                 needs but be careful:\n - {}",
+                                self.get_best_match(&suggestions))
+                    })
                 } else {
-                    self.get_best_match(&suggestions);
+                    None
                 }
+            } else {
+                None
+            };
+            let mut err = self.report_mismatched_types(origin, expected, expr_ty, e);
+            if let Some(suggestions) = suggestions {
+                err.help(&suggestions);
             }
+<<<<<<< HEAD
             self.report_mismatched_types(&cause, expected, expr_ty, e);
+=======
+            err.emit();
+>>>>>>> Return DiagnosticBuilder to add help suggestions
         }
     }
 
     fn get_best_match(&self, methods: &[MethodInfo<'tcx>]) -> String {
         if methods.len() == 1 {
-            println!("unique match ==> {:?}", methods[0].item.name());
-            return String::new();
+            return format!(" - {}", methods[0].item.name());
         }
         let no_argument_methods: Vec<&MethodInfo> =
             methods.iter()
                    .filter(|ref x| self.has_not_input_arg(&*x.item))
                    .collect();
         if no_argument_methods.len() > 0 {
-            for ref method in no_argument_methods {
-                println!("best match ==> {:?}", method.item.name());
-            }
+            no_argument_methods.iter()
+                               .map(|method| format!("{}", method.item.name()))
+                               .collect::<Vec<String>>()
+                               .join("\n - ")
         } else {
-            for ref method in methods.iter() {
-                println!("not best ==> {:?}", method.item.name());
-            }
+            methods.iter()
+                   .map(|method| format!("{}", method.item.name()))
+                   .collect::<Vec<String>>()
+                   .join("\n - ")
         }
-        String::new()
     }
 
     fn get_impl_id(&self, impl_: &ImplOrTraitItem<'tcx>) -> Option<DefId> {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 58dff935a16..92d96b40719 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -2986,7 +2986,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 }
             }
             Err(e) => {
-                self.report_mismatched_types(&cause, expected_ty, found_ty, e);
+                self.report_mismatched_types(&cause, expected_ty, found_ty, e).emit();
                 self.tcx.types.err
             }
         }
@@ -3880,7 +3880,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 match result {
                     Ok(ty) => unified = ty,
                     Err(e) => {
-                        self.report_mismatched_types(&cause, unified, e_ty, e);
+                        self.report_mismatched_types(&cause, unified, e_ty, e).emit();
                     }
                 }
             }
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index f575d4d8bab..0e5a16987c1 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -356,7 +356,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
                         infcx.report_mismatched_types(&cause,
                                                       mk_ptr(mt_b.ty),
                                                       target,
-                                                      ty::error::TypeError::Mutability);
+                                                      ty::error::TypeError::Mutability).emit();
                     }
                     (mt_a.ty, mt_b.ty, unsize_trait, None)
                 };
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 50d4c3cd0c9..ec17813ed2a 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -185,7 +185,7 @@ fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                 true
             }
             Err(err) => {
-                infcx.report_mismatched_types(cause, expected, actual, err);
+                infcx.report_mismatched_types(cause, expected, actual, err).emit();
                 false
             }
         }