From df714cfda728e201dd6b2227caa425bca3e048c7 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 17 Oct 2014 09:11:10 -0400 Subject: [PATCH] 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. --- src/librustc/middle/borrowck/graphviz.rs | 8 ++++---- src/librustc/middle/cfg/graphviz.rs | 16 ++++++++-------- ...ded-method-type-parameters-cross-crate-lib.rs | 11 ++++++++++- ...bounded-method-type-parameters-cross-crate.rs | 6 +++--- .../compile-fail/wrong-mul-method-signature.rs | 12 +++++++++--- 5 files changed, 34 insertions(+), 19 deletions(-) diff --git a/src/librustc/middle/borrowck/graphviz.rs b/src/librustc/middle/borrowck/graphviz.rs index aab7fe8f31e..6c6750ad24b 100644 --- a/src/librustc/middle/borrowck/graphviz.rs +++ b/src/librustc/middle/borrowck/graphviz.rs @@ -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) } } diff --git a/src/librustc/middle/cfg/graphviz.rs b/src/librustc/middle/cfg/graphviz.rs index bc48e476aec..fcd9a166c6a 100644 --- a/src/librustc/middle/cfg/graphviz.rs +++ b/src/librustc/middle/cfg/graphviz.rs @@ -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) } } diff --git a/src/test/auxiliary/regions-bounded-method-type-parameters-cross-crate-lib.rs b/src/test/auxiliary/regions-bounded-method-type-parameters-cross-crate-lib.rs index 1e9fd035f44..000e42b9703 100644 --- a/src/test/auxiliary/regions-bounded-method-type-parameters-cross-crate-lib.rs +++ b/src/test/auxiliary/regions-bounded-method-type-parameters-cross-crate-lib.rs @@ -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!() } } diff --git a/src/test/compile-fail/regions-bounded-method-type-parameters-cross-crate.rs b/src/test/compile-fail/regions-bounded-method-type-parameters-cross-crate.rs index 06f26800b50..1705cfec6e2 100644 --- a/src/test/compile-fail/regions-bounded-method-type-parameters-cross-crate.rs +++ b/src/test/compile-fail/regions-bounded-method-type-parameters-cross-crate.rs @@ -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 } diff --git a/src/test/compile-fail/wrong-mul-method-signature.rs b/src/test/compile-fail/wrong-mul-method-signature.rs index e3aed148a23..aead739d3e0 100644 --- a/src/test/compile-fail/wrong-mul-method-signature.rs +++ b/src/test/compile-fail/wrong-mul-method-signature.rs @@ -58,7 +58,13 @@ impl Mul 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; }