Skip to content

Commit 4658688

Browse files
Return DiagnosticBuilder to add help suggestions
1 parent 9549fd5 commit 4658688

File tree

7 files changed

+45
-186
lines changed

7 files changed

+45
-186
lines changed

src/librustc/infer/error_reporting.rs

Lines changed: 1 addition & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,13 @@ use hir::def::Def;
8282
use hir::def_id::DefId;
8383
use infer::{self, TypeOrigin};
8484
use middle::region;
85-
use ty::{self, /*ImplOrTraitItem, Ty,*/ TyCtxt, TypeFoldable};
85+
use ty::{self, TyCtxt, TypeFoldable};
8686
use ty::{Region, ReFree};
8787
use ty::error::TypeError;
8888

8989
use std::cell::{Cell, RefCell};
9090
use std::char::from_u32;
9191
use std::fmt;
92-
//use std::rc::Rc;
9392
use syntax::ast;
9493
use syntax::parse::token;
9594
use syntax::ptr::P;
@@ -233,22 +232,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
233232
}
234233
}
235234

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

651586
diag.span_label(span, &terr);
@@ -658,32 +593,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
658593
self.tcx.note_and_explain_type_err(diag, terr, span);
659594
}
660595

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

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

15071507
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
@@ -470,7 +470,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
470470
} else {
471471
(result_ty, arm_ty)
472472
};
473-
self.report_mismatched_types(origin, expected, found, e);
473+
self.report_mismatched_types(origin, expected, found, e).emit();
474474
self.tcx.types.err
475475
}
476476
};

src/librustc_typeck/check/demand.rs

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
5151
assert!(obligations.is_empty());
5252
},
5353
Err(e) => {
54-
self.report_mismatched_types(origin, expected, actual, e);
54+
self.report_mismatched_types(origin, expected, actual, e).emit();
5555
}
5656
}
5757
}
@@ -71,7 +71,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
7171
assert!(obligations.is_empty());
7272
},
7373
Err(e) => {
74-
self.report_mismatched_types(origin, expected, actual, e);
74+
self.report_mismatched_types(origin, expected, actual, e).emit();
7575
}
7676
}
7777
}
@@ -83,7 +83,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
8383
let origin = TypeOrigin::Misc(expr.span);
8484
let expr_ty = self.resolve_type_vars_with_obligations(checked_ty);
8585
let mode = probe::Mode::MethodCall;
86-
if let Ok(methods) = self.probe_return(syntax_pos::DUMMY_SP, mode, expected,
86+
let suggestions =
87+
if let Ok(methods) = self.probe_return(syntax_pos::DUMMY_SP, mode, expected,
8788
checked_ty, ast::DUMMY_NODE_ID) {
8889
let suggestions: Vec<_> =
8990
methods.iter()
@@ -94,43 +95,55 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
9495
None
9596
}})
9697
.collect();
97-
let safe_suggestions: Vec<_> =
98-
suggestions.iter()
99-
.map(|ref x| MethodInfo::new(
100-
self.find_attr(x.id, "safe_suggestion"),
101-
x.id,
102-
x.item.clone()))
103-
.filter(|ref x| x.ast.is_some())
104-
.collect();
105-
if safe_suggestions.len() > 0 {
106-
self.get_best_match(&safe_suggestions);
98+
if suggestions.len() > 0 {
99+
let safe_suggestions: Vec<_> =
100+
suggestions.iter()
101+
.map(|ref x| MethodInfo::new(
102+
self.find_attr(x.id, "safe_suggestion"),
103+
x.id,
104+
x.item.clone()))
105+
.filter(|ref x| x.ast.is_some())
106+
.collect();
107+
Some(if safe_suggestions.len() > 0 {
108+
self.get_best_match(&safe_suggestions)
109+
} else {
110+
format!("no safe suggestion found, here are functions which match your \
111+
needs but be careful:\n - {}",
112+
self.get_best_match(&suggestions))
113+
})
107114
} else {
108-
self.get_best_match(&suggestions);
115+
None
109116
}
117+
} else {
118+
None
119+
};
120+
let mut err = self.report_mismatched_types(origin, expected, expr_ty, e);
121+
if let Some(suggestions) = suggestions {
122+
err.help(&suggestions);
110123
}
111-
self.report_mismatched_types(origin, expected, expr_ty, e);
124+
err.emit();
112125
}
113126
}
114127

115128
fn get_best_match(&self, methods: &[MethodInfo<'tcx>]) -> String {
116129
if methods.len() == 1 {
117-
println!("unique match ==> {:?}", methods[0].item.name());
118-
return String::new();
130+
return format!(" - {}", methods[0].item.name());
119131
}
120132
let no_argument_methods: Vec<&MethodInfo> =
121133
methods.iter()
122134
.filter(|ref x| self.has_not_input_arg(&*x.item))
123135
.collect();
124136
if no_argument_methods.len() > 0 {
125-
for ref method in no_argument_methods {
126-
println!("best match ==> {:?}", method.item.name());
127-
}
137+
no_argument_methods.iter()
138+
.map(|method| format!("{}", method.item.name()))
139+
.collect::<Vec<String>>()
140+
.join("\n - ")
128141
} else {
129-
for ref method in methods.iter() {
130-
println!("not best ==> {:?}", method.item.name());
131-
}
142+
methods.iter()
143+
.map(|method| format!("{}", method.item.name()))
144+
.collect::<Vec<String>>()
145+
.join("\n - ")
132146
}
133-
String::new()
134147
}
135148

136149
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
@@ -2893,7 +2893,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
28932893
}
28942894
}
28952895
Err(e) => {
2896-
self.report_mismatched_types(origin, expected, found, e);
2896+
self.report_mismatched_types(origin, expected, found, e).emit();
28972897
self.tcx.types.err
28982898
}
28992899
}
@@ -3663,7 +3663,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
36633663
match result {
36643664
Ok(ty) => unified = ty,
36653665
Err(e) => {
3666-
self.report_mismatched_types(origin, unified, e_ty, e);
3666+
self.report_mismatched_types(origin, unified, e_ty, e).emit();
36673667
}
36683668
}
36693669
}

src/librustc_typeck/coherence/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
374374
infcx.report_mismatched_types(origin,
375375
mk_ptr(mt_b.ty),
376376
target,
377-
ty::error::TypeError::Mutability);
377+
ty::error::TypeError::Mutability).emit();
378378
}
379379
(mt_a.ty, mt_b.ty, unsize_trait, None)
380380
};

src/librustc_typeck/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
205205
true
206206
}
207207
Err(err) => {
208-
infcx.report_mismatched_types(origin, expected, actual, err);
208+
infcx.report_mismatched_types(origin, expected, actual, err).emit();
209209
false
210210
}
211211
}

0 commit comments

Comments
 (0)