1 // Copyright 2012 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 `@ToStr`, then the trait
34 methods (`to_str()`, 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 `ToStr` imported, and I call `to_str()` on a value of type `T`,
40 then we will go off to find out whether there is an impl of `ToStr`
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 `@self`, which means that it expects a
76 receiver of type `@Foo`. If we have a receiver of type `@Foo`, but we
77 waited to search for that impl until we have deref'd the `@` away and
78 obtained the type `Foo`, we would never match this method.
83 use middle::subst::Subst;
87 use middle::typeck::astconv::AstConv;
88 use middle::typeck::check::{FnCtxt, impl_self_ty};
89 use middle::typeck::check::{structurally_resolved_type};
90 use middle::typeck::check::vtable;
91 use middle::typeck::check;
92 use middle::typeck::infer;
93 use middle::typeck::{method_map_entry, method_origin, method_param};
94 use middle::typeck::{method_static, method_object};
95 use middle::typeck::{param_numbered, param_self, param_index};
96 use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig;
97 use util::common::indenter;
98 use util::ppaux::Repr;
100 use std::cell::RefCell;
101 use std::hashmap::HashSet;
104 use syntax::ast::{DefId, SelfValue, SelfRegion, SelfBox};
105 use syntax::ast::{SelfUniq, SelfStatic, NodeId};
106 use syntax::ast::{MutMutable, MutImmutable};
109 use syntax::parse::token;
112 pub enum CheckTraitsFlag {
114 CheckTraitsAndInherentMethods,
118 pub enum AutoderefReceiverFlag {
120 DontAutoderefReceiver,
126 // In a call `a.b::<X, Y, ...>(...)`:
127 expr: &ast::Expr, // The expression `a.b(...)`.
128 self_expr: &ast::Expr, // The expression `a`.
129 callee_id: NodeId, /* Where to store `a.b`'s type,
130 * also the scope of the call */
131 m_name: ast::Name, // The name `b`.
132 self_ty: ty::t, // The type of `a`.
133 supplied_tps: &[ty::t], // The list of types X, Y, ... .
134 deref_args: check::DerefArgs, // Whether we autopointer first.
135 check_traits: CheckTraitsFlag, // Whether we check traits only.
136 autoderef_receiver: AutoderefReceiverFlag)
137 -> Option<method_map_entry> {
138 let impl_dups = @RefCell::new(HashSet::new());
139 let lcx = LookupContext {
142 self_expr: self_expr,
143 callee_id: callee_id,
145 supplied_tps: supplied_tps,
146 impl_dups: impl_dups,
147 inherent_candidates: @RefCell::new(~[]),
148 extension_candidates: @RefCell::new(~[]),
149 deref_args: deref_args,
150 check_traits: check_traits,
151 autoderef_receiver: autoderef_receiver,
154 let self_ty = structurally_resolved_type(fcx, self_expr.span, self_ty);
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 let mme = lcx.search(self_ty);
166 debug!("searching extension candidates");
167 lcx.reset_candidates();
168 lcx.push_bound_candidates(self_ty);
169 lcx.push_extension_candidates();
170 return lcx.search(self_ty);
173 pub struct LookupContext<'a> {
176 self_expr: &'a ast::Expr,
179 supplied_tps: &'a [ty::t],
180 impl_dups: @RefCell<HashSet<DefId>>,
181 inherent_candidates: @RefCell<~[Candidate]>,
182 extension_candidates: @RefCell<~[Candidate]>,
183 deref_args: check::DerefArgs,
184 check_traits: CheckTraitsFlag,
185 autoderef_receiver: AutoderefReceiverFlag,
189 * A potential method that might be called, assuming the receiver
190 * is of a suitable type.
193 pub struct Candidate {
194 rcvr_match_condition: RcvrMatchCondition,
195 rcvr_substs: ty::substs,
196 method_ty: @ty::Method,
197 origin: method_origin,
200 /// This type represents the conditions under which the receiver is
201 /// considered to "match" a given method candidate. Typically the test
202 /// is whether the receiver is of a particular type. However, this
203 /// type is the type of the receiver *after accounting for the
204 /// method's self type* (e.g., if the method is an `@self` method, we
205 /// have *already verified* that the receiver is of some type `@T` and
206 /// now we must check that the type `T` is correct). Unfortunately,
207 /// because traits are not types, this is a pain to do.
209 enum RcvrMatchCondition {
210 RcvrMatchesIfObject(ast::DefId),
211 RcvrMatchesIfSubtype(ty::t)
214 impl<'a> LookupContext<'a> {
215 fn search(&self, self_ty: ty::t) -> Option<method_map_entry> {
216 let mut self_ty = self_ty;
217 let mut autoderefs = 0;
219 debug!("loop: self_ty={} autoderefs={}",
220 self.ty_to_str(self_ty), autoderefs);
222 match self.deref_args {
223 check::DontDerefArgs => {
224 match self.search_for_autoderefd_method(self_ty,
226 Some(mme) => { return Some(mme); }
230 match self.search_for_autoptrd_method(self_ty,
232 Some(mme) => { return Some(mme); }
236 check::DoDerefArgs => {
237 match self.search_for_autoptrd_method(self_ty,
239 Some(mme) => { return Some(mme); }
243 match self.search_for_autoderefd_method(self_ty,
245 Some(mme) => { return Some(mme); }
251 // Don't autoderef if we aren't supposed to.
252 if self.autoderef_receiver == DontAutoderefReceiver {
256 // Otherwise, perform autoderef.
257 match self.deref(self_ty) {
266 self.search_for_autosliced_method(self_ty, autoderefs)
269 fn deref(&self, ty: ty::t) -> Option<ty::t> {
270 match ty::deref(ty, false) {
273 Some(structurally_resolved_type(self.fcx,
280 // ______________________________________________________________________
281 // Candidate collection (see comment at start of file)
283 fn reset_candidates(&self) {
284 self.inherent_candidates.set(~[]);
285 self.extension_candidates.set(~[]);
288 fn push_inherent_candidates(&self, self_ty: ty::t) {
290 * Collect all inherent candidates into
291 * `self.inherent_candidates`. See comment at the start of
292 * the file. To find the inherent candidates, we repeatedly
293 * deref the self-ty to find the "base-type". So, for
294 * example, if the receiver is @@C where `C` is a struct type,
295 * we'll want to find the inherent impls for `C`.
298 let mut self_ty = self_ty;
300 match get(self_ty).sty {
301 ty_trait(did, ref substs, _, _, _) => {
302 self.push_inherent_candidates_from_object(did, substs);
303 self.push_inherent_impl_candidates_for_type(did);
305 ty_enum(did, _) | ty_struct(did, _) => {
306 if self.check_traits == CheckTraitsAndInherentMethods {
307 self.push_inherent_impl_candidates_for_type(did);
310 _ => { /* No inherent methods in these types */ }
313 // n.b.: Generally speaking, we only loop if we hit the
314 // fallthrough case in the match above. The exception
315 // would be newtype enums.
316 self_ty = match self.deref(self_ty) {
323 fn push_bound_candidates(&self, self_ty: ty::t) {
324 let mut self_ty = self_ty;
326 match get(self_ty).sty {
328 self.push_inherent_candidates_from_param(self_ty, p);
331 // Call is of the form "self.foo()" and appears in one
332 // of a trait's default method implementations.
333 self.push_inherent_candidates_from_self(self_ty);
335 _ => { /* No bound methods in these types */ }
338 self_ty = match self.deref(self_ty) {
345 fn push_extension_candidates(&self) {
346 // If the method being called is associated with a trait, then
347 // find all the impls of that trait. Each of those are
349 let trait_map: &resolve::TraitMap = &self.fcx.ccx.trait_map;
350 let opt_applicable_traits = trait_map.find(&self.expr.id);
351 for applicable_traits in opt_applicable_traits.iter() {
352 let applicable_traits = applicable_traits.borrow();
353 for trait_did in applicable_traits.get().iter() {
354 ty::populate_implementations_for_trait_if_necessary(
358 // Look for explicit implementations.
359 let trait_impls = self.tcx().trait_impls.borrow();
360 let opt_impl_infos = trait_impls.get().find(trait_did);
361 for impl_infos in opt_impl_infos.iter() {
362 let impl_infos = impl_infos.borrow();
363 for impl_info in impl_infos.get().iter() {
364 let mut extension_candidates =
365 self.extension_candidates.borrow_mut();
366 self.push_candidates_from_impl(
367 extension_candidates.get(), *impl_info);
375 // Determine the index of a method in the list of all methods belonging
376 // to a trait and its supertraits.
377 fn get_method_index(&self,
378 trait_ref: @TraitRef,
380 n_method: uint) -> uint {
381 let tcx = self.tcx();
383 // We need to figure the "real index" of the method in a
384 // listing of all the methods of an object. We do this by
385 // iterating down the supertraits of the object's trait until
386 // we find the trait the method came from, counting up the
387 // methods from them.
388 let mut method_count = 0;
389 ty::each_bound_trait_and_supertraits(tcx, &[subtrait], |bound_ref| {
390 if bound_ref.def_id == trait_ref.def_id { false }
392 method_count += ty::trait_methods(tcx, bound_ref.def_id).len();
396 return method_count + n_method;
400 fn push_inherent_candidates_from_object(&self,
402 substs: &ty::substs) {
403 debug!("push_inherent_candidates_from_object(did={}, substs={})",
404 self.did_to_str(did),
405 substs_to_str(self.tcx(), substs));
406 let _indenter = indenter();
408 // It is illegal to invoke a method on a trait instance that
409 // refers to the `self` type. An error will be reported by
410 // `enforce_object_limitations()` if the method refers
411 // to the `Self` type. Substituting ty_err here allows
412 // compiler to soldier on.
414 // `confirm_candidate()` also relies upon this substitution
416 let rcvr_substs = substs {
417 self_ty: Some(ty::mk_err()),
420 let trait_ref = @TraitRef { def_id: did, substs: rcvr_substs.clone() };
422 self.push_inherent_candidates_from_bounds_inner(&[trait_ref],
423 |new_trait_ref, m, method_num, _bound_num| {
425 self.get_method_index(new_trait_ref, trait_ref, method_num);
426 let mut m = (*m).clone();
427 // We need to fix up the transformed self type.
428 m.fty.sig.inputs[0] =
429 self.construct_transformed_self_ty_for_object(
430 did, &rcvr_substs, &m);
433 rcvr_match_condition: RcvrMatchesIfObject(did),
434 rcvr_substs: new_trait_ref.substs.clone(),
436 origin: method_object(method_object {
437 trait_id: new_trait_ref.def_id,
438 object_trait_id: did,
439 method_num: method_num,
440 real_index: vtable_index
446 fn push_inherent_candidates_from_param(&self,
448 param_ty: param_ty) {
449 debug!("push_inherent_candidates_from_param(param_ty={:?})",
451 self.push_inherent_candidates_from_bounds(
453 self.fcx.inh.param_env.type_param_bounds[param_ty.idx].trait_bounds,
454 param_numbered(param_ty.idx));
458 fn push_inherent_candidates_from_self(&self,
460 debug!("push_inherent_candidates_from_self()");
461 self.push_inherent_candidates_from_bounds(
463 [self.fcx.inh.param_env.self_param_bound.unwrap()],
467 fn push_inherent_candidates_from_bounds(&self,
469 bounds: &[@TraitRef],
470 param: param_index) {
471 self.push_inherent_candidates_from_bounds_inner(bounds,
472 |trait_ref, m, method_num, bound_num| {
474 rcvr_match_condition: RcvrMatchesIfSubtype(self_ty),
475 rcvr_substs: trait_ref.substs.clone(),
477 origin: method_param(
479 trait_id: trait_ref.def_id,
480 method_num: method_num,
482 bound_num: bound_num,
488 // Do a search through a list of bounds, using a callback to actually
489 // create the candidates.
490 fn push_inherent_candidates_from_bounds_inner(&self,
491 bounds: &[@TraitRef],
492 mk_cand: |tr: @TraitRef,
497 let tcx = self.tcx();
498 let mut next_bound_idx = 0; // count only trait bounds
500 ty::each_bound_trait_and_supertraits(tcx, bounds, |bound_trait_ref| {
501 let this_bound_idx = next_bound_idx;
504 let trait_methods = ty::trait_methods(tcx, bound_trait_ref.def_id);
505 match trait_methods.iter().position(|m| {
506 m.explicit_self != ast::SelfStatic &&
507 m.ident.name == self.m_name })
510 let method = trait_methods[pos];
512 let cand = mk_cand(bound_trait_ref, method,
513 pos, this_bound_idx);
515 debug!("pushing inherent candidate for param: {:?}", cand);
516 let mut inherent_candidates = self.inherent_candidates
518 inherent_candidates.get().push(cand);
521 debug!("trait doesn't contain method: {:?}",
522 bound_trait_ref.def_id);
523 // check next trait or bound
531 fn push_inherent_impl_candidates_for_type(&self, did: DefId) {
532 // Read the inherent implementation candidates for this type from the
533 // metadata if necessary.
534 ty::populate_implementations_for_type_if_necessary(self.tcx(), did);
536 let inherent_impls = self.tcx().inherent_impls.borrow();
537 let opt_impl_infos = inherent_impls.get().find(&did);
538 for impl_infos in opt_impl_infos.iter() {
539 let impl_infos = impl_infos.borrow();
540 for impl_info in impl_infos.get().iter() {
541 let mut inherent_candidates = self.inherent_candidates
543 self.push_candidates_from_impl(inherent_candidates.get(),
549 fn push_candidates_from_impl(&self,
550 candidates: &mut ~[Candidate],
551 impl_info: &ty::Impl) {
553 let mut impl_dups = self.impl_dups.borrow_mut();
554 if !impl_dups.get().insert(impl_info.did) {
555 return; // already visited
558 debug!("push_candidates_from_impl: {} {} {}",
559 token::interner_get(self.m_name),
560 impl_info.ident.repr(self.tcx()),
561 impl_info.methods.map(|m| m.ident).repr(self.tcx()));
564 match impl_info.methods.iter().position(|m| m.ident.name == self.m_name) {
566 None => { return; } // No method with the right name.
570 let method = ty::method(self.tcx(), impl_info.methods[idx].def_id);
572 // determine the `self` of the impl with fresh
573 // variables for each parameter:
574 let location_info = &vtable::location_info_for_expr(self.self_expr);
575 let vcx = self.fcx.vtable_context();
576 let ty::ty_param_substs_and_ty {
579 } = impl_self_ty(&vcx, location_info, impl_info.did);
581 candidates.push(Candidate {
582 rcvr_match_condition: RcvrMatchesIfSubtype(impl_ty),
583 rcvr_substs: impl_substs,
585 origin: method_static(method.def_id)
589 // ______________________________________________________________________
590 // Candidate selection (see comment at start of file)
592 fn search_for_autoderefd_method(&self,
595 -> Option<method_map_entry> {
596 let (self_ty, autoadjust) =
597 self.consider_reborrow(self_ty, autoderefs);
598 match self.search_for_method(self_ty) {
601 debug!("(searching for autoderef'd method) writing \
602 adjustment ({}) to {}",
605 self.fcx.write_adjustment(self.self_expr.id, @autoadjust);
611 fn consider_reborrow(&self,
614 -> (ty::t, ty::AutoAdjustment) {
616 * In the event that we are invoking a method with a receiver
617 * of a borrowed type like `&T`, `&mut T`, or `&mut [T]`,
618 * we will "reborrow" the receiver implicitly. For example, if
619 * you have a call `r.inc()` and where `r` has type `&mut T`,
620 * then we treat that like `(&mut *r).inc()`. This avoids
621 * consuming the original pointer.
623 * You might think that this would be a natural byproduct of
624 * the auto-deref/auto-ref process. This is true for `~T`
625 * but not for an `&mut T` receiver. With `~T`, we would
626 * begin by testing for methods with a self type `~T`,
627 * then autoderef to `T`, then autoref to `&mut T`. But with
628 * an `&mut T` receiver the process begins with `&mut T`, only
629 * without any autoadjustments.
632 let tcx = self.tcx();
633 return match ty::get(self_ty).sty {
634 ty::ty_rptr(_, self_mt) if default_method_hack(self_mt) => {
636 ty::AutoDerefRef(ty::AutoDerefRef {
637 autoderefs: autoderefs,
640 ty::ty_rptr(_, self_mt) => {
642 self.infcx().next_region_var(
643 infer::Autoref(self.expr.span));
644 (ty::mk_rptr(tcx, region, self_mt),
645 ty::AutoDerefRef(ty::AutoDerefRef {
646 autoderefs: autoderefs+1,
647 autoref: Some(ty::AutoPtr(region, self_mt.mutbl))}))
649 ty::ty_vec(self_mt, vstore_slice(_)) => {
651 self.infcx().next_region_var(
652 infer::Autoref(self.expr.span));
653 (ty::mk_vec(tcx, self_mt, vstore_slice(region)),
654 ty::AutoDerefRef(ty::AutoDerefRef {
655 autoderefs: autoderefs,
656 autoref: Some(ty::AutoBorrowVec(region, self_mt.mutbl))}))
658 ty_trait(did, ref substs, ty::RegionTraitStore(_), mutbl, bounds) => {
660 self.infcx().next_region_var(
661 infer::Autoref(self.expr.span));
662 (ty::mk_trait(tcx, did, substs.clone(),
663 ty::RegionTraitStore(region),
665 ty::AutoDerefRef(ty::AutoDerefRef {
666 autoderefs: autoderefs,
667 autoref: Some(ty::AutoBorrowObj(region, mutbl))}))
671 ty::AutoDerefRef(ty::AutoDerefRef {
672 autoderefs: autoderefs,
677 fn default_method_hack(self_mt: ty::mt) -> bool {
678 // FIXME(#6129). Default methods can't deal with autoref.
680 // I am a horrible monster and I pray for death. Currently
681 // the default method code fails when you try to reborrow
682 // because it is not handling types correctly. In lieu of
683 // fixing that, I am introducing this horrible hack. - ndm
684 self_mt.mutbl == MutImmutable && ty::type_is_self(self_mt.ty)
688 fn search_for_autosliced_method(&self,
691 -> Option<method_map_entry> {
694 * Searches for a candidate by converting things like
697 let tcx = self.tcx();
698 let sty = ty::get(self_ty).sty.clone();
700 ty_vec(mt, vstore_box) |
701 ty_vec(mt, vstore_uniq) |
702 ty_vec(mt, vstore_slice(_)) | // NDM(#3148)
703 ty_vec(mt, vstore_fixed(_)) => {
704 // First try to borrow to a slice
705 let entry = self.search_for_some_kind_of_autorefd_method(
706 AutoBorrowVec, autoderefs, [MutImmutable, MutMutable],
707 |m,r| ty::mk_vec(tcx,
708 ty::mt {ty:mt.ty, mutbl:m},
711 if entry.is_some() { return entry; }
713 // Then try to borrow to a slice *and* borrow a pointer.
714 self.search_for_some_kind_of_autorefd_method(
715 AutoBorrowVecRef, autoderefs, [MutImmutable, MutMutable],
717 let slice_ty = ty::mk_vec(tcx,
718 ty::mt {ty:mt.ty, mutbl:m},
720 // NB: we do not try to autoref to a mutable
721 // pointer. That would be creating a pointer
722 // to a temporary pointer (the borrowed
723 // slice), so any update the callee makes to
724 // it can't be observed.
725 ty::mk_rptr(tcx, r, ty::mt {ty:slice_ty, mutbl:MutImmutable})
730 ty_str(vstore_uniq) |
731 ty_str(vstore_fixed(_)) => {
732 let entry = self.search_for_some_kind_of_autorefd_method(
733 AutoBorrowVec, autoderefs, [MutImmutable],
734 |_m,r| ty::mk_str(tcx, vstore_slice(r)));
736 if entry.is_some() { return entry; }
738 self.search_for_some_kind_of_autorefd_method(
739 AutoBorrowVecRef, autoderefs, [MutImmutable],
741 let slice_ty = ty::mk_str(tcx, vstore_slice(r));
742 ty::mk_rptr(tcx, r, ty::mt {ty:slice_ty, mutbl:m})
746 ty_trait(trt_did, trt_substs, _, _, b) => {
747 // Coerce ~/@/&Trait instances to &Trait.
749 self.search_for_some_kind_of_autorefd_method(
750 AutoBorrowObj, autoderefs, [MutImmutable, MutMutable],
752 ty::mk_trait(tcx, trt_did, trt_substs.clone(),
753 RegionTraitStore(reg), trt_mut, b)
758 // This case should probably be handled similarly to
767 fn search_for_autoptrd_method(&self, self_ty: ty::t, autoderefs: uint)
768 -> Option<method_map_entry> {
771 * Converts any type `T` to `&M T` where `M` is an
772 * appropriate mutability.
775 let tcx = self.tcx();
776 match ty::get(self_ty).sty {
777 ty_bare_fn(..) | ty_box(..) | ty_uniq(..) | ty_rptr(..) |
778 ty_infer(IntVar(_)) |
779 ty_infer(FloatVar(_)) |
780 ty_self(_) | ty_param(..) | ty_nil | ty_bot | ty_bool |
781 ty_char | ty_int(..) | ty_uint(..) |
782 ty_float(..) | ty_enum(..) | ty_ptr(..) | ty_struct(..) | ty_tup(..) |
783 ty_str(..) | ty_vec(..) | ty_trait(..) | ty_closure(..) => {
784 self.search_for_some_kind_of_autorefd_method(
785 AutoPtr, autoderefs, [MutImmutable, MutMutable],
786 |m,r| ty::mk_rptr(tcx, r, ty::mt {ty:self_ty, mutbl:m}))
791 ty_unboxed_vec(_) | ty_type | ty_infer(TyVar(_)) => {
792 self.bug(format!("Unexpected type: {}",
793 self.ty_to_str(self_ty)));
798 fn search_for_some_kind_of_autorefd_method(
800 kind: |Region, ast::Mutability| -> ty::AutoRef,
802 mutbls: &[ast::Mutability],
803 mk_autoref_ty: |ast::Mutability, ty::Region| -> ty::t)
804 -> Option<method_map_entry> {
805 // This is hokey. We should have mutability inference as a
806 // variable. But for now, try &const, then &, then &mut:
808 self.infcx().next_region_var(
809 infer::Autoref(self.expr.span));
810 for mutbl in mutbls.iter() {
811 let autoref_ty = mk_autoref_ty(*mutbl, region);
812 match self.search_for_method(autoref_ty) {
815 self.fcx.write_adjustment(
817 @ty::AutoDerefRef(ty::AutoDerefRef {
818 autoderefs: autoderefs,
819 autoref: Some(kind(region, *mutbl))}));
827 fn search_for_method(&self, rcvr_ty: ty::t)
828 -> Option<method_map_entry> {
829 debug!("search_for_method(rcvr_ty={})", self.ty_to_str(rcvr_ty));
830 let _indenter = indenter();
832 // I am not sure that inherent methods should have higher
833 // priority, but it is necessary ATM to handle some of the
836 debug!("searching inherent candidates");
837 let mut inherent_candidates = self.inherent_candidates.borrow_mut();
838 match self.consider_candidates(rcvr_ty, inherent_candidates.get()) {
845 debug!("searching extension candidates");
846 let mut extension_candidates = self.extension_candidates.borrow_mut();
847 match self.consider_candidates(rcvr_ty, extension_candidates.get()) {
857 fn consider_candidates(&self,
859 candidates: &mut ~[Candidate])
860 -> Option<method_map_entry> {
861 // FIXME(pcwalton): Do we need to clone here?
862 let relevant_candidates: ~[Candidate] =
863 candidates.iter().map(|c| (*c).clone()).
864 filter(|c| self.is_relevant(rcvr_ty, c)).collect();
866 let relevant_candidates = self.merge_candidates(relevant_candidates);
868 if relevant_candidates.len() == 0 {
872 if relevant_candidates.len() > 1 {
873 self.tcx().sess.span_err(
875 "multiple applicable methods in scope");
876 for (idx, candidate) in relevant_candidates.iter().enumerate() {
877 self.report_candidate(idx, &candidate.origin);
881 Some(self.confirm_candidate(rcvr_ty, &relevant_candidates[0]))
884 fn merge_candidates(&self, candidates: &[Candidate]) -> ~[Candidate] {
885 let mut merged = ~[];
887 while i < candidates.len() {
888 let candidate_a = &candidates[i];
890 let mut skip = false;
893 while j < candidates.len() {
894 let candidate_b = &candidates[j];
895 debug!("attempting to merge {:?} and {:?}",
896 candidate_a, candidate_b);
897 let candidates_same = match (&candidate_a.origin,
898 &candidate_b.origin) {
899 (&method_param(ref p1), &method_param(ref p2)) => {
900 let same_trait = p1.trait_id == p2.trait_id;
901 let same_method = p1.method_num == p2.method_num;
902 let same_param = p1.param_num == p2.param_num;
903 // The bound number may be different because
904 // multiple bounds may lead to the same trait
906 same_trait && same_method && same_param
920 // There are more than one of these and we need only one
923 merged.push(candidate_a.clone());
930 fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
931 -> method_map_entry {
932 // This method performs two sets of substitutions, one after the other:
933 // 1. Substitute values for any type/lifetime parameters from the impl and
934 // method declaration into the method type. This is the function type
935 // before it is called; it may still include late bound region variables.
936 // 2. Instantiate any late bound lifetime parameters in the method itself
937 // with fresh region variables.
939 let tcx = self.tcx();
941 debug!("confirm_candidate(expr={}, candidate={})",
943 self.cand_to_str(candidate));
945 self.enforce_object_limitations(candidate);
946 self.enforce_drop_trait_limitations(candidate);
948 // static methods should never have gotten this far:
949 assert!(candidate.method_ty.explicit_self != SelfStatic);
951 // Determine the values for the type parameters of the method.
952 // If they were not explicitly supplied, just construct fresh
954 let num_supplied_tps = self.supplied_tps.len();
955 let num_method_tps = candidate.method_ty.generics.type_param_defs.len();
957 if num_supplied_tps == 0u {
958 self.fcx.infcx().next_ty_vars(num_method_tps)
959 } else if num_method_tps == 0u {
962 "this method does not take type parameters");
963 self.fcx.infcx().next_ty_vars(num_method_tps)
964 } else if num_supplied_tps != num_method_tps {
967 "incorrect number of type \
968 parameters given for this method");
969 self.fcx.infcx().next_ty_vars(num_method_tps)
971 self.supplied_tps.to_owned()
975 // Construct the full set of type parameters for the method,
976 // which is equal to the class tps + the method tps.
977 let all_substs = substs {
978 tps: vec::append(candidate.rcvr_substs.tps.clone(), m_substs),
979 regions: candidate.rcvr_substs.regions.clone(),
980 self_ty: candidate.rcvr_substs.self_ty,
983 let ref bare_fn_ty = candidate.method_ty.fty;
985 // Compute the method type with type parameters substituted
986 debug!("fty={} all_substs={}",
987 bare_fn_ty.repr(tcx),
988 ty::substs_to_str(tcx, &all_substs));
990 let fn_sig = &bare_fn_ty.sig;
991 let inputs = match candidate.origin {
992 method_object(..) => {
993 // For annoying reasons, we've already handled the
994 // substitution of self for object calls.
995 let args = fn_sig.inputs.slice_from(1).iter().map(|t| {
996 t.subst(tcx, &all_substs)
998 Some(fn_sig.inputs[0]).move_iter().chain(args).collect()
1000 _ => fn_sig.inputs.subst(tcx, &all_substs)
1002 let fn_sig = ty::FnSig {
1003 binder_id: fn_sig.binder_id,
1005 output: fn_sig.output.subst(tcx, &all_substs),
1006 variadic: fn_sig.variadic
1009 debug!("after subst, fty={}", fn_sig.repr(tcx));
1011 // Replace any bound regions that appear in the function
1012 // signature with region variables
1013 let (_, fn_sig) = replace_bound_regions_in_fn_sig( tcx, &fn_sig, |br| {
1014 self.fcx.infcx().next_region_var(
1015 infer::BoundRegionInFnCall(self.expr.span, br))
1017 let transformed_self_ty = fn_sig.inputs[0];
1018 let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
1020 purity: bare_fn_ty.purity,
1021 abis: bare_fn_ty.abis.clone(),
1023 debug!("after replacing bound regions, fty={}", self.ty_to_str(fty));
1025 // before we only checked whether self_ty could be a subtype
1026 // of rcvr_ty; now we actually make it so (this may cause
1027 // variables to unify etc). Since we checked beforehand, and
1028 // nothing has changed in the meantime, this unification
1029 // should never fail.
1030 match self.fcx.mk_subty(false, infer::Misc(self.self_expr.span),
1031 rcvr_ty, transformed_self_ty) {
1034 self.bug(format!("{} was a subtype of {} but now is not?",
1035 self.ty_to_str(rcvr_ty),
1036 self.ty_to_str(transformed_self_ty)));
1040 self.fcx.write_ty(self.callee_id, fty);
1041 self.fcx.write_substs(self.callee_id, all_substs);
1043 origin: candidate.origin
1047 fn construct_transformed_self_ty_for_object(
1049 trait_def_id: ast::DefId,
1050 rcvr_substs: &ty::substs,
1051 method_ty: &ty::Method) -> ty::t
1054 * This is a bit tricky. We have a match against a trait method
1055 * being invoked on an object, and we want to generate the
1056 * self-type. As an example, consider a trait
1059 * fn r_method<'a>(&'a self);
1060 * fn u_method(~self);
1063 * Now, assuming that `r_method` is being called, we want the
1064 * result to be `&'a Foo`. Assuming that `u_method` is being
1065 * called, we want the result to be `~Foo`. Of course,
1066 * this transformation has already been done as part of
1067 * `method_ty.fty.sig.inputs[0]`, but there the type
1068 * is expressed in terms of `Self` (i.e., `&'a Self`, `~Self`).
1069 * Because objects are not standalone types, we can't just substitute
1070 * `s/Self/Foo/`, so we must instead perform this kind of hokey
1074 let substs = ty::substs {regions: rcvr_substs.regions.clone(),
1076 tps: rcvr_substs.tps.clone()};
1077 match method_ty.explicit_self {
1078 ast::SelfStatic => {
1079 self.bug(~"static method for object type receiver");
1082 ty::mk_err() // error reported in `enforce_object_limitations()`
1084 ast::SelfRegion(..) | ast::SelfBox | ast::SelfUniq => {
1085 let transformed_self_ty = method_ty.fty.sig.inputs[0];
1086 match ty::get(transformed_self_ty).sty {
1087 ty::ty_rptr(r, mt) => { // must be SelfRegion
1088 ty::mk_trait(self.tcx(), trait_def_id,
1089 substs, RegionTraitStore(r), mt.mutbl,
1090 ty::EmptyBuiltinBounds())
1092 ty::ty_box(_) => { // must be SelfBox
1093 ty::mk_trait(self.tcx(), trait_def_id,
1094 substs, BoxTraitStore, ast::MutImmutable,
1095 ty::EmptyBuiltinBounds())
1097 ty::ty_uniq(_) => { // must be SelfUniq
1098 ty::mk_trait(self.tcx(), trait_def_id,
1099 substs, UniqTraitStore, ast::MutImmutable,
1100 ty::EmptyBuiltinBounds())
1104 format!("'impossible' transformed_self_ty: {}",
1105 transformed_self_ty.repr(self.tcx())));
1112 fn enforce_object_limitations(&self, candidate: &Candidate) {
1114 * There are some limitations to calling functions through an
1115 * object, because (a) the self type is not known
1116 * (that's the whole point of a trait instance, after all, to
1117 * obscure the self type) and (b) the call must go through a
1118 * vtable and hence cannot be monomorphized.
1121 match candidate.origin {
1122 method_static(..) | method_param(..) => {
1123 return; // not a call to a trait instance
1125 method_object(..) => {}
1128 match candidate.method_ty.explicit_self {
1129 ast::SelfStatic => { // reason (a) above
1130 self.tcx().sess.span_err(
1132 "cannot call a method without a receiver \
1133 through an object");
1136 ast::SelfValue => { // reason (a) above
1137 self.tcx().sess.span_err(
1139 "cannot call a method with a by-value receiver \
1140 through an object");
1143 ast::SelfRegion(..) | ast::SelfBox | ast::SelfUniq => {}
1147 let check_for_self_ty = |ty| {
1148 if ty::type_has_self(ty) {
1149 self.tcx().sess.span_err(
1151 "cannot call a method whose type contains a \
1152 self-type through an object");
1158 let ref sig = candidate.method_ty.fty.sig;
1159 let mut found_self_ty = false;
1160 for &input_ty in sig.inputs.iter() {
1161 if check_for_self_ty(input_ty) {
1162 found_self_ty = true;
1167 check_for_self_ty(sig.output);
1170 if candidate.method_ty.generics.has_type_params() { // reason (b) above
1171 self.tcx().sess.span_err(
1173 "cannot call a generic method through an object");
1177 fn enforce_drop_trait_limitations(&self, candidate: &Candidate) {
1178 // No code can call the finalize method explicitly.
1180 match candidate.origin {
1181 method_static(method_id) => {
1182 let destructors = self.tcx().destructors.borrow();
1183 bad = destructors.get().contains(&method_id);
1185 // FIXME: does this properly enforce this on everything now
1186 // that self has been merged in? -sully
1187 method_param(method_param { trait_id: trait_id, .. }) |
1188 method_object(method_object { trait_id: trait_id, .. }) => {
1189 let destructor_for_type = self.tcx()
1190 .destructor_for_type
1192 bad = destructor_for_type.get().contains_key(&trait_id);
1197 self.tcx().sess.span_err(self.expr.span,
1198 "explicit call to destructor");
1202 // `rcvr_ty` is the type of the expression. It may be a subtype of a
1203 // candidate method's `self_ty`.
1204 fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool {
1205 debug!("is_relevant(rcvr_ty={}, candidate={})",
1206 self.ty_to_str(rcvr_ty), self.cand_to_str(candidate));
1208 return match candidate.method_ty.explicit_self {
1210 debug!("(is relevant?) explicit self is static");
1215 rcvr_matches_ty(self.fcx, rcvr_ty, candidate)
1218 SelfRegion(_, m) => {
1219 debug!("(is relevant?) explicit self is a region");
1220 match ty::get(rcvr_ty).sty {
1221 ty::ty_rptr(_, mt) => {
1222 mutability_matches(mt.mutbl, m) &&
1223 rcvr_matches_ty(self.fcx, mt.ty, candidate)
1226 ty::ty_trait(self_did, _, RegionTraitStore(_), self_m, _) => {
1227 mutability_matches(self_m, m) &&
1228 rcvr_matches_object(self_did, candidate)
1236 debug!("(is relevant?) explicit self is a box");
1237 match ty::get(rcvr_ty).sty {
1238 ty::ty_box(typ) => {
1239 rcvr_matches_ty(self.fcx, typ, candidate)
1242 ty::ty_trait(self_did, _, BoxTraitStore, ast::MutImmutable, _) => {
1243 rcvr_matches_object(self_did, candidate)
1251 debug!("(is relevant?) explicit self is a unique pointer");
1252 match ty::get(rcvr_ty).sty {
1253 ty::ty_uniq(typ) => {
1254 rcvr_matches_ty(self.fcx, typ, candidate)
1257 ty::ty_trait(self_did, _, UniqTraitStore, _, _) => {
1258 rcvr_matches_object(self_did, candidate)
1266 fn rcvr_matches_object(self_did: ast::DefId,
1267 candidate: &Candidate) -> bool {
1268 match candidate.rcvr_match_condition {
1269 RcvrMatchesIfObject(desired_did) => {
1270 self_did == desired_did
1272 RcvrMatchesIfSubtype(_) => {
1278 fn rcvr_matches_ty(fcx: @FnCtxt,
1280 candidate: &Candidate) -> bool {
1281 match candidate.rcvr_match_condition {
1282 RcvrMatchesIfObject(_) => {
1285 RcvrMatchesIfSubtype(of_type) => {
1286 fcx.can_mk_subty(rcvr_ty, of_type).is_ok()
1291 fn mutability_matches(self_mutbl: ast::Mutability,
1292 candidate_mutbl: ast::Mutability)
1294 //! True if `self_mutbl <: candidate_mutbl`
1295 self_mutbl == candidate_mutbl
1299 fn report_candidate(&self, idx: uint, origin: &method_origin) {
1301 method_static(impl_did) => {
1302 // If it is an instantiated default method, use the original
1303 // default method for error reporting.
1304 let did = match provided_source(self.tcx(), impl_did) {
1308 self.report_static_candidate(idx, did)
1310 method_param(ref mp) => {
1311 self.report_param_candidate(idx, (*mp).trait_id)
1313 method_object(ref mo) => {
1314 self.report_trait_candidate(idx, mo.trait_id)
1319 fn report_static_candidate(&self, idx: uint, did: DefId) {
1320 let span = if did.crate == ast::LOCAL_CRATE {
1322 match self.tcx().items.find(did.node) {
1323 Some(ast_map::NodeMethod(m, _, _)) => m.span,
1324 Some(ast_map::NodeTraitMethod(trait_method, _, _)) => {
1325 match *trait_method {
1326 ast::Provided(m) => m.span,
1328 fail!("report_static_candidate, bad item {:?}",
1333 _ => fail!("report_static_candidate: bad item {:?}", did)
1339 self.tcx().sess.span_note(
1341 format!("candidate \\#{} is `{}`",
1343 ty::item_path_str(self.tcx(), did)));
1346 fn report_param_candidate(&self, idx: uint, did: DefId) {
1347 self.tcx().sess.span_note(
1349 format!("candidate \\#{} derives from the bound `{}`",
1351 ty::item_path_str(self.tcx(), did)));
1354 fn report_trait_candidate(&self, idx: uint, did: DefId) {
1355 self.tcx().sess.span_note(
1357 format!("candidate \\#{} derives from the type of the receiver, \
1358 which is the trait `{}`",
1360 ty::item_path_str(self.tcx(), did)));
1363 fn infcx(&self) -> @infer::InferCtxt {
1367 fn tcx(&self) -> ty::ctxt {
1371 fn ty_to_str(&self, t: ty::t) -> ~str {
1372 self.fcx.infcx().ty_to_str(t)
1375 fn cand_to_str(&self, cand: &Candidate) -> ~str {
1376 format!("Candidate(rcvr_ty={}, rcvr_substs={}, origin={:?})",
1377 cand.rcvr_match_condition.repr(self.tcx()),
1378 ty::substs_to_str(self.tcx(), &cand.rcvr_substs),
1382 fn did_to_str(&self, did: DefId) -> ~str {
1383 ty::item_path_str(self.tcx(), did)
1386 fn bug(&self, s: ~str) -> ! {
1387 self.tcx().sess.span_bug(self.self_expr.span, s)
1391 impl Repr for RcvrMatchCondition {
1392 fn repr(&self, tcx: ty::ctxt) -> ~str {
1394 RcvrMatchesIfObject(d) => {
1395 format!("RcvrMatchesIfObject({})", d.repr(tcx))
1397 RcvrMatchesIfSubtype(t) => {
1398 format!("RcvrMatchesIfSubtype({})", t.repr(tcx))