diff options
-rw-r--r-- | src/mir/from_hir.cpp | 24 | ||||
-rw-r--r-- | src/mir/from_hir.hpp | 3 | ||||
-rw-r--r-- | src/mir/mir_builder.cpp | 25 |
3 files changed, 49 insertions, 3 deletions
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp index 4a540c14..5a0ca03a 100644 --- a/src/mir/from_hir.cpp +++ b/src/mir/from_hir.cpp @@ -929,7 +929,13 @@ namespace { } else { - TODO(node.span(), "Support emitting CoerceUnsized-based _Unsize ops in MIR - " << ty_in << " -> " << ty_out); + // NOTES: (from IRC: eddyb) + // < eddyb> they're required that T and U are the same struct definition (with different type parameters) and exactly one field differs in type between T and U (ignoring PhantomData) + // < eddyb> Mutabah: I forgot to mention that the field that differs in type must also impl CoerceUnsized + + // TODO: Just emit a cast and leave magic handling to codegen + // - This code _could_ do inspection of the types and insert a destructure+unsize+restructure, but that does't handle direct `T: CoerceUnsize<U>` + m_builder.set_result( node.span(), ::MIR::RValue::make_Cast({ mv$(ptr_lval), node.m_res_type.clone() }) ); } } void visit(::HIR::ExprNode_Index& node) override @@ -1002,13 +1008,25 @@ namespace { TU_MATCH_DEF( ::HIR::TypeRef::Data, (ty_val.m_data), (te), ( + if( m_builder.lang_Box() ) + { + if( ty_val.m_data.is_Path() + && ty_val.m_data.as_Path().path.m_data.is_Generic() + && ty_val.m_data.as_Path().path.m_data.as_Generic().m_path == *m_builder.lang_Box() + ) + { + // Box magically derefs. + // HACK: Break out of the switch used for TU_MATCH_DEF + break; + } + } BUG(sp, "Deref on unsupported type - " << ty_val); ), - //(Array, - // ), (Pointer, + // Deref on a pointer - TODO: Requires unsafe ), (Borrow, + // Deref on a borrow - Always valid... assuming borrowck is there :) ) ) diff --git a/src/mir/from_hir.hpp b/src/mir/from_hir.hpp index c5106bd0..1f9007a5 100644 --- a/src/mir/from_hir.hpp +++ b/src/mir/from_hir.hpp @@ -78,6 +78,8 @@ class MirBuilder const ::HIR::Function::args_t& m_args; ::MIR::Function& m_output; + const ::HIR::SimplePath* m_lang_Box; + unsigned int m_current_block; bool m_block_active; @@ -111,6 +113,7 @@ public: MirBuilder(const Span& sp, const StaticTraitResolve& resolve, const ::HIR::Function::args_t& args, ::MIR::Function& output); ~MirBuilder(); + const ::HIR::SimplePath* lang_Box() const { return m_lang_Box; } const ::HIR::Crate& crate() const { return m_resolve.m_crate; } // - Values diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp index 89141042..eb40f58b 100644 --- a/src/mir/mir_builder.cpp +++ b/src/mir/mir_builder.cpp @@ -16,10 +16,15 @@ MirBuilder::MirBuilder(const Span& sp, const StaticTraitResolve& resolve, const m_resolve(resolve), m_args(args), m_output(output), + m_lang_Box(nullptr), m_block_active(false), m_result_valid(false), m_fcn_scope(*this, 0) { + if( resolve.m_crate.m_lang_items.count("owned_box") > 0 ) { + m_lang_Box = &resolve.m_crate.m_lang_items.at("owned_box"); + } + set_cur_block( new_bb_unlinked() ); m_scopes.push_back( ScopeDef { sp } ); m_scope_stack.push_back( 0 ); @@ -652,6 +657,25 @@ void MirBuilder::with_val_type(const Span& sp, const ::MIR::LValue& val, ::std:: ( BUG(sp, "Deref on unexpected type - " << ty); ), + (Path, + if( m_lang_Box ) + { + TU_IFLET( ::HIR::Path::Data, te.path.m_data, Generic, e, + if( e.m_path == *m_lang_Box ) { + cb( e.m_params.m_types.at(0) ); + } + else { + BUG(sp, "Deref on unexpected type - " << ty); + } + ) + else { + BUG(sp, "Deref on unexpected type - " << ty); + } + } + else { + BUG(sp, "Deref on unexpected type - " << ty); + } + ), (Pointer, cb(*te.inner); ), @@ -910,6 +934,7 @@ void MirBuilder::moved_lvalue(const Span& sp, const ::MIR::LValue& lv) if( lvalue_is_copy(sp, lv) ) { } else { + // TODO: Move out of owned_box _is_ valid, and marks the box slot for shallow drop BUG(sp, "Move out of deref with non-Copy values - &move? - " << lv); moved_lvalue(sp, *e.val); } |