method.rs 48.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
/*!

# Method lookup

Method lookup can be rather complex due to the interaction of a number
of factors, such as self types, autoderef, trait lookup, etc.  The
algorithm is divided into two parts: candidate collection and
candidate selection.

## Candidate collection

A `Candidate` is a method item that might plausibly be the method
being invoked.  Candidates are grouped into two kinds, inherent and
extension.  Inherent candidates are those that are derived from the
type of the receiver itself.  So, if you have a receiver of some
nominal type `Foo` (e.g., a struct), any methods defined within an
impl like `impl Foo` are inherent methods.  Nothing needs to be
imported to use an inherent method, they are associated with the type
itself (note that inherent impls can only be defined in the same
module as the type itself).

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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
methods (`to_str()`, in this case) are inherently associated with it.
Another case is type parameters, in which case the methods of their
bounds are inherent.

Extension candidates are derived from imported traits.  If I have the
trait `ToStr` imported, and I call `to_str()` on a value of type `T`,
then we will go off to find out whether there is an impl of `ToStr`
for `T`.  These kinds of method calls are called "extension methods".
They can be defined in any module, not only the one that defined `T`.
Furthermore, you must import the trait to call such a method.

For better or worse, we currently give weight to inherent methods over
extension methods during candidate selection (below).

## Candidate selection

Once we know the set of candidates, we can go off and try to select
which one is actually being called.  We do this by taking the type of
the receiver, let's call it R, and checking whether it matches against
the expected receiver type for each of the collected candidates.  We
first check for inherent candidates and see whether we get exactly one
match (zero means keep searching, more than one is an error).  If so,
we return that as the candidate.  Otherwise we search the extension
candidates in the same way.

If find no matching candidate at all, we proceed to auto-deref the
receiver type and search again.  We keep doing that until we cannot
61 62 63 64 65 66
auto-deref any longer.  At each step, we also check for candidates
based on "autoptr", which if the current type is `T`, checks for `&mut
T`, `&const T`, and `&T` receivers.  Finally, at the very end, we will
also try autoslice, which converts `~[]` to `&[]` (there is no point
at trying autoslice earlier, because no autoderefable type is also
sliceable).
67 68 69 70 71 72 73 74 75 76 77 78 79 80

## Why two phases?

You might wonder why we first collect the candidates and then select.
Both the inherent candidate collection and the candidate selection
proceed by progressively deref'ing the receiver type, after all.  The
answer is that two phases are needed to elegantly deal with explicit
self.  After all, if there is an impl for the type `Foo`, it can
define a method with the type `@self`, which means that it expects a
receiver of type `@Foo`.  If we have a receiver of type `@Foo`, but we
waited to search for that impl until we have deref'd the `@` away and
obtained the type `Foo`, we would never match this method.

*/
81

82
use middle::resolve;
83
use middle::ty::*;
84
use middle::ty;
85
use middle::typeck::check::{FnCtxt, impl_self_ty};
86 87
use middle::typeck::check::{structurally_resolved_type};
use middle::typeck::check::vtable::VtableContext;
88
use middle::typeck::check::vtable;
89
use middle::typeck::check;
90
use middle::typeck::infer;
91
use middle::typeck::{method_map_entry, method_origin, method_param};
92
use middle::typeck::{method_self, method_static, method_trait, method_super};
93
use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig;
94
use util::common::indenter;
95

96
use core::hashmap::HashSet;
97
use std::list::Nil;
98
use syntax::ast::{def_id, sty_value, sty_region, sty_box};
99
use syntax::ast::{sty_uniq, sty_static, node_id};
100
use syntax::ast::{m_const, m_mutbl, m_imm};
101
use syntax::ast;
P
Patrick Walton 已提交
102
use syntax::ast_map;
103

104
#[deriving(Eq)]
105 106 107 108 109
pub enum CheckTraitsFlag {
    CheckTraitsOnly,
    CheckTraitsAndInherentMethods,
}

110
#[deriving(Eq)]
111 112 113 114
pub enum AutoderefReceiverFlag {
    AutoderefReceiver,
    DontAutoderefReceiver,
}
B
Brian Anderson 已提交
115

116 117 118 119
pub fn lookup(
        fcx: @mut FnCtxt,

        // In a call `a.b::<X, Y, ...>(...)`:
120
        expr: @ast::expr,                   // The expression `a.b(...)`.
121
        self_expr: @ast::expr,              // The expression `a`.
N
Niko Matsakis 已提交
122 123
        callee_id: node_id,                 /* Where to store `a.b`'s type,
                                             * also the scope of the call */ 
124 125 126 127 128 129 130
        m_name: ast::ident,                 // The ident `b`.
        self_ty: ty::t,                     // The type of `a`.
        supplied_tps: &[ty::t],             // The list of types X, Y, ... .
        deref_args: check::DerefArgs,       // Whether we autopointer first.
        check_traits: CheckTraitsFlag,      // Whether we check traits only.
        autoderef_receiver: AutoderefReceiverFlag)
     -> Option<method_map_entry> {
N
Niko Matsakis 已提交
131
    let mut impl_dups = @mut HashSet::new();
132
    let lcx = LookupContext {
B
Brian Anderson 已提交
133 134 135
        fcx: fcx,
        expr: expr,
        self_expr: self_expr,
136
        callee_id: callee_id,
B
Brian Anderson 已提交
137 138
        m_name: m_name,
        supplied_tps: supplied_tps,
N
Niko Matsakis 已提交
139
        impl_dups: impl_dups,
A
Alex Crichton 已提交
140 141
        inherent_candidates: @mut ~[],
        extension_candidates: @mut ~[],
142
        deref_args: deref_args,
143
        check_traits: check_traits,
144
        autoderef_receiver: autoderef_receiver,
145
    };
146
    let mme = lcx.do_lookup(self_ty);
147
    debug!("method lookup for %s yielded %?", expr.repr(fcx.tcx()), mme);
L
Luqman Aden 已提交
148
    return mme;
B
Brian Anderson 已提交
149 150
}

151
pub struct LookupContext<'self> {
152
    fcx: @mut FnCtxt,
153 154
    expr: @ast::expr,
    self_expr: @ast::expr,
155
    callee_id: node_id,
156
    m_name: ast::ident,
157
    supplied_tps: &'self [ty::t],
