Skip to content

Commit 044b07d

Browse files
Update to last master
1 parent 3bb3278 commit 044b07d

File tree

3 files changed

+44
-121
lines changed

3 files changed

+44
-121
lines changed

src/librustc_typeck/check/demand.rs

Lines changed: 26 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ use rustc::traits::ObligationCause;
1717
use syntax::ast;
1818
use syntax_pos::{self, Span};
1919
use rustc::hir;
20-
use rustc::ty::{self, ImplOrTraitItem};
20+
use rustc::hir::def::Def;
21+
use rustc::ty::{self, AssociatedItem};
2122

2223
use super::method::probe;
2324

@@ -31,11 +32,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
3132
self.register_predicates(obligations);
3233
},
3334
Err(e) => {
34-
<<<<<<< HEAD
35-
self.report_mismatched_types(&cause, expected, actual, e);
36-
=======
37-
self.report_mismatched_types(origin, expected, actual, e).emit();
38-
>>>>>>> Return DiagnosticBuilder to add help suggestions
35+
self.report_mismatched_types(&cause, expected, actual, e).emit();
3936
}
4037
}
4138
}
@@ -59,128 +56,47 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
5956
}
6057
}
6158

62-
/// This function is used to determine potential "simple" improvements or users' errors and
63-
/// provide them useful help. For example:
64-
///
65-
/// ```
66-
/// fn some_fn(s: &str) {}
67-
///
68-
/// let x = "hey!".to_owned();
69-
/// some_fn(x); // error
70-
/// ```
71-
///
72-
/// No need to find every potential function which could make a coercion to transform a
73-
/// `String` into a `&str` since a `&` would do the trick!
74-
///
75-
/// In addition of this check, it also checks between references mutability state. If the
76-
/// expected is mutable but the provided isn't, maybe we could just say "Hey, try with
77-
/// `&mut`!".
78-
fn check_ref(&self,
79-
expr: &hir::Expr,
80-
checked_ty: Ty<'tcx>,
81-
expected: Ty<'tcx>)
82-
-> Option<String> {
83-
match (&expected.sty, &checked_ty.sty) {
84-
(&ty::TyRef(_, expected_mutability),
85-
&ty::TyRef(_, checked_mutability)) => {
86-
// check if there is a mutability difference
87-
if checked_mutability.mutbl == hir::Mutability::MutImmutable &&
88-
checked_mutability.mutbl != expected_mutability.mutbl &&
89-
self.can_sub_types(&checked_mutability.ty,
90-
expected_mutability.ty).is_ok() {
91-
if let Ok(src) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
92-
return Some(format!("try with `&mut {}`", &src.replace("&", "")));
93-
}
94-
}
95-
None
96-
}
97-
(&ty::TyRef(_, mutability), _) => {
98-
// Check if it can work when put into a ref. For example:
99-
//
100-
// ```
101-
// fn bar(x: &mut i32) {}
102-
//
103-
// let x = 0u32;
104-
// bar(&x); // error, expected &mut
105-
// ```
106-
let ref_ty = match mutability.mutbl {
107-
hir::Mutability::MutMutable => self.tcx.mk_mut_ref(
108-
self.tcx.mk_region(ty::ReStatic),
109-
checked_ty),
110-
hir::Mutability::MutImmutable => self.tcx.mk_imm_ref(
111-
self.tcx.mk_region(ty::ReStatic),
112-
checked_ty),
113-
};
114-
if self.try_coerce(expr, ref_ty, expected).is_ok() {
115-
if let Ok(src) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
116-
return Some(format!("try with `{}{}`",
117-
match mutability.mutbl {
118-
hir::Mutability::MutMutable => "&mut ",
119-
hir::Mutability::MutImmutable => "&",
120-
},
121-
&src));
122-
}
123-
}
124-
None
125-
}
126-
_ => None,
127-
}
128-
}
129-
13059
// Checks that the type of `expr` can be coerced to `expected`.
13160
pub fn demand_coerce(&self, expr: &hir::Expr, checked_ty: Ty<'tcx>, expected: Ty<'tcx>) {
13261
let expected = self.resolve_type_vars_with_obligations(expected);
13362
if let Err(e) = self.try_coerce(expr, checked_ty, expected) {
13463
let cause = self.misc(expr.span);
13564
let expr_ty = self.resolve_type_vars_with_obligations(checked_ty);
13665
let mode = probe::Mode::MethodCall;
137-
let suggestions = if let Some(s) = self.check_ref(expr, checked_ty, expected) {
138-
Some(s)
139-
} else {
140-
let suggestions = self.probe_for_return_type(syntax_pos::DUMMY_SP,
141-
mode,
142-
expected,
143-
checked_ty,
144-
ast::DUMMY_NODE_ID);
145-
if suggestions.len() > 0 {
146-
Some(format!("here are some functions which \
147-
might fulfill your needs:\n - {}",
148-
self.get_best_match(&suggestions)))
149-
} else {
150-
None
151-
}
66+
let suggestions = self.probe_for_return_type(syntax_pos::DUMMY_SP,
67+
mode,
68+
expected,
69+
checked_ty,
70+
ast::DUMMY_NODE_ID);
71+
let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e);
72+
if suggestions.len() > 0 {
73+
err.help(&format!("here are some functions which \
74+
might fulfill your needs:\n - {}",
75+
self.get_best_match(&suggestions)));
15276
};
153-
let mut err = self.report_mismatched_types(origin, expected, expr_ty, e);
154-
if let Some(suggestions) = suggestions {
155-
err.help(&suggestions);
156-
}
157-
<<<<<<< HEAD
158-
self.report_mismatched_types(&cause, expected, expr_ty, e);
159-
=======
16077
err.emit();
161-
>>>>>>> Return DiagnosticBuilder to add help suggestions
16278
}
16379
}
16480

