summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2018-12-29 13:32:51 +0800
committerJohn Hodge <tpg@mutabah.net>2018-12-29 13:32:51 +0800
commit24086285e2b5035dd23a4e5088baeb27f7774fe9 (patch)
tree0725015e99ba3c2f492184b20663ccb850e3c222
parent0a47863a680677817631f507ea6f6565b537487e (diff)
downloadmrust-24086285e2b5035dd23a4e5088baeb27f7774fe9.tar.gz
Lower MIR - Handing of irrefutable enum matches, some other tweaks
-rw-r--r--src/hir_typeck/static.cpp81
-rw-r--r--src/hir_typeck/static.hpp1
-rw-r--r--src/mir/cleanup.cpp9
-rw-r--r--src/mir/from_hir.cpp83
-rw-r--r--src/trans/codegen_c.cpp1
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, &params, 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