-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Description
I tried this code (in a file named ice.rs
):
use std::io::BufRead;
fn main() {
let stdin = std::io::stdin();
let line = stdin.lock().lines().next().unwrap().unwrap();
println!("{}", line);
}
I expected RUST_BACKTRACE=1 rustc -Z nll ice.rs
to succeed. Instead, I got the following error:
error: internal compiler error: /checkout/src/librustc_mir/borrow_check/nll/mod.rs:309: region is not an ReVar: ReStatic
note: the compiler unexpectedly panicked. this is a bug.
note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports
note: rustc 1.24.0-nightly (6fa53b00e 2017-12-09) running on x86_64-unknown-linux-gnu
note: run with `RUST_BACKTRACE=1` for a backtrace
thread 'rustc' panicked at 'Box<Any>', /checkout/src/librustc_errors/lib.rs:501:8
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
stack backtrace:
0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
at /checkout/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
1: std::sys_common::backtrace::print
at /checkout/src/libstd/sys_common/backtrace.rs:68
at /checkout/src/libstd/sys_common/backtrace.rs:57
2: std::panicking::default_hook::{{closure}}
at /checkout/src/libstd/panicking.rs:381
3: std::panicking::default_hook
at /checkout/src/libstd/panicking.rs:391
4: std::panicking::rust_panic_with_hook
at /checkout/src/libstd/panicking.rs:577
5: std::panicking::begin_panic
6: rustc_errors::Handler::bug
7: <std::thread::local::LocalKey<T>>::with
8: rustc::ty::context::tls::with_opt
9: rustc::session::opt_span_bug_fmt
10: rustc::session::bug_fmt
11: rustc::ty::structural_impls::<impl rustc::ty::fold::TypeFoldable<'tcx> for &'tcx rustc::ty::TyS<'tcx>>::super_visit_with
12: <rustc_mir::borrow_check::nll::constraint_generation::ConstraintGeneration<'cg, 'cx, 'gcx, 'tcx> as rustc::mir::visit::Visitor<'tcx>>::visit_basic_block_data
13: rustc_mir::borrow_check::do_mir_borrowck
14: <std::thread::local::LocalKey<T>>::with
15: rustc::ty::context::GlobalCtxt::enter_local
16: rustc_mir::borrow_check::mir_borrowck
17: rustc::ty::maps::<impl rustc::ty::maps::queries::mir_borrowck<'tcx>>::compute_result
18: rustc::dep_graph::graph::DepGraph::with_task_impl
19: rustc_errors::Handler::track_diagnostics
20: rustc::ty::maps::plumbing::<impl rustc::ty::context::TyCtxt<'a, 'gcx, 'tcx>>::cycle_check
21: rustc::ty::maps::<impl rustc::ty::maps::queries::mir_borrowck<'tcx>>::force
22: rustc::ty::maps::<impl rustc::ty::maps::queries::mir_borrowck<'tcx>>::try_get
23: rustc::ty::maps::TyCtxtAt::mir_borrowck
24: rustc::ty::maps::<impl rustc::ty::context::TyCtxt<'a, 'tcx, 'lcx>>::mir_borrowck
25: rustc_driver::driver::phase_3_run_analysis_passes::{{closure}}::{{closure}}
26: <std::thread::local::LocalKey<T>>::with
27: <std::thread::local::LocalKey<T>>::with
28: rustc::ty::context::TyCtxt::create_and_enter
29: rustc_driver::driver::compile_input
30: rustc_driver::run_compiler
My output of rustc --version --verbose
is:
rustc 1.24.0-nightly (6fa53b00e 2017-12-09)
binary: rustc
commit-hash: 6fa53b00e7450060a3af9b1ef63169db37e589c2
commit-date: 2017-12-09
host: x86_64-unknown-linux-gnu
release: 1.24.0-nightly
LLVM version: 4.0
Probably related context
I tried the following example (in a file named weird.rs
):
use std::io::BufRead;
fn main() {
let line = std::io::stdin().lock().lines().next().unwrap().unwrap();
println!("{}", line);
}
I expected rustc -Z borrowck=compare weird.rs
to succeed. Instead, I got the following error:
error[E0597]: borrowed value does not live long enough (Ast)
--> weird.rs:4:72
|
4 | let line = std::io::stdin().lock().lines().next().unwrap().unwrap();
| ---------------- temporary value created here ^ temporary value dropped here while still borrowed
|
= note: values in a scope are dropped in the opposite order they are created
= note: consider using a `let` binding to increase its lifetime
error[E0597]: borrowed value does not live long enough (Mir)
--> weird.rs:4:73
|
4 | let line = std::io::stdin().lock().lines().next().unwrap().unwrap();
| ---------------- temporary value created here ^ temporary value dropped here while still borrowed
5 | println!("{}", line);
6 | }
| - temporary value needs to live until here
|
= note: consider using a `let` binding to increase its lifetime
error: aborting due to 2 previous errors
I tried to understand why the borrow checker does not understand that the lock is dropped before the temporary is dropped. So I wrote the following example (in a file named test.rs
):
struct Foo(i32);
struct Lock<'a>(&'a Foo);
impl Foo {
fn new(value: i32) -> Foo { Foo(value) }
fn lock(&self) -> Lock { Lock(self) }
}
impl<'a> Lock<'a> {
fn read(self) -> i32 { (self.0).0 }
}
impl<'a> std::ops::Drop for Lock<'a> {
fn drop(&mut self) {}
}
fn main() {
let value = {
Foo::new(42).lock().read() // fail
// let foo = Foo::new(42); foo.lock().read() // fail
// let value = Foo::new(42).lock().read(); value // fail
// let foo = Foo::new(42); let value = foo.lock().read(); value // pass
// let foo = Foo::new(42); let lock = foo.lock(); lock.read() // pass
};
println!("{}", value);
}
I expected rustc -Z borrowck=compare test.rs
to succeed for all versions. Instead, only the last 2 versions succeeded. The first 3 versions failed. Notice how the 3rd and 4th versions just differ by assigning the result value into a variable.
Then, I stepped on #21114 and considered using NLL and discovered that rustc -Z nll -Z borrowck=compare test.rs
only fails for AST and not for MIR for the first 3 versions. It still succeeds for the last 2 versions. In particular, for the first 3 versions, rustc -Z nll -Z borrowck=mir test.rs
succeeds while rustc -Z nll -Z borrowck=ast test.rs
fails.
Activity
pnkfelix commentedon Dec 13, 2017
Thanks for the report!
pnkfelix commentedon Dec 19, 2017
FYI here is a version that doesn't rely on reading from stdin (and thus may serve as a better basis for a unit test when this is fixed):
(I factored it into two methods because the error here is arising from
fn first_line
, so having it in its own function may ease inspecting the MIR etc)arielb1 commentedon Dec 19, 2017
cc @nikomatsakis
nikomatsakis commentedon Dec 20, 2017
Works on nll-master (i.e., the code found here #46862).
nikomatsakis commentedon Dec 20, 2017
However, the error message on the original example is not quite what I had hoped for:
gives
ia0 commentedon Dec 24, 2017
Thanks for the fix! I confirm that the ICE has disappeared in nightly. Should we close the issue? (Or keep it open for the weird.rs case since I would expect this example to type-check?)
nikomatsakis commentedon Jan 4, 2018
Hmm, I am seeing an ICE on the playground.
nikomatsakis commentedon Jan 4, 2018
Oh, that's an ICE when the code executes. The example that @pnkfelix gave compiles successfully.
nikomatsakis commentedon Jan 4, 2018
@ia0 the code now type-checks and executes, so I'm going to close the issue.
ia0 commentedon Jan 4, 2018
Yes, in the playground stdin seems to be empty, so the first unwrap is wrong (there are no lines to read).
Thanks again for the work on this!