N
Niko Matsakis 已提交
158
    impl_dups: @mut HashSet<def_id>,
A
Alex Crichton 已提交
159 160
    inherent_candidates: @mut ~[Candidate],
    extension_candidates: @mut ~[Candidate],
161
    deref_args: check::DerefArgs,
162
    check_traits: CheckTraitsFlag,
163
    autoderef_receiver: AutoderefReceiverFlag,
164 165
}

166 167
/**
 * A potential method that might be called, assuming the receiver
168 169 170
 * is of a suitable type.
 */
pub struct Candidate {
171 172
    rcvr_ty: ty::t,
    rcvr_substs: ty::substs,
173
    method_ty: @ty::method,
174 175
    origin: method_origin,
}
176

177
pub impl<'self> LookupContext<'self> {
178
    fn do_lookup(&self, self_ty: ty::t) -> Option<method_map_entry> {
179
        let self_ty = structurally_resolved_type(self.fcx,
T
Tim Chevalier 已提交
180 181 182
                                                     self.self_expr.span,
                                                     self_ty);

183 184
        debug!("do_lookup(self_ty=%s, expr=%s, self_expr=%s)",
               self.ty_to_str(self_ty),
185 186
               self.expr.repr(self.tcx()),
               self.self_expr.repr(self.tcx()));
187 188 189

        // Prepare the list of candidates
        self.push_inherent_candidates(self_ty);
190
        self.push_extension_candidates(self_ty);
191

A
Alex Crichton 已提交
192
        let mut enum_dids = ~[];
193 194
        let mut self_ty = self_ty;
        let mut autoderefs = 0;
195
        loop {
196 197 198
            debug!("loop: self_ty=%s autoderefs=%u",
                   self.ty_to_str(self_ty), autoderefs);

199 200 201 202
            match self.deref_args {
                check::DontDerefArgs => {
                    match self.search_for_autoderefd_method(self_ty,
                                                            autoderefs) {
L
Luqman Aden 已提交
203
                        Some(mme) => { return Some(mme); }
204 205 206 207 208
                        None => {}
                    }

                    match self.search_for_autoptrd_method(self_ty,
                                                          autoderefs) {
L
Luqman Aden 已提交
209
                        Some(mme) => { return Some(mme); }
210 211 212 213 214 215
                        None => {}
                    }
                }
                check::DoDerefArgs => {
                    match self.search_for_autoptrd_method(self_ty,
                                                          autoderefs) {
L
Luqman Aden 已提交
216
                        Some(mme) => { return Some(mme); }
217 218 219 220 221
                        None => {}
                    }

                    match self.search_for_autoderefd_method(self_ty,
                                                            autoderefs) {
L
Luqman Aden 已提交
222
                        Some(mme) => { return Some(mme); }
223 224 225
                        None => {}
                    }
                }
226 227
            }

228 229 230 231 232 233
            // Don't autoderef if we aren't supposed to.
            if self.autoderef_receiver == DontAutoderefReceiver {
                break;
            }

            // Otherwise, perform autoderef.
A
Alex Crichton 已提交
234
            match self.deref(self_ty, &mut enum_dids) {
235 236 237 238 239 240
                None => { break; }
                Some(ty) => {
                    self_ty = ty;
                    autoderefs += 1;
                }
            }
241
        }
242

243
        self.search_for_autosliced_method(self_ty, autoderefs)
244
    }
245

246 247
    fn deref(&self, ty: ty::t, enum_dids: &mut ~[ast::def_id])
            -> Option<ty::t> {
248 249 250 251
        match ty::get(ty).sty {
            ty_enum(did, _) => {
                // Watch out for newtype'd enums like "enum t = @T".
                // See discussion in typeck::check::do_autoderef().
T
Tim Chevalier 已提交
252
                if enum_dids.contains(&did) {
253
                    return None;
254
                }
255
                enum_dids.push(did);
256
            }
257
            _ => {}
258 259
        }

260 261 262 263 264 265 266 267
        match ty::deref(self.tcx(), ty, false) {
            None => None,
            Some(t) => {
                Some(structurally_resolved_type(self.fcx,
                                                self.self_expr.span,
                                                t.ty))
            }
        }
268 269
    }

270 271 272 273 274 275 276 277 278 279
    // ______________________________________________________________________
    // Candidate collection (see comment at start of file)

