rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
99.1k stars 12.8k forks source link

MIR borrowck: ICE: EndRegion not found #45702

Closed arielb1 closed 7 years ago

arielb1 commented 7 years ago

MIR borrowck ICEs when an error involving a region whose EndRegion is missing occurs (this occurs when a region can never end within the function). Instead it should emit a correct diagnostic.

This can occur for both free regions (e.g. issue-25579):

fn free(x: &mut u32) -> &u32 {
    let result = &*x;
    *(&mut *x) = 1;
    result
}

fn main() {}

And for infinite loops:

fn loopy() {
    let mut _addr;
    let x = 0;
    loop {
        _addr = &mut x;
        maybe_panic();
    }
}

fn maybe_panic() {}
fn main() {}

Causing this ICE:

error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable (Ast)
 --> x.rs:3:12
  |
2 |     let result = &*x;
  |                   -- immutable borrow occurs here
3 |     *(&mut *x) = 1;
  |            ^^ mutable borrow occurs here
4 |     result
5 | }
  | - immutable borrow ends here

error: internal compiler error: unexpected panic

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.23.0-dev running on x86_64-unknown-linux-gnu

note: run with `RUST_BACKTRACE=1` for a backtrace

thread 'rustc' panicked at 'end region not found for ReFree(DefId { krate: CrateNum(0), index: DefIndex(0:3) => x[317d]::free[0] }, BrAnon(0))', rust://src/librustc_mir/dataflow/impls/borrows.rs:121:8
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
stack backtrace:
   0: std::sys::imp::backtrace::tracing::imp::unwind_backtrace
             at rust://src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1: std::sys_common::backtrace::_print
             at rust://src/libstd/sys_common/backtrace.rs:69
   2: std::panicking::default_hook::{{closure}}
             at rust://src/libstd/sys_common/backtrace.rs:58
             at rust://src/libstd/panicking.rs:381
   3: std::panicking::default_hook
             at rust://src/libstd/panicking.rs:391
   4: std::panicking::rust_panic_with_hook
             at rust://src/libstd/panicking.rs:577
   5: std::panicking::begin_panic
             at rust://src/libstd/panicking.rs:538
   6: std::panicking::begin_panic_fmt
             at rust://src/libstd/panicking.rs:522
   7: rustc_mir::dataflow::impls::borrows::Borrows::region_span
             at rust://src/librustc_mir/dataflow/impls/borrows.rs:121
   8: rustc_mir::borrow_check::MirBorrowckCtxt::access_lvalue::{{closure}}
             at rust://src/libcore/ptr.rs:0
   9: rustc_mir::borrow_check::MirBorrowckCtxt::access_lvalue
             at rust://src/librustc_mir/borrow_check.rs:856
             at rust://src/librustc_mir/borrow_check.rs:414
  10: <rustc_mir::borrow_check::MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> as rustc_mir::dataflow::DataflowResultsConsumer<'b, 'gcx>>::visit_statement_entry
             at rust://src/librustc_mir/borrow_check.rs:495
             at rust://src/librustc_mir/borrow_check.rs:211
  11: rustc_mir::borrow_check::mir_borrowck::{{closure}}
             at rust://src/librustc_mir/dataflow/mod.rs:309
             at rust://src/librustc_mir/dataflow/mod.rs:299
             at rust://src/librustc_mir/borrow_check.rs:115
  12: rustc_mir::borrow_check::mir_borrowck
             at rust://src/librustc/infer/mod.rs:375
             at rust://src/librustc/ty/context.rs:1511
             at rust://src/libstd/thread/local.rs:377
             at rust://src/libstd/thread/local.rs:288
             at rust://src/librustc/ty/context.rs:1508
             at rust://src/librustc/ty/context.rs:1319
             at rust://src/librustc/infer/mod.rs:375
             at rust://src/librustc_mir/borrow_check.rs:61
  13: rustc::dep_graph::graph::DepGraph::with_task_impl
             at rust://src/librustc/ty/maps/plumbing.rs:390
             at rust://src/librustc/dep_graph/graph.rs:287
  14: rustc::ty::maps::<impl rustc::ty::maps::queries::mir_borrowck<'tcx>>::force
             at rust://src/librustc/dep_graph/graph.rs:203
             at rust://src/librustc/ty/maps/plumbing.rs:442
             at rust://src/librustc_errors/lib.rs:566
             at rust://src/librustc/ty/maps/plumbing.rs:435
             at rust://src/librustc/ty/maps/plumbing.rs:130
             at rust://src/librustc/ty/maps/plumbing.rs:434
  15: rustc::ty::maps::<impl rustc::ty::maps::queries::mir_borrowck<'tcx>>::try_get
             at rust://src/librustc/ty/maps/plumbing.rs:313
             at rust://src/librustc/ty/maps/plumbing.rs:471
  16: rustc::ty::maps::TyCtxtAt::mir_borrowck
             at rust://src/librustc/ty/maps/plumbing.rs:510
  17: rustc::ty::maps::<impl rustc::ty::context::TyCtxt<'a, 'tcx, 'lcx>>::mir_borrowck
             at rust://src/librustc/ty/maps/plumbing.rs:503
  18: rustc_driver::driver::phase_3_run_analysis_passes::{{closure}}::{{closure}}
             at rust://src/librustc_driver/driver.rs:1095
  19: rustc::ty::context::TyCtxt::create_and_enter
             at rust://src/librustc/util/common.rs:120
             at rust://src/librustc_driver/driver.rs:1093
             at rust://src/librustc/ty/context.rs:1511
             at rust://src/libstd/thread/local.rs:377
             at rust://src/libstd/thread/local.rs:288
             at rust://src/librustc/ty/context.rs:1508
             at rust://src/librustc/ty/context.rs:1495
             at rust://src/libstd/thread/local.rs:377
             at rust://src/libstd/thread/local.rs:288
             at rust://src/librustc/ty/context.rs:1492
             at rust://src/librustc/ty/context.rs:1136
  20: rustc_driver::driver::compile_input
             at rust://src/librustc_driver/driver.rs:1041
             at rust://src/librustc_driver/driver.rs:210
  21: rustc_driver::run_compiler
             at rust://src/librustc_driver/lib.rs:252
nikomatsakis commented 7 years ago

The ICE here is caused by the assert in this function, opt_region_end_span:

https://github.com/rust-lang/rust/blob/563dc5171fd5d96f9714b4e722ad1d80a25f1dba/src/librustc_mir/dataflow/impls/borrows.rs#L126-L134

This function finds the Span (location in the input source code) that a region ends. If you look at the error that the AST borrowck (i.e., older style borrowck) emits, we are basically computing the point where to write that "immutable borrow ends here" message:

error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable (Ast)
 --> x.rs:3:12
  |
2 |     let result = &*x;
  |                   -- immutable borrow occurs here
3 |     *(&mut *x) = 1;
  |            ^^ mutable borrow occurs here
4 |     result
5 | }
  | - immutable borrow ends here

Right now, there is a kind of complicated assertion. It is saying that one of two things should be:

The problem is that in cases where the region never properly ends, we won't find an EndRegion statement. I think what we want to do is rewrite the function a bit.

So, when we are done, if nonlexical_reionck is None, this function should always return Some(s) for some span, but sometimes it will be the end of the function.

vramana commented 7 years ago

Hi, I want to work on this bug.