Skip to content

Commit 07a3ede

Browse files
Return DiagnosticBuilder to add help suggestions
1 parent 021d97d commit 07a3ede

File tree

7 files changed

+50
-183
lines changed

7 files changed

+50
-183
lines changed

src/librustc/infer/error_reporting.rs

Lines changed: 0 additions & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ use ty::error::TypeError;
9090
use std::cell::{Cell, RefCell};
9191
use std::char::from_u32;
9292
use std::fmt;
93-
//use std::rc::Rc;
9493
use syntax::ast;
9594
use syntax::ptr::P;
9695
use syntax::symbol::Symbol;
@@ -234,22 +233,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
234233
}
235234
}
236235

237-
/*struct MethodInfo<'tcx> {
238-
ast: Option<ast::Attribute>,
239-
id: DefId,
240-
item: Rc<ImplOrTraitItem<'tcx>>,
241-
}
242-
243-
impl<'tcx> MethodInfo<'tcx> {
244-
fn new(ast: Option<ast::Attribute>, id: DefId, item: Rc<ImplOrTraitItem<'tcx>>) -> MethodInfo {
245-
MethodInfo {
246-
ast: ast,
247-
id: id,
248-
item: item,
249-
}
250-
}
251-
}*/
252-
253236
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
254237
pub fn report_region_errors(&self,
255238
errors: &Vec<RegionResolutionError<'tcx>>) {
@@ -599,54 +582,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
599582
diag.note_expected_found(&"type", &expected, &found);
600583
}
601584
}
602-
603-
//if let Some((found, (expected_ty, expected))) = self.get_ids(values) {
604-
// look for expected with found id
605-
/*self.tcx.populate_inherent_implementations_for_type_if_necessary(found);
606-
if let Some(impl_infos) = self.tcx.inherent_impls.borrow().get(&found) {
607-
let mut methods: Vec<MethodInfo> = Vec::new();
608-
for impl_ in impl_infos {
609-
methods.append(&mut self.tcx
610-
.impl_or_trait_items(*impl_)
611-
.iter()
612-
.map(|&did| MethodInfo::new(None, did, Rc::new(self.tcx.impl_or_trait_item(did))))
613-
.filter(|ref x| {
614-
self.matches_return_type(&*x.item, &expected_ty)
615-
})
616-
.collect());
617-
}
618-
for did in self.tcx.sess.cstore.implementations_of_trait(None) {
619-
if did == found {
620-
methods.append(
621-
self.tcx.sess.cstore.impl_or_trait_items(did)
622-
.iter()
623-
.map(|&did| MethodInfo::new(None, did, Rc::new(self.tcx.impl_or_trait_item(did))))
624-
.filter(|ref x| {
625-
self.matches_return_type(&*x.item, &expected_ty)
626-
})
627-
.collect());
628-
;
629-
}
630-
}
631-
let safe_suggestions: Vec<_> =
632-
methods.iter()
633-
.map(|ref x| MethodInfo::new(self.find_attr(x.id, "safe_suggestion"), x.id, x.item.clone()))
634-
.filter(|ref x| x.ast.is_some())
635-
.collect();
636-
if safe_suggestions.len() > 0 {
637-
println!("safe");
638-
self.get_best_match(&safe_suggestions);
639-
} else {
640-
println!("not safe");
641-
self.get_best_match(&methods);
642-
}*/
643-
/*let mode = probe::Mode::MethodCall;
644-
if let Ok(ret) = self.probe_return(DUMMY_SP, mode, expected, found, DUMMY_NODE_ID) {
645-
println!("got it");
646-
} else {
647-
println!("sad...");
648-
}*/
649-
//}
650585
}
651586

652587
diag.span_label(span, &terr);
@@ -659,32 +594,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
659594
self.tcx.note_and_explain_type_err(diag, terr, span);
660595
}
661596

662-
/*fn get_best_match(&self, methods: &[MethodInfo<'tcx>]) -> String {
663-
let no_argument_methods: Vec<&MethodInfo> =
664-
methods.iter()
665-
.filter(|ref x| self.has_not_input_arg(&*x.item))
666-
.collect();
667-
if no_argument_methods.len() > 0 {
668-
for ref method in no_argument_methods {
669-
println!("best match ==> {:?}", method.item.name());
670-
}
671-
} else {
672-
for ref method in methods.iter() {
673-
println!("not best ==> {:?}", method.item.name());
674-
}
675-
}
676-
String::new()
677-
}
678-
679-
fn find_attr(&self, def_id: DefId, attr_name: &str) -> Option<ast::Attribute> {
680-
for item in self.tcx.get_attrs(def_id).iter() {
681-
if item.check_name(attr_name) {
682-
return Some(item.clone());
683-
}
684-
}
685-
None
686-
}*/
687-
688597
pub fn report_and_explain_type_error(&self,
689598
trace: TypeTrace<'tcx>,
690599
terr: &TypeError<'tcx>)
@@ -713,69 +622,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
713622
}
714623
}
715624

716-
/*fn has_not_input_arg(&self, method: &ImplOrTraitItem<'tcx>) -> bool {
717-
match *method {
718-
ImplOrTraitItem::MethodTraitItem(ref x) => {
719-
x.fty.sig.skip_binder().inputs.len() == 1
720-
}
721-
_ => false,
722-
}
723-
}
724-
725-
fn matches_return_type(&self, method: &ImplOrTraitItem<'tcx>, expected: &ty::Ty<'tcx>) -> bool {
726-
match *method {
727-
ImplOrTraitItem::MethodTraitItem(ref x) => {
728-
self.can_sub_types(x.fty.sig.skip_binder().output, expected).is_ok()
729-
}
730-
_ => false,
731-
}
732-
}
733-
734-
fn get_id(&self, ty: Ty<'tcx>) -> Option<DefId> {
735-
match ty.sty {
736-
ty::TyTrait(box ref data) => Some(data.principal.def_id()),
737-
ty::TyAdt(def, _) => Some(def.did),
738-
ty::TyBox(ref ty) => self.get_id(*ty), // since we don't want box's methods by type's
739-
ty::TyChar => self.tcx.lang_items.char_impl(),
740-
ty::TyStr => self.tcx.lang_items.str_impl(),
741-
ty::TySlice(_) => self.tcx.lang_items.slice_impl(),
742-
ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
743-
self.tcx.lang_items.const_ptr_impl()
744-
}
745-
ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
746-
self.tcx.lang_items.mut_ptr_impl()
747-
}
748-
ty::TyInt(ast::IntTy::I8) => self.tcx.lang_items.i8_impl(),
749-
ty::TyInt(ast::IntTy::I16) => self.tcx.lang_items.i16_impl(),
750-
ty::TyInt(ast::IntTy::I32) => self.tcx.lang_items.i32_impl(),
751-
ty::TyInt(ast::IntTy::I64) => self.tcx.lang_items.i64_impl(),
752-
ty::TyInt(ast::IntTy::Is) => self.tcx.lang_items.isize_impl(),
753-
ty::TyUint(ast::UintTy::U8) => self.tcx.lang_items.u8_impl(),
754-
ty::TyUint(ast::UintTy::U16) => self.tcx.lang_items.u16_impl(),
755-
ty::TyUint(ast::UintTy::U32) => self.tcx.lang_items.u32_impl(),
756-
ty::TyUint(ast::UintTy::U64) => self.tcx.lang_items.u64_impl(),
757-
ty::TyUint(ast::UintTy::Us) => self.tcx.lang_items.usize_impl(),
758-
ty::TyFloat(ast::FloatTy::F32) => self.tcx.lang_items.f32_impl(),
759-
ty::TyFloat(ast::FloatTy::F64) => self.tcx.lang_items.f64_impl(),
760-
_ => None,
761-
}
762-
}
763-
764-
// Yep, returned value super ugly. it'll certainly become `Option<(DefId, ty::Ty<'tcx>)>`
765-
// in a close future. Or maybe a struct?
766-
fn get_ids(&self, values: Option<ValuePairs<'tcx>>) -> Option<(DefId, (ty::Ty<'tcx>, DefId))> {
767-
match values {
768-
// for now, only handling non trait types
769-
Some(infer::Types(ref exp_found)) => {
770-
match (self.get_id(exp_found.found), self.get_id(exp_found.expected)) {
771-
(Some(found), Some(expected)) => Some((found, (exp_found.expected, expected))),
772-
_ => None,
773-
}
774-
}
775-
_ => None,
776-
}
777-
}*/
778-
779625
fn expected_found_str<T: fmt::Display + TypeFoldable<'tcx>>(
780626
&self,
781627
exp_found: &ty::error::ExpectedFound<T>)

src/librustc/infer/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1367,9 +1367,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
13671367
cause: &ObligationCause<'tcx>,
13681368
expected: Ty<'tcx>,
13691369
actual: Ty<'tcx>,
1370-
err: TypeError<'tcx>) {
1370+
err: TypeError<'tcx>) -> DiagnosticBuilder<'tcx> {
13711371
let trace = TypeTrace::types(cause, true, expected, actual);
1372-
self.report_and_explain_type_error(trace, &err).emit();
1372+
self.report_and_explain_type_error(trace, &err)
13731373
}
13741374

13751375
pub fn report_conflicting_default_types(&self,

src/librustc_typeck/check/_match.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
481481
} else {
482482
(result_ty, arm_ty)
483483
};
484-
self.report_mismatched_types(&cause, expected, found, e);
484+
self.report_mismatched_types(&cause, expected, found, e).emit();
485485
self.tcx.types.err
486486
}
487487
};

src/librustc_typeck/check/demand.rs

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
5151
self.register_predicates(obligations);
5252
},
5353
Err(e) => {
54+
<<<<<<< HEAD
5455
self.report_mismatched_types(&cause, expected, actual, e);
56+
=======
57+
self.report_mismatched_types(origin, expected, actual, e).emit();
58+
>>>>>>> Return DiagnosticBuilder to add help suggestions
5559
}
5660
}
5761
}
@@ -70,7 +74,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
7074
self.register_predicates(obligations);
7175
},
7276
Err(e) => {
73-
self.report_mismatched_types(cause, expected, actual, e);
77+
self.report_mismatched_types(cause, expected, actual, e).emit();
7478
}
7579
}
7680
}
@@ -82,7 +86,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
8286
let cause = self.misc(expr.span);
8387
let expr_ty = self.resolve_type_vars_with_obligations(checked_ty);
8488
let mode = probe::Mode::MethodCall;
85-
if let Ok(methods) = self.probe_return(syntax_pos::DUMMY_SP, mode, expected,
89+
let suggestions =
90+
if let Ok(methods) = self.probe_return(syntax_pos::DUMMY_SP, mode, expected,
8691
checked_ty, ast::DUMMY_NODE_ID) {
8792
let suggestions: Vec<_> =
8893
methods.iter()
@@ -93,43 +98,59 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
9398
None
9499
}})
95100
.collect();
96-
let safe_suggestions: Vec<_> =
97-
suggestions.iter()
98-
.map(|ref x| MethodInfo::new(
99-
self.find_attr(x.id, "safe_suggestion"),
100-
x.id,
101-
x.item.clone()))
102-
.filter(|ref x| x.ast.is_some())
103-
.collect();
104-
if safe_suggestions.len() > 0 {
105-
self.get_best_match(&safe_suggestions);
101+
if suggestions.len() > 0 {
102+
let safe_suggestions: Vec<_> =
103+
suggestions.iter()
104+
.map(|ref x| MethodInfo::new(
105+
self.find_attr(x.id, "safe_suggestion"),
106+
x.id,
107+
x.item.clone()))
108+
.filter(|ref x| x.ast.is_some())
109+
.collect();
110+
Some(if safe_suggestions.len() > 0 {
111+
self.get_best_match(&safe_suggestions)
112+
} else {
113+
format!("no safe suggestion found, here are functions which match your \
114+
needs but be careful:\n - {}",
115+
self.get_best_match(&suggestions))
116+
})
106117
} else {
107-
self.get_best_match(&suggestions);
118+
None
108119
}
120+
} else {
121+
None
122+
};
123+
let mut err = self.report_mismatched_types(origin, expected, expr_ty, e);
124+
if let Some(suggestions) = suggestions {
125+
err.help(&suggestions);
109126
}
127+
<<<<<<< HEAD
110128
self.report_mismatched_types(&cause, expected, expr_ty, e);
129+
=======
130+
err.emit();
131+
>>>>>>> Return DiagnosticBuilder to add help suggestions
111132
}
112133
}
113134

114135
fn get_best_match(&self, methods: &[MethodInfo<'tcx>]) -> String {
115136
if methods.len() == 1 {
116-
println!("unique match ==> {:?}", methods[0].item.name());
117-
return String::new();
137+
return format!(" - {}", methods[0].item.name());
118138
}
119139
let no_argument_methods: Vec<&MethodInfo> =
120140
methods.iter()
121141
.filter(|ref x| self.has_not_input_arg(&*x.item))
122142
.collect();
123143
if no_argument_methods.len() > 0 {
124-
for ref method in no_argument_methods {
125-
println!("best match ==> {:?}", method.item.name());
126-
}
144+
no_argument_methods.iter()
145+
.map(|method| format!("{}", method.item.name()))
146+
.collect::<Vec<String>>()
147+
.join("\n - ")
127148
} else {
128-
for ref method in methods.iter() {
129-
println!("not best ==> {:?}", method.item.name());
130-
}
149+
methods.iter()
150+
.map(|method| format!("{}", method.item.name()))
151+
.collect::<Vec<String>>()
152+
.join("\n - ")
131153
}
132-
String::new()
133154
}
134155

135156
fn get_impl_id(&self, impl_: &ImplOrTraitItem<'tcx>) -> Option<DefId> {

src/librustc_typeck/check/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2986,7 +2986,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
29862986
}
29872987
}
29882988
Err(e) => {
2989-
self.report_mismatched_types(&cause, expected_ty, found_ty, e);
2989+
self.report_mismatched_types(&cause, expected_ty, found_ty, e).emit();
29902990
self.tcx.types.err
29912991
}
29922992
}
@@ -3880,7 +3880,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
38803880
match result {
38813881
Ok(ty) => unified = ty,
38823882
Err(e) => {
3883-
self.report_mismatched_types(&cause, unified, e_ty, e);
3883+
self.report_mismatched_types(&cause, unified, e_ty, e).emit();
38843884
}
38853885
}
38863886
}

src/librustc_typeck/coherence/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
356356
infcx.report_mismatched_types(&cause,
357357
mk_ptr(mt_b.ty),
358358
target,
359-
ty::error::TypeError::Mutability);
359+
ty::error::TypeError::Mutability).emit();
360360
}
361361
(mt_a.ty, mt_b.ty, unsize_trait, None)
362362
};

src/librustc_typeck/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
185185
true
186186
}
187187
Err(err) => {
188-
infcx.report_mismatched_types(cause, expected, actual, err);
188+
infcx.report_mismatched_types(cause, expected, actual, err).emit();
189189
false
190190
}
191191
}

0 commit comments

Comments
 (0)