    fn push_inherent_candidates(&self, self_ty: ty::t) {
        /*!
         * Collect all inherent candidates into
         * `self.inherent_candidates`.  See comment at the start of
         * the file.  To find the inherent candidates, we repeatedly
         * deref the self-ty to find the "base-type".  So, for
         * example, if the receiver is @@C where `C` is a struct type,
280 281
         * we'll want to find the inherent impls for `C`.
         */
282

A
Alex Crichton 已提交
283
        let mut enum_dids = ~[];
284 285 286 287
        let mut self_ty = self_ty;
        loop {
            match get(self_ty).sty {
                ty_param(p) => {
288
                    self.push_inherent_candidates_from_param(self_ty, p);
289
                }
290
                ty_trait(did, ref substs, store, _) => {
291
                    self.push_inherent_candidates_from_trait(
292
                        self_ty, did, substs, store);
293 294
                    self.push_inherent_impl_candidates_for_type(did);
                }
295
                ty_self(self_did) => {
296 297
                    // Call is of the form "self.foo()" and appears in one
                    // of a trait's default method implementations.
298 299 300 301 302
                    let substs = substs {
                        self_r: None,
                        self_ty: None,
                        tps: ~[]
                    };
303 304
                    self.push_inherent_candidates_from_self(
                        self_ty, self_did, &substs);
305
                }
306
                ty_enum(did, _) | ty_struct(did, _) => {
307 308 309
                    if self.check_traits == CheckTraitsAndInherentMethods {
                        self.push_inherent_impl_candidates_for_type(did);
                    }
310 311 312
                }
                _ => { /* No inherent methods in these types */ }
            }
313

314 315 316
            // n.b.: Generally speaking, we only loop if we hit the
            // fallthrough case in the match above.  The exception
            // would be newtype enums.
A
Alex Crichton 已提交
317
            self_ty = match self.deref(self_ty, &mut enum_dids) {
318 319
                None => { return; }
                Some(ty) => { ty }
320
            }
321
        }
322 323
    }

324
    fn push_extension_candidates(&self, self_ty: ty::t) {
325 326 327
        // If the method being called is associated with a trait, then
        // find all the impls of that trait.  Each of those are
        // candidates.
328 329
        let trait_map: &mut resolve::TraitMap = &mut self.fcx.ccx.trait_map;
        let opt_applicable_traits = trait_map.find(&self.expr.id);
330 331 332
        for opt_applicable_traits.each |applicable_traits| {
            for applicable_traits.each |trait_did| {
                let coherence_info = self.fcx.ccx.coherence_info;
333 334

                // Look for explicit implementations.
335
                let opt_impl_infos =
336
                    coherence_info.extension_methods.find(trait_did);
337 338 339
                for opt_impl_infos.each |impl_infos| {
                    for impl_infos.each |impl_info| {
                        self.push_candidates_from_impl(
A
Alex Crichton 已提交
340
                            self.extension_candidates, *impl_info);
341 342
                    }
                }
343 344

                // Look for default methods.
345
                match self.tcx().provided_methods.find(trait_did) {
346
                    Some(&methods) => {
347
                        self.push_candidates_from_provided_methods(
A
Alex Crichton 已提交
348
                            self.extension_candidates, self_ty, *trait_did,
349 350 351 352
                            methods);
                    }
                    None => {}
                }
353 354
            }
        }
355 356
    }

357 358
    fn push_inherent_candidates_from_param(&self,
                                           rcvr_ty: ty::t,
359
                                           param_ty: param_ty) {
360 361 362
        debug!("push_inherent_candidates_from_param(param_ty=%?)",
               param_ty);
        let _indenter = indenter();
363

364 365
        let tcx = self.tcx();
        let mut next_bound_idx = 0; // count only trait bounds
N
Niko Matsakis 已提交
366 367 368 369 370 371 372 373
        let type_param_def = match tcx.ty_param_defs.find(&param_ty.def_id.node) {
            Some(t) => t,
            None => {
                tcx.sess.span_bug(
                    self.expr.span,
                    fmt!("No param def for %?", param_ty));
            }
        };
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392

        for ty::each_bound_trait_and_supertraits(tcx, type_param_def.bounds)
            |bound_trait_ref|
        {
            let this_bound_idx = next_bound_idx;
            next_bound_idx += 1;

            let trait_methods = ty::trait_methods(tcx, bound_trait_ref.def_id);
            let pos = {
                match trait_methods.position(|m| {
                    m.self_ty != ast::sty_static &&
                        m.ident == self.m_name })
                {
                    Some(pos) => pos,
                    None => {
                        debug!("trait doesn't contain method: %?",
                               bound_trait_ref.def_id);
                        loop; // check next trait or bound
                    }
393 394
                }
            };
395
            let method = trait_methods[pos];
396

397 398
            let cand = Candidate {
                rcvr_ty: rcvr_ty,
399
                rcvr_substs: copy bound_trait_ref.substs,
400 401 402 403 404 405 406 407 408
                method_ty: method,
                origin: method_param(
                    method_param {
                        trait_id: bound_trait_ref.def_id,
                        method_num: pos,
                        param_num: param_ty.idx,
                        bound_num: this_bound_idx,
                    })
            };
409

410 411
            debug!("pushing inherent candidate for param: %?", cand);
            self.inherent_candidates.push(cand);
412 413 414
        }
    }

415 416 417
    fn push_inherent_candidates_from_trait(&self,
                                           self_ty: ty::t,
                                           did: def_id,
418
                                           substs: &ty::substs,
419
                                           store: ty::TraitStore) {
420 421 422 423
        debug!("push_inherent_candidates_from_trait(did=%s, substs=%s)",
               self.did_to_str(did),
               substs_to_str(self.tcx(), substs));
        let _indenter = indenter();
424

425
        let tcx = self.tcx();
426 427 428 429 430
        let ms = ty::trait_methods(tcx, did);
        let index = match vec::position(*ms, |m| m.ident == self.m_name) {
            Some(i) => i,
            None => { return; } // no method with the right name
        };
431
        let method = ms[index];
432

433
        /* FIXME(#5762) we should transform the vstore in accordance
434 435 436 437 438
           with the self type

        match method.self_type {
            ast::sty_region(_) => {
                return; // inapplicable
439
            }
440
            ast::sty_region(_) => vstore_slice(r)
441 442
            ast::sty_box(_) => vstore_box, // XXX NDM mutability
            ast::sty_uniq(_) => vstore_uniq
443
        }
444
        */
445

446 447 448 449 450
        // It is illegal to invoke a method on a trait instance that
        // refers to the `self` type.  Nonetheless, we substitute
        // `trait_ty` for `self` here, because it allows the compiler
        // to soldier on.  An error will be reported should this
        // candidate be selected if the method refers to `self`.
451 452 453
        //
        // NB: `confirm_candidate()` also relies upon this substitution
        // for Self.
454 455 456 457
        let rcvr_substs = substs {
            self_ty: Some(self_ty),
            ../*bad*/copy *substs
        };
458 459

        self.inherent_candidates.push(Candidate {
460
            rcvr_ty: self_ty,
L
Luqman Aden 已提交
461
            rcvr_substs: rcvr_substs,
462
            method_ty: method,
463
            origin: method_trait(did, index, store)
464
        });
465 466
    }

467 468 469 470
    fn push_inherent_candidates_from_self(&self,
                                          self_ty: ty::t,
                                          did: def_id,
                                          substs: &ty::substs) {
471 472 473 474 475 476
        struct MethodInfo {
            method_ty: @ty::method,
            trait_def_id: ast::def_id,
            index: uint
        }

477
        let tcx = self.tcx();
478
        // First, try self methods
479
        let mut method_info: Option<MethodInfo> = None;
480
        let methods = ty::trait_methods(tcx, did);
481
        match vec::position(*methods, |m| m.ident == self.m_name) {
482
            Some(i) => {
483 484 485 486 487
                method_info = Some(MethodInfo {
                    method_ty: methods[i],
                    index: i,
                    trait_def_id: did
                });
488 489
            }
            None => ()
490
        }
491
        // No method found yet? Check each supertrait
492
        if method_info.is_none() {
493 494 495 496 497 498
            for ty::trait_supertraits(tcx, did).each() |trait_ref| {
                let supertrait_methods =
                    ty::trait_methods(tcx, trait_ref.def_id);
                match vec::position(*supertrait_methods,
                                    |m| m.ident == self.m_name) {
                    Some(i) => {
499 500 501 502 503
                        method_info = Some(MethodInfo {
                            method_ty: supertrait_methods[i],
                            index: i,
                            trait_def_id: trait_ref.def_id
                        });
504 505 506 507 508 509
                        break;
                    }
                    None => ()
                }
            }
        }
510 511
        match method_info {
            Some(ref info) => {
512
                // We've found a method -- return it
513
                let rcvr_substs = substs {self_ty: Some(self_ty),
514
                                          ..copy *substs };
515 516 517 518
                let origin = if did == info.trait_def_id {
                    method_self(info.trait_def_id, info.index)
                } else {
                    method_super(info.trait_def_id, info.index)
519 520
                };
                self.inherent_candidates.push(Candidate {
521
                    rcvr_ty: self_ty,
L
Luqman Aden 已提交
522
                    rcvr_substs: rcvr_substs,
523
                    method_ty: info.method_ty,
524 525 526 527 528
                    origin: origin
                });
            }
            _ => return
        }
529 530
    }

531
    fn push_inherent_impl_candidates_for_type(&self, did: def_id) {
532
        let opt_impl_infos =
533
            self.fcx.ccx.coherence_info.inherent_methods.find(&did);
534 535 536
        for opt_impl_infos.each |impl_infos| {
            for impl_infos.each |impl_info| {
                self.push_candidates_from_impl(
A
Alex Crichton 已提交
537
                    self.inherent_candidates, *impl_info);
538 539 540
            }
        }
    }
541

A
Alex Crichton 已提交
542
    fn push_candidates_from_impl(&self, candidates: &mut ~[Candidate],
543
                                 impl_info: &resolve::Impl) {
544
        if !self.impl_dups.insert(impl_info.did) {
545 546
            return; // already visited
        }
547

548
        let idx = {
549
            match impl_info.methods.position(|m| m.ident == self.m_name) {
550 551 552 553
                Some(idx) => idx,
                None => { return; } // No method with the right name.
            }
        };
554

555
        let method = ty::method(self.tcx(), impl_info.methods[idx].did);
556

557 558
        // determine the `self` of the impl with fresh
        // variables for each parameter:
559
        let location_info = &vtable::location_info_for_expr(self.self_expr);
560 561 562 563
        let vcx = VtableContext {
            ccx: self.fcx.ccx,
            infcx: self.fcx.infcx()
        };
564 565 566 567
        let ty::ty_param_substs_and_ty {
            substs: impl_substs,
            ty: impl_ty
        } = impl_self_ty(&vcx, location_info, impl_info.did);
568

569 570
        candidates.push(Candidate {
            rcvr_ty: impl_ty,
L
Luqman Aden 已提交
571
            rcvr_substs: impl_substs,
572 573
            method_ty: method,
            origin: method_static(method.def_id)
574 575
        });
    }
576

577 578
    fn push_candidates_from_provided_methods(
            &self,
A
Alex Crichton 已提交
579
            candidates: &mut ~[Candidate],
580 581
            self_ty: ty::t,
            trait_def_id: def_id,
A
Alex Crichton 已提交
582
            methods: &mut ~[@ProvidedMethodInfo]) {
583 584 585 586 587 588 589 590 591 592 593
        debug!("(pushing candidates from provided methods) considering trait \
                id %d:%d",
               trait_def_id.crate,
               trait_def_id.node);

        for methods.each |provided_method_info| {
            if provided_method_info.method_info.ident != self.m_name { loop; }

            debug!("(pushing candidates from provided methods) adding \
                    candidate");

594 595 596
            let method = ty::method(self.tcx(),
                                    provided_method_info.method_info.did);

597
            // XXX: Needs to support generics.
598 599 600 601 602
            let dummy_substs = substs {
                self_r: None,
                self_ty: None,
                tps: ~[]
            };
603 604

            candidates.push(Candidate {
605 606
                rcvr_ty: self_ty,
                rcvr_substs: dummy_substs,
607
                method_ty: method,
608 609 610 611 612
                origin: method_static(provided_method_info.method_info.did)
            });
        }
    }

613 614 615 616 617 618 619 620 621
    // ______________________________________________________________________
    // Candidate selection (see comment at start of file)

