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.
4 //
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.
10
11 /*!
12
13 # Method lookup
14
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
18 candidate selection.
19
20 ## Candidate collection
21
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).
31
32 Inherent candidates are not always derived from impls. If you have a
33 trait instance, such as a value of type `Box<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
36 bounds are inherent.
37
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.
44
45 For better or worse, we currently give weight to inherent methods over
46 extension methods during candidate selection (below).
47
48 ## Candidate selection
49
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.
58
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
66 sliceable).
67
68 ## Why two phases?
69
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.
79
80 */
81
82
83 use middle::subst::Subst;
84 use middle::ty::*;
85 use middle::ty;
86 use middle::typeck::astconv::AstConv;
87 use middle::typeck::check::{FnCtxt, PreferMutLvalue, impl_self_ty};
88 use middle::typeck::check;
89 use middle::typeck::infer;
90 use middle::typeck::MethodCallee;
91 use middle::typeck::{MethodOrigin, MethodParam};
92 use middle::typeck::{MethodStatic, MethodObject};
93 use middle::typeck::{param_numbered, param_self, param_index};
94 use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
95 use util::common::indenter;
96 use util::ppaux;
97 use util::ppaux::Repr;
98
99 use collections::HashSet;
100 use std::rc::Rc;
101 use syntax::ast::{DefId, SelfValue, SelfRegion};
102 use syntax::ast::{SelfUniq, SelfStatic};
103 use syntax::ast::{MutMutable, MutImmutable};
104 use syntax::ast;
105 use syntax::codemap::Span;
106 use syntax::parse::token;
107 use syntax::owned_slice::OwnedSlice;
108
109 #[deriving(Eq)]
110 pub enum CheckTraitsFlag {
111 CheckTraitsOnly,
112 CheckTraitsAndInherentMethods,
113 }
114
115 #[deriving(Eq)]
116 pub enum AutoderefReceiverFlag {
117 AutoderefReceiver,
118 DontAutoderefReceiver,
119 }
120
121 #[deriving(Eq)]
122 pub enum StaticMethodsFlag {
123 ReportStaticMethods,
124 IgnoreStaticMethods,
125 }
126
127 pub fn lookup<'a>(
128 fcx: &'a FnCtxt<'a>,
129
130 // In a call `a.b::<X, Y, ...>(...)`:
131 expr: &ast::Expr, // The expression `a.b(...)`.
132 self_expr: &'a ast::Expr, // The expression `a`.
133 m_name: ast::Name, // The name `b`.
134 self_ty: ty::t, // The type of `a`.
135 supplied_tps: &'a [ty::t], // The list of types X, Y, ... .
136 deref_args: check::DerefArgs, // Whether we autopointer first.
137 check_traits: CheckTraitsFlag, // Whether we check traits only.
138 autoderef_receiver: AutoderefReceiverFlag,
139 report_statics: StaticMethodsFlag)
140 -> Option<MethodCallee> {
141 let mut lcx = LookupContext {
142 fcx: fcx,
143 span: expr.span,
144 self_expr: Some(self_expr),
145 m_name: m_name,
146 supplied_tps: supplied_tps,
147 impl_dups: HashSet::new(),
148 inherent_candidates: Vec::new(),
149 extension_candidates: Vec::new(),
150 deref_args: deref_args,
151 check_traits: check_traits,
152 autoderef_receiver: autoderef_receiver,
153 report_statics: report_statics,
154 };
155
156 debug!("method lookup(self_ty={}, expr={}, self_expr={})",
157 self_ty.repr(fcx.tcx()), expr.repr(fcx.tcx()),
158 self_expr.repr(fcx.tcx()));
159
160 debug!("searching inherent candidates");
161 lcx.push_inherent_candidates(self_ty);
162 let mme = lcx.search(self_ty);
163 if mme.is_some() {
164 return mme;
165 }
166
167 debug!("searching extension candidates");
168 lcx.reset_candidates();
169 lcx.push_bound_candidates(self_ty, None);
170 lcx.push_extension_candidates(expr.id);
171 lcx.search(self_ty)
172 }
173
174 pub fn lookup_in_trait<'a>(
175 fcx: &'a FnCtxt<'a>,
176
177 // In a call `a.b::<X, Y, ...>(...)`:
178 span: Span, // The expression `a.b(...)`'s span.
179 self_expr: Option<&'a ast::Expr>, // The expression `a`, if available.
180 m_name: ast::Name, // The name `b`.
181 trait_did: DefId, // The trait to limit the lookup to.
182 self_ty: ty::t, // The type of `a`.
183 supplied_tps: &'a [ty::t], // The list of types X, Y, ... .
184 autoderef_receiver: AutoderefReceiverFlag,
185 report_statics: StaticMethodsFlag)
186 -> Option<MethodCallee> {
187 let mut lcx = LookupContext {
188 fcx: fcx,
189 span: span,
190 self_expr: self_expr,
191 m_name: m_name,
192 supplied_tps: supplied_tps,
193 impl_dups: HashSet::new(),
194 inherent_candidates: Vec::new(),
195 extension_candidates: Vec::new(),
196 deref_args: check::DoDerefArgs,
197 check_traits: CheckTraitsOnly,
198 autoderef_receiver: autoderef_receiver,
199 report_statics: report_statics,
200 };
201
202 debug!("method lookup_in_trait(self_ty={}, self_expr={})",
203 self_ty.repr(fcx.tcx()), self_expr.map(|e| e.repr(fcx.tcx())));
204
205 lcx.push_bound_candidates(self_ty, Some(trait_did));
206 lcx.push_extension_candidate(trait_did);
207 lcx.search(self_ty)
208 }
209
210 // Determine the index of a method in the list of all methods belonging
211 // to a trait and its supertraits.
212 fn get_method_index(tcx: &ty::ctxt,
213 trait_ref: &TraitRef,
214 subtrait: Rc<TraitRef>,
215 n_method: uint) -> uint {
216 // We need to figure the "real index" of the method in a
217 // listing of all the methods of an object. We do this by
218 // iterating down the supertraits of the object's trait until
219 // we find the trait the method came from, counting up the
220 // methods from them.
221 let mut method_count = 0;
222 ty::each_bound_trait_and_supertraits(tcx, &[subtrait], |bound_ref| {
223 if bound_ref.def_id == trait_ref.def_id { false }
224 else {
225 method_count += ty::trait_methods(tcx, bound_ref.def_id).len();
226 true
227 }
228 });
229 method_count + n_method
230 }
231
232 fn construct_transformed_self_ty_for_object(
233 tcx: &ty::ctxt,
234 span: Span,
235 trait_def_id: ast::DefId,
236 rcvr_substs: &ty::substs,
237 method_ty: &ty::Method)
238 -> ty::t {
239 /*!
240 * This is a bit tricky. We have a match against a trait method
241 * being invoked on an object, and we want to generate the
242 * self-type. As an example, consider a trait
243 *
244 * trait Foo {
245 * fn r_method<'a>(&'a self);
246 * fn u_method(Box<self>);
247 * }
248 *
249 * Now, assuming that `r_method` is being called, we want the
250 * result to be `&'a Foo`. Assuming that `u_method` is being
251 * called, we want the result to be `Box<Foo>`. Of course,
252 * this transformation has already been done as part of
253 * `method_ty.fty.sig.inputs[0]`, but there the type
254 * is expressed in terms of `Self` (i.e., `&'a Self`, `Box<Self>`).
255 * Because objects are not standalone types, we can't just substitute
256 * `s/Self/Foo/`, so we must instead perform this kind of hokey
257 * match below.
258 */
259
260 let substs = ty::substs {regions: rcvr_substs.regions.clone(),
261 self_ty: None,
262 tps: rcvr_substs.tps.clone()};
263 match method_ty.explicit_self {
264 ast::SelfStatic => {
265 tcx.sess.span_bug(span, "static method for object type receiver");
266 }
267 ast::SelfValue => {
268 ty::mk_err() // error reported in `enforce_object_limitations()`
269 }
270 ast::SelfRegion(..) | ast::SelfUniq => {
271 let transformed_self_ty = *method_ty.fty.sig.inputs.get(0);
272 match ty::get(transformed_self_ty).sty {
273 ty::ty_rptr(r, mt) => { // must be SelfRegion
274 let r = r.subst(tcx, &substs); // handle Early-Bound lifetime
275 ty::mk_trait(tcx, trait_def_id, substs,
276 RegionTraitStore(r, mt.mutbl),
277 ty::EmptyBuiltinBounds())
278 }
279 ty::ty_uniq(_) => { // must be SelfUniq
280 ty::mk_trait(tcx, trait_def_id, substs,
281 UniqTraitStore,
282 ty::EmptyBuiltinBounds())
283 }
284 _ => {
285 tcx.sess.span_bug(span,
286 format!("'impossible' transformed_self_ty: {}",
287 transformed_self_ty.repr(tcx)));
288 }
289 }
290 }
291 }
292 }
293
294 struct LookupContext<'a> {
295 fcx: &'a FnCtxt<'a>,
296 span: Span,
297
298 // The receiver to the method call. Only `None` in the case of
299 // an overloaded autoderef, where the receiver may be an intermediate
300 // state like "the expression `x` when it has been autoderef'd
301 // twice already".
302 self_expr: Option<&'a ast::Expr>,
303
304 m_name: ast::Name,
305 supplied_tps: &'a [ty::t],
306 impl_dups: HashSet<DefId>,
307 inherent_candidates: Vec<Candidate>,
308 extension_candidates: Vec<Candidate>,
309 deref_args: check::DerefArgs,
310 check_traits: CheckTraitsFlag,
311 autoderef_receiver: AutoderefReceiverFlag,
312 report_statics: StaticMethodsFlag,
313 }
314
315 /**
316 * A potential method that might be called, assuming the receiver
317 * is of a suitable type.
318 */
319 #[deriving(Clone)]
320 struct Candidate {
321 rcvr_match_condition: RcvrMatchCondition,
322 rcvr_substs: ty::substs,
323 method_ty: Rc<ty::Method>,
324 origin: MethodOrigin,
325 }
326
327 /// This type represents the conditions under which the receiver is
328 /// considered to "match" a given method candidate. Typically the test
329 /// is whether the receiver is of a particular type. However, this
330 /// type is the type of the receiver *after accounting for the
331 /// method's self type* (e.g., if the method is an `Box<self>` method, we
332 /// have *already verified* that the receiver is of some type `Box<T>` and
333 /// now we must check that the type `T` is correct). Unfortunately,
334 /// because traits are not types, this is a pain to do.
335 #[deriving(Clone)]
336 pub enum RcvrMatchCondition {
337 RcvrMatchesIfObject(ast::DefId),
338 RcvrMatchesIfSubtype(ty::t)
339 }
340
341 impl<'a> LookupContext<'a> {
342 fn search(&self, self_ty: ty::t) -> Option<MethodCallee> {
343 let span = self.self_expr.map_or(self.span, |e| e.span);
344 let self_expr_id = self.self_expr.map(|e| e.id);
345
346 let (self_ty, autoderefs, result) =
347 check::autoderef(
348 self.fcx, span, self_ty, self_expr_id, PreferMutLvalue,
349 |self_ty, autoderefs| self.search_step(self_ty, autoderefs));
350
351 match result {
352 Some(Some(result)) => Some(result),
353 _ => {
354 if self.is_overloaded_deref() {
355 // If we are searching for an overloaded deref, no
356 // need to try coercing a `~[T]` to an `&[T]` and
357 // searching for an overloaded deref on *that*.
358 None
359 } else {
360 self.search_for_autosliced_method(self_ty, autoderefs)
361 }
362 }
363 }
364 }
365
366 fn search_step(&self,
367 self_ty: ty::t,
368 autoderefs: uint)
369 -> Option<Option<MethodCallee>> {
370 debug!("search_step: self_ty={} autoderefs={}",
371 self.ty_to_str(self_ty), autoderefs);
372
373 match self.deref_args {
374 check::DontDerefArgs => {
375 match self.search_for_autoderefd_method(self_ty, autoderefs) {
376 Some(result) => return Some(Some(result)),
377 None => {}
378 }
379
380 match self.search_for_autoptrd_method(self_ty, autoderefs) {
381 Some(result) => return Some(Some(result)),
382 None => {}
383 }
384 }
385 check::DoDerefArgs => {
386 match self.search_for_autoptrd_method(self_ty, autoderefs) {
387 Some(result) => return Some(Some(result)),
388 None => {}
389 }
390
391 match self.search_for_autoderefd_method(self_ty, autoderefs) {
392 Some(result) => return Some(Some(result)),
393 None => {}
394 }
395 }
396 }
397
398 // Don't autoderef if we aren't supposed to.
399 if self.autoderef_receiver == DontAutoderefReceiver {
400 Some(None)
401 } else {
402 None
403 }
404 }
405
406 fn is_overloaded_deref(&self) -> bool {
407 self.self_expr.is_none()
408 }
409
410 // ______________________________________________________________________
411 // Candidate collection (see comment at start of file)
412
413 fn reset_candidates(&mut self) {
414 self.inherent_candidates = Vec::new();
415 self.extension_candidates = Vec::new();
416 }
417
418 fn push_inherent_candidates(&mut self, self_ty: ty::t) {
419 /*!
420 * Collect all inherent candidates into
421 * `self.inherent_candidates`. See comment at the start of
422 * the file. To find the inherent candidates, we repeatedly
423 * deref the self-ty to find the "base-type". So, for
424 * example, if the receiver is Box<Box<C>> where `C` is a struct type,
425 * we'll want to find the inherent impls for `C`.
426 */
427
428 let span = self.self_expr.map_or(self.span, |e| e.span);
429 check::autoderef(self.fcx, span, self_ty, None, PreferMutLvalue, |self_ty, _| {
430 match get(self_ty).sty {
431 ty_trait(box TyTrait { def_id, ref substs, .. }) => {
432 self.push_inherent_candidates_from_object(def_id, substs);
433 self.push_inherent_impl_candidates_for_type(def_id);
434 }
435 ty_enum(did, _) | ty_struct(did, _) => {
436 if self.check_traits == CheckTraitsAndInherentMethods {
437 self.push_inherent_impl_candidates_for_type(did);
438 }
439 }
440 _ => { /* No inherent methods in these types */ }
441 }
442
443 // Don't autoderef if we aren't supposed to.
444 if self.autoderef_receiver == DontAutoderefReceiver {
445 Some(())
446 } else {
447 None
448 }
449 });
450 }
451
452 fn push_bound_candidates(&mut self, self_ty: ty::t, restrict_to: Option<DefId>) {
453 let span = self.self_expr.map_or(self.span, |e| e.span);
454 check::autoderef(self.fcx, span, self_ty, None, PreferMutLvalue, |self_ty, _| {
455 match get(self_ty).sty {
456 ty_param(p) => {
457 self.push_inherent_candidates_from_param(self_ty, restrict_to, p);
458 }
459 ty_self(..) => {
460 // Call is of the form "self.foo()" and appears in one
461 // of a trait's default method implementations.
462 self.push_inherent_candidates_from_self(self_ty, restrict_to);
463 }
464 _ => { /* No bound methods in these types */ }
465 }
466
467 // Don't autoderef if we aren't supposed to.
468 if self.autoderef_receiver == DontAutoderefReceiver {
469 Some(())
470 } else {
471 None
472 }
473 });
474 }
475
476 fn push_extension_candidate(&mut self, trait_did: DefId) {
477 ty::populate_implementations_for_trait_if_necessary(self.tcx(), trait_did);
478
479 // Look for explicit implementations.
480 let impl_methods = self.tcx().impl_methods.borrow();
481 for impl_infos in self.tcx().trait_impls.borrow().find(&trait_did).iter() {
482 for impl_did in impl_infos.borrow().iter() {
483 let methods = impl_methods.get(impl_did);
484 self.push_candidates_from_impl(*impl_did, methods.as_slice(), true);
485 }
486 }
487 }
488
489 fn push_extension_candidates(&mut self, expr_id: ast::NodeId) {
490 // If the method being called is associated with a trait, then
491 // find all the impls of that trait. Each of those are
492 // candidates.
493 let opt_applicable_traits = self.fcx.ccx.trait_map.find(&expr_id);
494 for applicable_traits in opt_applicable_traits.move_iter() {
495 for trait_did in applicable_traits.iter() {
496 self.push_extension_candidate(*trait_did);
497 }
498 }
499 }
500
501 fn push_inherent_candidates_from_object(&mut self,
502 did: DefId,
503 substs: &ty::substs) {
504 debug!("push_inherent_candidates_from_object(did={}, substs={})",
505 self.did_to_str(did),
506 substs.repr(self.tcx()));
507 let _indenter = indenter();
508 let tcx = self.tcx();
509 let span = self.span;
510
511 // It is illegal to invoke a method on a trait instance that
512 // refers to the `self` type. An error will be reported by
513 // `enforce_object_limitations()` if the method refers
514 // to the `Self` type. Substituting ty_err here allows
515 // compiler to soldier on.
516 //
517 // `confirm_candidate()` also relies upon this substitution
518 // for Self. (fix)
519 let rcvr_substs = substs {
520 self_ty: Some(ty::mk_err()),
521 ..(*substs).clone()
522 };
523 let trait_ref = Rc::new(TraitRef {
524 def_id: did,
525 substs: rcvr_substs.clone()
526 });
527
528 self.push_inherent_candidates_from_bounds_inner(&[trait_ref.clone()],
529 |new_trait_ref, m, method_num, _bound_num| {
530 let vtable_index = get_method_index(tcx, &*new_trait_ref,
531 trait_ref.clone(), method_num);
532 let mut m = (*m).clone();
533 // We need to fix up the transformed self type.
534 *m.fty.sig.inputs.get_mut(0) =
535 construct_transformed_self_ty_for_object(
536 tcx, span, did, &rcvr_substs, &m);
537
538 Some(Candidate {
539 rcvr_match_condition: RcvrMatchesIfObject(did),
540 rcvr_substs: new_trait_ref.substs.clone(),
541 method_ty: Rc::new(m),
542 origin: MethodObject(MethodObject {
543 trait_id: new_trait_ref.def_id,
544 object_trait_id: did,
545 method_num: method_num,
546 real_index: vtable_index
547 })
548 })
549 });
550 }
551
552 fn push_inherent_candidates_from_param(&mut self,
553 rcvr_ty: ty::t,
554 restrict_to: Option<DefId>,
555 param_ty: param_ty) {
556 debug!("push_inherent_candidates_from_param(param_ty={:?})",
557 param_ty);
558 self.push_inherent_candidates_from_bounds(
559 rcvr_ty,
560 self.fcx
561 .inh
562 .param_env
563 .type_param_bounds
564 .get(param_ty.idx)
565 .trait_bounds
566 .as_slice(),
567 restrict_to,
568 param_numbered(param_ty.idx));
569 }
570
571
572 fn push_inherent_candidates_from_self(&mut self,
573 rcvr_ty: ty::t,
574 restrict_to: Option<DefId>) {
575 debug!("push_inherent_candidates_from_self()");
576 self.push_inherent_candidates_from_bounds(
577 rcvr_ty,
578 [self.fcx.inh.param_env.self_param_bound.clone().unwrap()],
579 restrict_to,
580 param_self)
581 }
582
583 fn push_inherent_candidates_from_bounds(&mut self,
584 self_ty: ty::t,
585 bounds: &[Rc<TraitRef>],
586 restrict_to: Option<DefId>,
587 param: param_index) {
588 self.push_inherent_candidates_from_bounds_inner(bounds,
589 |trait_ref, m, method_num, bound_num| {
590 match restrict_to {
591 Some(trait_did) => {
592 if trait_did != trait_ref.def_id {
593 return None;
594 }
595 }
596 _ => {}
597 }
598 Some(Candidate {
599 rcvr_match_condition: RcvrMatchesIfSubtype(self_ty),
600 rcvr_substs: trait_ref.substs.clone(),
601 method_ty: m,
602 origin: MethodParam(MethodParam {
603 trait_id: trait_ref.def_id,
604 method_num: method_num,
605 param_num: param,
606 bound_num: bound_num,
607 })
608 })
609 })
610 }
611
612 // Do a search through a list of bounds, using a callback to actually
613 // create the candidates.
614 fn push_inherent_candidates_from_bounds_inner(&mut self,
615 bounds: &[Rc<TraitRef>],
616 mk_cand: |tr: Rc<TraitRef>,
617 m: Rc<ty::Method>,
618 method_num: uint,
619 bound_num: uint|
620 -> Option<Candidate>) {
621 let tcx = self.tcx();
622 let mut next_bound_idx = 0; // count only trait bounds
623
624 ty::each_bound_trait_and_supertraits(tcx, bounds, |bound_trait_ref| {
625 let this_bound_idx = next_bound_idx;
626 next_bound_idx += 1;
627
628 let trait_methods = ty::trait_methods(tcx, bound_trait_ref.def_id);
629 match trait_methods.iter().position(|m| {
630 m.explicit_self != ast::SelfStatic &&
631 m.ident.name == self.m_name }) {
632 Some(pos) => {
633 let method = trait_methods.get(pos).clone();
634
635 match mk_cand(bound_trait_ref, method, pos, this_bound_idx) {
636 Some(cand) => {
637 debug!("pushing inherent candidate for param: {}",
638 cand.repr(self.tcx()));
639 self.inherent_candidates.push(cand);
640 }
641 None => {}
642 }
643 }
644 None => {
645 debug!("trait doesn't contain method: {:?}",
646 bound_trait_ref.def_id);
647 // check next trait or bound
648 }
649 }
650 true
651 });
652 }
653
654
655 fn push_inherent_impl_candidates_for_type(&mut self, did: DefId) {
656 // Read the inherent implementation candidates for this type from the
657 // metadata if necessary.
658 ty::populate_implementations_for_type_if_necessary(self.tcx(), did);
659
660 let impl_methods = self.tcx().impl_methods.borrow();
661 for impl_infos in self.tcx().inherent_impls.borrow().find(&did).iter() {
662 for impl_did in impl_infos.borrow().iter() {
663 let methods = impl_methods.get(impl_did);
664 self.push_candidates_from_impl(*impl_did, methods.as_slice(), false);
665 }
666 }
667 }
668
669 fn push_candidates_from_impl(&mut self,
670 impl_did: DefId,
671 impl_methods: &[DefId],
672 is_extension: bool) {
673 let did = if self.report_statics == ReportStaticMethods {
674 // we only want to report each base trait once
675 match ty::impl_trait_ref(self.tcx(), impl_did) {
676 Some(trait_ref) => trait_ref.def_id,
677 None => impl_did
678 }
679 } else {
680 impl_did
681 };
682
683 if !self.impl_dups.insert(did) {
684 return; // already visited
685 }
686
687 debug!("push_candidates_from_impl: {} {}",
688 token::get_name(self.m_name),
689 impl_methods.iter().map(|&did| ty::method(self.tcx(), did).ident)
690 .collect::<Vec<ast::Ident>>()
691 .repr(self.tcx()));
692
693 let method = match impl_methods.iter().map(|&did| ty::method(self.tcx(), did))
694 .find(|m| m.ident.name == self.m_name) {
695 Some(method) => method,
696 None => { return; } // No method with the right name.
697 };
698
699 // determine the `self` of the impl with fresh
700 // variables for each parameter:
701 let span = self.self_expr.map_or(self.span, |e| e.span);
702 let vcx = self.fcx.vtable_context();
703 let ty::ty_param_substs_and_ty {
704 substs: impl_substs,
705 ty: impl_ty
706 } = impl_self_ty(&vcx, span, impl_did);
707
708 let candidates = if is_extension {
709 &mut self.extension_candidates
710 } else {
711 &mut self.inherent_candidates
712 };
713
714 candidates.push(Candidate {
715 rcvr_match_condition: RcvrMatchesIfSubtype(impl_ty),
716 rcvr_substs: impl_substs,
717 origin: MethodStatic(method.def_id),
718 method_ty: method,
719 });
720 }
721
722 // ______________________________________________________________________
723 // Candidate selection (see comment at start of file)
724
725 fn search_for_autoderefd_method(&self,
726 self_ty: ty::t,
727 autoderefs: uint)
728 -> Option<MethodCallee> {
729 let (self_ty, auto_deref_ref) =
730 self.consider_reborrow(self_ty, autoderefs);
731
732 // Hacky. For overloaded derefs, there may be an adjustment
733 // added to the expression from the outside context, so we do not store
734 // an explicit adjustment, but rather we hardwire the single deref
735 // that occurs in trans and mem_categorization.
736 let adjustment = match self.self_expr {
737 Some(expr) => Some((expr.id, ty::AutoDerefRef(auto_deref_ref))),
738 None => return None
739 };
740
741 match self.search_for_method(self_ty) {
742 None => None,
743 Some(method) => {
744 debug!("(searching for autoderef'd method) writing \
745 adjustment {:?} for {}", adjustment, self.ty_to_str( self_ty));
746 match adjustment {
747 Some((self_expr_id, adj)) => {
748 self.fcx.write_adjustment(self_expr_id, adj);
749 }
750 None => {}
751 }
752 Some(method)
753 }
754 }
755 }
756
757 fn consider_reborrow(&self,
758 self_ty: ty::t,
759 autoderefs: uint)
760 -> (ty::t, ty::AutoDerefRef) {
761 /*!
762 * In the event that we are invoking a method with a receiver
763 * of a borrowed type like `&T`, `&mut T`, or `&mut [T]`,
764 * we will "reborrow" the receiver implicitly. For example, if
765 * you have a call `r.inc()` and where `r` has type `&mut T`,
766 * then we treat that like `(&mut *r).inc()`. This avoids
767 * consuming the original pointer.
768 *
769 * You might think that this would be a natural byproduct of
770 * the auto-deref/auto-ref process. This is true for `Box<T>`
771 * but not for an `&mut T` receiver. With `Box<T>`, we would
772 * begin by testing for methods with a self type `Box<T>`,
773 * then autoderef to `T`, then autoref to `&mut T`. But with
774 * an `&mut T` receiver the process begins with `&mut T`, only
775 * without any autoadjustments.
776 */
777
778 let tcx = self.tcx();
779 return match ty::get(self_ty).sty {
780 ty::ty_rptr(_, self_mt) if default_method_hack(self_mt) => {
781 (self_ty,
782 ty::AutoDerefRef {
783 autoderefs: autoderefs,
784 autoref: None})
785 }
786 ty::ty_rptr(_, self_mt) => {
787 let region =
788 self.infcx().next_region_var(infer::Autoref(self.span));
789 let (extra_derefs, auto) = match ty::get(self_mt.ty).sty {
790 ty::ty_vec(_, None) => (0, ty::AutoBorrowVec(region, self_mt.mutbl)),
791 ty::ty_str => (0, ty::AutoBorrowVec(region, self_mt.mutbl)),
792 _ => (1, ty::AutoPtr(region, self_mt.mutbl)),
793 };
794 (ty::mk_rptr(tcx, region, self_mt),
795 ty::AutoDerefRef {
796 autoderefs: autoderefs + extra_derefs,
797 autoref: Some(auto)})
798 }
799
800 ty::ty_trait(box ty::TyTrait {
801 def_id, ref substs, store: ty::RegionTraitStore(_, mutbl), bounds
802 }) => {
803 let region =
804 self.infcx().next_region_var(infer::Autoref(self.span));
805 (ty::mk_trait(tcx, def_id, substs.clone(),
806 ty::RegionTraitStore(region, mutbl), bounds),
807 ty::AutoDerefRef {
808 autoderefs: autoderefs,
809 autoref: Some(ty::AutoBorrowObj(region, mutbl))})
810 }
811 _ => {
812 (self_ty,
813 ty::AutoDerefRef {
814 autoderefs: autoderefs,
815 autoref: None})
816 }
817 };
818
819 fn default_method_hack(self_mt: ty::mt) -> bool {
820 // FIXME(#6129). Default methods can't deal with autoref.
821 //
822 // I am a horrible monster and I pray for death. Currently
823 // the default method code fails when you try to reborrow
824 // because it is not handling types correctly. In lieu of
825 // fixing that, I am introducing this horrible hack. - ndm
826 self_mt.mutbl == MutImmutable && ty::type_is_self(self_mt.ty)
827 }
828 }
829
830 fn auto_slice_vec(&self, mt: ty::mt, autoderefs: uint) -> Option<MethodCallee> {
831 let tcx = self.tcx();
832 debug!("auto_slice_vec {}", ppaux::ty_to_str(tcx, mt.ty));
833
834 // First try to borrow to a slice
835 let entry = self.search_for_some_kind_of_autorefd_method(
836 AutoBorrowVec, autoderefs, [MutImmutable, MutMutable],
837 |m,r| ty::mk_slice(tcx, r,
838 ty::mt {ty:mt.ty, mutbl:m}));
839
840 if entry.is_some() {
841 return entry;
842 }
843
844 // Then try to borrow to a slice *and* borrow a pointer.
845 self.search_for_some_kind_of_autorefd_method(
846 AutoBorrowVecRef, autoderefs, [MutImmutable, MutMutable],
847 |m,r| {
848 let slice_ty = ty::mk_slice(tcx, r,
849 ty::mt {ty:mt.ty, mutbl:m});
850 // NB: we do not try to autoref to a mutable
851 // pointer. That would be creating a pointer
852 // to a temporary pointer (the borrowed
853 // slice), so any update the callee makes to
854 // it can't be observed.
855 ty::mk_rptr(tcx, r, ty::mt {ty:slice_ty, mutbl:MutImmutable})
856 })
857 }
858
859
860 fn auto_slice_str(&self, autoderefs: uint) -> Option<MethodCallee> {
861 let tcx = self.tcx();
862 debug!("auto_slice_str");
863
864 let entry = self.search_for_some_kind_of_autorefd_method(
865 AutoBorrowVec, autoderefs, [MutImmutable],
866 |_m,r| ty::mk_str_slice(tcx, r, MutImmutable));
867
868 if entry.is_some() {
869 return entry;
870 }
871
872 self.search_for_some_kind_of_autorefd_method(
873 AutoBorrowVecRef, autoderefs, [MutImmutable],
874 |m,r| {
875 let slice_ty = ty::mk_str_slice(tcx, r, m);
876 ty::mk_rptr(tcx, r, ty::mt {ty:slice_ty, mutbl:m})
877 })
878 }
879
880 fn search_for_autosliced_method(&self,
881 self_ty: ty::t,
882 autoderefs: uint)
883 -> Option<MethodCallee> {
884 /*!
885 * Searches for a candidate by converting things like
886 * `~[]` to `&[]`.
887 */
888
889 let tcx = self.tcx();
890 debug!("search_for_autosliced_method {}", ppaux::ty_to_str(tcx, self_ty));
891
892 let sty = ty::get(self_ty).sty.clone();
893 match sty {
894 ty_rptr(_, mt) => match ty::get(mt.ty).sty {
895 ty_vec(mt, None) => self.auto_slice_vec(mt, autoderefs),
896 _ => None
897 },
898 ty_uniq(t) => match ty::get(t).sty {
899 ty_vec(mt, None) => self.auto_slice_vec(mt, autoderefs),
900 ty_str => self.auto_slice_str(autoderefs),
901 _ => None
902 },
903 ty_vec(mt, Some(_)) => self.auto_slice_vec(mt, autoderefs),
904
905 ty_trait(box ty::TyTrait {
906 def_id: trt_did,
907 substs: trt_substs,
908 bounds: b,
909 ..
910 }) => {
911 // Coerce Box/&Trait instances to &Trait.
912
913 self.search_for_some_kind_of_autorefd_method(
914 AutoBorrowObj, autoderefs, [MutImmutable, MutMutable],
915 |m, r| {
916 ty::mk_trait(tcx, trt_did, trt_substs.clone(),
917 RegionTraitStore(r, m), b)
918 })
919 }
920
921 ty_closure(..) => {
922 // This case should probably be handled similarly to
923 // Trait instances.
924 None
925 }
926
927 _ => None
928 }
929 }
930
931 fn search_for_autoptrd_method(&self, self_ty: ty::t, autoderefs: uint)
932 -> Option<MethodCallee> {
933 /*!
934 *
935 * Converts any type `T` to `&M T` where `M` is an
936 * appropriate mutability.
937 */
938
939 let tcx = self.tcx();
940 match ty::get(self_ty).sty {
941 ty_bare_fn(..) | ty_box(..) | ty_uniq(..) | ty_rptr(..) |
942 ty_infer(IntVar(_)) |
943 ty_infer(FloatVar(_)) |
944 ty_self(_) | ty_param(..) | ty_nil | ty_bot | ty_bool |
945 ty_char | ty_int(..) | ty_uint(..) |
946 ty_float(..) | ty_enum(..) | ty_ptr(..) | ty_struct(..) | ty_tup(..) |
947 ty_str | ty_vec(..) | ty_trait(..) | ty_closure(..) => {
948 self.search_for_some_kind_of_autorefd_method(
949 AutoPtr, autoderefs, [MutImmutable, MutMutable],
950 |m,r| ty::mk_rptr(tcx, r, ty::mt {ty:self_ty, mutbl:m}))
951 }
952
953 ty_err => None,
954
955 ty_infer(TyVar(_)) => {
956 self.bug(format!("unexpected type: {}",
957 self.ty_to_str(self_ty)));
958 }
959 }
960 }
961
962 fn search_for_some_kind_of_autorefd_method(
963 &self,
964 kind: |Region, ast::Mutability| -> ty::AutoRef,
965 autoderefs: uint,
966 mutbls: &[ast::Mutability],
967 mk_autoref_ty: |ast::Mutability, ty::Region| -> ty::t)
968 -> Option<MethodCallee> {
969 // Hacky. For overloaded derefs, there may be an adjustment
970 // added to the expression from the outside context, so we do not store
971 // an explicit adjustment, but rather we hardwire the single deref
972 // that occurs in trans and mem_categorization.
973 let self_expr_id = match self.self_expr {
974 Some(expr) => Some(expr.id),
975 None => {
976 assert_eq!(autoderefs, 0);
977 assert_eq!(kind(ty::ReEmpty, ast::MutImmutable),
978 ty::AutoPtr(ty::ReEmpty, ast::MutImmutable));
979 None
980 }
981 };
982
983 // This is hokey. We should have mutability inference as a
984 // variable. But for now, try &const, then &, then &mut:
985 let region =
986 self.infcx().next_region_var(infer::Autoref(self.span));
987 for mutbl in mutbls.iter() {
988 let autoref_ty = mk_autoref_ty(*mutbl, region);
989 match self.search_for_method(autoref_ty) {
990 None => {}
991 Some(method) => {
992 match self_expr_id {
993 Some(self_expr_id) => {
994 self.fcx.write_adjustment(
995 self_expr_id,
996 ty::AutoDerefRef(ty::AutoDerefRef {
997 autoderefs: autoderefs,
998 autoref: Some(kind(region, *mutbl))
999 }));
1000 }
1001 None => {}
1002 }
1003 return Some(method);
1004 }
1005 }
1006 }
1007 None
1008 }
1009
1010 fn search_for_method(&self, rcvr_ty: ty::t) -> Option<MethodCallee> {
1011 debug!("search_for_method(rcvr_ty={})", self.ty_to_str(rcvr_ty));
1012 let _indenter = indenter();
1013
1014 // I am not sure that inherent methods should have higher
1015 // priority, but it is necessary ATM to handle some of the
1016 // existing code.
1017
1018 debug!("searching inherent candidates");
1019 match self.consider_candidates(rcvr_ty, self.inherent_candidates.as_slice()) {
1020 None => {}
1021 Some(mme) => {
1022 return Some(mme);
1023 }
1024 }
1025
1026 debug!("searching extension candidates");
1027 self.consider_candidates(rcvr_ty, self.extension_candidates.as_slice())
1028 }
1029
1030 fn consider_candidates(&self, rcvr_ty: ty::t,
1031 candidates: &[Candidate])
1032 -> Option<MethodCallee> {
1033 // FIXME(pcwalton): Do we need to clone here?
1034 let relevant_candidates: Vec<Candidate> =
1035 candidates.iter().map(|c| (*c).clone()).
1036 filter(|c| self.is_relevant(rcvr_ty, c)).collect();
1037
1038 let relevant_candidates =
1039 self.merge_candidates(relevant_candidates.as_slice());
1040
1041 if relevant_candidates.len() == 0 {
1042 return None;
1043 }
1044
1045 if self.report_statics == ReportStaticMethods {
1046 // lookup should only be called with ReportStaticMethods if a regular lookup failed
1047 assert!(relevant_candidates.iter().all(|c| c.method_ty.explicit_self == SelfStatic));
1048
1049 self.tcx().sess.fileline_note(self.span,
1050 "found defined static methods, maybe a `self` is missing?");
1051
1052 for (idx, candidate) in relevant_candidates.iter().enumerate() {
1053 self.report_candidate(idx, &candidate.origin);
1054 }
1055
1056 // return something so we don't get errors for every mutability
1057 return Some(MethodCallee {
1058 origin: relevant_candidates.get(0).origin,
1059 ty: ty::mk_err(),
1060 substs: substs::empty()
1061 });
1062 }
1063
1064 if relevant_candidates.len() > 1 {
1065 self.tcx().sess.span_err(
1066 self.span,
1067 "multiple applicable methods in scope");
1068 for (idx, candidate) in relevant_candidates.iter().enumerate() {
1069 self.report_candidate(idx, &candidate.origin);
1070 }
1071 }
1072
1073 Some(self.confirm_candidate(rcvr_ty, relevant_candidates.get(0)))
1074 }
1075
1076 fn merge_candidates(&self, candidates: &[Candidate]) -> Vec<Candidate> {
1077 let mut merged = Vec::new();
1078 let mut i = 0;
1079 while i < candidates.len() {
1080 let candidate_a = &candidates[i];
1081
1082 let mut skip = false;
1083
1084 let mut j = i + 1;
1085 while j < candidates.len() {
1086 let candidate_b = &candidates[j];
1087 debug!("attempting to merge {} and {}",
1088 candidate_a.repr(self.tcx()),
1089 candidate_b.repr(self.tcx()));
1090 let candidates_same = match (&candidate_a.origin,
1091 &candidate_b.origin) {
1092 (&MethodParam(ref p1), &MethodParam(ref p2)) => {
1093 let same_trait = p1.trait_id == p2.trait_id;
1094 let same_method = p1.method_num == p2.method_num;
1095 let same_param = p1.param_num == p2.param_num;
1096 // The bound number may be different because
1097 // multiple bounds may lead to the same trait
1098 // impl
1099 same_trait && same_method && same_param
1100 }
1101 _ => false
1102 };
1103 if candidates_same {
1104 skip = true;
1105 break;
1106 }
1107 j += 1;
1108 }
1109
1110 i += 1;
1111
1112 if skip {
1113 // There are more than one of these and we need only one
1114 continue;
1115 } else {
1116 merged.push(candidate_a.clone());
1117 }
1118 }
1119
1120 return merged;
1121 }
1122
1123 fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
1124 -> MethodCallee {
1125 // This method performs two sets of substitutions, one after the other:
1126 // 1. Substitute values for any type/lifetime parameters from the impl and
1127 // method declaration into the method type. This is the function type
1128 // before it is called; it may still include late bound region variables.
1129 // 2. Instantiate any late bound lifetime parameters in the method itself
1130 // with fresh region variables.
1131
1132 let tcx = self.tcx();
1133
1134 debug!("confirm_candidate(rcvr_ty={}, candidate={})",
1135 self.ty_to_str(rcvr_ty),
1136 candidate.repr(self.tcx()));
1137
1138 self.enforce_object_limitations(candidate);
1139 self.enforce_drop_trait_limitations(candidate);
1140
1141 // static methods should never have gotten this far:
1142 assert!(candidate.method_ty.explicit_self != SelfStatic);
1143
1144 // Determine the values for the generic parameters of the method.
1145 // If they were not explicitly supplied, just construct fresh
1146 // variables.
1147 let num_supplied_tps = self.supplied_tps.len();
1148 let num_method_tps = candidate.method_ty.generics.type_param_defs().len();
1149 let m_substs = {
1150 if num_supplied_tps == 0u {
1151 self.fcx.infcx().next_ty_vars(num_method_tps)
1152 } else if num_method_tps == 0u {
1153 tcx.sess.span_err(
1154 self.span,
1155 "this method does not take type parameters");
1156 self.fcx.infcx().next_ty_vars(num_method_tps)
1157 } else if num_supplied_tps != num_method_tps {
1158 tcx.sess.span_err(
1159 self.span,
1160 "incorrect number of type \
1161 parameters given for this method");
1162 self.fcx.infcx().next_ty_vars(num_method_tps)
1163 } else {
1164 Vec::from_slice(self.supplied_tps)
1165 }
1166 };
1167
1168 // Determine values for the early-bound lifetime parameters.
1169 // FIXME -- permit users to manually specify lifetimes
1170 let mut all_regions: Vec<Region> = match candidate.rcvr_substs.regions {
1171 NonerasedRegions(ref v) => v.iter().map(|r| r.clone()).collect(),
1172 ErasedRegions => tcx.sess.span_bug(self.span, "ErasedRegions")
1173 };
1174 let m_regions =
1175 self.fcx.infcx().region_vars_for_defs(
1176 self.span,
1177 candidate.method_ty.generics.region_param_defs.as_slice());
1178 for &r in m_regions.iter() {
1179 all_regions.push(r);
1180 }
1181
1182 // Construct the full set of type parameters for the method,
1183 // which is equal to the class tps + the method tps.
1184 let all_substs = substs {
1185 tps: candidate.rcvr_substs.tps.clone().append(m_substs.as_slice()),
1186 regions: NonerasedRegions(OwnedSlice::from_vec(all_regions)),
1187 self_ty: candidate.rcvr_substs.self_ty,
1188 };
1189
1190 let ref bare_fn_ty = candidate.method_ty.fty;
1191
1192 // Compute the method type with type parameters substituted
1193 debug!("fty={} all_substs={}",
1194 bare_fn_ty.repr(tcx),
1195 ty::substs_to_str(tcx, &all_substs));
1196
1197 let fn_sig = &bare_fn_ty.sig;
1198 let inputs = match candidate.origin {
1199 MethodObject(..) => {
1200 // For annoying reasons, we've already handled the
1201 // substitution of self for object calls.
1202 let args = fn_sig.inputs.slice_from(1).iter().map(|t| {
1203 t.subst(tcx, &all_substs)
1204 });
1205 Some(*fn_sig.inputs.get(0)).move_iter().chain(args).collect()
1206 }
1207 _ => fn_sig.inputs.subst(tcx, &all_substs)
1208 };
1209 let fn_sig = ty::FnSig {
1210 binder_id: fn_sig.binder_id,
1211 inputs: inputs,
1212 output: fn_sig.output.subst(tcx, &all_substs),
1213 variadic: fn_sig.variadic
1214 };
1215
1216 debug!("after subst, fty={}", fn_sig.repr(tcx));
1217
1218 // Replace any bound regions that appear in the function
1219 // signature with region variables
1220 let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(
1221 tcx, &fn_sig,
1222 |br| self.fcx.infcx().next_region_var(
1223 infer::LateBoundRegion(self.span, br)));
1224 let transformed_self_ty = *fn_sig.inputs.get(0);
1225 let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
1226 sig: fn_sig,
1227 fn_style: bare_fn_ty.fn_style,
1228 abi: bare_fn_ty.abi.clone(),
1229 });
1230 debug!("after replacing bound regions, fty={}", self.ty_to_str(fty));
1231
1232 // Before, we only checked whether self_ty could be a subtype
1233 // of rcvr_ty; now we actually make it so (this may cause
1234 // variables to unify etc). Since we checked beforehand, and
1235 // nothing has changed in the meantime, this unification
1236 // should never fail.
1237 let span = self.self_expr.map_or(self.span, |e| e.span);
1238 match self.fcx.mk_subty(false, infer::Misc(span),
1239 rcvr_ty, transformed_self_ty) {
1240 Ok(_) => {}
1241 Err(_) => {
1242 self.bug(format!("{} was a subtype of {} but now is not?",
1243 self.ty_to_str(rcvr_ty),
1244 self.ty_to_str(transformed_self_ty)));
1245 }
1246 }
1247
1248 MethodCallee {
1249 origin: candidate.origin,
1250 ty: fty,
1251 substs: all_substs
1252 }
1253 }
1254
1255 fn enforce_object_limitations(&self, candidate: &Candidate) {
1256 /*!
1257 * There are some limitations to calling functions through an
1258 * object, because (a) the self type is not known
1259 * (that's the whole point of a trait instance, after all, to
1260 * obscure the self type) and (b) the call must go through a
1261 * vtable and hence cannot be monomorphized.
1262 */
1263
1264 match candidate.origin {
1265 MethodStatic(..) | MethodParam(..) => {
1266 return; // not a call to a trait instance
1267 }
1268 MethodObject(..) => {}
1269 }
1270
1271 match candidate.method_ty.explicit_self {
1272 ast::SelfStatic => { // reason (a) above
1273 self.tcx().sess.span_err(
1274 self.span,
1275 "cannot call a method without a receiver \
1276 through an object");
1277 }
1278
1279 ast::SelfValue => { // reason (a) above
1280 self.tcx().sess.span_err(
1281 self.span,
1282 "cannot call a method with a by-value receiver \
1283 through an object");
1284 }
1285
1286 ast::SelfRegion(..) | ast::SelfUniq => {}
1287 }
1288
1289 // reason (a) above
1290 let check_for_self_ty = |ty| {
1291 if ty::type_has_self(ty) {
1292 self.tcx().sess.span_err(
1293 self.span,
1294 "cannot call a method whose type contains a \
1295 self-type through an object");
1296 true
1297 } else {
1298 false
1299 }
1300 };
1301 let ref sig = candidate.method_ty.fty.sig;
1302 let mut found_self_ty = false;
1303 for &input_ty in sig.inputs.iter() {
1304 if check_for_self_ty(input_ty) {
1305 found_self_ty = true;
1306 break;
1307 }
1308 }
1309 if !found_self_ty {
1310 check_for_self_ty(sig.output);
1311 }
1312
1313 if candidate.method_ty.generics.has_type_params() { // reason (b) above
1314 self.tcx().sess.span_err(
1315 self.span,
1316 "cannot call a generic method through an object");
1317 }
1318 }
1319
1320 fn enforce_drop_trait_limitations(&self, candidate: &Candidate) {
1321 // No code can call the finalize method explicitly.
1322 let bad;
1323 match candidate.origin {
1324 MethodStatic(method_id) => {
1325 bad = self.tcx().destructors.borrow().contains(&method_id);
1326 }
1327 // FIXME: does this properly enforce this on everything now
1328 // that self has been merged in? -sully
1329 MethodParam(MethodParam { trait_id: trait_id, .. }) |
1330 MethodObject(MethodObject { trait_id: trait_id, .. }) => {
1331 bad = self.tcx().destructor_for_type.borrow()
1332 .contains_key(&trait_id);
1333 }
1334 }
1335
1336 if bad {
1337 self.tcx().sess.span_err(self.span,
1338 "explicit call to destructor");
1339 }
1340 }
1341
1342 // `rcvr_ty` is the type of the expression. It may be a subtype of a
1343 // candidate method's `self_ty`.
1344 fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool {
1345 debug!("is_relevant(rcvr_ty={}, candidate={})",
1346 self.ty_to_str(rcvr_ty), candidate.repr(self.tcx()));
1347
1348 return match candidate.method_ty.explicit_self {
1349 SelfStatic => {
1350 debug!("(is relevant?) explicit self is static");
1351 self.report_statics == ReportStaticMethods
1352 }
1353
1354 SelfValue => {
1355 rcvr_matches_ty(self.fcx, rcvr_ty, candidate)
1356 }
1357
1358 SelfRegion(_, m) => {
1359 debug!("(is relevant?) explicit self is a region");
1360 match ty::get(rcvr_ty).sty {
1361 ty::ty_rptr(_, mt) => {
1362 match ty::get(mt.ty).sty {
1363 ty::ty_vec(_, None) | ty::ty_str => false,
1364 _ => mutability_matches(mt.mutbl, m) &&
1365 rcvr_matches_ty(self.fcx, mt.ty, candidate),
1366 }
1367 }
1368
1369 ty::ty_trait(box ty::TyTrait {
1370 def_id: self_did, store: RegionTraitStore(_, self_m), ..
1371 }) => {
1372 mutability_matches(self_m, m) &&
1373 rcvr_matches_object(self_did, candidate)
1374 }
1375
1376 _ => false
1377 }
1378 }
1379
1380 SelfUniq => {
1381 debug!("(is relevant?) explicit self is a unique pointer");
1382 match ty::get(rcvr_ty).sty {
1383 ty::ty_uniq(typ) => {
1384 match ty::get(typ).sty {
1385 ty::ty_vec(_, None) | ty::ty_str => false,
1386 _ => rcvr_matches_ty(self.fcx, typ, candidate),
1387 }
1388 }
1389
1390 ty::ty_trait(box ty::TyTrait {
1391 def_id: self_did, store: UniqTraitStore, ..
1392 }) => {
1393 rcvr_matches_object(self_did, candidate)
1394 }
1395
1396 _ => false
1397 }
1398 }
1399 };
1400
1401 fn rcvr_matches_object(self_did: ast::DefId,
1402 candidate: &Candidate) -> bool {
1403 match candidate.rcvr_match_condition {
1404 RcvrMatchesIfObject(desired_did) => {
1405 self_did == desired_did
1406 }
1407 RcvrMatchesIfSubtype(_) => {
1408 false
1409 }
1410 }
1411 }
1412
1413 fn rcvr_matches_ty(fcx: &FnCtxt,
1414 rcvr_ty: ty::t,
1415 candidate: &Candidate) -> bool {
1416 match candidate.rcvr_match_condition {
1417 RcvrMatchesIfObject(_) => {
1418 false
1419 }
1420 RcvrMatchesIfSubtype(of_type) => {
1421 fcx.can_mk_subty(rcvr_ty, of_type).is_ok()
1422 }
1423 }
1424 }
1425
1426 fn mutability_matches(self_mutbl: ast::Mutability,
1427 candidate_mutbl: ast::Mutability)
1428 -> bool {
1429 //! True if `self_mutbl <: candidate_mutbl`
1430 self_mutbl == candidate_mutbl
1431 }
1432 }
1433
1434 fn report_candidate(&self, idx: uint, origin: &MethodOrigin) {
1435 match *origin {
1436 MethodStatic(impl_did) => {
1437 let did = if self.report_statics == ReportStaticMethods {
1438 // If we're reporting statics, we want to report the trait
1439 // definition if possible, rather than an impl
1440 match ty::trait_method_of_method(self.tcx(), impl_did) {
1441 None => {debug!("(report candidate) No trait method found"); impl_did},
1442 Some(trait_did) => {debug!("(report candidate) Found trait ref"); trait_did}
1443 }
1444 } else {
1445 // If it is an instantiated default method, use the original
1446 // default method for error reporting.
1447 match provided_source(self.tcx(), impl_did) {
1448 None => impl_did,
1449 Some(did) => did
1450 }
1451 };
1452 self.report_static_candidate(idx, did)
1453 }
1454 MethodParam(ref mp) => {
1455 self.report_param_candidate(idx, (*mp).trait_id)
1456 }
1457 MethodObject(ref mo) => {
1458 self.report_trait_candidate(idx, mo.trait_id)
1459 }
1460 }
1461 }
1462
1463 fn report_static_candidate(&self, idx: uint, did: DefId) {
1464 let span = if did.krate == ast::LOCAL_CRATE {
1465 self.tcx().map.span(did.node)
1466 } else {
1467 self.span
1468 };
1469 self.tcx().sess.span_note(
1470 span,
1471 format!("candidate \\#{} is `{}`",
1472 idx+1u,
1473 ty::item_path_str(self.tcx(), did)));
1474 }
1475
1476 fn report_param_candidate(&self, idx: uint, did: DefId) {
1477 self.tcx().sess.span_note(
1478 self.span,
1479 format!("candidate \\#{} derives from the bound `{}`",
1480 idx+1u,
1481 ty::item_path_str(self.tcx(), did)));
1482 }
1483
1484 fn report_trait_candidate(&self, idx: uint, did: DefId) {
1485 self.tcx().sess.span_note(
1486 self.span,
1487 format!("candidate \\#{} derives from the type of the receiver, \
1488 which is the trait `{}`",
1489 idx+1u,
1490 ty::item_path_str(self.tcx(), did)));
1491 }
1492
1493 fn infcx(&'a self) -> &'a infer::InferCtxt<'a> {
1494 &self.fcx.inh.infcx
1495 }
1496
1497 fn tcx(&self) -> &'a ty::ctxt {
1498 self.fcx.tcx()
1499 }
1500
1501 fn ty_to_str(&self, t: ty::t) -> ~str {
1502 self.fcx.infcx().ty_to_str(t)
1503 }
1504
1505 fn did_to_str(&self, did: DefId) -> ~str {
1506 ty::item_path_str(self.tcx(), did)
1507 }
1508
1509 fn bug(&self, s: &str) -> ! {
1510 self.tcx().sess.span_bug(self.span, s)
1511 }
1512 }
1513
1514 impl Repr for Candidate {
1515 fn repr(&self, tcx: &ty::ctxt) -> ~str {
1516 format!("Candidate(rcvr_ty={}, rcvr_substs={}, method_ty={}, origin={:?})",
1517 self.rcvr_match_condition.repr(tcx),
1518 self.rcvr_substs.repr(tcx),
1519 self.method_ty.repr(tcx),
1520 self.origin)
1521 }
1522 }
1523
1524 impl Repr for RcvrMatchCondition {
1525 fn repr(&self, tcx: &ty::ctxt) -> ~str {
1526 match *self {
1527 RcvrMatchesIfObject(d) => {
1528 format!("RcvrMatchesIfObject({})", d.repr(tcx))
1529 }
1530 RcvrMatchesIfSubtype(t) => {
1531 format!("RcvrMatchesIfSubtype({})", t.repr(tcx))
1532 }
1533 }
1534 }
1535 }
librustc/middle/typeck/check/method.rs:1413:8-1413:8 -fn- definition:
fn rcvr_matches_ty(fcx: &FnCtxt,
rcvr_ty: ty::t,
candidate: &Candidate) -> bool {
references:- 31385: ty::ty_vec(_, None) | ty::ty_str => false,
1386: _ => rcvr_matches_ty(self.fcx, typ, candidate),
1387: }
librustc/middle/typeck/check/method.rs:115:16-115:16 -enum- definition:
pub enum AutoderefReceiverFlag {
AutoderefReceiver,
DontAutoderefReceiver,
references:- 7310: check_traits: CheckTraitsFlag,
311: autoderef_receiver: AutoderefReceiverFlag,
312: report_statics: StaticMethodsFlag,
librustc/middle/typeck/check/mod.rs:
2052: args: &[@ast::Expr],
2053: autoderef_receiver: AutoderefReceiverFlag,
2054: unbound_method: ||) -> ty::t {
librustc/middle/typeck/check/method.rs:319:19-319:19 -struct- definition:
struct Candidate {
rcvr_match_condition: RcvrMatchCondition,
rcvr_substs: ty::substs,
references:- 21318: */
320: struct Candidate {
--
714: candidates.push(Candidate {
715: rcvr_match_condition: RcvrMatchesIfSubtype(impl_ty),
--
1076: fn merge_candidates(&self, candidates: &[Candidate]) -> Vec<Candidate> {
1077: let mut merged = Vec::new();
--
1320: fn enforce_drop_trait_limitations(&self, candidate: &Candidate) {
1321: // No code can call the finalize method explicitly.
--
1401: fn rcvr_matches_object(self_did: ast::DefId,
1402: candidate: &Candidate) -> bool {
1403: match candidate.rcvr_match_condition {
--
1514: impl Repr for Candidate {
1515: fn repr(&self, tcx: &ty::ctxt) -> ~str {
librustc/middle/typeck/check/method.rs:1401:8-1401:8 -fn- definition:
fn rcvr_matches_object(self_did: ast::DefId,
candidate: &Candidate) -> bool {
match candidate.rcvr_match_condition {
references:- 21372: mutability_matches(self_m, m) &&
1373: rcvr_matches_object(self_did, candidate)
1374: }
--
1392: }) => {
1393: rcvr_matches_object(self_did, candidate)
1394: }
librustc/middle/typeck/check/method.rs:126:1-126:1 -fn- definition:
pub fn lookup<'a>(
fcx: &'a FnCtxt<'a>,
// In a call `a.b::<X, Y, ...>(...)`:
references:- 3librustc/middle/typeck/check/mod.rs:
1986: // Check for potential static matches (missing self parameters)
1987: method::lookup(fcx, expr, rcvr,
1988: method_name.node.name,
--
2377: let tps: Vec<ty::t> = tys.iter().map(|&ty| fcx.to_ty(ty)).collect();
2378: match method::lookup(fcx,
2379: expr,
librustc/middle/typeck/check/method.rs:109:16-109:16 -enum- definition:
pub enum CheckTraitsFlag {
CheckTraitsOnly,
CheckTraitsAndInherentMethods,
references:- 5136: deref_args: check::DerefArgs, // Whether we autopointer first.
137: check_traits: CheckTraitsFlag, // Whether we check traits only.
138: autoderef_receiver: AutoderefReceiverFlag,
--
309: deref_args: check::DerefArgs,
310: check_traits: CheckTraitsFlag,
311: autoderef_receiver: AutoderefReceiverFlag,
librustc/middle/typeck/check/method.rs:173:1-173:1 -fn- definition:
pub fn lookup_in_trait<'a>(
fcx: &'a FnCtxt<'a>,
// In a call `a.b::<X, Y, ...>(...)`:
references:- 3librustc/middle/typeck/check/mod.rs:
1376: (None, Some(trait_did)) => {
1377: method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
1378: token::intern("deref"), trait_did,
--
2056: Some(trait_did) => {
2057: method::lookup_in_trait(fcx, op_ex.span, Some(&*args[0]), opname,
2058: trait_did, self_t, [], autoderef_receiver,
librustc/middle/typeck/check/method.rs:1426:8-1426:8 -fn- definition:
fn mutability_matches(self_mutbl: ast::Mutability,
candidate_mutbl: ast::Mutability)
-> bool {
references:- 21363: ty::ty_vec(_, None) | ty::ty_str => false,
1364: _ => mutability_matches(mt.mutbl, m) &&
1365: rcvr_matches_ty(self.fcx, mt.ty, candidate),
--
1371: }) => {
1372: mutability_matches(self_m, m) &&
1373: rcvr_matches_object(self_did, candidate)
librustc/middle/typeck/check/method.rs:121:16-121:16 -enum- definition:
pub enum StaticMethodsFlag {
ReportStaticMethods,
IgnoreStaticMethods,
references:- 6122: pub enum StaticMethodsFlag {
--
184: autoderef_receiver: AutoderefReceiverFlag,
185: report_statics: StaticMethodsFlag)
186: -> Option<MethodCallee> {
--
311: autoderef_receiver: AutoderefReceiverFlag,
312: report_statics: StaticMethodsFlag,
313: }
librustc/middle/typeck/check/method.rs:293:1-293:1 -struct- definition:
struct LookupContext<'a> {
fcx: &'a FnCtxt<'a>,
span: Span,
references:- 3140: -> Option<MethodCallee> {
141: let mut lcx = LookupContext {
142: fcx: fcx,
--
341: impl<'a> LookupContext<'a> {
342: fn search(&self, self_ty: ty::t) -> Option<MethodCallee> {
librustc/middle/typeck/check/method.rs:335:19-335:19 -enum- definition:
pub enum RcvrMatchCondition {
RcvrMatchesIfObject(ast::DefId),
RcvrMatchesIfSubtype(ty::t)
references:- 4334: /// because traits are not types, this is a pain to do.
336: pub enum RcvrMatchCondition {
--
1524: impl Repr for RcvrMatchCondition {
1525: fn repr(&self, tcx: &ty::ctxt) -> ~str {