summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/hir_typeck/expr_cs.cpp31
-rw-r--r--src/hir_typeck/helpers.cpp2
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);