Return DiagnosticBuilder to add help suggestions
This commit is contained in:
parent
021d97d1c5
commit
07a3ede5f2
7 changed files with 50 additions and 183 deletions
|
|
@ -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>)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue