diff options
author | John Hodge <tpg@mutabah.net> | 2016-09-24 22:58:28 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-09-24 22:58:28 +0800 |
commit | 7fa72647893f4661b701da4344e8b40645fbb0e6 (patch) | |
tree | 5c63ee2080db7251583ac8f805a6190ab933dc10 | |
parent | 8d8dcfa8484a134cace25983ae8682da464d3ca8 (diff) | |
download | mrust-7fa72647893f4661b701da4344e8b40645fbb0e6.tar.gz |
MIR Gen - Support zero-arm matches - Since they can never be reached, emit a Diverge
-rw-r--r-- | src/mir/from_hir.cpp | 5 | ||||
-rw-r--r-- | src/mir/from_hir.hpp | 1 | ||||
-rw-r--r-- | src/mir/mir_builder.cpp | 19 |
3 files changed, 24 insertions, 1 deletions
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index a281cbaa..c6d9bcd3 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -378,7 +378,10 @@ namespace { if( node.m_arms.size() == 0 ) { // Nothing - TODO(node.span(), "Handle zero-arm match - can only match over ! or similar"); + //const auto& ty = node.m_value->m_res_type; + // TODO: Ensure that the type is a zero-variant enum or ! + m_builder.end_split_arm_early(node.span()); + m_builder.end_block( ::MIR::Terminator::make_Diverge({}) ); } else if( node.m_arms.size() == 1 && node.m_arms[0].m_patterns.size() == 1 && ! node.m_arms[0].m_cond ) { // - Shortcut: Single-arm match diff --git a/src/mir/from_hir.hpp b/src/mir/from_hir.hpp index c915cfcc..39890bbf 100644 --- a/src/mir/from_hir.hpp +++ b/src/mir/from_hir.hpp @@ -167,6 +167,7 @@ public: void terminate_scope(const Span& sp, ScopeHandle ); void terminate_scope_early(const Span& sp, const ScopeHandle& ); void end_split_arm(const Span& sp, const ScopeHandle& , bool reachable); + void end_split_arm_early(const Span& sp); const ScopeHandle& fcn_scope() const { return m_fcn_scope; diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp index f4f9db7e..c5564045 100644 --- a/src/mir/mir_builder.cpp +++ b/src/mir/mir_builder.cpp @@ -480,6 +480,25 @@ void MirBuilder::end_split_arm(const Span& sp, const ScopeHandle& handle, bool r // TODO: Undo moves from within the other scope sd_split.arms.push_back( {} ); } +void MirBuilder::end_split_arm_early(const Span& sp) +{ + // Terminate all scopes until a split is found. + while( ! m_scope_stack.empty() && ! m_scopes.at( m_scope_stack.back() ).data.is_Split() ) + { + auto& scope_def = m_scopes[m_scope_stack.back()]; + // Fully drop the scope + drop_scope_values(scope_def); + m_scope_stack.pop_back(); + complete_scope(scope_def); + } + + if( !m_scope_stack.empty() ) + { + auto& sd = m_scopes[ m_scope_stack.back() ]; + auto& sd_split = sd.data.as_Split(); + sd_split.arms.back().has_early_terminated = true; + } +} void MirBuilder::complete_scope(ScopeDef& sd) { sd.complete = true; |