summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-11-12 08:36:36 +0800
committerJohn Hodge <tpg@mutabah.net>2016-11-12 08:36:36 +0800
commit5cd8809d3e2e55f61ac8890255d67e13795b4a30 (patch)
tree9a0f79871da9f0c340b4571d87572ed81fb2cc11
parenta64152923668cf111618ea42e369bbb49296ae8c (diff)
downloadmrust-5cd8809d3e2e55f61ac8890255d67e13795b4a30.tar.gz
HIR Typecheck Expr - Coercion point in rhs of binops
-rw-r--r--Notes/Quirks.md5
-rw-r--r--src/hir_typeck/expr_cs.cpp15
2 files changed, 16 insertions, 4 deletions
diff --git a/Notes/Quirks.md b/Notes/Quirks.md
index 998c5d25..2b0705a9 100644
--- a/Notes/Quirks.md
+++ b/Notes/Quirks.md
@@ -49,3 +49,8 @@ The "base" value of a struct literal isn't always moved
======================================================
- Only the values used are moved, which can lead to the source not being moved (if all used values are Copy)
+
+Binops are coercion points
+==========================
+
+
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index 2996a92a..9338cbac 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -804,9 +804,15 @@ namespace {
auto _ = this->push_inner_coerce_scoped(false);
TRACE_FUNCTION_F(&node << "... "<<::HIR::ExprNode_BinOp::opname(node.m_op)<<" ...");
+
this->context.add_ivars( node.m_left ->m_res_type );
this->context.add_ivars( node.m_right->m_res_type );
+ const auto& left_ty = node.m_left ->m_res_type;
+ ::HIR::TypeRef right_ty_inner = this->context.m_ivars.new_ivar_tr();
+ const auto& right_ty = right_ty_inner;//node.m_right->m_res_type;
+ this->context.equate_types_coerce(node.span(), right_ty_inner, node.m_right);
+
switch(node.m_op)
{
case ::HIR::ExprNode_BinOp::Op::CmpEqu:
@@ -831,14 +837,14 @@ namespace {
assert(item_name);
const auto& op_trait = this->context.m_crate.get_lang_item_path(node.span(), item_name);
- this->context.equate_types_assoc(node.span(), ::HIR::TypeRef(), op_trait, ::make_vec1(node.m_right->m_res_type.clone()), node.m_left->m_res_type.clone(), "");
+ this->context.equate_types_assoc(node.span(), ::HIR::TypeRef(), op_trait, ::make_vec1(right_ty.clone()), left_ty.clone(), "");
break; }
case ::HIR::ExprNode_BinOp::Op::BoolAnd:
case ::HIR::ExprNode_BinOp::Op::BoolOr:
this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef(::HIR::CoreType::Bool));
- this->context.equate_types(node.span(), node.m_left ->m_res_type, ::HIR::TypeRef(::HIR::CoreType::Bool));
- this->context.equate_types(node.span(), node.m_right->m_res_type, ::HIR::TypeRef(::HIR::CoreType::Bool));
+ this->context.equate_types(node.span(), left_ty , ::HIR::TypeRef(::HIR::CoreType::Bool));
+ this->context.equate_types(node.span(), right_ty, ::HIR::TypeRef(::HIR::CoreType::Bool));
break;
default: {
const char* item_name = nullptr;
@@ -870,10 +876,11 @@ namespace {
const auto& op_trait = this->context.m_crate.get_lang_item_path(node.span(), item_name);
// NOTE: `true` marks the association as coming from a binary operation, which changes integer handling
- this->context.equate_types_assoc(node.span(), node.m_res_type, op_trait, ::make_vec1(node.m_right->m_res_type.clone()), node.m_left->m_res_type.clone(), "Output", true);
+ this->context.equate_types_assoc(node.span(), node.m_res_type, op_trait, ::make_vec1(right_ty.clone()), left_ty.clone(), "Output", true);
break; }
}
node.m_left ->visit( *this );
+ auto _2 = this->push_inner_coerce_scoped(true);
node.m_right->visit( *this );
}
void visit(::HIR::ExprNode_UniOp& node) override