Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MIR borrowck: ICE: EndRegion not found #45702

Closed
arielb1 opened this issue Nov 1, 2017 · 2 comments
Closed

MIR borrowck: ICE: EndRegion not found #45702

arielb1 opened this issue Nov 1, 2017 · 2 comments
Labels
A-borrow-checker Area: The borrow checker E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️

Comments

@arielb1
Copy link
Contributor

arielb1 commented Nov 1, 2017

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
@arielb1 arielb1 added A-borrow-checker Area: The borrow checker I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ WG-compiler-nll labels Nov 1, 2017
@nikomatsakis
Copy link
Contributor

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

/// Returns the span for the "end point" given region. This will
/// return `None` if NLL is enabled, since that concept has no
/// meaning there. Otherwise, it should return some.
pub fn opt_region_end_span(&self, region: &Region) -> Option<Span> {
let opt_span = self.region_span_map.get(region);
assert!(self.nonlexical_regioncx.is_some() ||
opt_span.is_some(), "end region not found for {:?}", region);
opt_span.map(|s| s.end_point())
}

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:

  • We are in non-lexical mode. In that case, there are no end-regions at all, so we just return None. This causes us not to write "immutable borrow ends here".
  • We are in lexical mode, in which case we should have found an EndRegion statement. These are special statements we insert into the MIR (only in lexical mode) that tell us where the various lexical lifetimes end.

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.

  • If we are in NLL mode (self.nonlexical_regionck.is_some()), then we should always return None.
  • Otherwise, check the region_span_map as we are doing and return Some(span.end_point()) if we find something in there, as we are doing now.
  • Otherwise, we want to return the span for the end of the function. This is the new part. As it happens, we can get this by returning self.mir.span.end_point():
    • self.mir is the MIR for the function we are checking
    • self.mir.span is the span in the source code where the function is defined
    • returning its end point should, I think, give us the behavior we want.

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.

@nikomatsakis nikomatsakis added the E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. label Nov 10, 2017
@vramana
Copy link
Contributor

vramana commented Nov 10, 2017

Hi, I want to work on this bug.

vramana added a commit to vramana/rust that referenced this issue Nov 10, 2017
bors added a commit that referenced this issue Nov 15, 2017
Fix MIR borrowck EndRegion not found

Fixes #45702

- [x] Add Tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-borrow-checker Area: The borrow checker E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️
Projects
None yet
Development

No branches or pull requests

3 participants