165-
fn format_method_suggestion(&self, method: &ImplOrTraitItem<'tcx>) -> String {
81+
fn format_method_suggestion(&self, method: &AssociatedItem) -> String {
16682
format!(".{}({})",
167-
method.name(),
83+
method.name,
16884
if self.has_not_input_arg(method) {
16985
""
17086
} else {
17187
"..."
17288
})
17389
}
17490

175-
fn display_suggested_methods(&self, methods: &[ImplOrTraitItem<'tcx>]) -> String {
91+
fn display_suggested_methods(&self, methods: &[AssociatedItem]) -> String {
17692
methods.iter()
17793
.take(5)
17894
.map(|method| self.format_method_suggestion(&*method))
17995
.collect::<Vec<String>>()
18096
.join("\n - ")
18197
}
18298

183-
fn get_best_match(&self, methods: &[ImplOrTraitItem<'tcx>]) -> String {
99+
fn get_best_match(&self, methods: &[AssociatedItem]) -> String {
184100
let no_argument_methods: Vec<_> =
185101
methods.iter()
186102
.filter(|ref x| self.has_not_input_arg(&*x))
@@ -194,10 +110,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
194110
}
195111

196112
// This function checks if the method isn't static and takes other arguments than `self`.
197-
fn has_not_input_arg(&self, method: &ImplOrTraitItem<'tcx>) -> bool {
198-
match *method {
199-
ImplOrTraitItem::MethodTraitItem(ref x) => {
200-
x.fty.sig.skip_binder().inputs.len() == 1
113+
fn has_not_input_arg(&self, method: &AssociatedItem) -> bool {
114+
match method.def() {
115+
Def::Method(def_id) => {
116+
match self.tcx.item_type(def_id).sty {
117+
ty::TypeVariants::TyFnDef(_, _, fty) => {
118+
fty.sig.skip_binder().inputs.len() == 1
119+
}
120+
_ => false,
121+
}
201122
}
202123
_ => false,
203124
}

src/librustc_typeck/check/method/probe.rs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ use super::suggest;
1616
use check::FnCtxt;
1717
use hir::def_id::DefId;
1818
use hir::def::Def;
19-
use rustc::infer::InferOk;
2019
use rustc::ty::subst::{Subst, Substs};
2120
use rustc::traits::{self, ObligationCause};
2221
use rustc::ty::{self, Ty, ToPolyTraitRef, TraitRef, TypeFoldable};
@@ -162,7 +161,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
162161
return_type: Ty<'tcx>,
163162
self_ty: Ty<'tcx>,
164163
scope_expr_id: ast::NodeId)
165-
-> Vec<ty::ImplOrTraitItem<'tcx>> {
164+
-> Vec<ty::AssociatedItem> {
166165
debug!("probe(self_ty={:?}, return_type={}, scope_expr_id={})",
167166
self_ty,
168167
return_type,
@@ -643,13 +642,14 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
643642
Ok(())
644643
}
645644

646-
pub fn matches_return_type(&self, method: &ty::ImplOrTraitItem<'tcx>,
645+
pub fn matches_return_type(&self, method: &ty::AssociatedItem,
647646
expected: ty::Ty<'tcx>) -> bool {
648-
match *method {
649-
ty::ImplOrTraitItem::MethodTraitItem(ref x) => {
647+
match method.def() {
648+
Def::Method(def_id) => {
649+
let fty = self.tcx.item_type(def_id).fn_sig();
650650
self.probe(|_| {
651-
let substs = self.fresh_substs_for_item(self.span, method.def_id());
652-
let output = x.fty.sig.output().subst(self.tcx, substs);
651+
let substs = self.fresh_substs_for_item(self.span, method.def_id);
652+
let output = fty.output().subst(self.tcx, substs);
653653
let (output, _) = self.replace_late_bound_regions_with_fresh_var(
654654
self.span, infer::FnCall, &output);
655655
self.can_sub_types(output, expected).is_ok()
@@ -906,12 +906,12 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
906906
}
907907

908908
fn candidate_method_names(&self) -> Vec<ast::Name> {
909-
let mut set = FnvHashSet();
909+
let mut set = FxHashSet();
910910
let mut names: Vec<_> =
911911
self.inherent_candidates
912912
.iter()
913913
.chain(&self.extension_candidates)
914-
.map(|candidate| candidate.item.name())
914+
.map(|candidate| candidate.item.name)
915915
.filter(|&name| set.insert(name))
916916
.collect();
917917

@@ -1353,19 +1353,21 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
13531353
/// Find item with name `item_name` defined in impl/trait `def_id`
13541354
/// and return it, or `None`, if no such item was defined there.
13551355
fn associated_item(&self, def_id: DefId) -> Option<ty::AssociatedItem> {
1356-
self.fcx.associated_item(def_id, self.item_name)
1356+
match self.looking_for {
1357+
LookingFor::MethodName(item_name) => self.fcx.associated_item(def_id, item_name),
1358+
_ => None,
1359+
}
13571360
}
13581361

1359-
fn impl_or_trait_item(&self, def_id: DefId) -> Option<ty::ImplOrTraitItem<'tcx>> {
1362+
fn impl_or_trait_item(&self, def_id: DefId) -> Option<ty::AssociatedItem> {
13601363
match self.looking_for {
13611364
LookingFor::MethodName(name) => {
1362-
self.fcx.impl_or_trait_item(def_id, name)
1365+
self.fcx.associated_item(def_id, name)
13631366
}
13641367
LookingFor::ReturnType(return_ty) => {
13651368
self.tcx
1366-
.impl_or_trait_items(def_id)
1367-
.iter()
1368-
.map(|&did| self.tcx.impl_or_trait_item(did))
1369+
.associated_items(def_id)
1370+
.map(|did| self.tcx.associated_item(did.def_id))
13691371
.find(|m| self.matches_return_type(m, return_ty))
13701372
}
13711373
}

src/librustc_typeck/check/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3697,7 +3697,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
36973697
match result {
36983698
Ok(ty) => ctxt.unified = ty,
36993699
Err(err) => {
3700-
self.report_mismatched_types(&cause, ctxt.unified, e_ty, err);
3700+
self.report_mismatched_types(&cause, ctxt.unified, e_ty, err).emit();
37013701
}
37023702
}
37033703

0 commit comments

Comments
 (0)