Description
Forked off of #10766
A question in #rust regarding a borrow checker error led me on the following exploration.
The four variants are labelled one
, tup
, two_tuple
, and two_fields
one
is just repeating the test case from the description (of Should&'a Value as &'a Trait
work? #10766). Its a sanity check that the old error message and behavior still persists.two_fields
is closest to what achin described in his bug report. The problem that the borrow checker reports for that code is interesting, and it is replicated by the more minimal test case at the end of this comment.- The other two cases are variants of
two_fields
that I made while trying to make as minimal a test case as possible.
% rustc --cfg two_fields --cfg two_tup /tmp/achin.rs
/tmp/achin.rs:32:8: 32:9 error: cannot infer an appropriate lifetime for region in type/impl due to conflicting requirements
/tmp/achin.rs:32 P{ car: v1 as &'a T, cdr: v2 as &'a T }
^
/tmp/achin.rs:32:34: 32:45 note: first, the lifetime must be contained by the expression at 32:34...
/tmp/achin.rs:32 P{ car: v1 as &'a T, cdr: v2 as &'a T }
^~~~~~~~~~~
/tmp/achin.rs:32:34: 32:45 note: ...so that automatically borrowed pointer is valid at the time of borrow
/tmp/achin.rs:32 P{ car: v1 as &'a T, cdr: v2 as &'a T }
^~~~~~~~~~~
/tmp/achin.rs:32:16: 32:27 note: but, the lifetime must also be contained by the expression at 32:16...
/tmp/achin.rs:32 P{ car: v1 as &'a T, cdr: v2 as &'a T }
^~~~~~~~~~~
/tmp/achin.rs:32:16: 32:27 note: ...so that automatically borrowed pointer is valid at the time of borrow
/tmp/achin.rs:32 P{ car: v1 as &'a T, cdr: v2 as &'a T }
^~~~~~~~~~~
error: aborting due to previous error
task 'rustc' failed at 'explicit failure', /Users/fklock/Dev/Mozilla/rust.git/src/libsyntax/diagnostic.rs:102
task '<main>' failed at 'explicit failure', /Users/fklock/Dev/Mozilla/rust.git/src/librustc/lib.rs:396
The interesting thing is that two_tuple
(and likewise tup
) do not exhibit that error, even though they are completely analogous code. This is probably representative of a bug somewhere in the borrow checker since it really should be treating a struct-tuple here the same as a struct with named fields. (Plus, you know, these borrows look okay to me... but I have not yet dived in and tried to understand what the problem is that they are trying to flag.)
The code:
#[cfg(one)]
mod one {
trait T {}
fn f<'a, V: T>(v: &'a V) -> &'a T {
v as &'a T
}
}
#[cfg(tup)]
mod tup {
trait T {}
fn f<'a, V: T>(v1: &'a V, v2: &'a V) -> (&'a T, &'a T) {
(v1 as &'a T, v2 as &'a T)
}
}
#[cfg(two_tuple)]
mod two {
trait T {}
struct P<'a>(&'a T, &'a T);
fn f<'a, V: T>(mut v1: &'a V, v2: &'a V) -> P<'a> {
P(v1 as &'a T, v2 as &'a T)
}
}
#[cfg(two_fields)]
mod two {
trait T {}
struct P<'a> { car: &'a T, cdr: &'a T }
fn f<'a, V: T>(mut v1: &'a V, v2: &'a V) -> P<'a> {
P{ car: v1 as &'a T, cdr: v2 as &'a T }
}
}
This is a slightly reduced test from the original one above (that was originally a comment on #10766).
#[cfg(two_tuple)]
pub mod two {
trait T {}
struct P<'a>(&'a T, &'a T);
pub fn f<'a>(car: &'a T, cdr: &'a T) -> P<'a> {
P(car, cdr)
}
}
#[cfg(two_fields)]
pub mod two {
trait T {}
struct P<'a> { car: &'a T, cdr: &'a T }
pub fn f<'a>(car: &'a T, cdr: &'a T) -> P<'a> {
P{ car: car, cdr: cdr }
}
}
fn main() {}
And here are the results:
% rustc --version
/Users/fklock/opt/rust-dbg/bin/rustc 0.9-pre (f817ed3 2013-12-09 13:51:32 -0800)
host: x86_64-apple-darwin
% rustc --cfg two_tuple /tmp/achin.rs
% rustc --cfg two_fields /tmp/achin.rs
/tmp/achin.rs:15:8: 15:9 error: cannot infer an appropriate lifetime for region in type/impl due to conflicting requirements
/tmp/achin.rs:15 P{ car: car, cdr: cdr }
^
/tmp/achin.rs:15:16: 15:19 note: first, the lifetime must be contained by the expression at 15:16...
/tmp/achin.rs:15 P{ car: car, cdr: cdr }
^~~
/tmp/achin.rs:15:16: 15:19 note: ...so that automatically borrowed pointer is valid at the time of borrow
/tmp/achin.rs:15 P{ car: car, cdr: cdr }
^~~
/tmp/achin.rs:15:26: 15:29 note: but, the lifetime must also be contained by the expression at 15:26...
/tmp/achin.rs:15 P{ car: car, cdr: cdr }
^~~
/tmp/achin.rs:15:26: 15:29 note: ...so that automatically borrowed pointer is valid at the time of borrow
/tmp/achin.rs:15 P{ car: car, cdr: cdr }
^~~
error: aborting due to previous error
task 'rustc' failed at 'explicit failure', /Users/fklock/Dev/Mozilla/rust.git/src/libsyntax/diagnostic.rs:102
task '<main>' failed at 'explicit failure', /Users/fklock/Dev/Mozilla/rust.git/src/librustc/lib.rs:393
[ERROR#1] %