Skip to content

Commit 3d2cf60

Browse files
committed
auto merge of #18121 : nikomatsakis/rust/method-call-use-trait-matching-infrastructure-2, r=pcwalton
Convert trait method dispatch to use new trait matching machinery. This fixes about 90% of #17918. What remains to be done is to make inherent dispatch work with conditional dispatch as well. I plan to do this in a future patch by generalizing the "method match" code slightly to work for inherent impls as well (the basic algorithm is precisely the same). Fixes #17178. This is a [breaking-change] for two reasons: 1. The old code was a bit broken. I found various minor cases, particularly around operators, where the old code incorrectly matched, but an extra `*` or other change is now required. (See commit e8cef25 ("Correct case where the old version of method lookup...") for examples.) 2. The old code didn't type check calls against the method signature from the *trait* but rather the *impl*. The two can be different in subtle ways. This makes the new method dispatch both more liberal and more conservative than the original. (See commit 8308332 ("The new method lookup mechanism typechecks...") for examples.) r? @pcwalton since he's been reviewing most of this series of changes f? @nick29581 for commit 39df55f ("Permit DST types to unify like other types") cc @aturon as this relates to library stabilization
2 parents 2130f22 + b066d09 commit 3d2cf60

38 files changed

+1464
-864
lines changed

src/libcore/num/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1374,7 +1374,7 @@ macro_rules! checkeddiv_int_impl(
13741374
if *v == 0 || (*self == $min && *v == -1) {
13751375
None
13761376
} else {
1377-
Some(self / *v)
1377+
Some(*self / *v)
13781378
}
13791379
}
13801380
}
@@ -1395,7 +1395,7 @@ macro_rules! checkeddiv_uint_impl(
13951395
if *v == 0 {
13961396
None
13971397
} else {
1398-
Some(self / *v)
1398+
Some(*self / *v)
13991399
}
14001400
}
14011401
}

