about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2017-11-08 04:46:44 -0500
committerNiko Matsakis <niko@alum.mit.edu>2017-11-08 05:29:03 -0500
commit629efae761d0a473ddeeb9a4f2e5c408d9ce99dc (patch)
treeac22b6828b0e32b27370010c942cf76501a432ed
parentdc6af49258f0b90489a9a8216d35306b27aaeed9 (diff)
look for the note on the guarantor, not the root cmt
This was causing upvar inference to fail for all cases where the move
was from a projection, not the root variable.
-rw-r--r--src/librustc_typeck/check/upvar.rs6
-rw-r--r--src/test/run-pass/unboxed-closures-move-from-projection-issue-30046.rs35
-rw-r--r--src/test/ui/unboxed-closures-infer-fn-once-move-from-projection.rs26
-rw-r--r--src/test/ui/unboxed-closures-infer-fn-once-move-from-projection.stderr16
4 files changed, 82 insertions, 1 deletions
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index d179b390a29..a6a81485b23 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -289,10 +289,14 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
         let guarantor = cmt.guarantor();
         debug!("adjust_upvar_borrow_kind_for_consume: guarantor={:?}",
                guarantor);
+        debug!("adjust_upvar_borrow_kind_for_consume: guarantor.cat={:?}",
+               guarantor.cat);
         match guarantor.cat {
             Categorization::Deref(_, mc::BorrowedPtr(..)) |
             Categorization::Deref(_, mc::Implicit(..)) => {
-                match cmt.note {
+                debug!("adjust_upvar_borrow_kind_for_consume: found deref with note {:?}",
+                       cmt.note);
+                match guarantor.note {
                     mc::NoteUpvarRef(upvar_id) => {
                         debug!("adjust_upvar_borrow_kind_for_consume: \
                                 setting upvar_id={:?} to by value",
diff --git a/src/test/run-pass/unboxed-closures-move-from-projection-issue-30046.rs b/src/test/run-pass/unboxed-closures-move-from-projection-issue-30046.rs
new file mode 100644
index 00000000000..d902ebc9dc9
--- /dev/null
+++ b/src/test/run-pass/unboxed-closures-move-from-projection-issue-30046.rs
@@ -0,0 +1,35 @@
+// Copyright 2014 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.
+
+#![allow(unused)]
+
+fn foo<F>(f: F)
+    where F: FnOnce()
+{
+}
+
+fn main() {
+    // Test that this closure is inferred to `FnOnce`
+    // because it moves from `y.as<Option::Some>.0`:
+    let x = Some(vec![1, 2, 3]);
+    foo(|| {
+        match x {
+            Some(y) => { }
+            None => { }
+        }
+    });
+
+    // Test that this closure is inferred to `FnOnce`
+    // because it moves from `y.0`:
+    let y = (vec![1, 2, 3], 0);
+    foo(|| {
+        let x = y.0;
+    });
+}
diff --git a/src/test/ui/unboxed-closures-infer-fn-once-move-from-projection.rs b/src/test/ui/unboxed-closures-infer-fn-once-move-from-projection.rs
new file mode 100644
index 00000000000..14ef3b5f178
--- /dev/null
+++ b/src/test/ui/unboxed-closures-infer-fn-once-move-from-projection.rs
@@ -0,0 +1,26 @@
+// Copyright 2014 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.
+
+#![allow(unused)]
+
+fn foo<F>(f: F)
+    where F: Fn()
+{
+}
+
+fn main() {
+    // Test that this closure is inferred to `FnOnce` because it moves
+    // from `y.0`. This affects the error output (the error is that
+    // the closure implements `FnOnce`, not that it moves from inside
+    // a `Fn` closure.)
+    let y = (vec![1, 2, 3], 0);
+    let c = || drop(y.0);
+    foo(c);
+}
diff --git a/src/test/ui/unboxed-closures-infer-fn-once-move-from-projection.stderr b/src/test/ui/unboxed-closures-infer-fn-once-move-from-projection.stderr
new file mode 100644
index 00000000000..d968c409396
--- /dev/null
+++ b/src/test/ui/unboxed-closures-infer-fn-once-move-from-projection.stderr
@@ -0,0 +1,16 @@
+error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
+  --> $DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:24:13
+   |
+24 |     let c = || drop(y.0);
+   |             ^^^^^^^^^^^^
+25 |     foo(c);
+   |     --- the requirement to implement `Fn` derives from here
+   |
+note: closure is `FnOnce` because it moves the variable `y` out of its environment
+  --> $DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:24:21
+   |
+24 |     let c = || drop(y.0);
+   |                     ^
+
+error: aborting due to previous error
+