1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
15 Method lookup can be rather complex due to the interaction of a number
16 of factors, such as self types, autoderef, trait lookup, etc. The
17 algorithm is divided into two parts: candidate collection and
20 ## Candidate collection
22 A `Candidate` is a method item that might plausibly be the method
23 being invoked. Candidates are grouped into two kinds, inherent and
24 extension. Inherent candidates are those that are derived from the
25 type of the receiver itself. So, if you have a receiver of some
26 nominal type `Foo` (e.g., a struct), any methods defined within an
27 impl like `impl Foo` are inherent methods. Nothing needs to be
28 imported to use an inherent method, they are associated with the type
29 itself (note that inherent impls can only be defined in the same
30 module as the type itself).
32 Inherent candidates are not always derived from impls. If you have a
33 trait instance, such as a value of type `Box<ToString>`, then the trait
34 methods (`to_string()`, in this case) are inherently associated with it.
35 Another case is type parameters, in which case the methods of their
38 Extension candidates are derived from imported traits. If I have the
39 trait `ToString` imported, and I call `to_string()` on a value of type `T`,
40 then we will go off to find out whether there is an impl of `ToString`
41 for `T`. These kinds of method calls are called "extension methods".
42 They can be defined in any module, not only the one that defined `T`.
43 Furthermore, you must import the trait to call such a method.
45 For better or worse, we currently give weight to inherent methods over
46 extension methods during candidate selection (below).
48 ## Candidate selection
50 Once we know the set of candidates, we can go off and try to select
51 which one is actually being called. We do this by taking the type of
52 the receiver, let's call it R, and checking whether it matches against
53 the expected receiver type for each of the collected candidates. We
54 first check for inherent candidates and see whether we get exactly one
55 match (zero means keep searching, more than one is an error). If so,
56 we return that as the candidate. Otherwise we search the extension
57 candidates in the same way.
59 If find no matching candidate at all, we proceed to auto-deref the
60 receiver type and search again. We keep doing that until we cannot
61 auto-deref any longer. At each step, we also check for candidates
62 based on "autoptr", which if the current type is `T`, checks for `&mut
63 T`, `&const T`, and `&T` receivers. Finally, at the very end, we will
64 also try autoslice, which converts `~[]` to `&[]` (there is no point
65 at trying autoslice earlier, because no autoderefable type is also
70 You might wonder why we first collect the candidates and then select.
71 Both the inherent candidate collection and the candidate selection
72 proceed by progressively deref'ing the receiver type, after all. The
73 answer is that two phases are needed to elegantly deal with explicit
74 self. After all, if there is an impl for the type `Foo`, it can
75 define a method with the type `Box<self>`, which means that it expects a
76 receiver of type `Box<Foo>`. If we have a receiver of type `Box<Foo>`, but we
77 waited to search for that impl until we have deref'd the `Box` away and
78 obtained the type `Foo`, we would never match this method.
84 use middle::subst::Subst;
88 use middle::typeck::astconv::AstConv;
89 use middle::typeck::check::{FnCtxt, PreferMutLvalue, impl_self_ty};
90 use middle::typeck::check;
91 use middle::typeck::infer;
92 use middle::typeck::MethodCallee;
93 use middle::typeck::{MethodOrigin, MethodParam, MethodTypeParam};
94 use middle::typeck::{MethodStatic, MethodStaticUnboxedClosure, MethodObject, MethodTraitObject};
95 use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
96 use middle::typeck::TypeAndSubsts;
97 use util::common::indenter;
99 use util::ppaux::Repr;
101 use std::collections::HashSet;
103 use syntax::ast::{DefId, MutImmutable, MutMutable};
105 use syntax::codemap::Span;
106 use syntax::parse::token;
108 #[deriving(PartialEq)]
109 pub enum CheckTraitsFlag {
111 CheckTraitsAndInherentMethods,
114 #[deriving(PartialEq)]
115 pub enum AutoderefReceiverFlag {
117 DontAutoderefReceiver,
120 #[deriving(PartialEq)]
121 pub enum StaticMethodsFlag {
126 pub fn lookup<'a, 'tcx>(
127 fcx: &'a FnCtxt<'a, 'tcx>,
129 // In a call `a.b::<X, Y, ...>(...)`:
130 expr: &ast::Expr, // The expression `a.b(...)`.
131 self_expr: &'a ast::Expr, // The expression `a`.
132 m_name: ast::Name, // The name `b`.
133 self_ty: ty::t, // The type of `a`.
134 supplied_tps: &'a [ty::t], // The list of types X, Y, ... .
135 deref_args: check::DerefArgs, // Whether we autopointer first.
136 check_traits: CheckTraitsFlag, // Whether we check traits only.
137 autoderef_receiver: AutoderefReceiverFlag,
138 report_statics: StaticMethodsFlag)
139 -> Option<MethodCallee> {
140 let mut lcx = LookupContext {
143 self_expr: Some(self_expr),
145 supplied_tps: supplied_tps,
146 impl_dups: HashSet::new(),
147 inherent_candidates: Vec::new(),
148 extension_candidates: Vec::new(),
149 deref_args: deref_args,
150 check_traits: check_traits,
151 autoderef_receiver: autoderef_receiver,
152 report_statics: report_statics,
155 debug!("method lookup(self_ty={}, expr={}, self_expr={})",
156 self_ty.repr(fcx.tcx()), expr.repr(fcx.tcx()),
157 self_expr.repr(fcx.tcx()));
159 debug!("searching inherent candidates");
160 lcx.push_inherent_candidates(self_ty);
161 debug!("searching extension candidates");
162 lcx.push_bound_candidates(self_ty, None);
163 lcx.push_extension_candidates(expr.id);
167 pub fn lookup_in_trait<'a, 'tcx>(
168 fcx: &'a FnCtxt<'a, 'tcx>,
170 // In a call `a.b::<X, Y, ...>(...)`:
171 span: Span, // The expression `a.b(...)`'s span.
172 self_expr: Option<&'a ast::Expr>, // The expression `a`, if available.
173 m_name: ast::Name, // The name `b`.
174 trait_did: DefId, // The trait to limit the lookup to.
175 self_ty: ty::t, // The type of `a`.
176 supplied_tps: &'a [ty::t], // The list of types X, Y, ... .
177 autoderef_receiver: AutoderefReceiverFlag,
178 report_statics: StaticMethodsFlag)
179 -> Option<MethodCallee> {
180 let mut lcx = LookupContext {
183 self_expr: self_expr,
185 supplied_tps: supplied_tps,
186 impl_dups: HashSet::new(),
187 inherent_candidates: Vec::new(),
188 extension_candidates: Vec::new(),
189 deref_args: check::DoDerefArgs,
190 check_traits: CheckTraitsOnly,
191 autoderef_receiver: autoderef_receiver,
192 report_statics: report_statics,
195 debug!("method lookup_in_trait(self_ty={}, self_expr={})",
196 self_ty.repr(fcx.tcx()), self_expr.map(|e| e.repr(fcx.tcx())));
198 lcx.push_bound_candidates(self_ty, Some(trait_did));
199 lcx.push_extension_candidate(trait_did);
203 // Determine the index of a method in the list of all methods belonging
204 // to a trait and its supertraits.
205 fn get_method_index(tcx: &ty::ctxt,
206 trait_ref: &TraitRef,
207 subtrait: Rc<TraitRef>,
208 n_method: uint) -> uint {
209 // We need to figure the "real index" of the method in a
210 // listing of all the methods of an object. We do this by
211 // iterating down the supertraits of the object's trait until
212 // we find the trait the method came from, counting up the
213 // methods from them.
214 let mut method_count = 0;
215 ty::each_bound_trait_and_supertraits(tcx, &[subtrait], |bound_ref| {
216 if bound_ref.def_id == trait_ref.def_id {
219 let trait_items = ty::trait_items(tcx, bound_ref.def_id);
220 for trait_item in trait_items.iter() {
222 ty::MethodTraitItem(_) => method_count += 1,
223 ty::TypeTraitItem(_) => {}
229 method_count + n_method
232 fn construct_transformed_self_ty_for_object(
235 trait_def_id: ast::DefId,
236 rcvr_substs: &subst::Substs,
237 rcvr_bounds: ty::ExistentialBounds,
238 method_ty: &ty::Method)
242 * This is a bit tricky. We have a match against a trait method
243 * being invoked on an object, and we want to generate the
244 * self-type. As an example, consider a trait
247 * fn r_method<'a>(&'a self);
248 * fn u_method(Box<self>);
251 * Now, assuming that `r_method` is being called, we want the
252 * result to be `&'a Foo`. Assuming that `u_method` is being
253 * called, we want the result to be `Box<Foo>`. Of course,
254 * this transformation has already been done as part of
255 * `method_ty.fty.sig.inputs[0]`, but there the type
256 * is expressed in terms of `Self` (i.e., `&'a Self`, `Box<Self>`).
257 * Because objects are not standalone types, we can't just substitute
258 * `s/Self/Foo/`, so we must instead perform this kind of hokey
262 let mut obj_substs = rcvr_substs.clone();
264 // The subst we get in has Err as the "Self" type. For an object
265 // type, we don't put any type into the Self paramspace, so let's
266 // make a copy of rcvr_substs that has the Self paramspace empty.
267 obj_substs.types.pop(subst::SelfSpace).unwrap();
269 match method_ty.explicit_self {
270 StaticExplicitSelfCategory => {
271 tcx.sess.span_bug(span, "static method for object type receiver");
273 ByValueExplicitSelfCategory => {
274 let tr = ty::mk_trait(tcx, trait_def_id, obj_substs, rcvr_bounds);
277 ByReferenceExplicitSelfCategory(..) | ByBoxExplicitSelfCategory => {
278 let transformed_self_ty = *method_ty.fty.sig.inputs.get(0);
279 match ty::get(transformed_self_ty).sty {
280 ty::ty_rptr(r, mt) => { // must be SelfRegion
281 let r = r.subst(tcx, rcvr_substs); // handle Early-Bound lifetime
282 let tr = ty::mk_trait(tcx, trait_def_id, obj_substs,
284 ty::mk_rptr(tcx, r, ty::mt{ ty: tr, mutbl: mt.mutbl })
286 ty::ty_uniq(_) => { // must be SelfUniq
287 let tr = ty::mk_trait(tcx, trait_def_id, obj_substs,
292 tcx.sess.span_bug(span,
293 format!("'impossible' transformed_self_ty: {}",
294 transformed_self_ty.repr(tcx)).as_slice());
301 struct LookupContext<'a, 'tcx: 'a> {
302 fcx: &'a FnCtxt<'a, 'tcx>,
305 // The receiver to the method call. Only `None` in the case of
306 // an overloaded autoderef, where the receiver may be an intermediate
307 // state like "the expression `x` when it has been autoderef'd
309 self_expr: Option<&'a ast::Expr>,
312 supplied_tps: &'a [ty::t],
313 impl_dups: HashSet<DefId>,
314 inherent_candidates: Vec<Candidate>,
315 extension_candidates: Vec<Candidate>,
316 deref_args: check::DerefArgs,
317 check_traits: CheckTraitsFlag,
318 autoderef_receiver: AutoderefReceiverFlag,
319 report_statics: StaticMethodsFlag,
323 * A potential method that might be called, assuming the receiver
324 * is of a suitable type.
328 rcvr_match_condition: RcvrMatchCondition,
329 rcvr_substs: subst::Substs,
330 method_ty: Rc<ty::Method>,
331 origin: MethodOrigin,
334 /// This type represents the conditions under which the receiver is
335 /// considered to "match" a given method candidate. Typically the test
336 /// is whether the receiver is of a particular type. However, this
337 /// type is the type of the receiver *after accounting for the
338 /// method's self type* (e.g., if the method is an `Box<self>` method, we
339 /// have *already verified* that the receiver is of some type `Box<T>` and
340 /// now we must check that the type `T` is correct). Unfortunately,
341 /// because traits are not types, this is a pain to do.
343 pub enum RcvrMatchCondition {
344 RcvrMatchesIfObject(ast::DefId),
345 RcvrMatchesIfSubtype(ty::t),
346 RcvrMatchesIfEqtype(ty::t)
349 impl<'a, 'tcx> LookupContext<'a, 'tcx> {
350 fn search(&self, self_ty: ty::t) -> Option<MethodCallee> {
351 let span = self.self_expr.map_or(self.span, |e| e.span);
352 let self_expr_id = self.self_expr.map(|e| e.id);
356 self.fcx, span, self_ty, self_expr_id, PreferMutLvalue,
357 |self_ty, autoderefs| self.search_step(self_ty, autoderefs));
360 Some(Some(result)) => Some(result),
365 fn search_step(&self,
368 -> Option<Option<MethodCallee>> {
369 debug!("search_step: self_ty={} autoderefs={}",
370 self.ty_to_string(self_ty), autoderefs);
372 match self.deref_args {
373 check::DontDerefArgs => {
374 match self.search_for_autoderefd_method(self_ty, autoderefs) {
375 Some(result) => return Some(Some(result)),
379 match self.search_for_autoptrd_method(self_ty, autoderefs) {
380 Some(result) => return Some(Some(result)),
384 check::DoDerefArgs => {
385 match self.search_for_autoptrd_method(self_ty, autoderefs) {
386 Some(result) => return Some(Some(result)),
390 match self.search_for_autoderefd_method(self_ty, autoderefs) {
391 Some(result) => return Some(Some(result)),
397 // If we are searching for an overloaded deref, no
398 // need to try coercing a `~[T]` to an `&[T]` and
399 // searching for an overloaded deref on *that*.
400 if !self.is_overloaded_deref() {
401 match self.search_for_autofatptrd_method(self_ty, autoderefs) {
402 Some(result) => return Some(Some(result)),
407 // Don't autoderef if we aren't supposed to.
408 if self.autoderef_receiver == DontAutoderefReceiver {
415 fn is_overloaded_deref(&self) -> bool {
416 self.self_expr.is_none()
419 // ______________________________________________________________________
420 // Candidate collection (see comment at start of file)
422 fn push_inherent_candidates(&mut self, self_ty: ty::t) {
424 * Collect all inherent candidates into
425 * `self.inherent_candidates`. See comment at the start of
426 * the file. To find the inherent candidates, we repeatedly
427 * deref the self-ty to find the "base-type". So, for
428 * example, if the receiver is Box<Box<C>> where `C` is a struct type,
429 * we'll want to find the inherent impls for `C`.
432 let span = self.self_expr.map_or(self.span, |e| e.span);
433 check::autoderef(self.fcx, span, self_ty, None, PreferMutLvalue, |self_ty, _| {
434 match get(self_ty).sty {
435 ty_trait(box TyTrait { def_id, ref substs, bounds, .. }) => {
436 self.push_inherent_candidates_from_object(
437 def_id, substs, bounds);
438 self.push_inherent_impl_candidates_for_type(def_id);
442 ty_unboxed_closure(did, _) => {
443 if self.check_traits == CheckTraitsAndInherentMethods {
444 self.push_inherent_impl_candidates_for_type(did);
447 _ => { /* No inherent methods in these types */ }
450 // Don't autoderef if we aren't supposed to.
451 if self.autoderef_receiver == DontAutoderefReceiver {
459 fn push_bound_candidates(&mut self, self_ty: ty::t, restrict_to: Option<DefId>) {
460 let span = self.self_expr.map_or(self.span, |e| e.span);
461 check::autoderef(self.fcx, span, self_ty, None, PreferMutLvalue, |self_ty, _| {
462 match get(self_ty).sty {
464 self.push_inherent_candidates_from_param(self_ty, restrict_to, p);
466 ty_unboxed_closure(closure_did, _) => {
467 self.push_unboxed_closure_call_candidates_if_applicable(
470 _ => { /* No bound methods in these types */ }
473 // Don't autoderef if we aren't supposed to.
474 if self.autoderef_receiver == DontAutoderefReceiver {
482 fn push_extension_candidate(&mut self, trait_did: DefId) {
483 ty::populate_implementations_for_trait_if_necessary(self.tcx(), trait_did);
485 // Look for explicit implementations.
486 let impl_items = self.tcx().impl_items.borrow();
487 for impl_infos in self.tcx().trait_impls.borrow().find(&trait_did).iter() {
488 for impl_did in impl_infos.borrow().iter() {
489 let items = impl_items.get(impl_did);
490 self.push_candidates_from_impl(*impl_did,
497 fn push_extension_candidates(&mut self, expr_id: ast::NodeId) {
498 // If the method being called is associated with a trait, then
499 // find all the impls of that trait. Each of those are
501 let opt_applicable_traits = self.fcx.ccx.trait_map.find(&expr_id);
502 for applicable_traits in opt_applicable_traits.into_iter() {
503 for trait_did in applicable_traits.iter() {
504 debug!("push_extension_candidates() found trait: {}",
505 if trait_did.krate == ast::LOCAL_CRATE {
506 self.fcx.ccx.tcx.map.node_to_string(trait_did.node)
508 "(external)".to_string()
510 self.push_extension_candidate(*trait_did);
515 fn push_unboxed_closure_call_candidate_if_applicable(
519 closure_function_type: &ClosureTy) {
520 let trait_item = ty::trait_items(self.tcx(), trait_did).get(0)
522 let method = match trait_item {
523 ty::MethodTraitItem(method) => method,
524 ty::TypeTraitItem(_) => {
526 "push_unboxed_closure_call_candidates_if_applicable(): \
527 unexpected associated type in function trait")
531 // Make sure it has the right name!
532 if method.ident.name != self.m_name {
536 // Get the tupled type of the arguments.
537 let arguments_type = *closure_function_type.sig.inputs.get(0);
538 let return_type = closure_function_type.sig.output;
541 self.fcx.infcx().next_region_var(infer::MiscVariable(self.span));
542 let unboxed_closure_type = ty::mk_unboxed_closure(self.tcx(),
545 self.extension_candidates.push(Candidate {
546 rcvr_match_condition:
547 RcvrMatchesIfSubtype(unboxed_closure_type),
548 rcvr_substs: subst::Substs::new_trait(
549 vec![arguments_type, return_type],
551 *self.fcx.infcx().next_ty_vars(1).get(0)),
553 origin: MethodStaticUnboxedClosure(closure_did),
557 fn push_unboxed_closure_call_candidates_if_applicable(
559 closure_did: DefId) {
560 match self.tcx().unboxed_closures.borrow().find(&closure_did) {
561 None => {} // Fall through to try inherited.
563 let tcx = self.tcx();
564 self.push_unboxed_closure_call_candidate_if_applicable(
565 closure.kind.trait_did(tcx),
567 &closure.closure_type);
572 match self.fcx.inh.unboxed_closures.borrow().find(&closure_did) {
574 let tcx = self.tcx();
575 self.push_unboxed_closure_call_candidate_if_applicable(
576 closure.kind.trait_did(tcx),
578 &closure.closure_type);
584 self.tcx().sess.bug("didn't find unboxed closure type in tcx map or \
585 inherited map, so there")
588 fn push_inherent_candidates_from_object(&mut self,
590 substs: &subst::Substs,
591 bounds: ty::ExistentialBounds) {
592 debug!("push_inherent_candidates_from_object(did={}, substs={})",
593 self.did_to_string(did),
594 substs.repr(self.tcx()));
595 let tcx = self.tcx();
596 let span = self.span;
598 // It is illegal to invoke a method on a trait instance that
599 // refers to the `self` type. An error will be reported by
600 // `enforce_object_limitations()` if the method refers
601 // to the `Self` type. Substituting ty_err here allows
602 // compiler to soldier on.
604 // `confirm_candidate()` also relies upon this substitution
606 let rcvr_substs = substs.with_self_ty(ty::mk_err());
607 let trait_ref = Rc::new(TraitRef {
609 substs: rcvr_substs.clone()
612 self.push_inherent_candidates_from_bounds_inner(
613 &[trait_ref.clone()],
614 |_this, new_trait_ref, m, method_num| {
616 get_method_index(tcx, &*new_trait_ref,
617 trait_ref.clone(), method_num);
618 let mut m = (*m).clone();
619 // We need to fix up the transformed self type.
620 *m.fty.sig.inputs.get_mut(0) =
621 construct_transformed_self_ty_for_object(
622 tcx, span, did, &rcvr_substs, bounds, &m);
625 rcvr_match_condition: RcvrMatchesIfObject(did),
626 rcvr_substs: new_trait_ref.substs.clone(),
627 method_ty: Rc::new(m),
628 origin: MethodTraitObject(MethodObject {
629 trait_ref: new_trait_ref,
630 object_trait_id: did,
631 method_num: method_num,
632 real_index: vtable_index
638 fn push_inherent_candidates_from_param(&mut self,
640 restrict_to: Option<DefId>,
642 debug!("push_inherent_candidates_from_param(param_ty={:?})",
644 self.push_inherent_candidates_from_bounds(
652 fn push_inherent_candidates_from_bounds(&mut self,
654 space: subst::ParamSpace,
656 restrict_to: Option<DefId>) {
658 self.fcx.inh.param_env.bounds.get(space, index).trait_bounds
660 self.push_inherent_candidates_from_bounds_inner(bounds,
661 |this, trait_ref, m, method_num| {
664 if trait_did != trait_ref.def_id {
671 let condition = match m.explicit_self {
672 ByReferenceExplicitSelfCategory(_, mt) if mt == MutMutable =>
673 RcvrMatchesIfEqtype(self_ty),
675 RcvrMatchesIfSubtype(self_ty)
678 debug!("found match: trait_ref={} substs={} m={}",
679 trait_ref.repr(this.tcx()),
680 trait_ref.substs.repr(this.tcx()),
682 assert_eq!(m.generics.types.get_slice(subst::TypeSpace).len(),
683 trait_ref.substs.types.get_slice(subst::TypeSpace).len());
684 assert_eq!(m.generics.regions.get_slice(subst::TypeSpace).len(),
685 trait_ref.substs.regions().get_slice(subst::TypeSpace).len());
686 assert_eq!(m.generics.types.get_slice(subst::SelfSpace).len(),
687 trait_ref.substs.types.get_slice(subst::SelfSpace).len());
688 assert_eq!(m.generics.regions.get_slice(subst::SelfSpace).len(),
689 trait_ref.substs.regions().get_slice(subst::SelfSpace).len());
691 rcvr_match_condition: condition,
692 rcvr_substs: trait_ref.substs.clone(),
694 origin: MethodTypeParam(MethodParam {
695 trait_ref: trait_ref,
696 method_num: method_num,
702 // Do a search through a list of bounds, using a callback to actually
703 // create the candidates.
704 fn push_inherent_candidates_from_bounds_inner(
706 bounds: &[Rc<TraitRef>],
707 mk_cand: |this: &mut LookupContext,
711 -> Option<Candidate>)
713 let tcx = self.tcx();
714 let mut cache = HashSet::new();
715 for bound_trait_ref in traits::transitive_bounds(tcx, bounds) {
716 // Already visited this trait, skip it.
717 if !cache.insert(bound_trait_ref.def_id) {
721 let trait_items = ty::trait_items(tcx, bound_trait_ref.def_id);
722 match trait_items.iter().position(|ti| {
724 ty::MethodTraitItem(ref m) => {
725 m.explicit_self != ty::StaticExplicitSelfCategory &&
726 m.ident.name == self.m_name
728 ty::TypeTraitItem(_) => false,
732 let method = match *trait_items.get(pos) {
733 ty::MethodTraitItem(ref method) => (*method).clone(),
734 ty::TypeTraitItem(_) => {
735 tcx.sess.bug("typechecking associated type as \
736 though it were a method")
745 debug!("pushing inherent candidate for param: {}",
746 cand.repr(self.tcx()));
747 self.inherent_candidates.push(cand);
753 debug!("trait doesn't contain method: {:?}",
754 bound_trait_ref.def_id);
755 // check next trait or bound
762 fn push_inherent_impl_candidates_for_type(&mut self, did: DefId) {
763 // Read the inherent implementation candidates for this type from the
764 // metadata if necessary.
765 ty::populate_implementations_for_type_if_necessary(self.tcx(), did);
767 let impl_items = self.tcx().impl_items.borrow();
768 for impl_infos in self.tcx().inherent_impls.borrow().find(&did).iter() {
769 for impl_did in impl_infos.iter() {
770 let items = impl_items.get(impl_did);
771 self.push_candidates_from_impl(*impl_did,
778 fn push_candidates_from_impl(&mut self,
780 impl_items: &[ImplOrTraitItemId],
781 is_extension: bool) {
782 let did = if self.report_statics == ReportStaticMethods {
783 // we only want to report each base trait once
784 match ty::impl_trait_ref(self.tcx(), impl_did) {
785 Some(trait_ref) => trait_ref.def_id,
792 if !self.impl_dups.insert(did) {
793 return; // already visited
796 debug!("push_candidates_from_impl: {} {}",
797 token::get_name(self.m_name),
800 ty::impl_or_trait_item(self.tcx(),
801 did.def_id()).ident()
803 .collect::<Vec<ast::Ident>>()
806 let method = match impl_items.iter()
808 ty::impl_or_trait_item(self.tcx(),
812 m.ident().name == self.m_name
814 Some(ty::MethodTraitItem(method)) => method,
815 Some(ty::TypeTraitItem(_)) | None => {
816 // No method with the right name.
821 // determine the `self` of the impl with fresh
822 // variables for each parameter:
823 let span = self.self_expr.map_or(self.span, |e| e.span);
827 } = impl_self_ty(self.fcx, span, impl_did);
829 let condition = match method.explicit_self {
830 ByReferenceExplicitSelfCategory(_, mt) if mt == MutMutable =>
831 RcvrMatchesIfEqtype(impl_ty),
833 RcvrMatchesIfSubtype(impl_ty)
836 let candidates = if is_extension {
837 &mut self.extension_candidates
839 &mut self.inherent_candidates
842 candidates.push(Candidate {
843 rcvr_match_condition: condition,
844 rcvr_substs: impl_substs,
845 origin: MethodStatic(method.def_id),
850 // ______________________________________________________________________
851 // Candidate selection (see comment at start of file)
853 fn search_for_autoderefd_method(&self,
856 -> Option<MethodCallee> {
857 // Hacky. For overloaded derefs, there may be an adjustment
858 // added to the expression from the outside context, so we do not store
859 // an explicit adjustment, but rather we hardwire the single deref
860 // that occurs in trans and mem_categorization.
861 if self.self_expr.is_none() {
865 let (self_ty, auto_deref_ref) = self.consider_reborrow(self_ty, autoderefs);
866 let adjustment = Some((self.self_expr.unwrap().id, ty::AdjustDerefRef(auto_deref_ref)));
868 match self.search_for_method(self_ty) {
871 debug!("(searching for autoderef'd method) writing \
872 adjustment {:?} for {}", adjustment, self.ty_to_string(self_ty));
874 Some((self_expr_id, adj)) => {
875 self.fcx.write_adjustment(self_expr_id, self.span, adj);
884 fn consider_reborrow(&self,
887 -> (ty::t, ty::AutoDerefRef) {
889 * In the event that we are invoking a method with a receiver
890 * of a borrowed type like `&T`, `&mut T`, or `&mut [T]`,
891 * we will "reborrow" the receiver implicitly. For example, if
892 * you have a call `r.inc()` and where `r` has type `&mut T`,
893 * then we treat that like `(&mut *r).inc()`. This avoids
894 * consuming the original pointer.
896 * You might think that this would be a natural byproduct of
897 * the auto-deref/auto-ref process. This is true for `Box<T>`
898 * but not for an `&mut T` receiver. With `Box<T>`, we would
899 * begin by testing for methods with a self type `Box<T>`,
900 * then autoderef to `T`, then autoref to `&mut T`. But with
901 * an `&mut T` receiver the process begins with `&mut T`, only
902 * without any autoadjustments.
905 let tcx = self.tcx();
906 return match ty::get(self_ty).sty {
907 ty::ty_rptr(_, self_mt) if default_method_hack(self_mt) => {
910 autoderefs: autoderefs,
913 ty::ty_rptr(_, self_mt) => {
915 self.infcx().next_region_var(infer::Autoref(self.span));
916 (ty::mk_rptr(tcx, region, self_mt),
918 autoderefs: autoderefs + 1,
919 autoref: Some(ty::AutoPtr(region, self_mt.mutbl, None))})
924 autoderefs: autoderefs,
929 fn default_method_hack(self_mt: ty::mt) -> bool {
930 // FIXME(#6129). Default methods can't deal with autoref.
932 // I am a horrible monster and I pray for death. Currently
933 // the default method code fails when you try to reborrow
934 // because it is not handling types correctly. In lieu of
935 // fixing that, I am introducing this horrible hack. - ndm
936 self_mt.mutbl == MutImmutable && ty::type_is_self(self_mt.ty)
940 // Takes an [T] - an unwrapped DST pointer (either ~ or &)
941 // [T] to &[T] or &&[T] (note that we started with a &[T] or ~[T] which has
942 // been implicitly derefed).
943 fn auto_slice_vec(&self, ty: ty::t, autoderefs: uint) -> Option<MethodCallee> {
944 let tcx = self.tcx();
945 debug!("auto_slice_vec {}", ppaux::ty_to_string(tcx, ty));
947 // First try to borrow to a slice
948 let entry = self.search_for_some_kind_of_autorefd_method(
949 |r, m| AutoPtr(r, m, None), autoderefs, [MutImmutable, MutMutable],
950 |m,r| ty::mk_slice(tcx, r,
951 ty::mt {ty:ty, mutbl:m}));
957 // Then try to borrow to a slice *and* borrow a pointer.
958 self.search_for_some_kind_of_autorefd_method(
959 |r, m| AutoPtr(r, ast::MutImmutable, Some( box AutoPtr(r, m, None))),
960 autoderefs, [MutImmutable, MutMutable],
962 let slice_ty = ty::mk_slice(tcx, r,
963 ty::mt {ty:ty, mutbl:m});
964 // NB: we do not try to autoref to a mutable
965 // pointer. That would be creating a pointer
966 // to a temporary pointer (the borrowed
967 // slice), so any update the callee makes to
968 // it can't be observed.
969 ty::mk_rptr(tcx, r, ty::mt {ty:slice_ty, mutbl:MutImmutable})
973 // [T, ..len] -> [T] or &[T] or &&[T]
974 fn auto_unsize_vec(&self, ty: ty::t, autoderefs: uint, len: uint) -> Option<MethodCallee> {
975 let tcx = self.tcx();
976 debug!("auto_unsize_vec {}", ppaux::ty_to_string(tcx, ty));
978 // First try to borrow to an unsized vec.
979 let entry = self.search_for_some_kind_of_autorefd_method(
980 |_r, _m| AutoUnsize(ty::UnsizeLength(len)),
981 autoderefs, [MutImmutable, MutMutable],
982 |_m, _r| ty::mk_vec(tcx, ty, None));
988 // Then try to borrow to a slice.
989 let entry = self.search_for_some_kind_of_autorefd_method(
990 |r, m| AutoPtr(r, m, Some(box AutoUnsize(ty::UnsizeLength(len)))),
991 autoderefs, [MutImmutable, MutMutable],
992 |m, r| ty::mk_slice(tcx, r, ty::mt {ty:ty, mutbl:m}));
998 // Then try to borrow to a slice *and* borrow a pointer.
999 self.search_for_some_kind_of_autorefd_method(
1000 |r, m| AutoPtr(r, m,
1001 Some(box AutoPtr(r, m,
1002 Some(box AutoUnsize(ty::UnsizeLength(len)))))),
1003 autoderefs, [MutImmutable, MutMutable],
1005 let slice_ty = ty::mk_slice(tcx, r, ty::mt {ty:ty, mutbl:m});
1006 ty::mk_rptr(tcx, r, ty::mt {ty:slice_ty, mutbl:MutImmutable})
1010 fn auto_slice_str(&self, autoderefs: uint) -> Option<MethodCallee> {
1011 let tcx = self.tcx();
1012 debug!("auto_slice_str");
1014 let entry = self.search_for_some_kind_of_autorefd_method(
1015 |r, m| AutoPtr(r, m, None), autoderefs, [MutImmutable],
1016 |_m, r| ty::mk_str_slice(tcx, r, MutImmutable));
1018 if entry.is_some() {
1022 self.search_for_some_kind_of_autorefd_method(
1023 |r, m| AutoPtr(r, ast::MutImmutable, Some( box AutoPtr(r, m, None))),
1024 autoderefs, [MutImmutable],
1026 let slice_ty = ty::mk_str_slice(tcx, r, m);
1027 ty::mk_rptr(tcx, r, ty::mt {ty:slice_ty, mutbl:m})
1031 // Coerce Box/&Trait instances to &Trait.
1032 fn auto_slice_trait(&self, ty: ty::t, autoderefs: uint) -> Option<MethodCallee> {
1033 debug!("auto_slice_trait");
1034 match ty::get(ty).sty {
1035 ty_trait(box ty::TyTrait {
1037 substs: ref trt_substs,
1040 let tcx = self.tcx();
1041 self.search_for_some_kind_of_autorefd_method(
1042 |r, m| AutoPtr(r, m, None),
1043 autoderefs, [MutImmutable, MutMutable],
1045 let tr = ty::mk_trait(tcx, trt_did, trt_substs.clone(), b);
1046 ty::mk_rptr(tcx, r, ty::mt{ ty: tr, mutbl: m })
1049 _ => fail!("Expected ty_trait in auto_slice_trait")
1053 fn search_for_autofatptrd_method(&self,
1056 -> Option<MethodCallee> {
1058 * Searches for a candidate by converting things like
1062 let tcx = self.tcx();
1063 debug!("search_for_autofatptrd_method {}", ppaux::ty_to_string(tcx, self_ty));
1065 let sty = ty::get(self_ty).sty.clone();
1067 ty_vec(ty, Some(len)) => self.auto_unsize_vec(ty, autoderefs, len),
1068 ty_vec(ty, None) => self.auto_slice_vec(ty, autoderefs),
1069 ty_str => self.auto_slice_str(autoderefs),
1070 ty_trait(..) => self.auto_slice_trait(self_ty, autoderefs),
1073 // This case should probably be handled similarly to
1082 fn search_for_autoptrd_method(&self, self_ty: ty::t, autoderefs: uint)
1083 -> Option<MethodCallee> {
1086 * Converts any type `T` to `&M T` where `M` is an
1087 * appropriate mutability.
1090 let tcx = self.tcx();
1091 match ty::get(self_ty).sty {
1092 ty_bare_fn(..) | ty_box(..) | ty_uniq(..) | ty_rptr(..) |
1093 ty_infer(IntVar(_)) |
1094 ty_infer(FloatVar(_)) |
1095 ty_param(..) | ty_nil | ty_bot | ty_bool |
1096 ty_char | ty_int(..) | ty_uint(..) |
1097 ty_float(..) | ty_enum(..) | ty_ptr(..) | ty_struct(..) |
1098 ty_unboxed_closure(..) | ty_tup(..) | ty_open(..) |
1099 ty_str | ty_vec(..) | ty_trait(..) | ty_closure(..) => {
1100 self.search_for_some_kind_of_autorefd_method(
1101 |r, m| AutoPtr(r, m, None), autoderefs, [MutImmutable, MutMutable],
1102 |m,r| ty::mk_rptr(tcx, r, ty::mt {ty:self_ty, mutbl:m}))
1107 ty_infer(TyVar(_)) |
1108 ty_infer(SkolemizedTy(_)) |
1109 ty_infer(SkolemizedIntTy(_)) => {
1110 self.bug(format!("unexpected type: {}",
1111 self.ty_to_string(self_ty)).as_slice());
1116 fn search_for_some_kind_of_autorefd_method(
1118 kind: |Region, ast::Mutability| -> ty::AutoRef,
1120 mutbls: &[ast::Mutability],
1121 mk_autoref_ty: |ast::Mutability, ty::Region| -> ty::t)
1122 -> Option<MethodCallee> {
1123 // Hacky. For overloaded derefs, there may be an adjustment
1124 // added to the expression from the outside context, so we do not store
1125 // an explicit adjustment, but rather we hardwire the single deref
1126 // that occurs in trans and mem_categorization.
1127 let self_expr_id = match self.self_expr {
1128 Some(expr) => Some(expr.id),
1130 assert_eq!(autoderefs, 0);
1131 assert!(kind(ty::ReEmpty, ast::MutImmutable) ==
1132 ty::AutoPtr(ty::ReEmpty, ast::MutImmutable, None));
1137 // This is hokey. We should have mutability inference as a
1138 // variable. But for now, try &const, then &, then &mut:
1140 self.infcx().next_region_var(infer::Autoref(self.span));
1141 for mutbl in mutbls.iter() {
1142 let autoref_ty = mk_autoref_ty(*mutbl, region);
1143 match self.search_for_method(autoref_ty) {
1146 match self_expr_id {
1147 Some(self_expr_id) => {
1148 self.fcx.write_adjustment(
1151 ty::AdjustDerefRef(ty::AutoDerefRef {
1152 autoderefs: autoderefs,
1153 autoref: Some(kind(region, *mutbl))
1158 return Some(method);
1165 fn search_for_method(&self, rcvr_ty: ty::t) -> Option<MethodCallee> {
1166 debug!("search_for_method(rcvr_ty={})", self.ty_to_string(rcvr_ty));
1167 let _indenter = indenter();
1169 // I am not sure that inherent methods should have higher
1170 // priority, but it is necessary ATM to handle some of the
1173 debug!("searching inherent candidates");
1174 match self.consider_candidates(rcvr_ty, self.inherent_candidates.as_slice()) {
1181 debug!("searching extension candidates");
1182 self.consider_candidates(rcvr_ty, self.extension_candidates.as_slice())
1185 fn consider_candidates(&self, rcvr_ty: ty::t,
1186 candidates: &[Candidate])
1187 -> Option<MethodCallee> {
1188 let relevant_candidates = self.filter_candidates(rcvr_ty, candidates);
1190 if relevant_candidates.len() == 0 {
1194 if self.report_statics == ReportStaticMethods {
1195 // lookup should only be called with ReportStaticMethods if a regular lookup failed
1196 assert!(relevant_candidates.iter()
1198 c.method_ty.explicit_self == ty::StaticExplicitSelfCategory
1201 self.tcx().sess.fileline_note(self.span,
1202 "found defined static methods, maybe a `self` is missing?");
1204 for (idx, candidate) in relevant_candidates.iter().enumerate() {
1205 self.report_candidate(idx, &candidate.origin);
1208 // return something so we don't get errors for every mutability
1209 return Some(MethodCallee {
1210 origin: relevant_candidates.get(0).origin.clone(),
1212 substs: subst::Substs::empty()
1216 if relevant_candidates.len() > 1 {
1217 span_err!(self.tcx().sess, self.span, E0034,
1218 "multiple applicable methods in scope");
1219 for (idx, candidate) in relevant_candidates.iter().enumerate() {
1220 self.report_candidate(idx, &candidate.origin);
1224 Some(self.confirm_candidate(rcvr_ty, relevant_candidates.get(0)))
1227 fn filter_candidates(&self, rcvr_ty: ty::t, candidates: &[Candidate]) -> Vec<Candidate> {
1228 let mut relevant_candidates: Vec<Candidate> = Vec::new();
1230 for candidate_a in candidates.iter().filter(|&c| self.is_relevant(rcvr_ty, c)) {
1231 // Skip this one if we already have one like it
1232 if !relevant_candidates.iter().any(|candidate_b| {
1233 debug!("attempting to merge {} and {}",
1234 candidate_a.repr(self.tcx()),
1235 candidate_b.repr(self.tcx()));
1236 match (&candidate_a.origin, &candidate_b.origin) {
1237 (&MethodTypeParam(ref p1), &MethodTypeParam(ref p2)) => {
1239 p1.trait_ref.def_id == p2.trait_ref.def_id;
1241 p1.method_num == p2.method_num;
1242 // it's ok to compare self-ty with `==` here because
1243 // they are always a TyParam
1245 p1.trait_ref.self_ty() == p2.trait_ref.self_ty();
1246 same_trait && same_method && same_param
1251 relevant_candidates.push(candidate_a.clone());
1258 fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
1261 // This method performs two sets of substitutions, one after the other:
1262 // 1. Substitute values for any type/lifetime parameters from the impl and
1263 // method declaration into the method type. This is the function type
1264 // before it is called; it may still include late bound region variables.
1265 // 2. Instantiate any late bound lifetime parameters in the method itself
1266 // with fresh region variables.
1268 let tcx = self.tcx();
1270 debug!("confirm_candidate(rcvr_ty={}, candidate={})",
1271 self.ty_to_string(rcvr_ty),
1272 candidate.repr(self.tcx()));
1274 self.enforce_object_limitations(candidate);
1275 self.enforce_drop_trait_limitations(candidate);
1277 // static methods should never have gotten this far:
1278 assert!(candidate.method_ty.explicit_self !=
1279 ty::StaticExplicitSelfCategory);
1281 // Determine the values for the generic parameters of the method.
1282 // If they were not explicitly supplied, just construct fresh
1284 let num_supplied_tps = self.supplied_tps.len();
1285 let num_method_tps = candidate.method_ty.generics.types.len(subst::FnSpace);
1287 if num_supplied_tps == 0u {
1288 self.fcx.infcx().next_ty_vars(num_method_tps)
1289 } else if num_method_tps == 0u {
1290 span_err!(tcx.sess, self.span, E0035,
1291 "does not take type parameters");
1292 self.fcx.infcx().next_ty_vars(num_method_tps)
1293 } else if num_supplied_tps != num_method_tps {
1294 span_err!(tcx.sess, self.span, E0036,
1295 "incorrect number of type parameters given for this method");
1296 self.fcx.infcx().next_ty_vars(num_method_tps)
1298 Vec::from_slice(self.supplied_tps)
1302 // Create subst for early-bound lifetime parameters, combining
1303 // parameters from the type and those from the method.
1305 // FIXME -- permit users to manually specify lifetimes
1307 self.fcx.infcx().region_vars_for_defs(
1309 candidate.method_ty.generics.regions.get_slice(subst::FnSpace));
1311 let all_substs = candidate.rcvr_substs.clone().with_method(m_types, m_regions);
1313 let ref bare_fn_ty = candidate.method_ty.fty;
1315 // Compute the method type with type parameters substituted
1316 debug!("fty={} all_substs={}",
1317 bare_fn_ty.repr(tcx),
1318 all_substs.repr(tcx));
1320 let fn_sig = &bare_fn_ty.sig;
1321 let inputs = match candidate.origin {
1322 MethodTraitObject(..) => {
1323 // For annoying reasons, we've already handled the
1324 // substitution of self for object calls.
1325 let args = fn_sig.inputs.slice_from(1).iter().map(|t| {
1326 t.subst(tcx, &all_substs)
1328 Some(*fn_sig.inputs.get(0)).into_iter().chain(args).collect()
1330 _ => fn_sig.inputs.subst(tcx, &all_substs)
1332 let fn_sig = ty::FnSig {
1333 binder_id: fn_sig.binder_id,
1335 output: fn_sig.output.subst(tcx, &all_substs),
1336 variadic: fn_sig.variadic
1339 debug!("after subst, fty={}", fn_sig.repr(tcx));
1341 // Replace any bound regions that appear in the function
1342 // signature with region variables
1343 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(
1345 |br| self.fcx.infcx().next_region_var(
1346 infer::LateBoundRegion(self.span, br)));
1347 let transformed_self_ty = *fn_sig.inputs.get(0);
1348 let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
1350 fn_style: bare_fn_ty.fn_style,
1351 abi: bare_fn_ty.abi.clone(),
1353 debug!("after replacing bound regions, fty={}", self.ty_to_string(fty));
1355 // Before, we only checked whether self_ty could be a subtype
1356 // of rcvr_ty; now we actually make it so (this may cause
1357 // variables to unify etc). Since we checked beforehand, and
1358 // nothing has changed in the meantime, this unification
1359 // should never fail.
1360 let span = self.self_expr.map_or(self.span, |e| e.span);
1361 match self.fcx.mk_subty(false, infer::Misc(span),
1362 rcvr_ty, transformed_self_ty) {
1366 "{} was a subtype of {} but now is not?",
1367 self.ty_to_string(rcvr_ty),
1368 self.ty_to_string(transformed_self_ty)).as_slice());
1372 self.fcx.add_obligations_for_parameters(
1373 traits::ObligationCause::misc(self.span),
1375 &candidate.method_ty.generics);
1378 origin: candidate.origin.clone(),
1384 fn enforce_object_limitations(&self, candidate: &Candidate) {
1386 * There are some limitations to calling functions through an
1387 * object, because (a) the self type is not known
1388 * (that's the whole point of a trait instance, after all, to
1389 * obscure the self type) and (b) the call must go through a
1390 * vtable and hence cannot be monomorphized.
1393 match candidate.origin {
1395 MethodTypeParam(..) |
1396 MethodStaticUnboxedClosure(..) => {
1397 return; // not a call to a trait instance
1399 MethodTraitObject(..) => {}
1402 match candidate.method_ty.explicit_self {
1403 ty::StaticExplicitSelfCategory => { // reason (a) above
1404 self.tcx().sess.span_err(
1406 "cannot call a method without a receiver \
1407 through an object");
1410 ty::ByValueExplicitSelfCategory |
1411 ty::ByReferenceExplicitSelfCategory(..) |
1412 ty::ByBoxExplicitSelfCategory => {}
1416 let check_for_self_ty = |ty| {
1417 if ty::type_has_self(ty) {
1418 span_err!(self.tcx().sess, self.span, E0038,
1419 "cannot call a method whose type contains a \
1420 self-type through an object");
1426 let ref sig = candidate.method_ty.fty.sig;
1427 let mut found_self_ty = false;
1428 for &input_ty in sig.inputs.iter() {
1429 if check_for_self_ty(input_ty) {
1430 found_self_ty = true;
1435 check_for_self_ty(sig.output);
1438 if candidate.method_ty.generics.has_type_params(subst::FnSpace) {
1440 span_err!(self.tcx().sess, self.span, E0039,
1441 "cannot call a generic method through an object");
1445 fn enforce_drop_trait_limitations(&self, candidate: &Candidate) {
1446 // No code can call the finalize method explicitly.
1448 match candidate.origin {
1449 MethodStatic(method_id) => {
1450 bad = self.tcx().destructors.borrow().contains(&method_id);
1452 MethodStaticUnboxedClosure(_) => bad = false,
1453 // FIXME: does this properly enforce this on everything now
1454 // that self has been merged in? -sully
1455 MethodTypeParam(MethodParam { trait_ref: ref trait_ref, .. }) |
1456 MethodTraitObject(MethodObject { trait_ref: ref trait_ref, .. }) => {
1457 bad = self.tcx().destructor_for_type.borrow()
1458 .contains_key(&trait_ref.def_id);
1463 span_err!(self.tcx().sess, self.span, E0040,
1464 "explicit call to destructor");
1468 // `rcvr_ty` is the type of the expression. It may be a subtype of a
1469 // candidate method's `self_ty`.
1470 fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool {
1471 debug!("is_relevant(rcvr_ty={}, candidate={})",
1472 self.ty_to_string(rcvr_ty), candidate.repr(self.tcx()));
1474 return match candidate.method_ty.explicit_self {
1475 StaticExplicitSelfCategory => {
1476 debug!("(is relevant?) explicit self is static");
1477 self.report_statics == ReportStaticMethods
1480 ByValueExplicitSelfCategory => {
1481 debug!("(is relevant?) explicit self is by-value");
1482 match ty::get(rcvr_ty).sty {
1483 ty::ty_uniq(typ) => {
1484 match ty::get(typ).sty {
1485 ty::ty_trait(box ty::TyTrait {
1489 rcvr_matches_object(self_did, candidate) ||
1490 rcvr_matches_ty(self.fcx,
1495 rcvr_matches_ty(self.fcx, rcvr_ty, candidate)
1499 _ => rcvr_matches_ty(self.fcx, rcvr_ty, candidate)
1503 ByReferenceExplicitSelfCategory(_, m) => {
1504 debug!("(is relevant?) explicit self is a region");
1505 match ty::get(rcvr_ty).sty {
1506 ty::ty_rptr(_, mt) => {
1507 match ty::get(mt.ty).sty {
1508 ty::ty_trait(box ty::TyTrait { def_id: self_did, .. }) => {
1509 mutability_matches(mt.mutbl, m) &&
1510 rcvr_matches_object(self_did, candidate)
1512 _ => mutability_matches(mt.mutbl, m) &&
1513 rcvr_matches_ty(self.fcx, mt.ty, candidate)
1521 ByBoxExplicitSelfCategory => {
1522 debug!("(is relevant?) explicit self is a unique pointer");
1523 match ty::get(rcvr_ty).sty {
1524 ty::ty_uniq(typ) => {
1525 match ty::get(typ).sty {
1526 ty::ty_trait(box ty::TyTrait { def_id: self_did, .. }) => {
1527 rcvr_matches_object(self_did, candidate)
1529 _ => rcvr_matches_ty(self.fcx, typ, candidate),
1538 fn rcvr_matches_object(self_did: ast::DefId,
1539 candidate: &Candidate) -> bool {
1540 match candidate.rcvr_match_condition {
1541 RcvrMatchesIfObject(desired_did) => {
1542 self_did == desired_did
1544 RcvrMatchesIfSubtype(_) | RcvrMatchesIfEqtype(_) => {
1550 fn rcvr_matches_ty(fcx: &FnCtxt,
1552 candidate: &Candidate) -> bool {
1553 match candidate.rcvr_match_condition {
1554 RcvrMatchesIfObject(_) => {
1557 RcvrMatchesIfSubtype(of_type) => {
1558 fcx.can_mk_subty(rcvr_ty, of_type).is_ok()
1560 RcvrMatchesIfEqtype(of_type) => {
1561 fcx.can_mk_eqty(rcvr_ty, of_type).is_ok()
1566 fn mutability_matches(self_mutbl: ast::Mutability,
1567 candidate_mutbl: ast::Mutability)
1569 //! True if `self_mutbl <: candidate_mutbl`
1570 self_mutbl == candidate_mutbl
1574 fn report_candidate(&self, idx: uint, origin: &MethodOrigin) {
1576 MethodStatic(impl_did) => {
1577 let did = if self.report_statics == ReportStaticMethods {
1578 // If we're reporting statics, we want to report the trait
1579 // definition if possible, rather than an impl
1580 match ty::trait_item_of_item(self.tcx(), impl_did) {
1581 None | Some(TypeTraitItemId(_)) => {
1582 debug!("(report candidate) No trait method \
1586 Some(MethodTraitItemId(trait_did)) => {
1587 debug!("(report candidate) Found trait ref");
1592 // If it is an instantiated default method, use the original
1593 // default method for error reporting.
1594 match provided_source(self.tcx(), impl_did) {
1599 self.report_static_candidate(idx, did)
1601 MethodStaticUnboxedClosure(did) => {
1602 self.report_static_candidate(idx, did)
1604 MethodTypeParam(ref mp) => {
1605 self.report_param_candidate(idx, mp.trait_ref.def_id)
1607 MethodTraitObject(ref mo) => {
1608 self.report_trait_candidate(idx, mo.trait_ref.def_id)
1613 fn report_static_candidate(&self, idx: uint, did: DefId) {
1614 let span = if did.krate == ast::LOCAL_CRATE {
1615 self.tcx().map.span(did.node)
1619 span_note!(self.tcx().sess, span,
1620 "candidate #{} is `{}`",
1621 idx + 1u, ty::item_path_str(self.tcx(), did));
1624 fn report_param_candidate(&self, idx: uint, did: DefId) {
1625 span_note!(self.tcx().sess, self.span,
1626 "candidate #{} derives from the bound `{}`",
1627 idx + 1u, ty::item_path_str(self.tcx(), did));
1630 fn report_trait_candidate(&self, idx: uint, did: DefId) {
1631 span_note!(self.tcx().sess, self.span,
1632 "candidate #{} derives from the type of the receiver, \
1633 which is the trait `{}`",
1634 idx + 1u, ty::item_path_str(self.tcx(), did));
1637 fn infcx(&'a self) -> &'a infer::InferCtxt<'a, 'tcx> {
1641 fn tcx(&self) -> &'a ty::ctxt<'tcx> {
1645 fn ty_to_string(&self, t: ty::t) -> String {
1646 self.fcx.infcx().ty_to_string(t)
1649 fn did_to_string(&self, did: DefId) -> String {
1650 ty::item_path_str(self.tcx(), did)
1653 fn bug(&self, s: &str) -> ! {
1654 self.tcx().sess.span_bug(self.span, s)
1658 impl Repr for Candidate {
1659 fn repr(&self, tcx: &ty::ctxt) -> String {
1660 format!("Candidate(rcvr_ty={}, rcvr_substs={}, method_ty={}, \
1662 self.rcvr_match_condition.repr(tcx),
1663 self.rcvr_substs.repr(tcx),
1664 self.method_ty.repr(tcx),
1669 impl Repr for RcvrMatchCondition {
1670 fn repr(&self, tcx: &ty::ctxt) -> String {
1672 RcvrMatchesIfObject(d) => {
1673 format!("RcvrMatchesIfObject({})", d.repr(tcx))
1675 RcvrMatchesIfSubtype(t) => {
1676 format!("RcvrMatchesIfSubtype({})", t.repr(tcx))
1678 RcvrMatchesIfEqtype(t) => {
1679 format!("RcvrMatchesIfEqtype({})", t.repr(tcx))