Skip to content

Commit

Permalink
look for the note on the guarantor, not the root cmt
Browse files Browse the repository at this point in the history
This was causing upvar inference to fail for all cases where the move
was from a projection, not the root variable.
  • Loading branch information
nikomatsakis committed Nov 8, 2017
1 parent dc6af49 commit 629efae
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 1 deletion.
6 changes: 5 additions & 1 deletion src/librustc_typeck/check/upvar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
});
}
26 changes: 26 additions & 0 deletions src/test/ui/unboxed-closures-infer-fn-once-move-from-projection.rs
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 629efae

Please sign in to comment.