diff options
author | John Hodge <tpg@ucc.asn.au> | 2017-06-02 12:12:59 +0800 |
---|---|---|
committer | John Hodge <tpg@ucc.asn.au> | 2017-06-02 12:12:59 +0800 |
commit | 6f45483d70b7da92adec01ab67f5c7450c421801 (patch) | |
tree | 9ec323205f437f35d7453e6444c46f4782ba75ad | |
parent | 6747de8643ffd4a0a1705ac4c00c8cfb9a957154 (diff) | |
download | mrust-6f45483d70b7da92adec01ab67f5c7450c421801.tar.gz |
Tweaks to handling of struct patterns
-rw-r--r-- | src/hir_conv/bind.cpp | 30 | ||||
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 23 | ||||
-rw-r--r-- | src/parse/root.cpp | 4 |
3 files changed, 41 insertions, 16 deletions
diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp index c7a0829a..cf443eb6 100644 --- a/src/hir_conv/bind.cpp +++ b/src/hir_conv/bind.cpp @@ -248,37 +248,41 @@ namespace { (Struct, const auto& str = get_struct_ptr(sp, m_crate, e.path); if(str.m_data.is_Named() ) { - e.binding = &str; } else if( str.m_data.is_Unit() && e.sub_patterns.size() == 0 ) { - e.binding = &str; + } + else if( str.m_data.is_Tuple() && str.m_data.as_Tuple().empty() && e.sub_patterns.size() == 0 ) { } else { - ERROR(sp, E0000, "Struct pattern on field-less struct " << e.path); + ERROR(sp, E0000, "Struct pattern `" << pat << "` on field-less struct " << e.path); } + e.binding = &str; ), (EnumTuple, auto p = get_enum_ptr(sp, m_crate, e.path); const auto& var = p.first->m_variants[p.second].second; - TU_IFLET(::HIR::Enum::Variant, var, Tuple, _, - e.binding_ptr = p.first; - e.binding_idx = p.second; - ) + if( var.is_Tuple() ) { + } else { ERROR(sp, E0000, "Enum tuple pattern on non-tuple variant " << e.path); } + e.binding_ptr = p.first; + e.binding_idx = p.second; ), (EnumStruct, auto p = get_enum_ptr(sp, m_crate, e.path); const auto& var = p.first->m_variants[p.second].second; - TU_IFLET(::HIR::Enum::Variant, var, Struct, _, - // All good - e.binding_ptr = p.first; - e.binding_idx = p.second; - ) + if( var.is_Struct() ) { + } + else if( var.is_Unit() && e.sub_patterns.empty() ) { + } + else if( var.is_Tuple() && var.as_Tuple().empty() && e.sub_patterns.empty() ) { + } else { - ERROR(sp, E0000, "Enum tuple pattern on non-tuple variant " << e.path); + ERROR(sp, E0000, "Enum struct pattern `" << pat << "` on non-struct variant " << e.path); } + e.binding_ptr = p.first; + e.binding_idx = p.second; ) ) } diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 5597b022..fb56abc4 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -1157,6 +1157,12 @@ namespace { const auto& enm = *e; auto it = ::std::find_if(enm.m_variants.begin(), enm.m_variants.end(), [&](const auto&v)->auto{ return v.first == var_name; }); assert(it != enm.m_variants.end()); + if( it->second.is_Unit() || it->second.is_Value() || it->second.is_Tuple() ) { + ASSERT_BUG(node.span(), node.m_values.size() == 0, "Values provided for unit-like variant"); + ASSERT_BUG(node.span(), ! node.m_base_value, "Values provided for unit-like variant"); + return ; + } + ASSERT_BUG(node.span(), it->second.is_Struct(), "_StructLiteral for non-struct variant - " << node.m_path); fields_ptr = &it->second.as_Struct(); generics = &enm.m_params; ), @@ -1164,10 +1170,14 @@ namespace { TODO(node.span(), "StructLiteral of a union - " << ty); ), (Struct, - if( e->m_data.is_Unit() ) + if( e->m_data.is_Unit() || e->m_data.is_Tuple() ) { ASSERT_BUG(node.span(), node.m_values.size() == 0, "Values provided for unit-like struct"); - ASSERT_BUG(node.span(), ! node.m_base_value, "Values provided for unit-like struct"); + + if( node.m_base_value ) { + auto _ = this->push_inner_coerce_scoped(false); + node.m_base_value->visit( *this ); + } return ; } @@ -3817,10 +3827,14 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type this->add_ivars_params( e.path.m_params ); this->equate_types( sp, type, ::HIR::TypeRef::new_path(e.path.clone(), ::HIR::TypeRef::TypePathBinding(e.binding)) ); + if( e.sub_patterns.empty() ) + return ; + assert(e.binding); const auto& str = *e.binding; + // - assert check from earlier pass - assert( str.m_data.is_Named() ); + ASSERT_BUG(sp, str.m_data.is_Named(), "Struct pattern on non-Named struct"); const auto& sd = str.m_data.as_Named(); const auto& params = e.path.m_params; @@ -3893,6 +3907,9 @@ void Context::add_binding(const Span& sp, ::HIR::Pattern& pat, const ::HIR::Type this->equate_types( sp, type, ::HIR::TypeRef::new_path(mv$(path), ::HIR::TypeRef::TypePathBinding(e.binding_ptr)) ); } + if( e.sub_patterns.empty() ) + return ; + assert(e.binding_ptr); const auto& enm = *e.binding_ptr; const auto& var = enm.m_variants[e.binding_idx].second; diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 2dc2ffc4..5f8ed0a3 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -824,6 +824,7 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems& meta_items) CHECK_TOK(tok, TOK_IDENT); ::std::string name = mv$(tok.str()); + // Tuple-like variants if( GET_TOK(tok, lex) == TOK_PAREN_OPEN ) { ::std::vector<TypeRef> types; @@ -850,6 +851,7 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems& meta_items) GET_TOK(tok, lex); variants.push_back( AST::EnumVariant(mv$(item_attrs), mv$(name), mv$(types)) ); } + // Struct-like variants else if( tok.type() == TOK_BRACE_OPEN ) { ::std::vector<::AST::StructItem> fields; @@ -880,12 +882,14 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems& meta_items) variants.push_back( AST::EnumVariant(mv$(item_attrs), mv$(name), mv$(fields)) ); } + // Value variants else if( tok.type() == TOK_EQUAL ) { auto node = Parse_Expr(lex); variants.push_back( AST::EnumVariant(mv$(item_attrs), mv$(name), mv$(node)) ); GET_TOK(tok, lex); } + // Unit variants else { variants.push_back( AST::EnumVariant(mv$(item_attrs), mv$(name), ::AST::Expr()) ); |