about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/middle/infer/region_inference/mod.rs13
-rw-r--r--src/test/compile-fail/issue-30438-a.rs33
-rw-r--r--src/test/compile-fail/issue-30438-b.rs34
-rw-r--r--src/test/compile-fail/issue-30438-c.rs30
4 files changed, 107 insertions, 3 deletions
diff --git a/src/librustc/middle/infer/region_inference/mod.rs b/src/librustc/middle/infer/region_inference/mod.rs
index 2c2b69ff85b..bfc770d53aa 100644
--- a/src/librustc/middle/infer/region_inference/mod.rs
+++ b/src/librustc/middle/infer/region_inference/mod.rs
@@ -1105,7 +1105,14 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
         for _ in 0..num_vars {
             graph.add_node(());
         }
-        let dummy_idx = graph.add_node(());
+
+        // Issue #30438: two distinct dummy nodes, one for incoming
+        // edges (dummy_source) and another for outgoing edges
+        // (dummy_sink). In `dummy -> a -> b -> dummy`, using one
+        // dummy node leads one to think (erroneously) there exists a
+        // path from `b` to `a`. Two dummy nodes sidesteps the issue.
+        let dummy_source = graph.add_node(());
+        let dummy_sink = graph.add_node(());
 
         for (constraint, _) in constraints.iter() {
             match *constraint {
@@ -1115,10 +1122,10 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
                                    *constraint);
                 }
                 ConstrainRegSubVar(_, b_id) => {
-                    graph.add_edge(dummy_idx, NodeIndex(b_id.index as usize), *constraint);
+                    graph.add_edge(dummy_source, NodeIndex(b_id.index as usize), *constraint);
                 }
                 ConstrainVarSubReg(a_id, _) => {
-                    graph.add_edge(NodeIndex(a_id.index as usize), dummy_idx, *constraint);
+                    graph.add_edge(NodeIndex(a_id.index as usize), dummy_sink, *constraint);
                 }
             }
         }
diff --git a/src/test/compile-fail/issue-30438-a.rs b/src/test/compile-fail/issue-30438-a.rs
new file mode 100644
index 00000000000..441815de81d
--- /dev/null
+++ b/src/test/compile-fail/issue-30438-a.rs
@@ -0,0 +1,33 @@
+// Copyright 2016 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.
+
+// Original regression test for Issue #30438.
+
+use std::ops::Index;
+
+struct Test<'a> {
+    s: &'a String
+}
+
+impl <'a> Index<usize> for Test<'a> {
+    type Output = Test<'a>;
+    fn index(&self, _: usize) -> &Self::Output {
+        return &Test { s: &self.s};
+        //~^ ERROR: borrowed value does not live long enough
+    }
+}
+
+fn main() {
+    let s = "Hello World".to_string();
+    let test = Test{s: &s};
+    let r = &test[0];
+    println!("{}", test.s); // OK since test is valid
+    println!("{}", r.s); // Segfault since value pointed by r has already been dropped
+}
diff --git a/src/test/compile-fail/issue-30438-b.rs b/src/test/compile-fail/issue-30438-b.rs
new file mode 100644
index 00000000000..981b196c4ae
--- /dev/null
+++ b/src/test/compile-fail/issue-30438-b.rs
@@ -0,0 +1,34 @@
+// Copyright 2016 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.
+
+// Modified regression test for Issue #30438 that exposed an
+// independent issue (see discussion on ticket).
+
+use std::ops::Index;
+
+struct Test<'a> {
+    s: &'a String
+}
+
+impl <'a> Index<usize> for Test<'a> {
+    type Output = Test<'a>;
+    fn index(&self, _: usize) -> &Self::Output {
+        &Test { s: &self.s}
+        //~^ ERROR: borrowed value does not live long enough
+    }
+}
+
+fn main() {
+    let s = "Hello World".to_string();
+    let test = Test{s: &s};
+    let r = &test[0];
+    println!("{}", test.s); // OK since test is valid
+    println!("{}", r.s); // Segfault since value pointed by r has already been dropped
+}
diff --git a/src/test/compile-fail/issue-30438-c.rs b/src/test/compile-fail/issue-30438-c.rs
new file mode 100644
index 00000000000..06d391af559
--- /dev/null
+++ b/src/test/compile-fail/issue-30438-c.rs
@@ -0,0 +1,30 @@
+// Copyright 2016 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.
+
+// Simplfied regression test for #30438, inspired by arielb1.
+
+trait Trait { type Out; }
+
+struct Test<'a> { s: &'a str }
+
+fn silly<'y, 'z>(_s: &'y Test<'z>) -> &'y <Test<'z> as Trait>::Out where 'z: 'static {
+    let x = Test { s: "this cannot last" };
+    &x
+    //~^ ERROR: `x` does not live long enough
+}
+
+impl<'b> Trait for Test<'b> { type Out = Test<'b>; }
+
+fn main() {
+    let orig = Test { s: "Hello World" };
+    let r = silly(&orig);
+    println!("{}", orig.s); // OK since `orig` is valid
+    println!("{}", r.s); // Segfault (method does not return a sane value)
+}