src/libcore/ops.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,7 @@ shr_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64)
638638
* ```
639639
*/
640640
#[lang="index"]
641-
pub trait Index<Index, Result> {
641+
pub trait Index<Index, Sized? Result> {
642642
/// The method for the indexing (`Foo[Bar]`) operation
643643
fn index<'a>(&'a self, index: &Index) -> &'a Result;
644644
}

src/librustc/middle/borrowck/graphviz.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,8 @@ impl<'a, 'tcx> dot::Labeller<'a, Node<'a>, Edge<'a>> for DataflowLabeller<'a, 't
142142
}
143143

144144
impl<'a, 'tcx> dot::GraphWalk<'a, Node<'a>, Edge<'a>> for DataflowLabeller<'a, 'tcx> {
145-
fn nodes(&self) -> dot::Nodes<'a, Node<'a>> { self.inner.nodes() }
146-
fn edges(&self) -> dot::Edges<'a, Edge<'a>> { self.inner.edges() }
147-
fn source(&self, edge: &Edge<'a>) -> Node<'a> { self.inner.source(edge) }
148-
fn target(&self, edge: &Edge<'a>) -> Node<'a> { self.inner.target(edge) }
145+
fn nodes(&'a self) -> dot::Nodes<'a, Node<'a>> { self.inner.nodes() }
146+
fn edges(&'a self) -> dot::Edges<'a, Edge<'a>> { self.inner.edges() }
147+
fn source(&'a self, edge: &Edge<'a>) -> Node<'a> { self.inner.source(edge) }
148+
fn target(&'a self, edge: &Edge<'a>) -> Node<'a> { self.inner.target(edge) }
149149
}

src/librustc/middle/cfg/graphviz.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -91,29 +91,29 @@ impl<'a, 'ast> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast> {
9191
}
9292

9393
impl<'a> dot::GraphWalk<'a, Node<'a>, Edge<'a>> for &'a cfg::CFG {
94-
fn nodes(&self) -> dot::Nodes<'a, Node<'a>> {
94+
fn nodes(&'a self) -> dot::Nodes<'a, Node<'a>> {
9595
let mut v = Vec::new();
9696
self.graph.each_node(|i, nd| { v.push((i, nd)); true });
9797
dot::maybe_owned_vec::Growable(v)
9898
}
99-
fn edges(&self) -> dot::Edges<'a, Edge<'a>> {
99+
fn edges(&'a self) -> dot::Edges<'a, Edge<'a>> {
100100
self.graph.all_edges().iter().collect()
101101
}
102-
fn source(&self, edge: &Edge<'a>) -> Node<'a> {
102+
fn source(&'a self, edge: &Edge<'a>) -> Node<'a> {
103103
let i = edge.source();
104104
(i, self.graph.node(i))
105105
}
106-
fn target(&self, edge: &Edge<'a>) -> Node<'a> {
106+
fn target(&'a self, edge: &Edge<'a>) -> Node<'a> {
107107
let i = edge.target();
108108
(i, self.graph.node(i))
109109
}
110110
}
111111

112112
impl<'a, 'ast> dot::GraphWalk<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast>
113113
{
114-
fn nodes(&self) -> dot::Nodes<'a, Node<'a>> { self.cfg.nodes() }
115-
fn edges(&self) -> dot::Edges<'a, Edge<'a>> { self.cfg.edges() }
116-
fn source(&self, edge: &Edge<'a>) -> Node<'a> { self.cfg.source(edge) }
117-
fn target(&self, edge: &Edge<'a>) -> Node<'a> { self.cfg.target(edge) }
114+
fn nodes(&'a self) -> dot::Nodes<'a, Node<'a>> { self.cfg.nodes() }
115+
fn edges(&'a self) -> dot::Edges<'a, Edge<'a>> { self.cfg.edges() }
116+
fn source(&'a self, edge: &Edge<'a>) -> Node<'a> { self.cfg.source(edge) }
117+
fn target(&'a self, edge: &Edge<'a>) -> Node<'a> { self.cfg.target(edge) }
118118
}
119119

src/librustc/middle/traits/doc.rs

+7
Original file line numberDiff line numberDiff line change
@@ -272,4 +272,11 @@ nested obligation `int : Bar<U>` to find out that `U=uint`.
272272
It would be good to only do *just as much* nested resolution as
273273
necessary. Currently, though, we just do a full resolution.
274274
275+
## Method matching
276+
277+
Method dispach follows a slightly different path than normal trait
278+
selection. This is because it must account for the transformed self
279+
type of the receiver and various other complications. The procedure is
280+
described in `select.rs` in the "METHOD MATCHING" section.
281+
275282
*/

src/librustc/middle/traits/mod.rs

+2-16
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ use syntax::codemap::{Span, DUMMY_SP};
2424
pub use self::fulfill::FulfillmentContext;
2525
pub use self::select::SelectionContext;
2626
pub use self::select::SelectionCache;
27+
pub use self::select::{MethodMatchResult, MethodMatched, MethodAmbiguous, MethodDidNotMatch};
28+
pub use self::select::{MethodMatchedData}; // intentionally don't export variants
2729
pub use self::util::supertraits;
2830
pub use self::util::transitive_bounds;
2931
pub use self::util::Supertraits;
@@ -219,22 +221,6 @@ pub struct VtableParamData {
219221
pub bound: Rc<ty::TraitRef>,
220222
}
221223

222-
pub fn evaluate_obligation<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
223-
param_env: &ty::ParameterEnvironment,
224-
obligation: &Obligation,
225-
typer: &Typer<'tcx>)
226-
-> bool
227-
{
228-
/*!
229-
* Attempts to resolve the obligation given. Returns `None` if
230-
* we are unable to resolve, either because of ambiguity or
231-
* due to insufficient inference.
232-
*/
233-
234-
let mut selcx = select::SelectionContext::new(infcx, param_env, typer);
235-
selcx.evaluate_obligation(obligation)
236-
}
237-
238224
pub fn select_inherent_impl<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
239225
param_env: &ty::ParameterEnvironment,
240226
typer: &Typer<'tcx>,

0 commit comments

Comments
 (0)