    fn search_for_autoderefd_method(
        &self,
        self_ty: ty::t,
        autoderefs: uint)
        -> Option<method_map_entry>
    {
622 623
        let (self_ty, autoadjust) =
            self.consider_reborrow(self_ty, autoderefs);
624 625
        match self.search_for_method(self_ty) {
            None => None,
L
Luqman Aden 已提交
626
            Some(mme) => {
627 628 629 630
                debug!("(searching for autoderef'd method) writing \
                       adjustment (%u) to %d",
                       autoderefs,
                       self.self_expr.id);
631
                self.fcx.write_adjustment(self.self_expr.id, @autoadjust);
632 633
                Some(mme)
            }
634 635 636
        }
    }

637 638 639 640 641 642 643
    fn consider_reborrow(&self,
                         self_ty: ty::t,
                         autoderefs: uint) -> (ty::t, ty::AutoAdjustment)
    {
        /*!
         *
         * In the event that we are invoking a method with a receiver
N
Niko Matsakis 已提交
644
         * of a borrowed type like `&T`, `&mut T`, or `&mut [T]`,
645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660
         * we will "reborrow" the receiver implicitly.  For example, if
         * you have a call `r.inc()` and where `r` has type `&mut T`,
         * then we treat that like `(&mut *r).inc()`.  This avoids
         * consuming the original pointer.
         *
         * You might think that this would be a natural byproduct of
         * the auto-deref/auto-ref process.  This is true for `@mut T`
         * but not for an `&mut T` receiver.  With `@mut T`, we would
         * begin by testing for methods with a self type `@mut T`,
         * then autoderef to `T`, then autoref to `&mut T`.  But with
         * an `&mut T` receiver the process begins with `&mut T`, only
         * without any autoadjustments.
         */

        let tcx = self.tcx();
        return match ty::get(self_ty).sty {
661 662 663 664 665 666
            ty::ty_rptr(_, self_mt) if default_method_hack(self_mt) => {
                (self_ty,
                 ty::AutoDerefRef(ty::AutoDerefRef {
                     autoderefs: autoderefs,
                     autoref: None}))
            }
N
Niko Matsakis 已提交
667 668
            ty::ty_rptr(_, self_mt) => {
                let region = self.infcx().next_region_var_nb(self.expr.span);
669
                (ty::mk_rptr(tcx, region, self_mt),
670
                 ty::AutoDerefRef(ty::AutoDerefRef {
671
                     autoderefs: autoderefs+1,
N
Niko Matsakis 已提交
672
                     autoref: Some(ty::AutoPtr(region, self_mt.mutbl))}))
673
            }
N
Niko Matsakis 已提交
674 675
            ty::ty_evec(self_mt, vstore_slice(_)) => {
                let region = self.infcx().next_region_var_nb(self.expr.span);
676
                (ty::mk_evec(tcx, self_mt, vstore_slice(region)),
677
                 ty::AutoDerefRef(ty::AutoDerefRef {
N
Niko Matsakis 已提交
678 679
                     autoderefs: autoderefs,
                     autoref: Some(ty::AutoBorrowVec(region, self_mt.mutbl))}))
680 681
            }
            _ => {
682 683 684 685
                (self_ty,
                 ty::AutoDerefRef(ty::AutoDerefRef {
                     autoderefs: autoderefs,
                     autoref: None}))
686 687
            }
        };
688 689 690 691 692 693 694 695 696 697

        fn default_method_hack(self_mt: ty::mt) -> bool {
            // FIXME(#6129). Default methods can't deal with autoref.
            //
            // I am a horrible monster and I pray for death. Currently
            // the default method code fails when you try to reborrow
            // because it is not handling types correctly. In lieu of
            // fixing that, I am introducing this horrible hack. - ndm
            self_mt.mutbl == m_imm && ty::type_is_self(self_mt.ty)
        }
698 699
    }

700 701 702 703 704 705 706 707 708 709
    fn search_for_autosliced_method(
        &self,
        self_ty: ty::t,
        autoderefs: uint)
        -> Option<method_map_entry>
    {
        /*!
         *
         * Searches for a candidate by converting things like
         * `~[]` to `&[]`. */
710

711
        let tcx = self.tcx();
712
        match ty::get(self_ty).sty {
713 714
            ty_evec(mt, vstore_box) |
            ty_evec(mt, vstore_uniq) |
715
            ty_evec(mt, vstore_slice(_)) | // NDM(#3148)
716
            ty_evec(mt, vstore_fixed(_)) => {
717 718
                // First try to borrow to a slice
                let entry = self.search_for_some_kind_of_autorefd_method(
719
                    AutoBorrowVec, autoderefs, [m_const, m_imm, m_mutbl],
720
                    |m,r| ty::mk_evec(tcx,
721
                                      ty::mt {ty:mt.ty, mutbl:m},
722 723 724 725 726 727 728 729 730
                                      vstore_slice(r)));

                if entry.is_some() { return entry; }

                // Then try to borrow to a slice *and* borrow a pointer.
                self.search_for_some_kind_of_autorefd_method(
                    AutoBorrowVecRef, autoderefs, [m_const, m_imm, m_mutbl],
                    |m,r| {
                        let slice_ty = ty::mk_evec(tcx,
731
                                                   ty::mt {ty:mt.ty, mutbl:m},
732 733 734 735 736 737
                                                   vstore_slice(r));
                        // NB: we do not try to autoref to a mutable
                        // pointer. That would be creating a pointer
                        // to a temporary pointer (the borrowed
                        // slice), so any update the callee makes to
                        // it can't be observed.
738
                        ty::mk_rptr(tcx, r, ty::mt {ty:slice_ty, mutbl:m_imm})
739
                    })
740
            }
741

742 743 744
            ty_estr(vstore_box) |
            ty_estr(vstore_uniq) |
            ty_estr(vstore_fixed(_)) => {
745
                let entry = self.search_for_some_kind_of_autorefd_method(
746
                    AutoBorrowVec, autoderefs, [m_imm],
747 748 749 750 751 752 753 754
                    |_m,r| ty::mk_estr(tcx, vstore_slice(r)));

                if entry.is_some() { return entry; }

                self.search_for_some_kind_of_autorefd_method(
                    AutoBorrowVecRef, autoderefs, [m_imm],
                    |m,r| {
                        let slice_ty = ty::mk_estr(tcx, vstore_slice(r));
755
                        ty::mk_rptr(tcx, r, ty::mt {ty:slice_ty, mutbl:m})
756
                    })
757 758
            }

759
            ty_trait(*) | ty_closure(*) => {
760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779
                // NDM---eventually these should be some variant of autoref
                None
            }

            _ => None
        }
    }

    fn search_for_autoptrd_method(
        &self,
        self_ty: ty::t,
        autoderefs: uint)
        -> Option<method_map_entry>
    {
        /*!
         *
         * Converts any type `T` to `&M T` where `M` is an
         * appropriate mutability.
         */

780
        let tcx = self.tcx();
781
        match ty::get(self_ty).sty {
782
            ty_bare_fn(*) | ty_box(*) | ty_uniq(*) | ty_rptr(*) |
783 784
            ty_infer(IntVar(_)) |
            ty_infer(FloatVar(_)) |
785
            ty_self(_) | ty_param(*) | ty_nil | ty_bot | ty_bool |
786
            ty_int(*) | ty_uint(*) |
787 788
            ty_float(*) | ty_enum(*) | ty_ptr(*) | ty_struct(*) | ty_tup(*) |
            ty_estr(*) | ty_evec(*) | ty_trait(*) | ty_closure(*) => {
789 790
                self.search_for_some_kind_of_autorefd_method(
                    AutoPtr, autoderefs, [m_const, m_imm, m_mutbl],
791
                    |m,r| ty::mk_rptr(tcx, r, ty::mt {ty:self_ty, mutbl:m}))
792
            }
793

794 795
            ty_err => None,

796 797 798 799
            ty_opaque_closure_ptr(_) | ty_unboxed_vec(_) |
            ty_opaque_box | ty_type | ty_infer(TyVar(_)) => {
                self.bug(fmt!("Unexpected type: %s",
                              self.ty_to_str(self_ty)));
800 801 802 803
            }
        }
    }

804
    fn search_for_some_kind_of_autorefd_method(
805
        &self,
N
Niko Matsakis 已提交
806
        kind: &fn(Region, ast::mutability) -> ty::AutoRef,
807 808
        autoderefs: uint,
        mutbls: &[ast::mutability],
809
        mk_autoref_ty: &fn(ast::mutability, ty::Region) -> ty::t)
810 811 812 813
        -> Option<method_map_entry>
    {
        // This is hokey. We should have mutability inference as a
        // variable.  But for now, try &const, then &, then &mut:
N
Niko Matsakis 已提交
814
        let region = self.infcx().next_region_var_nb(self.expr.span);
815
        for mutbls.each |mutbl| {
816
            let autoref_ty = mk_autoref_ty(*mutbl, region);
817 818
            match self.search_for_method(autoref_ty) {
                None => {}
L
Luqman Aden 已提交
819
                Some(mme) => {
820 821
                    self.fcx.write_adjustment(
                        self.self_expr.id,
822
                        @ty::AutoDerefRef(ty::AutoDerefRef {
823
                            autoderefs: autoderefs,
N
Niko Matsakis 已提交
824
                            autoref: Some(kind(region, *mutbl))}));
825 826
                    return Some(mme);
                }
827
            }
828
        }
829
        return None;
830 831
    }

832 833 834 835 836 837 838 839 840 841 842 843
    fn search_for_method(&self,
                         self_ty: ty::t)
        -> Option<method_map_entry>
    {
        debug!("search_for_method(self_ty=%s)", self.ty_to_str(self_ty));
        let _indenter = indenter();

        // I am not sure that inherent methods should have higher
        // priority, but it is necessary ATM to handle some of the
        // existing code.

        debug!("searching inherent candidates");
A
Alex Crichton 已提交
844
        match self.consider_candidates(self_ty, self.inherent_candidates) {
845
            None => {}
L
Luqman Aden 已提交
846 847
            Some(mme) => {
                return Some(mme);
848 849 850
            }
        }

851
        debug!("searching extension candidates");
A
Alex Crichton 已提交
852
        match self.consider_candidates(self_ty, self.extension_candidates) {
853 854 855
            None => {
                return None;
            }
L
Luqman Aden 已提交
856 857
            Some(mme) => {
                return Some(mme);
858 859
            }
        }
860 861
    }

862 863
    fn consider_candidates(&self,
                           self_ty: ty::t,
A
Alex Crichton 已提交
864
                           candidates: &mut ~[Candidate])
865 866 867
        -> Option<method_map_entry>
    {
        let relevant_candidates =
868
            candidates.filter_to_vec(|c| self.is_relevant(self_ty, c));
869

870 871
        let relevant_candidates = self.merge_candidates(relevant_candidates);

872 873
        if relevant_candidates.len() == 0 {
            return None;
874 875
        }

876 877 878 879 880 881
        if relevant_candidates.len() > 1 {
            self.tcx().sess.span_err(
                self.expr.span,
                ~"multiple applicable methods in scope");
            for uint::range(0, relevant_candidates.len()) |idx| {
                self.report_candidate(idx, &relevant_candidates[idx].origin);
882 883 884
            }
        }

885
        Some(self.confirm_candidate(self_ty, &relevant_candidates[0]))
886 887
    }

888 889 890 891
    fn merge_candidates(&self, candidates: &[Candidate]) -> ~[Candidate] {
        let mut merged = ~[];
        let mut i = 0;
        while i < candidates.len() {
892
            let candidate_a = /*bad*/copy candidates[i];
893 894 895 896 897

            let mut skip = false;

            let mut j = i + 1;
            while j < candidates.len() {
898
                let candidate_b = &candidates[j];
899 900 901 902
                debug!("attempting to merge %? and %?",
                       candidate_a, candidate_b);
                let candidates_same = match (&candidate_a.origin,
                                             &candidate_b.origin) {
903
                    (&method_param(ref p1), &method_param(ref p2)) => {
P
Patrick Walton 已提交
904 905 906
                        let same_trait = p1.trait_id == p2.trait_id;
                        let same_method = p1.method_num == p2.method_num;
                        let same_param = p1.param_num == p2.param_num;
907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933
                        // The bound number may be different because
                        // multiple bounds may lead to the same trait
                        // impl
                        same_trait && same_method && same_param
                    }
                    _ => false
                };
                if candidates_same {
                    skip = true;
                    break;
                }
                j += 1;
            }

            i += 1;

            if skip {
                // There are more than one of these and we need only one
                loop;
            } else {
                merged.push(candidate_a);
            }
        }

        return merged;
    }

934 935 936
    fn confirm_candidate(&self,
                         self_ty: ty::t,
                         candidate: &Candidate)
937 938
        -> method_map_entry
    {
939 940 941
        let tcx = self.tcx();
        let fty = self.fn_ty_from_origin(&candidate.origin);

942
        debug!("confirm_candidate(expr=%s, candidate=%s, fty=%s)",
943
               self.expr.repr(tcx),
944 945 946
               self.cand_to_str(candidate),
               self.ty_to_str(fty));

947
        self.enforce_trait_instance_limitations(fty, candidate);
948
        self.enforce_drop_trait_limitations(candidate);
949

950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971
        // static methods should never have gotten this far:
        assert!(candidate.method_ty.self_ty != sty_static);

        let transformed_self_ty = match candidate.origin {
            method_trait(*) => {
                match candidate.method_ty.self_ty {
                    sty_region(*) => {
                        // FIXME(#5762) again, preserving existing
                        // behavior here which (for &self) desires
                        // &@Trait where @Trait is the type of the
                        // receiver.  Here we fetch the method's
                        // transformed_self_ty which will be something
                        // like &'a Self.  We then perform a
                        // substitution which will replace Self with
                        // @Trait.
                        let t = candidate.method_ty.transformed_self_ty.get();
                        ty::subst(tcx, &candidate.rcvr_substs, t)
                    }
                    _ => {
                        candidate.rcvr_ty
                    }
                }
972
            }
973 974 975 976 977
            _ => {
                let t = candidate.method_ty.transformed_self_ty.get();
                ty::subst(tcx, &candidate.rcvr_substs, t)
            }
        };
978

979 980 981 982
        // Determine the values for the type parameters of the method.
        // If they were not explicitly supplied, just construct fresh
        // type variables.
        let num_supplied_tps = self.supplied_tps.len();
983
        let num_method_tps = candidate.method_ty.generics.type_param_defs.len();
984
        let m_substs = {
985
            if num_supplied_tps == 0u {
986 987
                self.fcx.infcx().next_ty_vars(num_method_tps)
            } else if num_method_tps == 0u {
988 989
                tcx.sess.span_err(
                    self.expr.span,
990
                    ~"this method does not take type parameters");
991 992
                self.fcx.infcx().next_ty_vars(num_method_tps)
            } else if num_supplied_tps != num_method_tps {
993 994
                tcx.sess.span_err(
                    self.expr.span,
995
                    ~"incorrect number of type \
996
                     parameters given for this method");
997
                self.fcx.infcx().next_ty_vars(num_method_tps)
998
            } else {
999 1000 1001 1002 1003 1004
                self.supplied_tps.to_vec()
            }
        };

        // Construct the full set of type parameters for the method,
        // which is equal to the class tps + the method tps.
1005
        let all_substs = substs {
1006 1007 1008 1009
            tps: vec::append(/*bad*/copy candidate.rcvr_substs.tps,
                             m_substs),
            ../*bad*/copy candidate.rcvr_substs
        };
1010

1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027
        // Compute the method type with type parameters substituted
        debug!("fty=%s all_substs=%s",
               self.ty_to_str(fty),
               ty::substs_to_str(tcx, &all_substs));
        let fty = ty::subst(tcx, &all_substs, fty);
        debug!("after subst, fty=%s", self.ty_to_str(fty));

        // Replace any bound regions that appear in the function
        // signature with region variables
        let bare_fn_ty = match ty::get(fty).sty {
            ty::ty_bare_fn(ref f) => copy *f,
            ref s => {
                tcx.sess.span_bug(
                    self.expr.span,
                    fmt!("Invoking method with non-bare-fn ty: %?", s));
            }
        };
1028
        let (_, opt_transformed_self_ty, fn_sig) =
1029
            replace_bound_regions_in_fn_sig(
1030
                tcx, @Nil, Some(transformed_self_ty), &bare_fn_ty.sig,
N
Niko Matsakis 已提交
1031
                |_br| self.fcx.infcx().next_region_var_nb(self.expr.span));
1032
        let transformed_self_ty = opt_transformed_self_ty.get();
1033 1034 1035
        let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {sig: fn_sig, ..bare_fn_ty});
        debug!("after replacing bound regions, fty=%s", self.ty_to_str(fty));

1036 1037
        let self_mode = get_mode_from_self_type(candidate.method_ty.self_ty);

1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052
        // before we only checked whether self_ty could be a subtype
        // of rcvr_ty; now we actually make it so (this may cause
        // variables to unify etc).  Since we checked beforehand, and
        // nothing has changed in the meantime, this unification
        // should never fail.
        match self.fcx.mk_subty(false, self.self_expr.span,
                                self_ty, transformed_self_ty) {
            result::Ok(_) => (),
            result::Err(_) => {
                self.bug(fmt!("%s was a subtype of %s but now is not?",
                              self.ty_to_str(self_ty),
                              self.ty_to_str(transformed_self_ty)));
            }
        }

1053 1054
        self.fcx.write_ty(self.callee_id, fty);
        self.fcx.write_substs(self.callee_id, all_substs);
1055
        method_map_entry {
1056
            self_arg: arg {
1057 1058
                ty: candidate.rcvr_ty,
            },
1059
            self_mode: self_mode,
1060
            explicit_self: candidate.method_ty.self_ty,
1061 1062
            origin: candidate.origin,
        }
1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077
    }

