about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2016-11-30 17:00:08 -0800
committerGuillaume Gomez <guillaume1.gomez@gmail.com>2016-12-20 11:37:15 +0100
commit044b07dd2089d8e3786c5939fc948710d722845f (patch)
tree06a46bd190fd4e62e55faf00b1760677235901ff /src
parent3bb3278e53f44e413101501043d86764037a8ca2 (diff)
downloadrust-044b07dd2089d8e3786c5939fc948710d722845f.tar.gz
rust-044b07dd2089d8e3786c5939fc948710d722845f.zip
Update to last master
Diffstat (limited to 'src')
-rw-r--r--src/librustc_typeck/check/demand.rs131
-rw-r--r--src/librustc_typeck/check/method/probe.rs32
-rw-r--r--src/librustc_typeck/check/mod.rs2
3 files changed, 44 insertions, 121 deletions
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 4704193da0c..c09fde04ba4 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -17,7 +17,8 @@ use rustc::traits::ObligationCause;
 use syntax::ast;
 use syntax_pos::{self, Span};
 use rustc::hir;
-use rustc::ty::{self, ImplOrTraitItem};
+use rustc::hir::def::Def;
+use rustc::ty::{self, AssociatedItem};
 
 use super::method::probe;
 
@@ -31,11 +32,7 @@ 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
+                self.report_mismatched_types(&cause, expected, actual, e).emit();
             }
         }
     }
@@ -59,74 +56,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
-    /// This function is used to determine potential "simple" improvements or users' errors and
-    /// provide them useful help. For example:
-    ///
-    /// ```
-    /// fn some_fn(s: &str) {}
-    ///
-    /// let x = "hey!".to_owned();
-    /// some_fn(x); // error
-    /// ```
-    ///
-    /// No need to find every potential function which could make a coercion to transform a
-    /// `String` into a `&str` since a `&` would do the trick!
-    ///
-    /// In addition of this check, it also checks between references mutability state. If the
-    /// expected is mutable but the provided isn't, maybe we could just say "Hey, try with
-    /// `&mut`!".
-    fn check_ref(&self,
-                 expr: &hir::Expr,
-                 checked_ty: Ty<'tcx>,
-                 expected: Ty<'tcx>)
-                 -> Option<String> {
-        match (&expected.sty, &checked_ty.sty) {
-            (&ty::TyRef(_, expected_mutability),
-             &ty::TyRef(_, checked_mutability)) => {
-                // check if there is a mutability difference
-                if checked_mutability.mutbl == hir::Mutability::MutImmutable &&
-                   checked_mutability.mutbl != expected_mutability.mutbl &&
-                   self.can_sub_types(&checked_mutability.ty,
-                                      expected_mutability.ty).is_ok() {
-                    if let Ok(src) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
-                        return Some(format!("try with `&mut {}`", &src.replace("&", "")));
-                    }
-                }
-                None
-            }
-            (&ty::TyRef(_, mutability), _) => {
-                // Check if it can work when put into a ref. For example:
-                //
-                // ```
-                // fn bar(x: &mut i32) {}
-                //
-                // let x = 0u32;
-                // bar(&x); // error, expected &mut
-                // ```
-                let ref_ty = match mutability.mutbl {
-                    hir::Mutability::MutMutable => self.tcx.mk_mut_ref(
-                                                       self.tcx.mk_region(ty::ReStatic),
-                                                       checked_ty),
-                    hir::Mutability::MutImmutable => self.tcx.mk_imm_ref(
-                                                       self.tcx.mk_region(ty::ReStatic),
-                                                       checked_ty),
-                };
-                if self.try_coerce(expr, ref_ty, expected).is_ok() {
-                    if let Ok(src) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
-                        return Some(format!("try with `{}{}`",
-                                            match mutability.mutbl {
-                                                hir::Mutability::MutMutable => "&mut ",
-                                                hir::Mutability::MutImmutable => "&",
-                                            },
-                                            &src));
-                    }
-                }
-                None
-            }
-            _ => None,
-        }
-    }
-
     // Checks that the type of `expr` can be coerced to `expected`.
     pub fn demand_coerce(&self, expr: &hir::Expr, checked_ty: Ty<'tcx>, expected: Ty<'tcx>) {
         let expected = self.resolve_type_vars_with_obligations(expected);
@@ -134,37 +63,24 @@ 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;
-            let suggestions = if let Some(s) = self.check_ref(expr, checked_ty, expected) {
-                Some(s)
-            } else {
-                let suggestions = self.probe_for_return_type(syntax_pos::DUMMY_SP,
-                                                             mode,
-                                                             expected,
-                                                             checked_ty,
-                                                             ast::DUMMY_NODE_ID);
-                if suggestions.len() > 0 {
-                    Some(format!("here are some functions which \
-                                  might fulfill your needs:\n - {}",
-                                 self.get_best_match(&suggestions)))
-                } else {
-                    None
-                }
+            let suggestions = self.probe_for_return_type(syntax_pos::DUMMY_SP,
+                                                         mode,
+                                                         expected,
+                                                         checked_ty,
+                                                         ast::DUMMY_NODE_ID);
+            let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e);
+            if suggestions.len() > 0 {
+                err.help(&format!("here are some functions which \
+                                   might fulfill your needs:\n - {}",
+                                  self.get_best_match(&suggestions)));
             };
-            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 format_method_suggestion(&self, method: &ImplOrTraitItem<'tcx>) -> String {
+    fn format_method_suggestion(&self, method: &AssociatedItem) -> String {
         format!(".{}({})",
-                method.name(),
+                method.name,
                 if self.has_not_input_arg(method) {
                     ""
                 } else {
@@ -172,7 +88,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 })
     }
 
-    fn display_suggested_methods(&self, methods: &[ImplOrTraitItem<'tcx>]) -> String {
+    fn display_suggested_methods(&self, methods: &[AssociatedItem]) -> String {
         methods.iter()
                .take(5)
                .map(|method| self.format_method_suggestion(&*method))
@@ -180,7 +96,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                .join("\n - ")
     }
 
-    fn get_best_match(&self, methods: &[ImplOrTraitItem<'tcx>]) -> String {
+    fn get_best_match(&self, methods: &[AssociatedItem]) -> String {
         let no_argument_methods: Vec<_> =
             methods.iter()
                    .filter(|ref x| self.has_not_input_arg(&*x))
@@ -194,10 +110,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     }
 
     // This function checks if the method isn't static and takes other arguments than `self`.
-    fn has_not_input_arg(&self, method: &ImplOrTraitItem<'tcx>) -> bool {
-        match *method {
-            ImplOrTraitItem::MethodTraitItem(ref x) => {
-                x.fty.sig.skip_binder().inputs.len() == 1
+    fn has_not_input_arg(&self, method: &AssociatedItem) -> bool {
+        match method.def() {
+            Def::Method(def_id) => {
+                match self.tcx.item_type(def_id).sty {
+                    ty::TypeVariants::TyFnDef(_, _, fty) => {
+                        fty.sig.skip_binder().inputs.len() == 1
+                    }
+                    _ => false,
+                }
             }
             _ => false,
         }
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index a1393aa882e..04d714f269a 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -16,7 +16,6 @@ use super::suggest;
 use check::FnCtxt;
 use hir::def_id::DefId;
 use hir::def::Def;
-use rustc::infer::InferOk;
 use rustc::ty::subst::{Subst, Substs};
 use rustc::traits::{self, ObligationCause};
 use rustc::ty::{self, Ty, ToPolyTraitRef, TraitRef, TypeFoldable};
@@ -162,7 +161,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                  return_type: Ty<'tcx>,
                                  self_ty: Ty<'tcx>,
                                  scope_expr_id: ast::NodeId)
-                                 -> Vec<ty::ImplOrTraitItem<'tcx>> {
+                                 -> Vec<ty::AssociatedItem> {
         debug!("probe(self_ty={:?}, return_type={}, scope_expr_id={})",
                self_ty,
                return_type,
@@ -643,13 +642,14 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
         Ok(())
     }
 
-    pub fn matches_return_type(&self, method: &ty::ImplOrTraitItem<'tcx>,
+    pub fn matches_return_type(&self, method: &ty::AssociatedItem,
                                expected: ty::Ty<'tcx>) -> bool {
-        match *method {
-            ty::ImplOrTraitItem::MethodTraitItem(ref x) => {
+        match method.def() {
+            Def::Method(def_id) => {
+                let fty = self.tcx.item_type(def_id).fn_sig();
                 self.probe(|_| {
-                    let substs = self.fresh_substs_for_item(self.span, method.def_id());
-                    let output = x.fty.sig.output().subst(self.tcx, substs);
+                    let substs = self.fresh_substs_for_item(self.span, method.def_id);
+                    let output = fty.output().subst(self.tcx, substs);
                     let (output, _) = self.replace_late_bound_regions_with_fresh_var(
                         self.span, infer::FnCall, &output);
                     self.can_sub_types(output, expected).is_ok()
@@ -906,12 +906,12 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
     }
 
     fn candidate_method_names(&self) -> Vec<ast::Name> {
-        let mut set = FnvHashSet();
+        let mut set = FxHashSet();
         let mut names: Vec<_> =
             self.inherent_candidates
                 .iter()
                 .chain(&self.extension_candidates)
-                .map(|candidate| candidate.item.name())
+                .map(|candidate| candidate.item.name)
                 .filter(|&name| set.insert(name))
                 .collect();
 
@@ -1353,19 +1353,21 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
     /// Find item with name `item_name` defined in impl/trait `def_id`
     /// and return it, or `None`, if no such item was defined there.
     fn associated_item(&self, def_id: DefId) -> Option<ty::AssociatedItem> {
-        self.fcx.associated_item(def_id, self.item_name)
+        match self.looking_for {
+            LookingFor::MethodName(item_name) => self.fcx.associated_item(def_id, item_name),
+            _ => None,
+        }
     }
 
-    fn impl_or_trait_item(&self, def_id: DefId) -> Option<ty::ImplOrTraitItem<'tcx>> {
+    fn impl_or_trait_item(&self, def_id: DefId) -> Option<ty::AssociatedItem> {
         match self.looking_for {
             LookingFor::MethodName(name) => {
-                self.fcx.impl_or_trait_item(def_id, name)
+                self.fcx.associated_item(def_id, name)
             }
             LookingFor::ReturnType(return_ty) => {
                 self.tcx
-                    .impl_or_trait_items(def_id)
-                    .iter()
-                    .map(|&did| self.tcx.impl_or_trait_item(did))
+                    .associated_items(def_id)
+                    .map(|did| self.tcx.associated_item(did.def_id))
                     .find(|m| self.matches_return_type(m, return_ty))
             }
         }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 92d96b40719..3086721852d 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -3697,7 +3697,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 match result {
                     Ok(ty) => ctxt.unified = ty,
                     Err(err) => {
-                        self.report_mismatched_types(&cause, ctxt.unified, e_ty, err);
+                        self.report_mismatched_types(&cause, ctxt.unified, e_ty, err).emit();
                     }
                 }