diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 31 | ||||
-rw-r--r-- | src/hir_typeck/helpers.cpp | 2 |
2 files changed, 28 insertions, 5 deletions
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 650d9ae5..f26ec08f 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -4514,9 +4514,6 @@ namespace { } ), (Function, - // NOTE: Functions don't coerce (TODO: They could lose the origin marker?) - context.equate_types(sp, ty_dst, node_ptr->m_res_type); - return true; ), (Closure, // TODO: Can closures coerce to anything? @@ -4696,8 +4693,32 @@ namespace { } ), (Function, - // TODO: Could capture-less closures coerce to fn() types? - context.equate_types(sp, ty_dst, ty_src); + TU_IFLET( ::HIR::TypeRef::Data, ty_src.m_data, Function, r_e, + if(l_e.m_abi != r_e.m_abi && l_e.is_unsafe == true && r_e.is_unsafe == false ) { + // LHS is unsafe, RHS is not - Insert a cast + + auto ty_dst_new = ty_src.clone(); + ty_dst_new.m_data.as_Function().is_unsafe = true; + context.equate_types(sp, ty_dst, ty_dst_new); + + // Add cast down + auto span = node_ptr->span(); + node_ptr->m_res_type = ty_src.clone(); + node_ptr = ::HIR::ExprNodeP(new ::HIR::ExprNode_Cast( mv$(span), mv$(node_ptr), ty_dst_new.clone() )); + node_ptr->m_res_type = mv$(ty_dst_new); + + context.m_ivars.mark_change(); + return true; + } + context.equate_types(sp, ty_dst, ty_src); + ) + else TU_IFLET( ::HIR::TypeRef::Data, ty_src.m_data, Closure, r_e, + // TODO: Could capture-less closures coerce to fn() types? + context.equate_types(sp, ty_dst, ty_src); + ) + else { + context.equate_types(sp, ty_dst, ty_src); + } return true; ), (Closure, diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index a3e0615a..d349ef23 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -884,6 +884,8 @@ bool HMTypeInferrence::types_equal(const ::HIR::TypeRef& rl, const ::HIR::TypeRe return types_equal(*le.m_rettype, *re.m_rettype); ), (Function, + if( le.is_unsafe != re.is_unsafe || le.m_abi != re.m_abi ) + return false; if( !type_list_equal(*this, le.m_arg_types, re.m_arg_types) ) return false; return types_equal(*le.m_rettype, *re.m_rettype); |