Skip to content

Commit

Permalink
The new method lookup mechanism typechecks calls against the method t…
Browse files Browse the repository at this point in the history
…ype declared in the trait, not in the impl. In some cases that results in tighter rules, and in some cases looser. Correct for that.
  • Loading branch information
nikomatsakis committed Oct 21, 2014
1 parent 98e237a commit df714cf
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 19 deletions.
8 changes: 4 additions & 4 deletions src/librustc/middle/borrowck/graphviz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) }
}
16 changes: 8 additions & 8 deletions src/librustc/middle/cfg/graphviz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,29 +91,29 @@ 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))
}
}

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) }
}

Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -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!() }
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
12 changes: 9 additions & 3 deletions src/test/compile-fail/wrong-mul-method-signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

0 comments on commit df714cf

Please sign in to comment.