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;
86 use middle::typeck::astconv::AstConv;
87 use middle::typeck::check::{FnCtxt, impl_self_ty};
88 use middle::typeck::check::{structurally_resolved_type};
89 use middle::typeck::check::vtable;
90 use middle::typeck::check;
91 use middle::typeck::infer;
92 use middle::typeck::MethodCallee;
93 use middle::typeck::{MethodOrigin, MethodParam};
94 use middle::typeck::{MethodStatic, MethodObject};
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 collections::HashSet;
104 use syntax::ast::{DefId, SelfValue, SelfRegion};
105 use syntax::ast::{SelfUniq, SelfStatic};
106 use syntax::ast::{MutMutable, MutImmutable};
108 use syntax::parse::token;
111 pub enum CheckTraitsFlag {
113 CheckTraitsAndInherentMethods,
117 pub enum AutoderefReceiverFlag {
119 DontAutoderefReceiver,
125 // In a call `a.b::<X, Y, ...>(...)`:
126 expr: &ast::Expr, // The expression `a.b(...)`.
127 self_expr: &ast::Expr, // The expression `a`.
128 m_name: ast::Name, // The name `b`.
129 self_ty: ty::t, // The type of `a`.
130 supplied_tps: &[ty::t], // The list of types X, Y, ... .
131 deref_args: check::DerefArgs, // Whether we autopointer first.
132 check_traits: CheckTraitsFlag, // Whether we check traits only.
133 autoderef_receiver: AutoderefReceiverFlag)
134 -> Option<MethodCallee> {
135 let lcx = LookupContext {
138 self_expr: self_expr,
140 supplied_tps: supplied_tps,
141 impl_dups: @RefCell::new(HashSet::new()),
142 inherent_candidates: @RefCell::new(~[]),
143 extension_candidates: @RefCell::new(~[]),
144 deref_args: deref_args,
145 check_traits: check_traits,
146 autoderef_receiver: autoderef_receiver,
149 let self_ty = structurally_resolved_type(fcx, self_expr.span, self_ty);
150 debug!("method lookup(self_ty={}, expr={}, self_expr={})",
151 self_ty.repr(fcx.tcx()), expr.repr(fcx.tcx()),
152 self_expr.repr(fcx.tcx()));
154 debug!("searching inherent candidates");
155 lcx.push_inherent_candidates(self_ty);
156 let mme = lcx.search(self_ty);
161 debug!("searching extension candidates");
162 lcx.reset_candidates();
163 lcx.push_bound_candidates(self_ty, None);
164 lcx.push_extension_candidates();
165 return lcx.search(self_ty);
168 pub fn lookup_in_trait(
171 // In a call `a.b::<X, Y, ...>(...)`:
172 expr: &ast::Expr, // The expression `a.b(...)`.
173 self_expr: &ast::Expr, // The expression `a`.
174 m_name: ast::Name, // The name `b`.
175 trait_did: DefId, // The trait to limit the lookup to.
176 self_ty: ty::t, // The type of `a`.
177 supplied_tps: &[ty::t], // The list of types X, Y, ... .
178 autoderef_receiver: AutoderefReceiverFlag)
179 -> Option<MethodCallee> {
180 let lcx = LookupContext {
183 self_expr: self_expr,
185 supplied_tps: supplied_tps,
186 impl_dups: @RefCell::new(HashSet::new()),
187 inherent_candidates: @RefCell::new(~[]),
188 extension_candidates: @RefCell::new(~[]),
189 deref_args: check::DoDerefArgs,
190 check_traits: CheckTraitsOnly,
191 autoderef_receiver: autoderef_receiver,
194 let self_ty = structurally_resolved_type(fcx, self_expr.span, self_ty);
195 debug!("method lookup_in_trait(self_ty={}, expr={}, self_expr={})",
196 self_ty.repr(fcx.tcx()), expr.repr(fcx.tcx()),
197 self_expr.repr(fcx.tcx()));
199 lcx.push_bound_candidates(self_ty, Some(trait_did));
200 lcx.push_extension_candidate(trait_did);
204 pub struct LookupContext<'a> {
207 self_expr: &'a ast::Expr,
209 supplied_tps: &'a [ty::t],
210 impl_dups: @RefCell<HashSet<DefId>>,
211 inherent_candidates: @RefCell<~[Candidate]>,
212 extension_candidates: @RefCell<~[Candidate]>,
213 deref_args: check::DerefArgs,
214 check_traits: CheckTraitsFlag,
215 autoderef_receiver: AutoderefReceiverFlag,
219 * A potential method that might be called, assuming the receiver
220 * is of a suitable type.
223 pub struct Candidate {
224 rcvr_match_condition: RcvrMatchCondition,
225 rcvr_substs: ty::substs,
226 method_ty: @ty::Method,
227 origin: MethodOrigin,
230 /// This type represents the conditions under which the receiver is
231 /// considered to "match" a given method candidate. Typically the test
232 /// is whether the receiver is of a particular type. However, this
233 /// type is the type of the receiver *after accounting for the
234 /// method's self type* (e.g., if the method is an `~self` method, we
235 /// have *already verified* that the receiver is of some type `~T` and
236 /// now we must check that the type `T` is correct). Unfortunately,
237 /// because traits are not types, this is a pain to do.
239 pub enum RcvrMatchCondition {
240 RcvrMatchesIfObject(ast::DefId),
241 RcvrMatchesIfSubtype(ty::t)
244 impl<'a> LookupContext<'a> {
245 fn search(&self, self_ty: ty::t) -> Option<MethodCallee> {
246 let mut self_ty = self_ty;
247 let mut autoderefs = 0;
249 debug!("loop: self_ty={} autoderefs={}",
250 self.ty_to_str(self_ty), autoderefs);
252 match self.deref_args {
253 check::DontDerefArgs => {
254 match self.search_for_autoderefd_method(self_ty,
256 Some(mme) => { return Some(mme); }
260 match self.search_for_autoptrd_method(self_ty,
262 Some(mme) => { return Some(mme); }
266 check::DoDerefArgs => {
267 match self.search_for_autoptrd_method(self_ty,
269 Some(mme) => { return Some(mme); }
273 match self.search_for_autoderefd_method(self_ty,
275 Some(mme) => { return Some(mme); }
281 // Don't autoderef if we aren't supposed to.
282 if self.autoderef_receiver == DontAutoderefReceiver {
286 // Otherwise, perform autoderef.
287 match self.deref(self_ty) {
296 self.search_for_autosliced_method(self_ty, autoderefs)
299 fn deref(&self, ty: ty::t) -> Option<ty::t> {
300 match ty::deref(ty, false) {
303 Some(structurally_resolved_type(self.fcx,
310 // ______________________________________________________________________
311 // Candidate collection (see comment at start of file)
313 fn reset_candidates(&self) {
314 self.inherent_candidates.set(~[]);
315 self.extension_candidates.set(~[]);
318 fn push_inherent_candidates(&self, self_ty: ty::t) {
320 * Collect all inherent candidates into
321 * `self.inherent_candidates`. See comment at the start of
322 * the file. To find the inherent candidates, we repeatedly
323 * deref the self-ty to find the "base-type". So, for
324 * example, if the receiver is @@C where `C` is a struct type,
325 * we'll want to find the inherent impls for `C`.
328 let mut self_ty = self_ty;
330 match get(self_ty).sty {
331 ty_trait(did, ref substs, _, _, _) => {
332 self.push_inherent_candidates_from_object(did, substs);
333 self.push_inherent_impl_candidates_for_type(did);
335 ty_enum(did, _) | ty_struct(did, _) => {
336 if self.check_traits == CheckTraitsAndInherentMethods {
337 self.push_inherent_impl_candidates_for_type(did);
340 _ => { /* No inherent methods in these types */ }
343 // n.b.: Generally speaking, we only loop if we hit the
344 // fallthrough case in the match above. The exception
345 // would be newtype enums.
346 self_ty = match self.deref(self_ty) {
353 fn push_bound_candidates(&self, self_ty: ty::t, restrict_to: Option<DefId>) {
354 let mut self_ty = self_ty;
356 match get(self_ty).sty {
358 self.push_inherent_candidates_from_param(self_ty, restrict_to, p);
361 // Call is of the form "self.foo()" and appears in one
362 // of a trait's default method implementations.
363 self.push_inherent_candidates_from_self(self_ty, restrict_to);
365 _ => { /* No bound methods in these types */ }
368 self_ty = match self.deref(self_ty) {
375 fn push_extension_candidate(&self, trait_did: DefId) {
376 ty::populate_implementations_for_trait_if_necessary(self.tcx(), trait_did);
378 // Look for explicit implementations.
379 let trait_impls = self.tcx().trait_impls.borrow();
380 for impl_infos in trait_impls.get().find(&trait_did).iter() {
381 for impl_info in impl_infos.borrow().get().iter() {
382 self.push_candidates_from_impl(
383 self.extension_candidates.borrow_mut().get(), *impl_info);
388 fn push_extension_candidates(&self) {
389 // If the method being called is associated with a trait, then
390 // find all the impls of that trait. Each of those are
392 let opt_applicable_traits = self.fcx.ccx.trait_map.find(&self.expr.id);
393 for applicable_traits in opt_applicable_traits.move_iter() {
394 for trait_did in applicable_traits.iter() {
395 self.push_extension_candidate(*trait_did);
400 // Determine the index of a method in the list of all methods belonging
401 // to a trait and its supertraits.
402 fn get_method_index(&self,
403 trait_ref: @TraitRef,
405 n_method: uint) -> uint {
406 let tcx = self.tcx();
408 // We need to figure the "real index" of the method in a
409 // listing of all the methods of an object. We do this by
410 // iterating down the supertraits of the object's trait until
411 // we find the trait the method came from, counting up the
412 // methods from them.
413 let mut method_count = 0;
414 ty::each_bound_trait_and_supertraits(tcx, &[subtrait], |bound_ref| {
415 if bound_ref.def_id == trait_ref.def_id { false }
417 method_count += ty::trait_methods(tcx, bound_ref.def_id).len();
421 return method_count + n_method;
425 fn push_inherent_candidates_from_object(&self,
427 substs: &ty::substs) {
428 debug!("push_inherent_candidates_from_object(did={}, substs={})",
429 self.did_to_str(did),
430 substs_to_str(self.tcx(), substs));
431 let _indenter = indenter();
433 // It is illegal to invoke a method on a trait instance that
434 // refers to the `self` type. An error will be reported by
435 // `enforce_object_limitations()` if the method refers
436 // to the `Self` type. Substituting ty_err here allows
437 // compiler to soldier on.
439 // `confirm_candidate()` also relies upon this substitution
441 let rcvr_substs = substs {
442 self_ty: Some(ty::mk_err()),
445 let trait_ref = @TraitRef { def_id: did, substs: rcvr_substs.clone() };
447 self.push_inherent_candidates_from_bounds_inner(&[trait_ref],
448 |new_trait_ref, m, method_num, _bound_num| {
450 self.get_method_index(new_trait_ref, trait_ref, method_num);
451 let mut m = (*m).clone();
452 // We need to fix up the transformed self type.
453 m.fty.sig.inputs[0] =
454 self.construct_transformed_self_ty_for_object(
455 did, &rcvr_substs, &m);
458 rcvr_match_condition: RcvrMatchesIfObject(did),
459 rcvr_substs: new_trait_ref.substs.clone(),
461 origin: MethodObject(MethodObject {
462 trait_id: new_trait_ref.def_id,
463 object_trait_id: did,
464 method_num: method_num,
465 real_index: vtable_index
471 fn push_inherent_candidates_from_param(&self,
473 restrict_to: Option<DefId>,
474 param_ty: param_ty) {
475 debug!("push_inherent_candidates_from_param(param_ty={:?})",
477 self.push_inherent_candidates_from_bounds(
479 self.fcx.inh.param_env.type_param_bounds[param_ty.idx].trait_bounds,
481 param_numbered(param_ty.idx));
485 fn push_inherent_candidates_from_self(&self,
487 restrict_to: Option<DefId>) {
488 debug!("push_inherent_candidates_from_self()");
489 self.push_inherent_candidates_from_bounds(
491 [self.fcx.inh.param_env.self_param_bound.unwrap()],
496 fn push_inherent_candidates_from_bounds(&self,
498 bounds: &[@TraitRef],
499 restrict_to: Option<DefId>,
500 param: param_index) {
501 self.push_inherent_candidates_from_bounds_inner(bounds,
502 |trait_ref, m, method_num, bound_num| {
505 if trait_did != trait_ref.def_id {
512 rcvr_match_condition: RcvrMatchesIfSubtype(self_ty),
513 rcvr_substs: trait_ref.substs.clone(),
515 origin: MethodParam(MethodParam {
516 trait_id: trait_ref.def_id,
517 method_num: method_num,
519 bound_num: bound_num,
525 // Do a search through a list of bounds, using a callback to actually
526 // create the candidates.
527 fn push_inherent_candidates_from_bounds_inner(&self,
528 bounds: &[@TraitRef],
529 mk_cand: |tr: @TraitRef,
533 -> Option<Candidate>) {
534 let tcx = self.tcx();
535 let mut next_bound_idx = 0; // count only trait bounds
537 ty::each_bound_trait_and_supertraits(tcx, bounds, |bound_trait_ref| {
538 let this_bound_idx = next_bound_idx;
541 let trait_methods = ty::trait_methods(tcx, bound_trait_ref.def_id);
542 match trait_methods.iter().position(|m| {
543 m.explicit_self != ast::SelfStatic &&
544 m.ident.name == self.m_name })
547 let method = trait_methods[pos];
549 match mk_cand(bound_trait_ref, method, pos, this_bound_idx) {
551 debug!("pushing inherent candidate for param: {:?}", cand);
552 self.inherent_candidates.borrow_mut().get().push(cand);
558 debug!("trait doesn't contain method: {:?}",
559 bound_trait_ref.def_id);
560 // check next trait or bound
568 fn push_inherent_impl_candidates_for_type(&self, did: DefId) {
569 // Read the inherent implementation candidates for this type from the
570 // metadata if necessary.
571 ty::populate_implementations_for_type_if_necessary(self.tcx(), did);
573 let inherent_impls = self.tcx().inherent_impls.borrow();
574 let opt_impl_infos = inherent_impls.get().find(&did);
575 for impl_infos in opt_impl_infos.iter() {
576 let impl_infos = impl_infos.borrow();
577 for impl_info in impl_infos.get().iter() {
578 let mut inherent_candidates = self.inherent_candidates
580 self.push_candidates_from_impl(inherent_candidates.get(),
586 fn push_candidates_from_impl(&self,
587 candidates: &mut ~[Candidate],
588 impl_info: &ty::Impl) {
590 let mut impl_dups = self.impl_dups.borrow_mut();
591 if !impl_dups.get().insert(impl_info.did) {
592 return; // already visited
596 debug!("push_candidates_from_impl: {} {} {}",
597 token::get_name(self.m_name),
598 impl_info.ident.repr(self.tcx()),
599 impl_info.methods.map(|m| m.ident).repr(self.tcx()));
602 match impl_info.methods.iter().position(|m| m.ident.name == self.m_name) {
604 None => { return; } // No method with the right name.
608 let method = ty::method(self.tcx(), impl_info.methods[idx].def_id);
610 // determine the `self` of the impl with fresh
611 // variables for each parameter:
612 let location_info = &vtable::location_info_for_expr(self.self_expr);
613 let vcx = self.fcx.vtable_context();
614 let ty::ty_param_substs_and_ty {
617 } = impl_self_ty(&vcx, location_info, impl_info.did);
619 candidates.push(Candidate {
620 rcvr_match_condition: RcvrMatchesIfSubtype(impl_ty),
621 rcvr_substs: impl_substs,
623 origin: MethodStatic(method.def_id)
627 // ______________________________________________________________________
628 // Candidate selection (see comment at start of file)
630 fn search_for_autoderefd_method(&self,
633 -> Option<MethodCallee> {
634 let (self_ty, autoadjust) =
635 self.consider_reborrow(self_ty, autoderefs);
636 match self.search_for_method(self_ty) {
639 debug!("(searching for autoderef'd method) writing \
640 adjustment ({}) to {}",
643 self.fcx.write_adjustment(self.self_expr.id, @autoadjust);
649 fn consider_reborrow(&self,
652 -> (ty::t, ty::AutoAdjustment) {
654 * In the event that we are invoking a method with a receiver
655 * of a borrowed type like `&T`, `&mut T`, or `&mut [T]`,
656 * we will "reborrow" the receiver implicitly. For example, if
657 * you have a call `r.inc()` and where `r` has type `&mut T`,
658 * then we treat that like `(&mut *r).inc()`. This avoids
659 * consuming the original pointer.
661 * You might think that this would be a natural byproduct of
662 * the auto-deref/auto-ref process. This is true for `~T`
663 * but not for an `&mut T` receiver. With `~T`, we would
664 * begin by testing for methods with a self type `~T`,
665 * then autoderef to `T`, then autoref to `&mut T`. But with
666 * an `&mut T` receiver the process begins with `&mut T`, only
667 * without any autoadjustments.
670 let tcx = self.tcx();
671 return match ty::get(self_ty).sty {
672 ty::ty_rptr(_, self_mt) if default_method_hack(self_mt) => {
674 ty::AutoDerefRef(ty::AutoDerefRef {
675 autoderefs: autoderefs,
678 ty::ty_rptr(_, self_mt) => {
680 self.infcx().next_region_var(
681 infer::Autoref(self.expr.span));
682 (ty::mk_rptr(tcx, region, self_mt),
683 ty::AutoDerefRef(ty::AutoDerefRef {
684 autoderefs: autoderefs+1,
685 autoref: Some(ty::AutoPtr(region, self_mt.mutbl))}))
687 ty::ty_vec(self_mt, vstore_slice(_)) => {
689 self.infcx().next_region_var(
690 infer::Autoref(self.expr.span));
691 (ty::mk_vec(tcx, self_mt, vstore_slice(region)),
692 ty::AutoDerefRef(ty::AutoDerefRef {
693 autoderefs: autoderefs,
694 autoref: Some(ty::AutoBorrowVec(region, self_mt.mutbl))}))
696 ty_trait(did, ref substs, ty::RegionTraitStore(_), mutbl, bounds) => {
698 self.infcx().next_region_var(
699 infer::Autoref(self.expr.span));
700 (ty::mk_trait(tcx, did, substs.clone(),
701 ty::RegionTraitStore(region),
703 ty::AutoDerefRef(ty::AutoDerefRef {
704 autoderefs: autoderefs,
705 autoref: Some(ty::AutoBorrowObj(region, mutbl))}))
709 ty::AutoDerefRef(ty::AutoDerefRef {
710 autoderefs: autoderefs,
715 fn default_method_hack(self_mt: ty::mt) -> bool {
716 // FIXME(#6129). Default methods can't deal with autoref.
718 // I am a horrible monster and I pray for death. Currently
719 // the default method code fails when you try to reborrow
720 // because it is not handling types correctly. In lieu of
721 // fixing that, I am introducing this horrible hack. - ndm
722 self_mt.mutbl == MutImmutable && ty::type_is_self(self_mt.ty)
726 fn search_for_autosliced_method(&self,
729 -> Option<MethodCallee> {
732 * Searches for a candidate by converting things like
735 let tcx = self.tcx();
736 let sty = ty::get(self_ty).sty.clone();
738 ty_vec(mt, vstore_uniq) |
739 ty_vec(mt, vstore_slice(_)) | // NDM(#3148)
740 ty_vec(mt, vstore_fixed(_)) => {
741 // First try to borrow to a slice
742 let entry = self.search_for_some_kind_of_autorefd_method(
743 AutoBorrowVec, autoderefs, [MutImmutable, MutMutable],
744 |m,r| ty::mk_vec(tcx,
745 ty::mt {ty:mt.ty, mutbl:m},
748 if entry.is_some() { return entry; }
750 // Then try to borrow to a slice *and* borrow a pointer.
751 self.search_for_some_kind_of_autorefd_method(
752 AutoBorrowVecRef, autoderefs, [MutImmutable, MutMutable],
754 let slice_ty = ty::mk_vec(tcx,
755 ty::mt {ty:mt.ty, mutbl:m},
757 // NB: we do not try to autoref to a mutable
758 // pointer. That would be creating a pointer
759 // to a temporary pointer (the borrowed
760 // slice), so any update the callee makes to
761 // it can't be observed.
762 ty::mk_rptr(tcx, r, ty::mt {ty:slice_ty, mutbl:MutImmutable})
766 ty_str(vstore_uniq) |
767 ty_str(vstore_fixed(_)) => {
768 let entry = self.search_for_some_kind_of_autorefd_method(
769 AutoBorrowVec, autoderefs, [MutImmutable],
770 |_m,r| ty::mk_str(tcx, vstore_slice(r)));
772 if entry.is_some() { return entry; }
774 self.search_for_some_kind_of_autorefd_method(
775 AutoBorrowVecRef, autoderefs, [MutImmutable],
777 let slice_ty = ty::mk_str(tcx, vstore_slice(r));
778 ty::mk_rptr(tcx, r, ty::mt {ty:slice_ty, mutbl:m})
782 ty_trait(trt_did, trt_substs, _, _, b) => {
783 // Coerce ~/@/&Trait instances to &Trait.
785 self.search_for_some_kind_of_autorefd_method(
786 AutoBorrowObj, autoderefs, [MutImmutable, MutMutable],
788 ty::mk_trait(tcx, trt_did, trt_substs.clone(),
789 RegionTraitStore(reg), trt_mut, b)
794 // This case should probably be handled similarly to
803 fn search_for_autoptrd_method(&self, self_ty: ty::t, autoderefs: uint)
804 -> Option<MethodCallee> {
807 * Converts any type `T` to `&M T` where `M` is an
808 * appropriate mutability.
811 let tcx = self.tcx();
812 match ty::get(self_ty).sty {
813 ty_bare_fn(..) | ty_box(..) | ty_uniq(..) | ty_rptr(..) |
814 ty_infer(IntVar(_)) |
815 ty_infer(FloatVar(_)) |
816 ty_self(_) | ty_param(..) | ty_nil | ty_bot | ty_bool |
817 ty_char | ty_int(..) | ty_uint(..) |
818 ty_float(..) | ty_enum(..) | ty_ptr(..) | ty_struct(..) | ty_tup(..) |
819 ty_str(..) | ty_vec(..) | ty_trait(..) | ty_closure(..) => {
820 self.search_for_some_kind_of_autorefd_method(
821 AutoPtr, autoderefs, [MutImmutable, MutMutable],
822 |m,r| ty::mk_rptr(tcx, r, ty::mt {ty:self_ty, mutbl:m}))
827 ty_unboxed_vec(_) | ty_infer(TyVar(_)) => {
828 self.bug(format!("unexpected type: {}",
829 self.ty_to_str(self_ty)));
834 fn search_for_some_kind_of_autorefd_method(
836 kind: |Region, ast::Mutability| -> ty::AutoRef,
838 mutbls: &[ast::Mutability],
839 mk_autoref_ty: |ast::Mutability, ty::Region| -> ty::t)
840 -> Option<MethodCallee> {
841 // This is hokey. We should have mutability inference as a
842 // variable. But for now, try &const, then &, then &mut:
844 self.infcx().next_region_var(
845 infer::Autoref(self.expr.span));
846 for mutbl in mutbls.iter() {
847 let autoref_ty = mk_autoref_ty(*mutbl, region);
848 match self.search_for_method(autoref_ty) {
851 self.fcx.write_adjustment(
853 @ty::AutoDerefRef(ty::AutoDerefRef {
854 autoderefs: autoderefs,
855 autoref: Some(kind(region, *mutbl))}));
863 fn search_for_method(&self, rcvr_ty: ty::t)
864 -> Option<MethodCallee> {
865 debug!("search_for_method(rcvr_ty={})", self.ty_to_str(rcvr_ty));
866 let _indenter = indenter();
868 // I am not sure that inherent methods should have higher
869 // priority, but it is necessary ATM to handle some of the
872 debug!("searching inherent candidates");
873 let mut inherent_candidates = self.inherent_candidates.borrow_mut();
874 match self.consider_candidates(rcvr_ty, inherent_candidates.get()) {
881 debug!("searching extension candidates");
882 let mut extension_candidates = self.extension_candidates.borrow_mut();
883 match self.consider_candidates(rcvr_ty, extension_candidates.get()) {
893 fn consider_candidates(&self,
895 candidates: &mut ~[Candidate])
896 -> Option<MethodCallee> {
897 // FIXME(pcwalton): Do we need to clone here?
898 let relevant_candidates: ~[Candidate] =
899 candidates.iter().map(|c| (*c).clone()).
900 filter(|c| self.is_relevant(rcvr_ty, c)).collect();
902 let relevant_candidates = self.merge_candidates(relevant_candidates);
904 if relevant_candidates.len() == 0 {
908 if relevant_candidates.len() > 1 {
909 self.tcx().sess.span_err(
911 "multiple applicable methods in scope");
912 for (idx, candidate) in relevant_candidates.iter().enumerate() {
913 self.report_candidate(idx, &candidate.origin);
917 Some(self.confirm_candidate(rcvr_ty, &relevant_candidates[0]))
920 fn merge_candidates(&self, candidates: &[Candidate]) -> ~[Candidate] {
921 let mut merged = ~[];
923 while i < candidates.len() {
924 let candidate_a = &candidates[i];
926 let mut skip = false;
929 while j < candidates.len() {
930 let candidate_b = &candidates[j];
931 debug!("attempting to merge {:?} and {:?}",
932 candidate_a, candidate_b);
933 let candidates_same = match (&candidate_a.origin,
934 &candidate_b.origin) {
935 (&MethodParam(ref p1), &MethodParam(ref p2)) => {
936 let same_trait = p1.trait_id == p2.trait_id;
937 let same_method = p1.method_num == p2.method_num;
938 let same_param = p1.param_num == p2.param_num;
939 // The bound number may be different because
940 // multiple bounds may lead to the same trait
942 same_trait && same_method && same_param
956 // There are more than one of these and we need only one
959 merged.push(candidate_a.clone());
966 fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
968 // This method performs two sets of substitutions, one after the other:
969 // 1. Substitute values for any type/lifetime parameters from the impl and
970 // method declaration into the method type. This is the function type
971 // before it is called; it may still include late bound region variables.
972 // 2. Instantiate any late bound lifetime parameters in the method itself
973 // with fresh region variables.
975 let tcx = self.tcx();
977 debug!("confirm_candidate(expr={}, candidate={})",
979 self.cand_to_str(candidate));
981 self.enforce_object_limitations(candidate);
982 self.enforce_drop_trait_limitations(candidate);
984 // static methods should never have gotten this far:
985 assert!(candidate.method_ty.explicit_self != SelfStatic);
987 // Determine the values for the type parameters of the method.
988 // If they were not explicitly supplied, just construct fresh
990 let num_supplied_tps = self.supplied_tps.len();
991 let num_method_tps = candidate.method_ty.generics.type_param_defs().len();
993 if num_supplied_tps == 0u {
994 self.fcx.infcx().next_ty_vars(num_method_tps)
995 } else if num_method_tps == 0u {
998 "this method does not take type parameters");
999 self.fcx.infcx().next_ty_vars(num_method_tps)
1000 } else if num_supplied_tps != num_method_tps {
1003 "incorrect number of type \
1004 parameters given for this method");
1005 self.fcx.infcx().next_ty_vars(num_method_tps)
1007 self.supplied_tps.to_owned()
1011 // Construct the full set of type parameters for the method,
1012 // which is equal to the class tps + the method tps.
1013 let all_substs = substs {
1014 tps: vec::append(candidate.rcvr_substs.tps.clone(), m_substs),
1015 regions: candidate.rcvr_substs.regions.clone(),
1016 self_ty: candidate.rcvr_substs.self_ty,
1019 let ref bare_fn_ty = candidate.method_ty.fty;
1021 // Compute the method type with type parameters substituted
1022 debug!("fty={} all_substs={}",
1023 bare_fn_ty.repr(tcx),
1024 ty::substs_to_str(tcx, &all_substs));
1026 let fn_sig = &bare_fn_ty.sig;
1027 let inputs = match candidate.origin {
1028 MethodObject(..) => {
1029 // For annoying reasons, we've already handled the
1030 // substitution of self for object calls.
1031 let args = fn_sig.inputs.slice_from(1).iter().map(|t| {
1032 t.subst(tcx, &all_substs)
1034 Some(fn_sig.inputs[0]).move_iter().chain(args).collect()
1036 _ => fn_sig.inputs.subst(tcx, &all_substs)
1038 let fn_sig = ty::FnSig {
1039 binder_id: fn_sig.binder_id,
1041 output: fn_sig.output.subst(tcx, &all_substs),
1042 variadic: fn_sig.variadic
1045 debug!("after subst, fty={}", fn_sig.repr(tcx));
1047 // Replace any bound regions that appear in the function
1048 // signature with region variables
1049 let (_, fn_sig) = replace_bound_regions_in_fn_sig( tcx, &fn_sig, |br| {
1050 self.fcx.infcx().next_region_var(
1051 infer::BoundRegionInFnCall(self.expr.span, br))
1053 let transformed_self_ty = fn_sig.inputs[0];
1054 let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
1056 purity: bare_fn_ty.purity,
1057 abis: bare_fn_ty.abis.clone(),
1059 debug!("after replacing bound regions, fty={}", self.ty_to_str(fty));
1061 // before we only checked whether self_ty could be a subtype
1062 // of rcvr_ty; now we actually make it so (this may cause
1063 // variables to unify etc). Since we checked beforehand, and
1064 // nothing has changed in the meantime, this unification
1065 // should never fail.
1066 match self.fcx.mk_subty(false, infer::Misc(self.self_expr.span),
1067 rcvr_ty, transformed_self_ty) {
1070 self.bug(format!("{} was a subtype of {} but now is not?",
1071 self.ty_to_str(rcvr_ty),
1072 self.ty_to_str(transformed_self_ty)));
1077 origin: candidate.origin,
1083 fn construct_transformed_self_ty_for_object(
1085 trait_def_id: ast::DefId,
1086 rcvr_substs: &ty::substs,
1087 method_ty: &ty::Method) -> ty::t
1090 * This is a bit tricky. We have a match against a trait method
1091 * being invoked on an object, and we want to generate the
1092 * self-type. As an example, consider a trait
1095 * fn r_method<'a>(&'a self);
1096 * fn u_method(~self);
1099 * Now, assuming that `r_method` is being called, we want the
1100 * result to be `&'a Foo`. Assuming that `u_method` is being
1101 * called, we want the result to be `~Foo`. Of course,
1102 * this transformation has already been done as part of
1103 * `method_ty.fty.sig.inputs[0]`, but there the type
1104 * is expressed in terms of `Self` (i.e., `&'a Self`, `~Self`).
1105 * Because objects are not standalone types, we can't just substitute
1106 * `s/Self/Foo/`, so we must instead perform this kind of hokey
1110 let substs = ty::substs {regions: rcvr_substs.regions.clone(),
1112 tps: rcvr_substs.tps.clone()};
1113 match method_ty.explicit_self {
1114 ast::SelfStatic => {
1115 self.bug(~"static method for object type receiver");
1118 ty::mk_err() // error reported in `enforce_object_limitations()`
1120 ast::SelfRegion(..) | ast::SelfUniq => {
1121 let transformed_self_ty = method_ty.fty.sig.inputs[0];
1122 match ty::get(transformed_self_ty).sty {
1123 ty::ty_rptr(r, mt) => { // must be SelfRegion
1124 ty::mk_trait(self.tcx(), trait_def_id,
1125 substs, RegionTraitStore(r), mt.mutbl,
1126 ty::EmptyBuiltinBounds())
1128 ty::ty_uniq(_) => { // must be SelfUniq
1129 ty::mk_trait(self.tcx(), trait_def_id,
1130 substs, UniqTraitStore, ast::MutImmutable,
1131 ty::EmptyBuiltinBounds())
1135 format!("'impossible' transformed_self_ty: {}",
1136 transformed_self_ty.repr(self.tcx())));
1143 fn enforce_object_limitations(&self, candidate: &Candidate) {
1145 * There are some limitations to calling functions through an
1146 * object, because (a) the self type is not known
1147 * (that's the whole point of a trait instance, after all, to
1148 * obscure the self type) and (b) the call must go through a
1149 * vtable and hence cannot be monomorphized.
1152 match candidate.origin {
1153 MethodStatic(..) | MethodParam(..) => {
1154 return; // not a call to a trait instance
1156 MethodObject(..) => {}
1159 match candidate.method_ty.explicit_self {
1160 ast::SelfStatic => { // reason (a) above
1161 self.tcx().sess.span_err(
1163 "cannot call a method without a receiver \
1164 through an object");
1167 ast::SelfValue => { // reason (a) above
1168 self.tcx().sess.span_err(
1170 "cannot call a method with a by-value receiver \
1171 through an object");
1174 ast::SelfRegion(..) | ast::SelfUniq => {}
1178 let check_for_self_ty = |ty| {
1179 if ty::type_has_self(ty) {
1180 self.tcx().sess.span_err(
1182 "cannot call a method whose type contains a \
1183 self-type through an object");
1189 let ref sig = candidate.method_ty.fty.sig;
1190 let mut found_self_ty = false;
1191 for &input_ty in sig.inputs.iter() {
1192 if check_for_self_ty(input_ty) {
1193 found_self_ty = true;
1198 check_for_self_ty(sig.output);
1201 if candidate.method_ty.generics.has_type_params() { // reason (b) above
1202 self.tcx().sess.span_err(
1204 "cannot call a generic method through an object");
1208 fn enforce_drop_trait_limitations(&self, candidate: &Candidate) {
1209 // No code can call the finalize method explicitly.
1211 match candidate.origin {
1212 MethodStatic(method_id) => {
1213 let destructors = self.tcx().destructors.borrow();
1214 bad = destructors.get().contains(&method_id);
1216 // FIXME: does this properly enforce this on everything now
1217 // that self has been merged in? -sully
1218 MethodParam(MethodParam { trait_id: trait_id, .. }) |
1219 MethodObject(MethodObject { trait_id: trait_id, .. }) => {
1220 let destructor_for_type = self.tcx()
1221 .destructor_for_type
1223 bad = destructor_for_type.get().contains_key(&trait_id);
1228 self.tcx().sess.span_err(self.expr.span,
1229 "explicit call to destructor");
1233 // `rcvr_ty` is the type of the expression. It may be a subtype of a
1234 // candidate method's `self_ty`.
1235 fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool {
1236 debug!("is_relevant(rcvr_ty={}, candidate={})",
1237 self.ty_to_str(rcvr_ty), self.cand_to_str(candidate));
1239 return match candidate.method_ty.explicit_self {
1241 debug!("(is relevant?) explicit self is static");
1246 rcvr_matches_ty(self.fcx, rcvr_ty, candidate)
1249 SelfRegion(_, m) => {
1250 debug!("(is relevant?) explicit self is a region");
1251 match ty::get(rcvr_ty).sty {
1252 ty::ty_rptr(_, mt) => {
1253 mutability_matches(mt.mutbl, m) &&
1254 rcvr_matches_ty(self.fcx, mt.ty, candidate)
1257 ty::ty_trait(self_did, _, RegionTraitStore(_), self_m, _) => {
1258 mutability_matches(self_m, m) &&
1259 rcvr_matches_object(self_did, candidate)
1267 debug!("(is relevant?) explicit self is a unique pointer");
1268 match ty::get(rcvr_ty).sty {
1269 ty::ty_uniq(typ) => {
1270 rcvr_matches_ty(self.fcx, typ, candidate)
1273 ty::ty_trait(self_did, _, UniqTraitStore, _, _) => {
1274 rcvr_matches_object(self_did, candidate)
1282 fn rcvr_matches_object(self_did: ast::DefId,
1283 candidate: &Candidate) -> bool {
1284 match candidate.rcvr_match_condition {
1285 RcvrMatchesIfObject(desired_did) => {
1286 self_did == desired_did
1288 RcvrMatchesIfSubtype(_) => {
1294 fn rcvr_matches_ty(fcx: @FnCtxt,
1296 candidate: &Candidate) -> bool {
1297 match candidate.rcvr_match_condition {
1298 RcvrMatchesIfObject(_) => {
1301 RcvrMatchesIfSubtype(of_type) => {
1302 fcx.can_mk_subty(rcvr_ty, of_type).is_ok()
1307 fn mutability_matches(self_mutbl: ast::Mutability,
1308 candidate_mutbl: ast::Mutability)
1310 //! True if `self_mutbl <: candidate_mutbl`
1311 self_mutbl == candidate_mutbl
1315 fn report_candidate(&self, idx: uint, origin: &MethodOrigin) {
1317 MethodStatic(impl_did) => {
1318 // If it is an instantiated default method, use the original
1319 // default method for error reporting.
1320 let did = match provided_source(self.tcx(), impl_did) {
1324 self.report_static_candidate(idx, did)
1326 MethodParam(ref mp) => {
1327 self.report_param_candidate(idx, (*mp).trait_id)
1329 MethodObject(ref mo) => {
1330 self.report_trait_candidate(idx, mo.trait_id)
1335 fn report_static_candidate(&self, idx: uint, did: DefId) {
1336 let span = if did.krate == ast::LOCAL_CRATE {
1337 self.tcx().map.span(did.node)
1341 self.tcx().sess.span_note(
1343 format!("candidate \\#{} is `{}`",
1345 ty::item_path_str(self.tcx(), did)));
1348 fn report_param_candidate(&self, idx: uint, did: DefId) {
1349 self.tcx().sess.span_note(
1351 format!("candidate \\#{} derives from the bound `{}`",
1353 ty::item_path_str(self.tcx(), did)));
1356 fn report_trait_candidate(&self, idx: uint, did: DefId) {
1357 self.tcx().sess.span_note(
1359 format!("candidate \\#{} derives from the type of the receiver, \
1360 which is the trait `{}`",
1362 ty::item_path_str(self.tcx(), did)));
1365 fn infcx(&'a self) -> &'a infer::InferCtxt {
1369 fn tcx(&self) -> ty::ctxt {
1373 fn ty_to_str(&self, t: ty::t) -> ~str {
1374 self.fcx.infcx().ty_to_str(t)
1377 fn cand_to_str(&self, cand: &Candidate) -> ~str {
1378 format!("Candidate(rcvr_ty={}, rcvr_substs={}, origin={:?})",
1379 cand.rcvr_match_condition.repr(self.tcx()),
1380 ty::substs_to_str(self.tcx(), &cand.rcvr_substs),
1384 fn did_to_str(&self, did: DefId) -> ~str {
1385 ty::item_path_str(self.tcx(), did)
1388 fn bug(&self, s: ~str) -> ! {
1389 self.tcx().sess.span_bug(self.self_expr.span, s)
1393 impl Repr for RcvrMatchCondition {
1394 fn repr(&self, tcx: ty::ctxt) -> ~str {
1396 RcvrMatchesIfObject(d) => {
1397 format!("RcvrMatchesIfObject({})", d.repr(tcx))
1399 RcvrMatchesIfSubtype(t) => {
1400 format!("RcvrMatchesIfSubtype({})", t.repr(tcx))