    fn enforce_trait_instance_limitations(&self,
                                          method_fty: ty::t,
                                          candidate: &Candidate)
    {
        /*!
         *
         * There are some limitations to calling functions through a
         * traint instance, because (a) the self type is not known
         * (that's the whole point of a trait instance, after all, to
         * obscure the self type) and (b) the call must go through a
         * vtable and hence cannot be monomorphized. */

        match candidate.origin {
1078 1079
            method_static(*) | method_param(*) |
                method_self(*) | method_super(*) => {
1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091
                return; // not a call to a trait instance
            }
            method_trait(*) => {}
        }

        if ty::type_has_self(method_fty) {
            self.tcx().sess.span_err(
                self.expr.span,
                ~"cannot call a method whose type contains a \
                  self-type through a boxed trait");
        }

1092
        if candidate.method_ty.generics.has_type_params() {
1093 1094 1095 1096 1097 1098
            self.tcx().sess.span_err(
                self.expr.span,
                ~"cannot call a generic method through a boxed trait");
        }
    }

1099 1100 1101 1102
    fn enforce_drop_trait_limitations(&self, candidate: &Candidate) {
        // No code can call the finalize method explicitly.
        let bad;
        match candidate.origin {
1103 1104
            method_static(method_id) | method_self(method_id, _)
                | method_super(method_id, _) => {
1105
                bad = self.tcx().destructors.contains(&method_id);
1106
            }
1107
            method_param(method_param { trait_id: trait_id, _ }) |
1108
            method_trait(trait_id, _, _) => {
1109
                bad = self.tcx().destructor_for_type.contains_key(&trait_id);
1110 1111 1112 1113 1114 1115 1116 1117 1118
            }
        }

        if bad {
            self.tcx().sess.span_err(self.expr.span,
                                     ~"explicit call to destructor");
        }
    }

1119
    fn is_relevant(&self, self_ty: ty::t, candidate: &Candidate) -> bool {
1120 1121 1122
        debug!("is_relevant(self_ty=%s, candidate=%s)",
               self.ty_to_str(self_ty), self.cand_to_str(candidate));

1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203
        // Check for calls to object methods.  We resolve these differently.
        //
        // FIXME(#5762)---we don't check that an @self method is only called
        // on an @Trait object here and so forth
        match candidate.origin {
            method_trait(*) => {
                match candidate.method_ty.self_ty {
                    sty_static | sty_value => {
                        return false;
                    }
                    sty_region(*) => {
                        // just echoing current behavior here, which treats
                        // an &self method on an @Trait object as requiring
                        // an &@Trait receiver (wacky)
                    }
                    sty_box(*) | sty_uniq(*) => {
                        return self.fcx.can_mk_subty(self_ty,
                                                     candidate.rcvr_ty).is_ok();
                    }
                };
            }
            _ => {}
        }

        return match candidate.method_ty.self_ty {
            sty_static => {
                false
            }

            sty_value => {
                self.fcx.can_mk_subty(self_ty, candidate.rcvr_ty).is_ok()
            }

            sty_region(_, m) => {
                match ty::get(self_ty).sty {
                    ty::ty_rptr(_, mt) => {
                        mutability_matches(mt.mutbl, m) &&
                        self.fcx.can_mk_subty(mt.ty, candidate.rcvr_ty).is_ok()
                    }

                    _ => false
                }
            }

            sty_box(m) => {
                match ty::get(self_ty).sty {
                    ty::ty_box(mt) => {
                        mutability_matches(mt.mutbl, m) &&
                        self.fcx.can_mk_subty(mt.ty, candidate.rcvr_ty).is_ok()
                    }

                    _ => false
                }
            }

            sty_uniq(m) => {
                match ty::get(self_ty).sty {
                    ty::ty_uniq(mt) => {
                        mutability_matches(mt.mutbl, m) &&
                        self.fcx.can_mk_subty(mt.ty, candidate.rcvr_ty).is_ok()
                    }

                    _ => false
                }
            }
        };

        fn mutability_matches(self_mutbl: ast::mutability,
                              candidate_mutbl: ast::mutability) -> bool {
            //! True if `self_mutbl <: candidate_mutbl`

            match (self_mutbl, candidate_mutbl) {
                (_, m_const) => true,
                (m_mutbl, m_mutbl) => true,
                (m_imm, m_imm) => true,
                (m_mutbl, m_imm) => false,
                (m_imm, m_mutbl) => false,
                (m_const, m_imm) => false,
                (m_const, m_mutbl) => false,
            }
        }
1204 1205 1206 1207 1208 1209 1210 1211 1212 1213
    }

