summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@ucc.asn.au>2019-01-20 19:28:25 +0800
committerJohn Hodge <tpg@ucc.asn.au>2019-01-20 19:28:25 +0800
commite0181acd038e516f4dc61be4afb7906366c1fa80 (patch)
treec55b05ab296bfebda670e675b85173feb9f86078
parent0293a98f61b2d82a473c5109ce33dc7bb2cb606e (diff)
downloadmrust-e0181acd038e516f4dc61be4afb7906366c1fa80.tar.gz
HIR Bind - Handle `Enum::Foo { .. }` patterns for everything
-rw-r--r--src/hir_conv/bind.cpp73
1 files changed, 68 insertions, 5 deletions
diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp
index 9d15da18..c979b2e6 100644
--- a/src/hir_conv/bind.cpp
+++ b/src/hir_conv/bind.cpp
@@ -266,6 +266,15 @@ namespace {
this->visit_pattern_Value(sp, pat, e.start);
this->visit_pattern_Value(sp, pat, e.end);
),
+ (StructValue,
+ const auto& str = get_struct_ptr(sp, m_crate, e.path);
+ TU_IFLET(::HIR::Struct::Data, str.m_data, Unit, _,
+ e.binding = &str;
+ )
+ else {
+ ERROR(sp, E0000, "Struct value pattern on non-unit struct " << e.path);
+ }
+ ),
(StructTuple,
const auto& str = get_struct_ptr(sp, m_crate, e.path);
TU_IFLET(::HIR::Struct::Data, str.m_data, Tuple, _,
@@ -288,6 +297,17 @@ namespace {
}
e.binding = &str;
),
+ (EnumValue,
+ auto p = get_enum_ptr(sp, m_crate, e.path);
+ if( p.first->m_data.is_Data() )
+ {
+ const auto& var = p.first->m_data.as_Data()[p.second];
+ if( var.is_struct || var.type != ::HIR::TypeRef::new_unit() )
+ ERROR(sp, E0000, "Enum value pattern on non-unit variant " << e.path);
+ }
+ e.binding_ptr = p.first;
+ e.binding_idx = p.second;
+ ),
(EnumTuple,
auto p = get_enum_ptr(sp, m_crate, e.path);
if( !p.first->m_data.is_Data() )
@@ -300,11 +320,54 @@ namespace {
),
(EnumStruct,
auto p = get_enum_ptr(sp, m_crate, e.path);
- if( !p.first->m_data.is_Data() )
- ERROR(sp, E0000, "Enum struct pattern `" << pat << "` on non-struct variant " << e.path);
- const auto& var = p.first->m_data.as_Data()[p.second];
- if( !var.is_struct )
- ERROR(sp, E0000, "Enum struct pattern `" << pat << "` on non-struct variant " << e.path);
+ if( !e.is_exhaustive && e.sub_patterns.empty() )
+ {
+ if( !p.first->m_data.is_Data() ) {
+ pat.m_data = ::HIR::Pattern::Data::make_EnumValue({
+ ::std::move(e.path), p.first, p.second
+ });
+ }
+ else {
+ const auto& var = p.first->m_data.as_Data()[p.second];
+ if( var.type == ::HIR::TypeRef::new_unit() )
+ {
+ pat.m_data = ::HIR::Pattern::Data::make_EnumValue({
+ ::std::move(e.path), p.first, p.second
+ });
+ }
+ else if( !var.is_struct )
+ {
+ ASSERT_BUG(sp, var.type.m_data.is_Path(), "");
+ ASSERT_BUG(sp, var.type.m_data.as_Path().binding.is_Struct(), "");
+ const auto& str = *var.type.m_data.as_Path().binding.as_Struct();
+ ASSERT_BUG(sp, str.m_data.is_Tuple(), "");
+ const auto& flds = str.m_data.as_Tuple();
+ ::std::vector<HIR::Pattern> subpats;
+ for(size_t i = 0; i < flds.size(); i ++)
+ subpats.push_back(::HIR::Pattern { });
+ pat.m_data = ::HIR::Pattern::Data::make_EnumTuple({
+ ::std::move(e.path), p.first, p.second, mv$(subpats)
+ });
+ }
+ else
+ {
+ // Keep as a struct pattern
+ }
+ }
+ }
+ else
+ {
+ if( !p.first->m_data.is_Data() )
+ {
+ ERROR(sp, E0000, "Enum struct pattern `" << pat << "` on non-struct variant " << e.path);
+ }
+ else
+ {
+ const auto& var = p.first->m_data.as_Data()[p.second];
+ if( !var.is_struct )
+ ERROR(sp, E0000, "Enum struct pattern `" << pat << "` on non-struct variant " << e.path);
+ }
+ }
e.binding_ptr = p.first;
e.binding_idx = p.second;
)