about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/infer/mod.rs3
-rw-r--r--src/librustc_typeck/check/demand.rs6
-rw-r--r--src/librustc_typeck/check/method/probe.rs150
3 files changed, 106 insertions, 53 deletions
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 6bbe40950b7..3e7cc0b1e3e 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -1367,7 +1367,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                    cause: &ObligationCause<'tcx>,
                                    expected: Ty<'tcx>,
                                    actual: Ty<'tcx>,
-                                   err: TypeError<'tcx>) -> DiagnosticBuilder<'tcx> {
+                                   err: TypeError<'tcx>)
+                                   -> DiagnosticBuilder<'tcx> {
         let trace = TypeTrace::types(cause, true, expected, actual);
         self.report_and_explain_type_error(trace, &err)
     }
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index c09fde04ba4..17d1bd77797 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -81,7 +81,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     fn format_method_suggestion(&self, method: &AssociatedItem) -> String {
         format!(".{}({})",
                 method.name,
-                if self.has_not_input_arg(method) {
+                if self.has_no_input_arg(method) {
                     ""
                 } else {
                     "..."
@@ -99,7 +99,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     fn get_best_match(&self, methods: &[AssociatedItem]) -> String {
         let no_argument_methods: Vec<_> =
             methods.iter()
-                   .filter(|ref x| self.has_not_input_arg(&*x))
+                   .filter(|ref x| self.has_no_input_arg(&*x))
                    .map(|x| x.clone())
                    .collect();
         if no_argument_methods.len() > 0 {
@@ -110,7 +110,7 @@ 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: &AssociatedItem) -> bool {
+    fn has_no_input_arg(&self, method: &AssociatedItem) -> bool {
         match method.def() {
             Def::Method(def_id) => {
                 match self.tcx.item_type(def_id).sty {
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index d2089fb4915..b11f6e837d2 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -37,6 +37,22 @@ pub enum LookingFor<'tcx> {
     ReturnType(Ty<'tcx>),
 }
 
+impl<'tcx> LookingFor<'tcx> {
+    pub fn is_method_name(&self) -> bool {
+        match *self {
+            LookingFor::MethodName(_) => true,
+            _ => false,
+        }
+    }
+
+    pub fn is_return_type(&self) -> bool {
+        match *self {
+            LookingFor::ReturnType(_) => true,
+            _ => false,
+        }
+    }
+}
+
 struct ProbeContext<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
     span: Span,
@@ -468,44 +484,81 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
 
         debug!("assemble_inherent_impl_probe {:?}", impl_def_id);
 
-        let item = match self.impl_or_trait_item(impl_def_id) {
-            Some(m) => m,
-            None => {
+        let items = self.impl_or_trait_item(impl_def_id);
+        if items.len() < 1 {
+            return // No method with correct name on this impl
+        }
+
+        if self.looking_for.is_method_name() {
+            let item = items[0];
+
+            if !self.has_applicable_self(&item) {
+                // No receiver declared. Not a candidate.
+                return self.record_static_candidate(ImplSource(impl_def_id));
+            }
+
+            if !item.vis.is_accessible_from(self.body_id, &self.tcx.map) {
+                self.private_candidate = Some(item.def());
                 return;
-            } // No method with correct name on this impl
-        };
+            }
 
-        if !self.has_applicable_self(&item) {
-            // No receiver declared. Not a candidate.
-            return self.record_static_candidate(ImplSource(impl_def_id));
-        }
+            let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id);
+            let impl_ty = impl_ty.subst(self.tcx, impl_substs);
 
-        if !item.vis.is_accessible_from(self.body_id, &self.tcx.map) {
-            self.private_candidate = Some(item.def());
-            return;
-        }
+            // Determine the receiver type that the method itself expects.
+            let xform_self_ty = self.xform_self_ty(&item, impl_ty, impl_substs);
 
-        let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id);
-        let impl_ty = impl_ty.subst(self.tcx, impl_substs);
-
-        // Determine the receiver type that the method itself expects.
-        let xform_self_ty = self.xform_self_ty(&item, impl_ty, impl_substs);
-
-        // We can't use normalize_associated_types_in as it will pollute the
-        // fcx's fulfillment context after this probe is over.
-        let cause = traits::ObligationCause::misc(self.span, self.body_id);
-        let mut selcx = &mut traits::SelectionContext::new(self.fcx);
-        let traits::Normalized { value: xform_self_ty, obligations } =
-            traits::normalize(selcx, cause, &xform_self_ty);
-        debug!("assemble_inherent_impl_probe: xform_self_ty = {:?}",
-               xform_self_ty);
-
-        self.inherent_candidates.push(Candidate {
-            xform_self_ty: xform_self_ty,
-            item: item,
-            kind: InherentImplCandidate(impl_substs, obligations),
-            import_id: self.import_id,
-        });
+            // We can't use normalize_associated_types_in as it will pollute the
+            // fcx's fulfillment context after this probe is over.
+            let cause = traits::ObligationCause::misc(self.span, self.body_id);
+            let mut selcx = &mut traits::SelectionContext::new(self.fcx);
+            let traits::Normalized { value: xform_self_ty, obligations } =
+                traits::normalize(selcx, cause, &xform_self_ty);
+            debug!("assemble_inherent_impl_probe: xform_self_ty = {:?}",
+                   xform_self_ty);
+
+            self.inherent_candidates.push(Candidate {
+                xform_self_ty: xform_self_ty,
+                item: item,
+                kind: InherentImplCandidate(impl_substs, obligations),
+                import_id: self.import_id,
+            });
+        } else {
+            for item in items {
+                if !self.has_applicable_self(&item) {
+                    // No receiver declared. Not a candidate.
+                    self.record_static_candidate(ImplSource(impl_def_id));
+                    continue
+                }
+
+                if !item.vis.is_accessible_from(self.body_id, &self.tcx.map) {
+                    self.private_candidate = Some(item.def());
+                    continue
+                }
+
+                let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id);
+                let impl_ty = impl_ty.subst(self.tcx, impl_substs);
+
+                // Determine the receiver type that the method itself expects.
+                let xform_self_ty = self.xform_self_ty(&item, impl_ty, impl_substs);
+
+                // We can't use normalize_associated_types_in as it will pollute the
+                // fcx's fulfillment context after this probe is over.
+                let cause = traits::ObligationCause::misc(self.span, self.body_id);
+                let mut selcx = &mut traits::SelectionContext::new(self.fcx);
+                let traits::Normalized { value: xform_self_ty, obligations } =
+                    traits::normalize(selcx, cause, &xform_self_ty);
+                debug!("assemble_inherent_impl_probe: xform_self_ty = {:?}",
+                       xform_self_ty);
+
+                self.inherent_candidates.push(Candidate {
+                    xform_self_ty: xform_self_ty,
+                    item: item,
+                    kind: InherentImplCandidate(impl_substs, obligations),
+                    import_id: self.import_id,
+                });
+            }
+        }
     }
 
     fn assemble_inherent_candidates_from_object(&mut self,
@@ -598,12 +651,11 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
 
         let tcx = self.tcx;
         for bound_trait_ref in traits::transitive_bounds(tcx, bounds) {
-            let item = match self.impl_or_trait_item(bound_trait_ref.def_id()) {
-                Some(v) => v,
-                None => {
-                    continue;
-                }
-            };
+            let items = self.impl_or_trait_item(bound_trait_ref.def_id());
+            if items.len() < 1 {
+                continue
+            }
+            let item = items[0];
 
             if !self.has_applicable_self(&item) {
                 self.record_static_candidate(TraitSource(bound_trait_ref.def_id()));
@@ -665,12 +717,11 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
         debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})",
                trait_def_id);
 
-        let item = match self.impl_or_trait_item(trait_def_id) {
-            Some(i) => i,
-            None => {
-                return Ok(());
-            }
-        };
+        let items = self.impl_or_trait_item(trait_def_id);
+        if items.len() < 1 {
+            return Ok(());
+        }
+        let item = items[0];
 
         // Check whether `trait_def_id` defines a method with suitable name:
         if !self.has_applicable_self(&item) {
@@ -1351,16 +1402,17 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
     }
 
     /// Find the method with the appropriate name (or return type, as the case may be).
-    fn impl_or_trait_item(&self, def_id: DefId) -> Option<ty::AssociatedItem> {
+    fn impl_or_trait_item(&self, def_id: DefId) -> Vec<ty::AssociatedItem> {
         match self.looking_for {
             LookingFor::MethodName(name) => {
-                self.fcx.associated_item(def_id, name)
+                self.fcx.associated_item(def_id, name).map_or(Vec::new(), |x| vec![x])
             }
             LookingFor::ReturnType(return_ty) => {
                 self.tcx
                     .associated_items(def_id)
                     .map(|did| self.tcx.associated_item(did.def_id))
-                    .find(|m| self.matches_return_type(m, return_ty))
+                    .filter(|m| self.matches_return_type(m, return_ty))
+                    .collect()
             }
         }
     }