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

ICE on pattern matching while compiling rust compiler #41169

Closed
nikhilshagri opened this issue Apr 8, 2017 · 5 comments
Closed

ICE on pattern matching while compiling rust compiler #41169

nikhilshagri opened this issue Apr 8, 2017 · 5 comments

Comments

@nikhilshagri
Copy link
Contributor

The rust compiler unexpectedly crashed while I was trying to fix a bug (#40402):

 $ RUST_BACKTRACE=1 ./x.py build src/libtest --stage 1
thread 'rustc' panicked at 'assertion failed: match e.node { ExprMatch(..) => true, _ => false, }', src/librustc/hir/map/mod.rs:856
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
stack backtrace:
   0: rustc::hir::map::Map::get_pattern_source
   1: <rustc_borrowck::borrowck::gather_loans::GatherLoanCtxt<'a, 'tcx> as rustc::middle::expr_use_visitor::Delegate<'tcx>>::consume_pat
   2: rustc::middle::mem_categorization::MemCategorizationContext::cat_pattern_
   3: rustc::middle::expr_use_visitor::ExprUseVisitor::walk_pat
   4: rustc::middle::expr_use_visitor::ExprUseVisitor::consume_body
   5: rustc_borrowck::borrowck::build_borrowck_dataflow_data
   6: rustc_borrowck::borrowck::check_crate
   7: rustc_driver::driver::phase_3_run_analysis_passes::{{closure}}
   8: rustc_driver::driver::phase_3_run_analysis_passes
   9: rustc_driver::driver::compile_input
  10: rustc_driver::run_compiler
  11: std::panicking::try::do_call
  12: __rust_maybe_catch_panic
  13: <F as alloc::boxed::FnBox<A>>::call_box
  14: std::sys::imp::thread::Thread::new::thread_start
  15: start_thread
  16: clone

error: Could not compile `core`.

For context, I was trying to add a method in hir/map/mod.rs while this happened. Here is the diff I have now:

diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index d7aa36b24f..7a9d0e0e3e 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -240,6 +240,12 @@ impl Forest {
     }
 }
 
+#[derive(Debug)]
+pub enum PatternSource<'hir> {
+    MatchExpr(&'hir Expr),
+    LetDecl(&'hir Local),
+}
+
 /// Represents a mapping from Node IDs to AST elements and their parent
 /// Node IDs
 #[derive(Clone)]
@@ -837,6 +843,46 @@ impl<'hir> Map<'hir> {
     pub fn node_to_pretty_string(&self, id: NodeId) -> String {
         print::to_string(self, |s| s.print_node(self.get(id)))
     }
+
+    pub fn get_pattern_source(&self, pat: &Pat) -> Option<PatternSource<'hir>> {
+        let result = self.walk_parent_nodes(pat.id, |node| match *node {
+            NodePat(_) => false,
+            _ => true,
+        }).expect("never found a parent for the pattern");
+
+        match self.find(result) {
+            Some(NodeExpr(e)) => {
+                // the enclosing expression must be a `match`
+                assert!(match e.node { ExprMatch(..) => true, _ => false });
+                Some(PatternSource::MatchExpr(e))
+            }
+            Some(NodeStmt(_)) => {
+                return None;
+            }
+            _ => {
+                warn!("No Node found for Nodeid: {:?}", result);
+                return None;
+            }
+        }
+    }
 }
 
 pub struct NodesMatchingSuffix<'a, 'hir:'a> {
diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
index 0577ba7f45..64bea0c544 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
@@ -108,6 +108,10 @@ pub fn gather_move_from_pat<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
         cmt: cmt,
         span_path_opt: pat_span_path_opt,
     };
+
+    let source = bccx.tcx.hir.get_pattern_source(move_pat);
+    debug!("gather_move_from_pat: move_pat={:?} source={:?}", move_pat, source);
+
     gather_move(bccx, move_data, move_error_collector, move_info);
 }
@arielb1
Copy link
Contributor

arielb1 commented Apr 9, 2017

This is an assertion coming from your patch:

thread 'rustc' panicked at 'assertion failed: match e.node { ExprMatch(..) => true, _ => false, }', src/librustc/hir/map/mod.rs:856
+                assert!(match e.node { ExprMatch(..) => true, _ => false });

You could try printing out e on the failure branch to see what it might be, for example

match e.node {
    ExprMatch(..) => true,
    _ => span_bug!(e.span, "unexpected expr {:?}", e.node)
}

@nikhilshagri
Copy link
Contributor Author

I replaced the assert with the match, but I'm getting an ICE on that one too, so it is not happening due to the assertion. The error message's a bit different though:

error: internal compiler error: src/librustc/hir/map/mod.rs:859: unexpected expr ExprClosure(CaptureByValue, FnDecl { inputs: [type(_), type(_)], output: DefaultReturn(src/libcore/iter/mod.rs:421:44: 421:44), variadic: false, has_implicit_self: false }, BodyId { node_id: NodeId(25707) }, src/libcore/iter/mod.rs:421:28: 421:43)
   --> src/libcore/iter/mod.rs:421:28
    |
421 |         self.it.fold(init, move |acc, elt| f(acc, elt.clone()))
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

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: run with `RUST_BACKTRACE=1` for a backtrace

thread 'rustc' panicked at 'Box<Any>', src/librustc_errors/lib.rs:375
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
stack backtrace:
   0: rustc::session::opt_span_bug_fmt::{{closure}}
   1: rustc::session::opt_span_bug_fmt
   2: rustc::session::span_bug_fmt
   3: rustc::hir::map::Map::get_pattern_source
   4: <rustc_borrowck::borrowck::gather_loans::GatherLoanCtxt<'a, 'tcx> as rustc::middle::expr_use_visitor::Delegate<'tcx>>::consume_pat
   5: rustc::middle::mem_categorization::MemCategorizationContext::cat_pattern_
   6: rustc::middle::expr_use_visitor::ExprUseVisitor::walk_pat
   7: rustc::middle::expr_use_visitor::ExprUseVisitor::consume_body
   8: rustc_borrowck::borrowck::build_borrowck_dataflow_data
   9: rustc_borrowck::borrowck::check_crate
  10: rustc_driver::driver::phase_3_run_analysis_passes::{{closure}}
  11: rustc_driver::driver::phase_3_run_analysis_passes
  12: rustc_driver::driver::compile_input
  13: rustc_driver::run_compiler
  14: std::panicking::try::do_call
  15: __rust_maybe_catch_panic
  16: <F as alloc::boxed::FnBox<A>>::call_box
  17: std::sys::imp::thread::Thread::new::thread_start
  18: start_thread
  19: clone

error: Could not compile `core`.

@goffrie
Copy link
Contributor

goffrie commented Apr 10, 2017

That ICE was exactly the point of the snippet, it's telling you that it found an ExprClosure (and not an ExprMatch).

@nikomatsakis
Copy link
Contributor

Seems like we need a third source, ArgumentPattern.

@nikomatsakis
Copy link
Contributor

Since this is a probem (I believe) with an in-progress patch, and not the current compiler, I'm going to close the issue. But @cynicaldevil, just to be clear, the situation is that I was suggesting we write a function (get_pattern_source()) that tried to categorize the context in which a pattern appeared; I had it signal a bug if some context was found that I had not anticipated. However, I didn't mean for that function to be complete -- that is, you'll have to add additional contexts, or else perhaps add an Other context and use that in place of signalling a bug (I tend to write code that tries to handle all cases and errors out otherwise, just to make sure I'm not missing something, but in this case it is perhaps ok to not be exhaustive, since this code is intended for use in error handling).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants