Skip to content

MIR-borrowck: ICE: End-user description not implemented for field access on `TyClosure #45698

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

Closed
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

This test:

fn main() {
    let x = 0;
    || {
        let y = &mut x;
        &mut x;
        *y = 1;
    };
}

Along with several compile-fail tests - e.g. https://github.com/rust-lang/rust/blob/2be4cc040211a85b17f21e813ff62351ae4de642/src/test/compile-fail/issue-25579.rs - causes an ICE with MIR borrowck:

error[E0595]: closure cannot assign to immutable local variable `x` (Ast)
 --> x.rs:3:5
  |
2 |     let x = 0;
  |         - consider changing this to `mut x`
3 |     || {
  |     ^^ cannot borrow mutably

error[E0499]: cannot borrow `**x` as mutable more than once at a time (Ast)
 --> x.rs:5:14
  |
4 |         let y = &mut x;
  |                      - first mutable borrow occurs here
5 |         &mut x;
  |              ^ second mutable borrow occurs here
6 |         *y = 1;
7 |     };
  |     - first borrow ends here

error: internal compiler error: rust://src/librustc_mir/borrow_check.rs:1300: End-user description not implemented for field access on `TyClosure(DefId { krate: CrateNum(0), index: DefIndex(1:9) => x[317d]::main[0]::{{closure}}[0] }, ClosureSubsts { substs: Slice([&mut i32]) })`

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 'Box<Any>', rust://src/librustc_errors/lib.rs:503: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: rustc_errors::Handler::bug
             at rust://src/librustc_errors/lib.rs:503
   7: rustc::session::opt_span_bug_fmt::{{closure}}
             at rust://src/librustc/session/mod.rs:981
   8: rustc::session::opt_span_bug_fmt
             at rust://src/librustc/ty/context.rs:0
   9: rustc::session::bug_fmt
             at rust://src/librustc/session/mod.rs:961
  10: rustc_mir::borrow_check::MirBorrowckCtxt::describe_field_from_ty
             at rust://src/librustc_mir/borrow_check.rs:1300
  11: rustc_mir::borrow_check::MirBorrowckCtxt::describe_field_from_ty
             at rust://src/librustc_mir/borrow_check.rs:0
  12: rustc_mir::borrow_check::MirBorrowckCtxt::describe_field
             at rust://src/librustc_mir/borrow_check.rs:0
  13: rustc_mir::borrow_check::MirBorrowckCtxt::describe_field
             at rust://src/librustc_mir/borrow_check.rs:1258
  14: rustc_mir::borrow_check::MirBorrowckCtxt::append_lvalue_to_string
             at rust://src/librustc_mir/borrow_check.rs:1208
  15: rustc_mir::borrow_check::MirBorrowckCtxt::append_lvalue_to_string
             at rust://src/librustc_mir/borrow_check.rs:1223
  16: rustc_mir::borrow_check::MirBorrowckCtxt::report_conflicting_borrow
             at rust://src/librustc_mir/borrow_check.rs:1181
             at rust://src/librustc_mir/borrow_check.rs:1123
  17: rustc_mir::borrow_check::MirBorrowckCtxt::access_lvalue::{{closure}}
             at rust://src/libcore/ptr.rs:0
  18: 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
  19: <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
  20: 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
  21: 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
  22: 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
  23: 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
  24: 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
  25: rustc::ty::maps::TyCtxtAt::mir_borrowck
             at rust://src/librustc/ty/maps/plumbing.rs:510
  26: rustc::ty::maps::<impl rustc::ty::context::TyCtxt<'a, 'tcx, 'lcx>>::mir_borrowck
             at rust://src/librustc/ty/maps/plumbing.rs:503
  27: rustc_driver::driver::phase_3_run_analysis_passes::{{closure}}::{{closure}}
             at rust://src/librustc_driver/driver.rs:1095
  28: 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
  29: rustc_driver::driver::compile_input
             at rust://src/librustc_driver/driver.rs:1041
             at rust://src/librustc_driver/driver.rs:210
  30: rustc_driver::run_compiler
             at rust://src/librustc_driver/lib.rs:252

This looks like just a place where the proper error message needs to be implemented - we should see what AST borrowck does and copy from that, because it's fairly fine-tuned.

@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

It seems like the first step is to stem the bleeding -- let's start by just naming the fields of the closure based on the upvars (that is, the variables that the closure captures from its environment).

The code to format an Lvalue starts here. It makes the incorrect assumption that when you have a field you want it to look like a.b, but let's leave fixing that to a second step. Right now, the problem is that producing the string for b is panicking.

That string is produced by describe_field which in turn invokes describe_field_from_ty. That function has a big case match of all the types that can have fields but we are hitting the _ case.

We want to extend that to consider ty::TyClosure (and probably eventually ty::TyGenerator too), something like:

ty::TyClosure(closure_def_id, _) => { ... }

The fields of a closure correspond to the captured variables; to get the name for the nth field, we have to use this really old and wacky API called tcx.freevars. If you have the closure def-id, you have to first convert it into a node-id, and then invoke tcx.with_freevars(node_id, |fv| ...). That closure gets invoked with the freevars fv, which will be a &[hir::Freevar] (where hir is src/librustc/hir). Something like this:

// Convert the def-id into a node-id. node-ids are only valid for
// the local code in the current crate, so this returns an `Option` in case
// the closure comes from another crate. But in that case we wouldn't
// be borrowck'ing it, so we can just unwrap:
let node_id = self.tcx.hir.as_local_node_id(closure_def_id).unwrap();

let local_def: hir::Def = self.tcx.with_freevars(node_id, |fv| fv[i].def);

Now we have a hir::Def, which I think corresponds to the local variable that was captured. To actually get its name we can convert that Def into a node-id, which is again a similar incantation:

let local_def_id = local_def.def_id();
let local_node_id = self.tcx.hir.as_local_node_id(local_def_id).unwrap();

then we can get the name with self.tcx.hir.name(local_node_id) and print it out.

OK, hope that works! If not, ask questions. =)

@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 am working on this bug.

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