diff options
author | John Hodge <tpg@mutabah.net> | 2018-12-29 13:32:51 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2018-12-29 13:32:51 +0800 |
commit | 24086285e2b5035dd23a4e5088baeb27f7774fe9 (patch) | |
tree | 0725015e99ba3c2f492184b20663ccb850e3c222 | |
parent | 0a47863a680677817631f507ea6f6565b537487e (diff) | |
download | mrust-24086285e2b5035dd23a4e5088baeb27f7774fe9.tar.gz |
Lower MIR - Handing of irrefutable enum matches, some other tweaks
-rw-r--r-- | src/hir_typeck/static.cpp | 81 | ||||
-rw-r--r-- | src/hir_typeck/static.hpp | 1 | ||||
-rw-r--r-- | src/mir/cleanup.cpp | 9 | ||||
-rw-r--r-- | src/mir/from_hir.cpp | 83 | ||||
-rw-r--r-- | src/trans/codegen_c.cpp | 1 |
5 files changed, 139 insertions, 36 deletions
diff --git a/src/hir_typeck/static.cpp b/src/hir_typeck/static.cpp index 64b04611..d40ee811 100644 --- a/src/hir_typeck/static.cpp +++ b/src/hir_typeck/static.cpp @@ -1600,7 +1600,7 @@ bool StaticTraitResolve::type_is_sized(const Span& sp, const ::HIR::TypeRef& ty) return true; ), (Diverge, - // The ! type is kinda Copy ... + // The ! type is kinda Sized ... return true; ), (Closure, @@ -1645,6 +1645,85 @@ bool StaticTraitResolve::type_is_sized(const Span& sp, const ::HIR::TypeRef& ty) ) throw ""; } +bool StaticTraitResolve::type_is_impossible(const Span& sp, const ::HIR::TypeRef& ty) const +{ + TU_MATCH_HDRA( (ty.m_data), {) + break; + default: + return false; + TU_ARMA(Diverge, _e) + return true; + TU_ARMA(Path, e) { + TU_MATCHA( (e.binding), (pbe), + (Unbound, + // BUG? + return false; + ), + (Opaque, + // TODO: This can only be with UfcsKnown, so check if the trait specifies ?Sized + return false; + ), + (Struct, + const auto& params = e.path.m_data.as_Generic().m_params; + // TODO: Check all fields, if one flags this, then it's impossible. + const auto& str = *pbe; + TU_MATCH_HDRA( (str.m_data), {) + TU_ARMA(Unit, e) + return false; + TU_ARMA(Tuple, e) { + for(const auto& fld : e) + { + const auto& tpl = fld.ent; + ::HIR::TypeRef tmp; + const auto& ty = (monomorphise_type_needed(tpl) ? tmp = monomorphise_type_with(sp, tpl, monomorphise_type_get_cb(sp, nullptr, ¶ms, nullptr)) : tpl); + if( type_is_impossible(sp, ty) ) + return true; + } + return false; + } + TU_ARMA(Named, e) + for(const auto& fld : e) + { + TODO(sp, "type_is_impossible for struct " << ty << " - " << fld.second.ent); + } + } + ), + (Enum, + // TODO: Check all variants. + TODO(sp, "type_is_impossible for enum " << ty); + ), + (Union, + // TODO: Check all variants? Or just one? + TODO(sp, "type_is_impossible for union " << ty); + ) + ) + return true; + } + TU_ARMA(Borrow, e) + return type_is_impossible(sp, *e.inner); + TU_ARMA(Pointer, e) { + return false; + //return type_is_impossible(sp, *e.inner); + } + TU_ARMA(Function, e) { + // TODO: Check all arguments? + return true; + } + TU_ARMA(Array, e) { + return type_is_impossible(sp, *e.inner); + } + TU_ARMA(Slice, e) { + return type_is_impossible(sp, *e.inner); + } + TU_ARMA(Tuple, e) { + for(const auto& ty : e) + if( type_is_impossible(sp, ty) ) + return true; + return false; + } + } + throw ""; +} bool StaticTraitResolve::can_unsize(const Span& sp, const ::HIR::TypeRef& dst_ty, const ::HIR::TypeRef& src_ty) const { diff --git a/src/hir_typeck/static.hpp b/src/hir_typeck/static.hpp index ae429a3f..f764f8f7 100644 --- a/src/hir_typeck/static.hpp +++ b/src/hir_typeck/static.hpp @@ -184,6 +184,7 @@ public: bool type_is_copy(const Span& sp, const ::HIR::TypeRef& ty) const; bool type_is_clone(const Span& sp, const ::HIR::TypeRef& ty) const; // 1.29 bool type_is_sized(const Span& sp, const ::HIR::TypeRef& ty) const; + bool type_is_impossible(const Span& sp, const ::HIR::TypeRef& ty) const; bool can_unsize(const Span& sp, const ::HIR::TypeRef& dst, const ::HIR::TypeRef& src) const; /// Returns `true` if the passed type either implements Drop, or contains a type that implements Drop diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp index 1a15ea22..f3e987d6 100644 --- a/src/mir/cleanup.cpp +++ b/src/mir/cleanup.cpp @@ -214,8 +214,8 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const MIR::TypeResolve& state, con TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty.m_data), (te), ( if( path == ::HIR::GenericPath() ) - MIR_TODO(state, "Literal of type " << ty << " - " << path << " - " << lit); - DEBUG("Unknown type " << ty << " - Return BorrowOf"); + MIR_TODO(state, "Literal of type " << ty << " - " << lit); + DEBUG("Unknown type " << ty << ", but a path was provided - Return ItemAddr " << path); return ::MIR::Constant( mv$(path) ); ), (Tuple, @@ -454,6 +454,11 @@ const ::HIR::Literal* MIR_Cleanup_GetConstant(const MIR::TypeResolve& state, con else { MIR_TODO(state, "Const with type " << ty); } + ), + (Function, + //MIR_TODO(state, "Const function pointer " << lit << " w/ type " << ty); + MIR_ASSERT(state, lit.is_BorrowPath(), ""); + return ::MIR::Constant::make_ItemAddr( lit.as_BorrowPath().clone() ); ) ) } diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 38d00a5a..2c45f5bb 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -207,22 +207,22 @@ namespace { allow_refutable = 2; } - TU_MATCHA( (pat.m_data), (e), - (Any, - ), - (Box, + TU_MATCH_HDRA( (pat.m_data), {) + TU_ARMA(Any, e) { + } + TU_ARMA(Box, e) { destructure_from_ex(sp, *e.sub, ::MIR::LValue::make_Deref({ box$( mv$(lval) ) }), allow_refutable); - ), - (Ref, + } + TU_ARMA(Ref, e) { destructure_from_ex(sp, *e.sub, ::MIR::LValue::make_Deref({ box$( mv$(lval) ) }), allow_refutable); - ), - (Tuple, + } + TU_ARMA(Tuple, e) { for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ ) { destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::make_Field({ box$( lval.clone() ), i}), allow_refutable); } - ), - (SplitTuple, + } + TU_ARMA(SplitTuple, e) { assert(e.total_size >= e.leading.size() + e.trailing.size()); for(unsigned int i = 0; i < e.leading.size(); i ++ ) { @@ -234,17 +234,17 @@ namespace { { destructure_from_ex(sp, e.trailing[i], ::MIR::LValue::make_Field({ box$( lval.clone() ), ofs+i}), allow_refutable); } - ), - (StructValue, + } + TU_ARMA(StructValue, e) { // Nothing. - ), - (StructTuple, + } + TU_ARMA(StructTuple, e) { for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ ) { destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::make_Field({ box$( lval.clone() ), i}), allow_refutable); } - ), - (Struct, + } + TU_ARMA(Struct, e) { const auto& str = *e.binding; const auto& fields = str.m_data.as_Named(); for(const auto& fld_pat : e.sub_patterns) @@ -252,31 +252,48 @@ namespace { unsigned idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto&x){ return x.first == fld_pat.first; } ) - fields.begin(); destructure_from_ex(sp, fld_pat.second, ::MIR::LValue::make_Field({ box$( lval.clone() ), idx}), allow_refutable); } - ), + } // Refutable - (Value, + TU_ARMA(Value, e) { ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected - " << pat); - ), - (Range, + } + TU_ARMA(Range, e) { ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected - " << pat); - ), - (EnumValue, + } + TU_ARMA(EnumValue, e) { const auto& enm = *e.binding_ptr; if( enm.num_variants() > 1 ) { ASSERT_BUG(sp, allow_refutable, "Refutable pattern not expected - " << pat); } - ), - (EnumTuple, + } + TU_ARMA(EnumTuple, e) { const auto& enm = *e.binding_ptr; - ASSERT_BUG(sp, enm.num_variants() == 1 || allow_refutable, "Refutable pattern not expected - " << pat); + const auto& variants = enm.m_data.as_Data(); + // TODO: Check that this is the only non-impossible arm + if( !allow_refutable ) + { + for(size_t i = 0; i < variants.size(); i ++) + { + const auto& var_ty = variants[i].type; + if( i == e.binding_idx ) { + continue; + } + ::HIR::TypeRef tmp; + const auto& ty = (monomorphise_type_needed(var_ty) ? tmp = monomorphise_type_with(sp, var_ty, monomorphise_type_get_cb(sp, nullptr, &e.path.m_params, nullptr)) : var_ty); + if( m_builder.resolve().type_is_impossible(sp, ty) ) { + continue; + } + ERROR(sp, E0000, "Variant " << variants[i].name << " not handled"); + } + } auto lval_var = ::MIR::LValue::make_Downcast({ box$(mv$(lval)), e.binding_idx }); for(unsigned int i = 0; i < e.sub_patterns.size(); i ++ ) { destructure_from_ex(sp, e.sub_patterns[i], ::MIR::LValue::make_Field({ box$( lval_var.clone() ), i}), allow_refutable); } - ), - (EnumStruct, + } + TU_ARMA(EnumStruct, e) { const auto& enm = *e.binding_ptr; 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); @@ -289,8 +306,8 @@ namespace { unsigned idx = ::std::find_if( fields.begin(), fields.end(), [&](const auto&x){ return x.first == fld_pat.first; } ) - fields.begin(); destructure_from_ex(sp, fld_pat.second, ::MIR::LValue::make_Field({ box$( lval_var.clone() ), idx}), allow_refutable); } - ), - (Slice, + } + TU_ARMA(Slice, e) { // These are only refutable if T is [T] bool ty_is_array = false; m_builder.with_val_type(sp, lval, [&ty_is_array](const auto& ty){ @@ -316,8 +333,8 @@ namespace { destructure_from_ex(sp, subpat, ::MIR::LValue::make_Field({ box$(lval.clone()), i }), allow_refutable ); } } - ), - (SplitSlice, + } + TU_ARMA(SplitSlice, e) { // These are only refutable if T is [T] bool ty_is_array = false; unsigned int array_size = 0; @@ -412,8 +429,8 @@ namespace { } } } - ) - ) + } + } // TU_MATCH_HDRA } // -- ExprVisitor diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp index 8bbbd033..0f2cd636 100644 --- a/src/trans/codegen_c.cpp +++ b/src/trans/codegen_c.cpp @@ -2730,6 +2730,7 @@ namespace { // Emit a call to box_free for the type ::HIR::GenericPath box_free { m_crate.get_lang_item_path(sp, "box_free"), { ity->clone() } }; // TODO: This is specific to the official liballoc's owned_box + // TODO: Shared logic with Box drop glue above. m_of << indent << Trans_Mangle(box_free) << "("; emit_lvalue(e.slot); m_of << "._0._0._0);\n"; } else |