summaryrefslogtreecommitdiff
path: root/src/mir
diff options
context:
space:
mode:
authorJohn Hodge <tpg@ucc.asn.au>2017-11-01 20:46:36 +0800
committerJohn Hodge <tpg@ucc.asn.au>2017-11-01 20:46:36 +0800
commitcb271f8ea98d1a5c65a5e636a0e73a85710027b4 (patch)
tree9694427c074c0e0d581cde6e01b6167016e0f844 /src/mir
parent8306f43ccdf0414b48891aa5eb04d8901899c052 (diff)
downloadmrust-cb271f8ea98d1a5c65a5e636a0e73a85710027b4.tar.gz
HIR - Refactor enums to only embed a single field (and give variants types)
Diffstat (limited to 'src/mir')
-rw-r--r--src/mir/cleanup.cpp46
-rw-r--r--src/mir/from_hir.cpp203
-rw-r--r--src/mir/from_hir_match.cpp153
-rw-r--r--src/mir/helpers.cpp36
-rw-r--r--src/mir/mir.cpp6
-rw-r--r--src/mir/mir.hpp3
-rw-r--r--src/mir/mir_builder.cpp43
-rw-r--r--src/mir/optimise.cpp2
-rw-r--r--src/mir/visit_crate_mir.cpp17
9 files changed, 227 insertions, 282 deletions
diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp
index 9718f046..455eef43 100644
--- a/src/mir/cleanup.cpp
+++ b/src/mir/cleanup.cpp
@@ -289,7 +289,7 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR
}
)
)
- return ::MIR::RValue::make_Struct({ te.path.m_data.as_Generic().clone(), ~0u, mv$(lvals) });
+ return ::MIR::RValue::make_Struct({ te.path.m_data.as_Generic().clone(), mv$(lvals) });
}
else if( te.binding.is_Enum() )
{
@@ -298,33 +298,19 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR
auto monomorph = [&](const auto& tpl) { return monomorphise_type(state.sp, enm.m_params, te.path.m_data.as_Generic().m_params, tpl); };
- ::std::vector< ::MIR::Param> lvals;
- MIR_ASSERT(state, lit_var.idx < enm.m_variants.size(), "Variant index out of range");
- TU_MATCHA( (enm.m_variants[lit_var.idx].second), (ve),
- (Unit,
- ),
- (Value,
- ),
- (Tuple,
- MIR_ASSERT(state, lit_var.vals.size() == ve.size(), "Value count mismatch in literal for " << ty << " #" << lit_var.idx << " - exp " << ve.size() << ", " << lit);
- for(unsigned int i = 0; i < ve.size(); i ++)
- {
- auto ent_ty = monomorph(ve[i].ent);
- auto rval = MIR_Cleanup_LiteralToRValue(state, mutator, lit_var.vals[i], ent_ty.clone(), ::HIR::GenericPath());
- lvals.push_back( mutator.in_temporary(mv$(ent_ty), mv$(rval)) );
- }
- ),
- (Struct,
- MIR_ASSERT(state, lit_var.vals.size() == ve.size(), "Value count mismatch in literal for " << ty << " #" << lit_var.idx << " - exp " << ve.size() << ", " << lit);
- for(unsigned int i = 0; i < ve.size(); i ++)
- {
- auto ent_ty = monomorph(ve[i].second.ent);
- auto rval = MIR_Cleanup_LiteralToRValue(state, mutator, lit_var.vals[i], ent_ty.clone(), ::HIR::GenericPath());
- lvals.push_back( mutator.in_temporary(mv$(ent_ty), mv$(rval)) );
- }
- )
- )
- return ::MIR::RValue::make_Struct({ te.path.m_data.as_Generic().clone(), lit_var.idx, mv$(lvals) });
+ MIR_ASSERT(state, lit_var.idx < enm.num_variants(), "Variant index out of range");
+ ::MIR::Param p;
+ if( const auto* e = enm.m_data.opt_Data() )
+ {
+ auto ty = monomorph( e->at(lit_var.idx).type );
+ auto rval = MIR_Cleanup_LiteralToRValue(state, mutator, *lit_var.val, ty.clone(), ::HIR::GenericPath());
+ p = mutator.in_temporary(mv$(ty), mv$(rval));
+ }
+ else
+ {
+ p = mutator.in_temporary(::HIR::TypeRef::new_unit(), ::MIR::RValue::make_Tuple({}));
+ }
+ return ::MIR::RValue::make_Variant({ te.path.m_data.as_Generic().clone(), lit_var.idx, mv$(p) });
}
else
{
@@ -540,7 +526,7 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const Span& sp, const StaticTraitR
)
auto new_path = ty_path.clone();
- return mutator.in_temporary( mv$(ty), ::MIR::RValue::make_Struct({ mv$(new_path), ~0u, mv$(vals) }) );
+ return mutator.in_temporary( mv$(ty), ::MIR::RValue::make_Struct({ mv$(new_path), mv$(vals) }) );
}
else if( ty.m_data.is_Pointer() )
{
@@ -820,7 +806,7 @@ bool MIR_Cleanup_Unsize_GetMetadata(const ::MIR::TypeResolve& state, MirMutator&
}
)
)
- return ::MIR::RValue::make_Struct({ dte.path.m_data.as_Generic().clone(), ~0u, mv$(ents) });
+ return ::MIR::RValue::make_Struct({ dte.path.m_data.as_Generic().clone(), mv$(ents) });
}
if( dst_ty.m_data.is_Borrow() )
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp
index 2a02b166..06a70d49 100644
--- a/src/mir/from_hir.cpp
+++ b/src/mir/from_hir.cpp
@@ -261,14 +261,14 @@ namespace {
),
(EnumValue,
const auto& enm = *e.binding_ptr;
- if( enm.m_variants.size() > 1 )
+ if( enm.num_variants() > 1 )
{
ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected - " << pat);
}
),
(EnumTuple,
const auto& enm = *e.binding_ptr;
- ASSERT_BUG(sp, enm.m_variants.size() == 1 || allow_refutable, "Refutable pattern not expected - " << pat);
+ ASSERT_BUG(sp, enm.num_variants() == 1 || allow_refutable, "Refutable pattern not expected - " << pat);
auto lval_var = ::MIR::LValue::make_Downcast({ box$(mv$(lval)), e.binding_idx });
for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ )
{
@@ -277,8 +277,11 @@ namespace {
),
(EnumStruct,
const auto& enm = *e.binding_ptr;
- ASSERT_BUG(sp, enm.m_variants.size() == 1 || allow_refutable, "Refutable pattern not expected - " << pat);
- const auto& fields = enm.m_variants[e.binding_idx].second.as_Struct();
+ ASSERT_BUG(sp, enm.num_variants() == 1 || allow_refutable, "Refutable pattern not expected - " << pat);
+ ASSERT_BUG(sp, enm.m_data.is_Data(), "Expected struct variant - " << pat);
+ const auto& var = enm.m_data.as_Data()[e.binding_idx];;
+ const auto& str = *var.type.m_data.as_Path().binding.as_Struct();
+ const auto& fields = str.m_data.as_Named();
auto lval_var = ::MIR::LValue::make_Downcast({ box$(mv$(lval)), e.binding_idx });
for(const auto& fld_pat : e.sub_patterns)
{
@@ -1691,25 +1694,47 @@ namespace {
values.push_back( m_builder.get_result_in_param(arg->span(), arg->m_res_type) );
}
- unsigned int variant_index = ~0u;
- if( !node.m_is_struct )
+ if( node.m_is_struct )
+ {
+ m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({
+ node.m_path.clone(),
+ mv$(values)
+ }) );
+ }
+ else
{
// Get the variant index from the enum.
auto enum_path = node.m_path.m_path;
enum_path.m_components.pop_back();
const auto& var_name = node.m_path.m_path.m_components.back();
const auto& enm = m_builder.crate().get_enum_by_path(sp, enum_path);
- auto var_it = ::std::find_if(enm.m_variants.begin(), enm.m_variants.end(), [&](const auto& x){ return x.first == var_name; });
- ASSERT_BUG(sp, var_it != enm.m_variants.end(), "Variant " << node.m_path.m_path << " isn't present");
- variant_index = var_it - enm.m_variants.begin();
- }
+ size_t idx = enm.find_variant(var_name);
+ ASSERT_BUG(sp, idx != SIZE_MAX, "Variant " << node.m_path.m_path << " isn't present");
- m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({
- node.m_path.clone(),
- variant_index,
- mv$(values)
- }) );
+ // TODO: Validation?
+ ASSERT_BUG(sp, enm.m_data.is_Data(), "TupleVariant on non-data enum - " << node.m_path.m_path);
+ const auto& var_ty = enm.m_data.as_Data()[idx].type;
+
+ // Take advantage of the identical generics to cheaply clone/monomorph the path.
+ const auto& str = *var_ty.m_data.as_Path().binding.as_Struct();
+ ::HIR::GenericPath struct_path = node.m_path.clone();
+ struct_path.m_path = var_ty.m_data.as_Path().path.m_data.as_Generic().m_path;
+
+ // Create struct instance
+ m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({
+ struct_path.clone(),
+ mv$(values)
+ }) );
+
+ auto ty = ::HIR::TypeRef::new_path( mv$(struct_path), &str );
+ auto v = m_builder.get_result_in_param(node.span(), ty);
+ m_builder.set_result(node.span(), ::MIR::RValue::make_Variant({
+ mv$(enum_path),
+ static_cast<unsigned>(idx),
+ mv$(v)
+ }) );
+ }
}
::std::vector< ::MIR::Param> get_args(/*const*/ ::std::vector<::HIR::ExprNodeP>& args)
@@ -1949,24 +1974,40 @@ namespace {
{
const Span& sp = node.span();
TRACE_FUNCTION_F("_UnitVariant");
- unsigned int variant_index = ~0u;
if( !node.m_is_struct )
{
// Get the variant index from the enum.
auto enum_path = node.m_path.m_path;
enum_path.m_components.pop_back();
const auto& var_name = node.m_path.m_path.m_components.back();
+
const auto& enm = m_builder.crate().get_enum_by_path(sp, enum_path);
- auto var_it = ::std::find_if(enm.m_variants.begin(), enm.m_variants.end(), [&](const auto& x){ return x.first == var_name; });
- ASSERT_BUG(sp, var_it != enm.m_variants.end(), "Variant " << node.m_path.m_path << " isn't present");
- variant_index = var_it - enm.m_variants.begin();
+ auto idx = enm.find_variant(var_name);
+ ASSERT_BUG(sp, idx != SIZE_MAX, "Variant " << node.m_path.m_path << " isn't present");
+
+ // VALIDATION
+ if( const auto* e = enm.m_data.opt_Data() )
+ {
+ const auto& var = (*e)[idx];
+ ASSERT_BUG(sp, !var.is_struct, "Variant " << node.m_path.m_path << " isn't a unit variant");
+ }
+
+ m_builder.set_result( node.span(), ::MIR::RValue::make_Tuple({}) );
+ auto v = m_builder.get_result_in_param(node.span(), ::HIR::TypeRef::new_unit());
+ m_builder.set_result( node.span(), ::MIR::RValue::make_Variant({
+ mv$(enum_path),
+ static_cast<unsigned>(idx),
+ mv$(v)
+ }) );
+ }
+ else
+ {
+ m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({
+ node.m_path.clone(),
+ {}
+ }) );
}
- m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({
- node.m_path.clone(),
- variant_index,
- {}
- }) );
}
void visit(::HIR::ExprNode_PathValue& node) override
{
@@ -1974,18 +2015,23 @@ namespace {
TRACE_FUNCTION_F("_PathValue - " << node.m_path);
TU_MATCH( ::HIR::Path::Data, (node.m_path.m_data), (pe),
(Generic,
+ // Enum variant constructor.
if( node.m_target == ::HIR::ExprNode_PathValue::ENUM_VAR_CONSTR ) {
auto enum_path = pe.m_path;
enum_path.m_components.pop_back();
const auto& var_name = pe.m_path.m_components.back();
+ // Validation only.
const auto& enm = m_builder.crate().get_enum_by_path(sp, enum_path);
- auto var_it = ::std::find_if(enm.m_variants.begin(), enm.m_variants.end(), [&](const auto& x){ return x.first == var_name; });
- ASSERT_BUG(sp, var_it != enm.m_variants.end(), "Variant " << pe.m_path << " isn't present");
- const auto& var = var_it->second;
- ASSERT_BUG(sp, var.is_Tuple(), "Variant " << pe.m_path << " isn't a tuple variant");
-
- // TODO: Ideally, the creation of the wrapper function would happen somewhere before this?
+ ASSERT_BUG(sp, enm.m_data.is_Data(), "Getting variant constructor of value varianta");
+ size_t idx = enm.find_variant(var_name);
+ ASSERT_BUG(sp, idx != SIZE_MAX, "Variant " << pe.m_path << " isn't present");
+ const auto& var = enm.m_data.as_Data()[idx];
+ ASSERT_BUG(sp, var.type.m_data.is_Path(), "Variant " << pe.m_path << " isn't a tuple");
+ const auto& str = *var.type.m_data.as_Path().binding.as_Struct();
+ ASSERT_BUG(sp, str.m_data.is_Tuple(), "Variant " << pe.m_path << " isn't a tuple");
+
+ // TODO: Ideally, the creation of the wrapper function would happen somewhere before trans?
auto tmp = m_builder.new_temporary( node.m_res_type );
m_builder.push_stmt_assign( sp, tmp.clone(), ::MIR::Constant::make_ItemAddr(node.m_path.clone()) );
m_builder.set_result( sp, mv$(tmp) );
@@ -2008,7 +2054,6 @@ namespace {
// TODO: Why is this still a PathValue?
m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({
pe.clone(),
- ~0u,
{}
}) );
),
@@ -2115,9 +2160,13 @@ namespace {
m_builder.set_result( node.span(), m_builder.get_variable(node.span(), node.m_slot) );
}
- void visit(::HIR::ExprNode_StructLiteral& node) override
+ void visit_sl_inner(::HIR::ExprNode_StructLiteral& node, const ::HIR::Struct& str, const ::HIR::GenericPath& path)
{
- TRACE_FUNCTION_F("_StructLiteral");
+ const Span& sp = node.span();
+
+ ASSERT_BUG(sp, str.m_data.is_Named(), "");
+ const ::HIR::t_struct_fields& fields = str.m_data.as_Named();
+
::MIR::LValue base_val;
if( node.m_base_value )
{
@@ -2126,37 +2175,6 @@ namespace {
base_val = m_builder.get_result_in_lvalue(node.m_base_value->span(), node.m_base_value->m_res_type);
}
- unsigned int variant_index = ~0u;
- const ::HIR::t_struct_fields* fields_ptr = nullptr;
- TU_MATCH(::HIR::TypeRef::TypePathBinding, (node.m_res_type.m_data.as_Path().binding), (e),
- (Unbound, ),
- (Opaque, ),
- (Enum,
- const auto& var_name = node.m_path.m_path.m_components.back();
- 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());
- variant_index = it - enm.m_variants.begin();
- fields_ptr = &it->second.as_Struct();
- ),
- (Union,
- BUG(node.span(), "_StructLiteral Union");
- ),
- (Struct,
- if(e->m_data.is_Unit()) {
- m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({
- node.m_path.clone(),
- variant_index,
- {}
- }) );
- return ;
- }
- fields_ptr = &e->m_data.as_Named();
- )
- )
- assert(fields_ptr);
- const ::HIR::t_struct_fields& fields = *fields_ptr;
-
::std::vector<bool> values_set;
::std::vector< ::MIR::Param> values;
values.resize( fields.size() );
@@ -2198,11 +2216,63 @@ namespace {
}
m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({
- node.m_path.clone(),
- variant_index,
+ path.clone(),
mv$(values)
}) );
}
+
+ void visit(::HIR::ExprNode_StructLiteral& node) override
+ {
+ TRACE_FUNCTION_F("_StructLiteral");
+
+ TU_MATCH(::HIR::TypeRef::TypePathBinding, (node.m_res_type.m_data.as_Path().binding), (e),
+ (Unbound, ),
+ (Opaque, ),
+ (Enum,
+ auto enum_path = node.m_path.m_path;
+ enum_path.m_components.pop_back();
+ const auto& var_name = node.m_path.m_path.m_components.back();
+
+ const auto& enm = *e;
+ size_t idx = enm.find_variant(var_name);
+ ASSERT_BUG(node.span(), idx != SIZE_MAX, "");
+ ASSERT_BUG(node.span(), enm.m_data.is_Data(), "");
+ const auto& var_ty = enm.m_data.as_Data()[idx].type;
+ const auto& str = *var_ty.m_data.as_Path().binding.as_Struct();
+
+ // Take advantage of the identical generics to cheaply clone/monomorph the path.
+ ::HIR::GenericPath struct_path = node.m_path.clone();
+ struct_path.m_path = var_ty.m_data.as_Path().path.m_data.as_Generic().m_path;
+
+ this->visit_sl_inner(node, str, struct_path);
+
+ // Create type of result from the above path
+ auto ty = ::HIR::TypeRef::new_path( mv$(struct_path), &str );
+ // Obtain in a param
+ auto v = m_builder.get_result_in_param(node.span(), ty);
+ // And create Variant
+ m_builder.set_result( node.span(), ::MIR::RValue::make_Variant({
+ mv$(enum_path),
+ static_cast<unsigned>(idx),
+ mv$(v)
+ }) );
+ ),
+ (Union,
+ BUG(node.span(), "_StructLiteral Union isn't valid?");
+ ),
+ (Struct,
+ if(e->m_data.is_Unit()) {
+ m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({
+ node.m_path.clone(),
+ {}
+ }) );
+ return ;
+ }
+
+ this->visit_sl_inner(node, *e, node.m_path);
+ )
+ )
+ }
void visit(::HIR::ExprNode_UnionLiteral& node) override
{
TRACE_FUNCTION_F("_UnionLiteral " << node.m_path);
@@ -2281,7 +2351,6 @@ namespace {
m_builder.set_result( node.span(), ::MIR::RValue::make_Struct({
node.m_obj_path.clone(),
- ~0u,
mv$(vals)
}) );
}
diff --git a/src/mir/from_hir_match.cpp b/src/mir/from_hir_match.cpp
index 55d7377e..61548fd2 100644
--- a/src/mir/from_hir_match.cpp
+++ b/src/mir/from_hir_match.cpp
@@ -806,57 +806,24 @@ void PatternRulesetBuilder::append_from_lit(const Span& sp, const ::HIR::Literal
(Enum,
ASSERT_BUG(sp, lit.is_Variant(), "Matching enum non-variant literal - " << lit);
auto var_idx = lit.as_Variant().idx;
- const auto& list = lit.as_Variant().vals;
+ const auto& subval = *lit.as_Variant().val;
auto monomorph = [&](const auto& ty) {
auto rv = monomorphise_type(sp, pbe->m_params, e.path.m_data.as_Generic().m_params, ty);
this->m_resolve.expand_associated_types(sp, rv);
return rv;
};
- ASSERT_BUG(sp, var_idx < pbe->m_variants.size(), "Literal refers to a variant out of range");
- const auto& var_def = pbe->m_variants.at(var_idx);
-
+ ASSERT_BUG(sp, var_idx < pbe->num_variants(), "Literal refers to a variant out of range");
PatternRulesetBuilder sub_builder { this->m_resolve };
- sub_builder.m_field_path = m_field_path;
- sub_builder.m_field_path.push_back(var_idx);
- sub_builder.m_field_path.push_back(0);
-
- TU_MATCH( ::HIR::Enum::Variant, (var_def.second), (fields_def),
- (Unit,
- ),
- (Value,
- ),
- (Tuple,
- ASSERT_BUG(sp, fields_def.size() == list.size(), "");
-
- for( unsigned int i = 0; i < list.size(); i ++ )
- {
- sub_builder.m_field_path.back() = i;
- const auto& val = list[i];
- const auto& ty_tpl = fields_def[i].ent;
-
- ::HIR::TypeRef tmp;
- const auto& subty = (monomorphise_type_needed(ty_tpl) ? tmp = monomorph(ty_tpl) : ty_tpl);
-
- sub_builder.append_from_lit( sp, val, subty );
- }
- ),
- (Struct,
- ASSERT_BUG(sp, fields_def.size() == list.size(), "");
-
- for( unsigned int i = 0; i < list.size(); i ++ )
- {
- sub_builder.m_field_path.back() = i;
- const auto& val = list[i];
- const auto& ty_tpl = fields_def[i].second.ent;
+ if( const auto* e = pbe->m_data.opt_Data() )
+ {
+ const auto& var_def = e->at(var_idx);
- ::HIR::TypeRef tmp;
- const auto& subty = (monomorphise_type_needed(ty_tpl) ? tmp = monomorph(ty_tpl) : ty_tpl);
+ sub_builder.m_field_path = m_field_path;
+ sub_builder.m_field_path.push_back(var_idx);
- sub_builder.append_from_lit( sp, val, subty );
- }
- )
- )
+ sub_builder.append_from_lit(sp, subval, monomorph(var_def.type));
+ }
this->push_rule( PatternRule::make_Variant({ var_idx, mv$(sub_builder.m_rules) }) );
)
@@ -1253,9 +1220,12 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa
this->push_rule( PatternRule::make_Variant( {pe.binding_idx, {} } ) );
),
(EnumTuple,
- const auto& var_def = pe.binding_ptr->m_variants.at(pe.binding_idx);
+ const auto& variants = pe.binding_ptr->m_data.as_Data();
+ const auto& var_def = variants.at(pe.binding_idx);
+ const auto& str = *var_def.type.m_data.as_Path().binding.as_Struct();
+ const auto& fields_def = str.m_data.as_Tuple();
- const auto& fields_def = var_def.second.as_Tuple();
+ // TODO: Unify with the struct pattern code?
PatternRulesetBuilder sub_builder { this->m_resolve };
sub_builder.m_field_path = m_field_path;
sub_builder.m_field_path.push_back(pe.binding_idx);
@@ -1276,8 +1246,11 @@ void PatternRulesetBuilder::append_from(const Span& sp, const ::HIR::Pattern& pa
this->push_rule( PatternRule::make_Variant({ pe.binding_idx, mv$(sub_builder.m_rules) }) );
),
(EnumStruct,
- const auto& var_def = pe.binding_ptr->m_variants.at(pe.binding_idx);
- const auto& fields_def = var_def.second.as_Struct();
+ const auto& variants = pe.binding_ptr->m_data.as_Data();
+ const auto& var_def = variants.at(pe.binding_idx);
+ const auto& str = *var_def.type.m_data.as_Path().binding.as_Struct();
+ const auto& fields_def = str.m_data.as_Named();
+
// 1. Create a vector of pattern indexes for each field in the variant.
::std::vector<unsigned int> tmp;
tmp.resize( fields_def.size(), ~0u );
@@ -1807,32 +1780,13 @@ namespace {
return &ty;
}
};
- ASSERT_BUG(sp, idx < pbe->m_variants.size(), "Variant index (" << idx << ") out of range (" << pbe->m_variants.size() << ") for enum " << *cur_ty);
- const auto& var = pbe->m_variants[idx];
-
- i++;
- assert(i < field_path.data.size());
- unsigned fld_idx = field_path.data[i];
+ ASSERT_BUG(sp, pbe->m_data.is_Data(), "Value enum being destructured - " << *cur_ty);
+ const auto& variants = pbe->m_data.as_Data();
+ ASSERT_BUG(sp, idx < variants.size(), "Variant index (" << idx << ") out of range (" << variants.size() << ") for enum " << *cur_ty);
+ const auto& var = variants[idx];
- TU_MATCHA( (var.second), (e),
- (Unit,
- BUG(sp, "Unit variant being destructured");
- ),
- (Value,
- BUG(sp, "Value variant being destructured");
- ),
- (Tuple,
- ASSERT_BUG(sp, fld_idx < e.size(), "Variant field index (" << fld_idx << ") out of range (" << e.size() << ") for enum " << *cur_ty << "::" << var.first);
- cur_ty = monomorph_to_ptr(e[fld_idx].ent);
- ),
- (Struct,
- ASSERT_BUG(sp, fld_idx < e.size(), "Variant field index (" << fld_idx << ") out of range (" << e.size() << ") for enum " << *cur_ty << "::" << var.first);
- cur_ty = monomorph_to_ptr(e[fld_idx].second.ent);
- )
- )
- DEBUG("*cur_ty = " << *cur_ty);
+ cur_ty = monomorph_to_ptr(var.type);
lval = ::MIR::LValue::make_Downcast({ box$(lval), idx });
- lval = ::MIR::LValue::make_Field({ box$(lval), fld_idx });
)
)
),
@@ -2206,7 +2160,7 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span&
unsigned int var_idx = re.idx;
auto next_bb = builder.new_bb_unlinked();
- auto var_count = pbe->m_variants.size();
+ auto var_count = pbe->num_variants();
// Generate a switch with only one option different.
::std::vector< ::MIR::BasicBlockId> arms(var_count, fail_bb);
@@ -2217,49 +2171,18 @@ int MIR_LowerHIR_Match_Simple__GeneratePattern(MirBuilder& builder, const Span&
if( re.sub_rules.size() > 0 )
{
- const auto& var_data = pbe->m_variants.at(re.idx).second;
- TU_MATCHA( (var_data), (ve),
- (Unit,
- // Nothing to recurse
- ),
- (Value,
- // Nothing to recurse
- ),
- (Tuple,
- // Create a dummy tuple to contain the inner types.
- ::std::vector< ::HIR::TypeRef> fake_ty_ents;
- fake_ty_ents.reserve( ve.size() );
- for(unsigned int i = 0; i < ve.size(); i ++)
- {
- fake_ty_ents.push_back( monomorph(ve[i].ent) );
- }
- ::HIR::TypeRef fake_tup = ::HIR::TypeRef( mv$(fake_ty_ents) );
-
- // Recurse with the new ruleset
- MIR_LowerHIR_Match_Simple__GeneratePattern(builder, sp,
- re.sub_rules.data(), re.sub_rules.size(),
- fake_tup, ::MIR::LValue::make_Downcast({ box$(val.clone()), var_idx }), rule.field_path.size()+1,
- fail_bb
- );
- ),
- (Struct,
- // Create a dummy tuple to contain the inner types.
- ::std::vector< ::HIR::TypeRef> fake_ty_ents;
- fake_ty_ents.reserve( ve.size() );
- for(unsigned int i = 0; i < ve.size(); i ++)
- {
- fake_ty_ents.push_back( monomorph(ve[i].second.ent) );
- }
- ::HIR::TypeRef fake_tup = ::HIR::TypeRef( mv$(fake_ty_ents) );
-
- // Recurse with the new ruleset
- MIR_LowerHIR_Match_Simple__GeneratePattern(builder, sp,
- re.sub_rules.data(), re.sub_rules.size(),
- fake_tup, ::MIR::LValue::make_Downcast({ box$(val.clone()), var_idx }), rule.field_path.size()+1,
- fail_bb
- );
- )
- )
+ ASSERT_BUG(sp, pbe->m_data.is_Data(), "Sub-rules present for non-data enum");
+ const auto& variants = pbe->m_data.as_Data();
+ const auto& var_ty = variants.at(re.idx).type;
+ ::HIR::TypeRef tmp;
+ const auto& var_ty_m = (monomorphise_type_needed(var_ty) ? tmp = monomorph(var_ty) : var_ty);
+
+ // Recurse with the new ruleset
+ MIR_LowerHIR_Match_Simple__GeneratePattern(builder, sp,
+ re.sub_rules.data(), re.sub_rules.size(),
+ var_ty_m, ::MIR::LValue::make_Downcast({ box$(val.clone()), var_idx }), rule.field_path.size()+1,
+ fail_bb
+ );
}
) // TypePathBinding::Enum
)
@@ -3098,7 +3021,7 @@ void MatchGenGrouped::gen_dispatch__enum(::HIR::TypeRef ty, ::MIR::LValue val, c
auto decison_arm = m_builder.pause_cur_block();
- auto var_count = pbe->m_variants.size();
+ auto var_count = pbe->num_variants();
::std::vector< ::MIR::BasicBlockId> arms(var_count, def_blk);
size_t arm_idx = 0;
for(size_t i = 0; i < rules.size(); i ++)
diff --git a/src/mir/helpers.cpp b/src/mir/helpers.cpp
index ddab9317..1e43e361 100644
--- a/src/mir/helpers.cpp
+++ b/src/mir/helpers.cpp
@@ -200,34 +200,20 @@ const ::HIR::TypeRef& ::MIR::TypeResolve::get_lvalue_type(::HIR::TypeRef& tmp, c
if( te.binding.is_Enum() )
{
const auto& enm = *te.binding.as_Enum();
- const auto& variants = enm.m_variants;
- MIR_ASSERT(*this, e.variant_index < variants.size(), "Variant index out of range");
+ MIR_ASSERT(*this, enm.m_data.is_Data(), "Downcast on non-data enum - " << ty);
+ const auto& variants = enm.m_data.as_Data();
+ MIR_ASSERT(*this, e.variant_index < variants.size(), "Variant index out of range for " << ty);
const auto& variant = variants[e.variant_index];
- // TODO: Make data variants refer to associated types (unify enum and struct handling)
- TU_MATCHA( (variant.second), (ve),
- (Value,
- ),
- (Unit,
- ),
- (Tuple,
- // HACK! Create tuple.
- ::std::vector< ::HIR::TypeRef> tys;
- for(const auto& fld : ve)
- tys.push_back( monomorphise_type(sp, enm.m_params, te.path.m_data.as_Generic().m_params, fld.ent) );
- tmp = ::HIR::TypeRef( mv$(tys) );
- m_resolve.expand_associated_types(sp, tmp);
- return tmp;
- ),
- (Struct,
- // HACK! Create tuple.
- ::std::vector< ::HIR::TypeRef> tys;
- for(const auto& fld : ve)
- tys.push_back( monomorphise_type(sp, enm.m_params, te.path.m_data.as_Generic().m_params, fld.second.ent) );
- tmp = ::HIR::TypeRef( mv$(tys) );
+
+ const auto& var_ty = variant.type;
+ if( monomorphise_type_needed(var_ty) ) {
+ tmp = monomorphise_type(sp, enm.m_params, te.path.m_data.as_Generic().m_params, var_ty);
m_resolve.expand_associated_types(sp, tmp);
return tmp;
- )
- )
+ }
+ else {
+ return var_ty;
+ }
}
else
{
diff --git a/src/mir/mir.cpp b/src/mir/mir.cpp
index 6af64001..18557304 100644
--- a/src/mir/mir.cpp
+++ b/src/mir/mir.cpp
@@ -384,8 +384,6 @@ namespace MIR {
(Struct,
if( are.path != bre.path )
return false;
- if( are.variant_idx != bre.variant_idx )
- return false;
return are.vals == bre.vals;
)
)
@@ -610,13 +608,13 @@ namespace MIR {
(Variant,
return ::MIR::RValue::make_Variant({ e.path.clone(), e.index, e.val.clone() });
),
- // Create a new instance of a struct (or enum)
+ // Create a new instance of a struct
(Struct,
decltype(e.vals) ret;
ret.reserve(e.vals.size());
for(const auto& v : e.vals)
ret.push_back( v.clone() );
- return ::MIR::RValue::make_Struct({ e.path.clone(), e.variant_idx, mv$(ret) });
+ return ::MIR::RValue::make_Struct({ e.path.clone(), mv$(ret) });
)
)
throw "";
diff --git a/src/mir/mir.hpp b/src/mir/mir.hpp
index 987e0498..3ce115b8 100644
--- a/src/mir/mir.hpp
+++ b/src/mir/mir.hpp
@@ -187,10 +187,9 @@ TAGGED_UNION_EX(RValue, (), Use, (
unsigned int index;
Param val;
}),
- // Create a new instance of a struct (or enum)
+ // Create a new instance of a struct
(Struct, struct {
::HIR::GenericPath path;
- unsigned int variant_idx; // if ~0, it's a struct
::std::vector<Param> vals;
})
), (),(), (
diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp
index 1e72282a..5776ebcf 100644
--- a/src/mir/mir_builder.cpp
+++ b/src/mir/mir_builder.cpp
@@ -1722,41 +1722,22 @@ void MirBuilder::with_val_type(const Span& sp, const ::MIR::LValue& val, ::std::
BUG(sp, "Downcast on unexpected type - " << ty);
),
(Path,
- // TODO: Union?
if( const auto* pbe = te.binding.opt_Enum() )
{
const auto& enm = **pbe;
- const auto& variants = enm.m_variants;
+ ASSERT_BUG(sp, enm.m_data.is_Data(), "Downcast on non-data enum");
+ const auto& variants = enm.m_data.as_Data();
ASSERT_BUG(sp, e.variant_index < variants.size(), "Variant index out of range");
const auto& variant = variants[e.variant_index];
- // TODO: Make data variants refer to associated types (unify enum and struct handling)
- TU_MATCHA( (variant.second), (ve),
- (Value,
- DEBUG("");
- cb(::HIR::TypeRef::new_unit());
- ),
- (Unit,
- cb(::HIR::TypeRef::new_unit());
- ),
- (Tuple,
- // HACK! Create tuple.
- ::std::vector< ::HIR::TypeRef> tys;
- for(const auto& fld : ve)
- tys.push_back( monomorphise_type(sp, enm.m_params, te.path.m_data.as_Generic().m_params, fld.ent) );
- ::HIR::TypeRef tup( mv$(tys) );
- m_resolve.expand_associated_types(sp, tup);
- cb(tup);
- ),
- (Struct,
- // HACK! Create tuple.
- ::std::vector< ::HIR::TypeRef> tys;
- for(const auto& fld : ve)
- tys.push_back( monomorphise_type(sp, enm.m_params, te.path.m_data.as_Generic().m_params, fld.second.ent) );
- ::HIR::TypeRef tup( mv$(tys) );
- m_resolve.expand_associated_types(sp, tup);
- cb(tup);
- )
- )
+
+ if( monomorphise_type_needed(variant.type) ) {
+ auto tmp = monomorphise_type(sp, enm.m_params, te.path.m_data.as_Generic().m_params, variant.type);
+ m_resolve.expand_associated_types(sp, tmp);
+ cb(tmp);
+ }
+ else {
+ cb(variant.type);
+ }
}
else if( const auto* pbe = te.binding.opt_Union() )
{
@@ -2070,7 +2051,7 @@ VarState& MirBuilder::get_val_state_mut(const Span& sp, const ::MIR::LValue& lv)
if( pb.is_Enum() )
{
const auto& enm = *pb.as_Enum();
- var_count = enm.m_variants.size();
+ var_count = enm.num_variants();
}
else if( const auto* pbe = pb.opt_Union() )
{
diff --git a/src/mir/optimise.cpp b/src/mir/optimise.cpp
index 9ed889d9..dc3967b4 100644
--- a/src/mir/optimise.cpp
+++ b/src/mir/optimise.cpp
@@ -1120,7 +1120,7 @@ bool MIR_Optimise_Inlining(::MIR::TypeResolve& state, ::MIR::Function& fcn, bool
return ::MIR::RValue::make_Variant({ this->monomorph(se.path), se.index, this->clone_param(se.val) });
),
(Struct,
- return ::MIR::RValue::make_Struct({ this->monomorph(se.path), se.variant_idx, this->clone_param_vec(se.vals) });
+ return ::MIR::RValue::make_Struct({ this->monomorph(se.path), this->clone_param_vec(se.vals) });
)
)
throw "";
diff --git a/src/mir/visit_crate_mir.cpp b/src/mir/visit_crate_mir.cpp
index 93d5f6ea..79d2e32a 100644
--- a/src/mir/visit_crate_mir.cpp
+++ b/src/mir/visit_crate_mir.cpp
@@ -72,14 +72,17 @@ void MIR::OuterVisitor::visit_enum(::HIR::ItemPath p, ::HIR::Enum& item)
{
auto _ = this->m_resolve.set_item_generics(item.m_params);
- // TODO: Use a different type depding on repr()
- auto enum_type = ::HIR::TypeRef(::HIR::CoreType::Isize);
-
- for(auto& var : item.m_variants)
+ if( auto* e = item.m_data.opt_Value() )
{
- TU_IFLET(::HIR::Enum::Variant, var.second, Value, e,
- m_cb(m_resolve, p + var.first, e.expr, {}, enum_type);
- )
+ // TODO: Use a different type depding on repr()
+ auto enum_type = ::HIR::TypeRef(::HIR::CoreType::Isize);
+
+ for(auto& var : e->variants)
+ {
+ if( var.expr ) {
+ m_cb(m_resolve, p + var.name, var.expr, {}, enum_type);
+ }
+ }
}
}