The new method lookup mechanism typechecks calls against the method type declared in the trait, not in the impl. In some cases that results in tighter rules, and in some cases looser. Correct for that.

This commit is contained in:
Niko Matsakis 2014-10-17 09:11:10 -04:00
parent 98e237a681
commit df714cfda7
5 changed files with 34 additions and 19 deletions

View File

@ -142,8 +142,8 @@ impl<'a, 'tcx> dot::Labeller<'a, Node<'a>, Edge<'a>> for DataflowLabeller<'a, 't
}
impl<'a, 'tcx> dot::GraphWalk<'a, Node<'a>, Edge<'a>> for DataflowLabeller<'a, 'tcx> {
fn nodes(&self) -> dot::Nodes<'a, Node<'a>> { self.inner.nodes() }
fn edges(&self) -> dot::Edges<'a, Edge<'a>> { self.inner.edges() }
fn source(&self, edge: &Edge<'a>) -> Node<'a> { self.inner.source(edge) }
fn target(&self, edge: &Edge<'a>) -> Node<'a> { self.inner.target(edge) }
fn nodes(&'a self) -> dot::Nodes<'a, Node<'a>> { self.inner.nodes() }
fn edges(&'a self) -> dot::Edges<'a, Edge<'a>> { self.inner.edges() }
fn source(&'a self, edge: &Edge<'a>) -> Node<'a> { self.inner.source(edge) }
fn target(&'a self, edge: &Edge<'a>) -> Node<'a> { self.inner.target(edge) }
}

View File

@ -91,19 +91,19 @@ impl<'a, 'ast> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast> {
}
impl<'a> dot::GraphWalk<'a, Node<'a>, Edge<'a>> for &'a cfg::CFG {
fn nodes(&self) -> dot::Nodes<'a, Node<'a>> {
fn nodes(&'a self) -> dot::Nodes<'a, Node<'a>> {
let mut v = Vec::new();
self.graph.each_node(|i, nd| { v.push((i, nd)); true });
dot::maybe_owned_vec::Growable(v)
}
fn edges(&self) -> dot::Edges<'a, Edge<'a>> {
fn edges(&'a self) -> dot::Edges<'a, Edge<'a>> {
self.graph.all_edges().iter().collect()
}
fn source(&self, edge: &Edge<'a>) -> Node<'a> {
fn source(&'a self, edge: &Edge<'a>) -> Node<'a> {
let i = edge.source();
(i, self.graph.node(i))
}
fn target(&self, edge: &Edge<'a>) -> Node<'a> {
fn target(&'a self, edge: &Edge<'a>) -> Node<'a> {
let i = edge.target();
(i, self.graph.node(i))
}
@ -111,9 +111,9 @@ impl<'a> dot::GraphWalk<'a, Node<'a>, Edge<'a>> for &'a cfg::CFG {
impl<'a, 'ast> dot::GraphWalk<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast>
{
fn nodes(&self) -> dot::Nodes<'a, Node<'a>> { self.cfg.nodes() }
fn edges(&self) -> dot::Edges<'a, Edge<'a>> { self.cfg.edges() }
fn source(&self, edge: &Edge<'a>) -> Node<'a> { self.cfg.source(edge) }
fn target(&self, edge: &Edge<'a>) -> Node<'a> { self.cfg.target(edge) }
fn nodes(&'a self) -> dot::Nodes<'a, Node<'a>> { self.cfg.nodes() }
fn edges(&'a self) -> dot::Edges<'a, Edge<'a>> { self.cfg.edges() }
fn source(&'a self, edge: &Edge<'a>) -> Node<'a> { self.cfg.source(edge) }
fn target(&'a self, edge: &Edge<'a>) -> Node<'a> { self.cfg.target(edge) }
}

View File

@ -9,7 +9,7 @@
// except according to those terms.
// Check that method bounds declared on traits/impls in a cross-crate
// scenario work. This is the libary portion of the test.
// scenario work. This is the library portion of the test.
pub enum MaybeOwned<'a> {
Owned(int),
@ -24,10 +24,19 @@ pub struct Inv<'a> { // invariant w/r/t 'a
// trait, so I'll use that as the template for this test.
pub trait IntoMaybeOwned<'a> {
fn into_maybe_owned(self) -> MaybeOwned<'a>;
// Note: without this `into_inv` method, the trait is
// contravariant w/r/t `'a`, since if you look strictly at the
// interface, it only returns `'a`. This complicates the
// downstream test since it wants invariance to force an error.
// Hence we add this method.
fn into_inv(self) -> Inv<'a>;
fn bigger_region<'b:'a>(self, b: Inv<'b>);
}
impl<'a> IntoMaybeOwned<'a> for Inv<'a> {
fn into_maybe_owned(self) -> MaybeOwned<'a> { fail!() }
fn into_inv(self) -> Inv<'a> { fail!() }
fn bigger_region<'b:'a>(self, b: Inv<'b>) { fail!() }
}

View File

@ -18,15 +18,15 @@ use lib::Inv;
use lib::MaybeOwned;
use lib::IntoMaybeOwned;
fn call_into_maybe_owned<'a,F:IntoMaybeOwned<'a>>(f: F) {
fn call_into_maybe_owned<'x,F:IntoMaybeOwned<'x>>(f: F) {
// Exercise a code path I found to be buggy. We were not encoding
// the region parameters from the receiver correctly on trait
// methods.
f.into_maybe_owned();
}
fn call_bigger_region<'a, 'b>(a: Inv<'a>, b: Inv<'b>) {
// Here the value provided for 'y is 'b, and hence 'b:'a does not hold.
fn call_bigger_region<'x, 'y>(a: Inv<'x>, b: Inv<'y>) {
// Here the value provided for 'y is 'y, and hence 'y:'x does not hold.
a.bigger_region(b) //~ ERROR cannot infer
}

View File

@ -58,7 +58,13 @@ impl Mul<f64, i32> for Vec3 {
}
pub fn main() {
Vec1 { x: 1.0 } * 2.0;
Vec2 { x: 1.0, y: 2.0 } * 2.0;
Vec3 { x: 1.0, y: 2.0, z: 3.0 } * 2.0;
// Check that the usage goes from the trait declaration:
let x: Vec1 = Vec1 { x: 1.0 } * 2.0; // this is OK
let x: Vec2 = Vec2 { x: 1.0, y: 2.0 } * 2.0; // trait had reversed order
//~^ ERROR mismatched types
//~^^ ERROR mismatched types
let x: i32 = Vec3 { x: 1.0, y: 2.0, z: 3.0 } * 2.0;
}