diff options
author | John Hodge <tpg@mutabah.net> | 2016-08-17 13:39:25 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-08-17 13:39:25 +0800 |
commit | 8107e295ac63a84f6445400ca6c5d785090968e3 (patch) | |
tree | 1602725a89721499b4434ca6d0976e625fa3e726 | |
parent | d31c674953f0d17f2fbcdc6087003259f363b271 (diff) | |
download | mrust-8107e295ac63a84f6445400ca6c5d785090968e3.tar.gz |
MIR Gen - Some sanity checks on casts (incomplete)
-rw-r--r-- | src/mir/from_hir.cpp | 99 |
1 files changed, 93 insertions, 6 deletions
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 4c9d1aaf..d8bcd49c 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -219,9 +219,10 @@ namespace { this->visit_node_ptr(node.m_code); m_loop_stack.pop_back(); - // If there's a stray result, drop i + // If there's a stray result, drop it if( m_builder.has_result() ) { assert( m_builder.block_active() ); + // TODO: Does this result have to be dropped? Ideally this should always be () //::MIR::RValue res = m_builder.get_result(node.span()); //if( res.is_Use() ) { // m_builder.push_stmt_drop( mv$(res.as_Use()) ); @@ -634,18 +635,104 @@ namespace { this->visit_node_ptr(node.m_value); auto val = m_builder.lvalue_or_temp( node.m_value->m_res_type, m_builder.get_result(node.m_value->span()) ); - #if 0 - TU_MATCH_DEF( ::HIR::TypeRef::Data, (node.m_res_type->m_data), (de), + const auto& ty_out = node.m_res_type; + const auto& ty_in = node.m_value->m_res_type; + + TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty_out.m_data), (de), ( + BUG(node.span(), "Invalid cast to " << ty_out); + ), + (Pointer, + if( ty_in.m_data.is_Primitive() && ty_in.m_data.as_Primitive() == ::HIR::CoreType::Usize ) { + // TODO: Only valid if T: Sized in *{const/mut/move} T + } + else TU_IFLET( ::HIR::TypeRef::Data, ty_in.m_data, Borrow, se, + if( *de.inner != *se.inner ) { + BUG(node.span(), "Cannot cast to " << ty_out << " from " << ty_in); + } + // Valid + ) + else TU_IFLET( ::HIR::TypeRef::Data, ty_in.m_data, Function, se, + if( *de.inner != ::HIR::TypeRef::new_unit() ) { + BUG(node.span(), "Cannot cast to " << ty_out << " from " << ty_in); + } + // Valid + ) + else TU_IFLET( ::HIR::TypeRef::Data, ty_in.m_data, Pointer, se, + // Valid + ) + else { + BUG(node.span(), "Cannot cast to pointer from " << ty_in); + } ), (Primitive, switch(de) { - + case ::HIR::CoreType::Str: + BUG(node.span(), "Cannot cast to str"); + break; + case ::HIR::CoreType::Char: + if( ty_in.m_data.is_Primitive() && ty_in.m_data.as_Primitive() == ::HIR::CoreType::U8 ) { + // Valid + } + else { + BUG(node.span(), "Cannot cast to char from " << ty_in); + } + break; + case ::HIR::CoreType::Bool: + BUG(node.span(), "Cannot cast to bool"); + break; + case ::HIR::CoreType::F32: + case ::HIR::CoreType::F64: + TU_IFLET(::HIR::TypeRef::Data, ty_in.m_data, Primitive, se, + switch(de) + { + case ::HIR::CoreType::Str: + case ::HIR::CoreType::Char: + case ::HIR::CoreType::Bool: + BUG(node.span(), "Cannot cast to " << ty_out << " from " << ty_in); + break; + default: + // Valid + break; + } + ) + else { + BUG(node.span(), "Cannot cast to " << ty_out << " from " << ty_in); + } + break; + default: + TU_IFLET(::HIR::TypeRef::Data, ty_in.m_data, Primitive, se, + switch(de) + { + case ::HIR::CoreType::Str: + BUG(node.span(), "Cannot cast to " << ty_out << " from " << ty_in); + default: + // Valid + break; + } + ) + else TU_IFLET(::HIR::TypeRef::Data, ty_in.m_data, Path, se, + TU_IFLET(::HIR::TypeRef::TypePathBinding, se.binding, Enum, pbe, + // TODO: Check if it's a repr(ty/C) enum - and if the type matches + ) + else { + BUG(node.span(), "Cannot cast to " << ty_out << " from " << ty_in); + } + ) + else if( de == ::HIR::CoreType::Usize && ty_in.m_data.is_Pointer() ) { + // TODO: Only valid for T: Sized? + } + else if( de == ::HIR::CoreType::Usize && ty_in.m_data.is_Function() ) { + // TODO: Always valid? + } + else { + BUG(node.span(), "Cannot cast to " << ty_out << " from " << ty_in); + } + break; } ) ) - #endif auto res = m_builder.new_temporary(node.m_res_type); m_builder.push_stmt_assign(res.clone(), ::MIR::RValue::make_Cast({ mv$(val), node.m_res_type.clone() })); m_builder.set_result( node.span(), mv$(res) ); @@ -879,7 +966,7 @@ namespace { } void visit(::HIR::ExprNode_CallMethod& node) override { - // TODO: Allow use on trait objects. + // TODO: Allow use on trait objects? May not be needed, depends. BUG(node.span(), "Leftover _CallMethod"); } void visit(::HIR::ExprNode_Field& node) override |