1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 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
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Copyright 2014 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.

//! # 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. This
//! file provides an overview of the process. More detailed notes are in
//! the code itself, naturally.
//!
//! One way to think of method lookup is that we convert an expression of
//! the form:
//!
//!     receiver.method(...)
//!
//! into a more explicit UFCS form:
//!
//!     Trait::method(ADJ(receiver), ...) // for a trait call
//!     ReceiverType::method(ADJ(receiver), ...) // for an inherent method call
//!
//! Here `ADJ` is some kind of adjustment, which is typically a series of
//! autoderefs and then possibly an autoref (e.g., `&**receiver`). However
//! we sometimes do other adjustments and coercions along the way, in
//! particular unsizing (e.g., converting from `[T, ..n]` to `[T]`).
//!
//! ## The Two Phases
//!
//! Method lookup is divided into two major phases: probing (`probe.rs`)
//! and confirmation (`confirm.rs`). The probe phase is when we decide
//! what method to call and how to adjust the receiver. The confirmation
//! phase "applies" this selection, updating the side-tables, unifying
//! type variables, and otherwise doing side-effectful things.
//!
//! One reason for this division is to be more amenable to caching.  The
//! probe phase produces a "pick" (`probe::Pick`), which is designed to be
//! cacheable across method-call sites. Therefore, it does not include
//! inference variables or other information.
//!
//! ## Probe phase
//!
//! The probe phase (`probe.rs`) decides what method is being called and
//! how to adjust the receiver.
//!
//! ### Steps
//!
//! The first thing that the probe phase does is to create a series of
//! *steps*. This is done by progressively dereferencing the receiver type
//! until it cannot be deref'd anymore, as well as applying an optional
//! "unsize" step. So if the receiver has type `Rc<Box<[T, ..3]>>`, this
//! might yield:
//!
//!     Rc<Box<[T, ..3]>>
//!     Box<[T, ..3]>
//!     [T, ..3]
//!     [T]
//!
//! ### Candidate assembly
//!
//! We then search along those steps to create a list of *candidates*. A
//! `Candidate` is a method item that might plausibly be the method being
//! invoked. For each candidate, we'll derive a "transformed self type"
//! that takes into account explicit self.
//!
//! 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).
//!
//! FIXME: Inherent candidates are not always derived from impls.  If you
//! have a trait object, such as a value of type `Box<ToString>`, then the
//! trait methods (`to_string()`, in this case) are inherently associated
//! with it. Another case is type parameters, in which case the methods of
//! their bounds are inherent. However, this part of the rules is subject
//! to change: when DST's "impl Trait for Trait" is complete, trait object
//! dispatch could be subsumed into trait matching, and the type parameter
//! behavior should be reconsidered in light of where clauses.
//!
//! **Extension candidates** are derived from imported traits.  If I have
//! the trait `ToString` imported, and I call `to_string()` on a value of
//! type `T`, then we will go off to find out whether there is an impl of
//! `ToString` 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.
//!
//! So, let's continue our example. Imagine that we were calling a method
//! `foo` with the receiver `Rc<Box<[T, ..3]>>` and there is a trait `Foo`
//! that defines it with `&self` for the type `Rc<U>` as well as a method
//! on the type `Box` that defines `Foo` but with `&mut self`. Then we
//! might have two candidates:
//!
//!     &Rc<Box<[T, ..3]>> from the impl of `Foo` for `Rc<U>` where `U=Box<T, ..3]>
//!     &mut Box<[T, ..3]>> from the inherent impl on `Box<U>` where `U=[T, ..3]`
//!
//! ### Candidate search
//!
//! Finally, to actually pick the method, we will search down the steps,
//! trying to match the receiver type against the candidate types. At
//! each step, we also consider an auto-ref and auto-mut-ref to see whether
//! that makes any of the candidates match. We pick the first step where
//! we find a match.
//!
//! In the case of our example, the first step is `Rc<Box<[T, ..3]>>`,
//! which does not itself match any candidate. But when we autoref it, we
//! get the type `&Rc<Box<[T, ..3]>>` which does match. We would then
//! recursively consider all where-clauses that appear on the impl: if
//! those match (or we cannot rule out that they do), then this is the
//! method we would pick. Otherwise, we would continue down the series of
//! steps.