    fn fn_ty_from_origin(&self, origin: &method_origin) -> ty::t {
        return match *origin {
            method_static(did) => {
                ty::lookup_item_type(self.tcx(), did).ty
            }
            method_param(ref mp) => {
                type_of_trait_method(self.tcx(), mp.trait_id, mp.method_num)
            }
1214 1215
            method_trait(did, idx, _) | method_self(did, idx) |
                method_super(did, idx) => {
1216 1217 1218 1219 1220 1221 1222 1223
                type_of_trait_method(self.tcx(), did, idx)
            }
        };

        fn type_of_trait_method(tcx: ty::ctxt,
                                trait_did: def_id,
                                method_num: uint) -> ty::t {
            let trait_methods = ty::trait_methods(tcx, trait_did);
1224
            ty::mk_bare_fn(tcx, copy trait_methods[method_num].fty)
1225 1226 1227
        }
    }

1228
    fn report_candidate(&self, idx: uint, origin: &method_origin) {
1229 1230 1231 1232
        match *origin {
            method_static(impl_did) => {
                self.report_static_candidate(idx, impl_did)
            }
1233 1234
            method_param(ref mp) => {
                self.report_param_candidate(idx, (*mp).trait_id)
1235
            }
1236 1237
            method_trait(trait_did, _, _) | method_self(trait_did, _)
                | method_super(trait_did, _) => {
1238
                self.report_trait_candidate(idx, trait_did)
1239 1240 1241 1242
            }
        }
    }

1243
    fn report_static_candidate(&self, idx: uint, did: def_id) {
1244
        let span = if did.crate == ast::local_crate {
1245
            match self.tcx().items.find(&did.node) {
A
Alex Crichton 已提交
1246
              Some(&ast_map::node_method(m, _, _)) => m.span,
1247
              _ => fail!(fmt!("report_static_candidate: bad item %?", did))
1248
            }
1249 1250
        } else {
            self.expr.span
1251
        };
1252 1253 1254 1255 1256 1257
        self.tcx().sess.span_note(
            span,
            fmt!("candidate #%u is `%s`",
                 (idx+1u),
                 ty::item_path_str(self.tcx(), did)));
    }
1258

1259
    fn report_param_candidate(&self, idx: uint, did: def_id) {
1260 1261 1262 1263 1264 1265
        self.tcx().sess.span_note(
            self.expr.span,
            fmt!("candidate #%u derives from the bound `%s`",
                 (idx+1u),
                 ty::item_path_str(self.tcx(), did)));
    }
1266

1267
    fn report_trait_candidate(&self, idx: uint, did: def_id) {
1268 1269 1270 1271 1272 1273 1274 1275
        self.tcx().sess.span_note(
            self.expr.span,
            fmt!("candidate #%u derives from the type of the receiver, \
                  which is the trait `%s`",
                 (idx+1u),
                 ty::item_path_str(self.tcx(), did)));
    }

1276
    fn infcx(&self) -> @mut infer::InferCtxt {
1277 1278 1279
        self.fcx.inh.infcx
    }

1280
    fn tcx(&self) -> ty::ctxt {
1281 1282 1283
        self.fcx.tcx()
    }

1284
    fn ty_to_str(&self, t: ty::t) -> ~str {
1285 1286
        self.fcx.infcx().ty_to_str(t)
    }
1287

1288
    fn cand_to_str(&self, cand: &Candidate) -> ~str {
1289
        fmt!("Candidate(rcvr_ty=%s, rcvr_substs=%s, origin=%?)",
1290 1291 1292 1293 1294 1295
             self.ty_to_str(cand.rcvr_ty),
             ty::substs_to_str(self.tcx(), &cand.rcvr_substs),
             cand.origin)
    }

    fn did_to_str(&self, did: def_id) -> ~str {
1296
        ty::item_path_str(self.tcx(), did)
1297
    }
1298

1299
    fn bug(&self, s: ~str) -> ! {
1300
        self.tcx().sess.bug(s)
1301
    }
1302 1303
}

1304 1305 1306 1307 1308
pub fn get_mode_from_self_type(self_type: ast::self_ty_) -> SelfMode {
    match self_type {
        sty_value => ty::ByCopy,
        _ => ty::ByRef,
    }
1309
}