summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-07-10 15:51:40 +1000
committerJohn Hodge <tpg@mutabah.net>2016-07-10 15:51:40 +1000
commit58f02a54af41fcd4c035cb21ed5051c9a87556ae (patch)
tree7073442012f3b4ac09e6e862040fac3987583ac9
parent0176e8d8d2a9c535db06a9b07658226d46f264da (diff)
downloadmrust-58f02a54af41fcd4c035cb21ed5051c9a87556ae.tar.gz
HIR Typecheck CS - Magic inferrence passthrough for uniops too
-rw-r--r--src/hir_typeck/expr_cs.cpp54
1 files changed, 38 insertions, 16 deletions
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index c85adf2c..38a7a21d 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -45,8 +45,8 @@ struct Context
::HIR::TypeRef impl_ty;
::std::string name; // if "", no type is used (and left is ignored) - Just does trait selection
- // HACK: binops are special - the result when both types are primitives is ALWAYS the lefthand side
- bool is_binop;
+ // HACK: operators are special - the result when both types are primitives is ALWAYS the lefthand side
+ bool is_operator;
friend ::std::ostream& operator<<(::std::ostream& os, const Associated& v) {
if( v.name == "" ) {
@@ -103,7 +103,7 @@ struct Context
// - Equate two types, allowing inferrence
void equate_types_coerce(const Span& sp, const ::HIR::TypeRef& l, ::HIR::ExprNodeP& node_ptr);
// - Equate a type to an associated type (if name == "", no equation is done, but trait is searched)
- void equate_types_assoc(const Span& sp, const ::HIR::TypeRef& l, const ::HIR::SimplePath& trait, ::std::vector< ::HIR::TypeRef> ty_args, const ::HIR::TypeRef& impl_ty, const char *name, bool is_binop=false);
+ void equate_types_assoc(const Span& sp, const ::HIR::TypeRef& l, const ::HIR::SimplePath& trait, ::std::vector< ::HIR::TypeRef> ty_args, const ::HIR::TypeRef& impl_ty, const char *name, bool is_op=false);
// - List `t` as a possible type for `ivar_index`
void possible_equate_type_to(unsigned int ivar_index, const ::HIR::TypeRef& t);
@@ -599,10 +599,10 @@ namespace {
this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Unique, node.m_value->m_res_type.clone()));
break;
case ::HIR::ExprNode_UniOp::Op::Invert:
- this->context.equate_types_assoc(node.span(), node.m_res_type, this->context.m_crate.get_lang_item_path(node.span(), "not"), {}, node.m_value->m_res_type.clone(), "Output");
+ this->context.equate_types_assoc(node.span(), node.m_res_type, this->context.m_crate.get_lang_item_path(node.span(), "not"), {}, node.m_value->m_res_type.clone(), "Output", true);
break;
case ::HIR::ExprNode_UniOp::Op::Negate:
- this->context.equate_types_assoc(node.span(), node.m_res_type, this->context.m_crate.get_lang_item_path(node.span(), "neg"), {}, node.m_value->m_res_type.clone(), "Output");
+ this->context.equate_types_assoc(node.span(), node.m_res_type, this->context.m_crate.get_lang_item_path(node.span(), "neg"), {}, node.m_value->m_res_type.clone(), "Output", true);
break;
}
node.m_value->visit( *this );
@@ -2308,7 +2308,7 @@ void Context::equate_types_coerce(const Span& sp, const ::HIR::TypeRef& l, ::HIR
});
DEBUG("equate_types_coerce(" << this->link_coerce.back() << ")");
}
-void Context::equate_types_assoc(const Span& sp, const ::HIR::TypeRef& l, const ::HIR::SimplePath& trait, ::std::vector< ::HIR::TypeRef> ty_args, const ::HIR::TypeRef& impl_ty, const char *name, bool is_binop)
+void Context::equate_types_assoc(const Span& sp, const ::HIR::TypeRef& l, const ::HIR::SimplePath& trait, ::std::vector< ::HIR::TypeRef> ty_args, const ::HIR::TypeRef& impl_ty, const char *name, bool is_op)
{
::HIR::PathParams pp;
pp.m_types = mv$(ty_args);
@@ -2320,7 +2320,7 @@ void Context::equate_types_assoc(const Span& sp, const ::HIR::TypeRef& l, const
mv$(pp),
impl_ty.clone(),
name,
- is_binop
+ is_op
});
DEBUG("equate_types_assoc(" << this->link_assoc.back() << ")");
}
@@ -2782,13 +2782,33 @@ namespace {
)
}
};
- if( v.is_binop ) {
- const auto& left = context.get_type(v.impl_ty); // yes, impl = LHS of binop
- const auto& right = context.get_type(v.params.m_types.at(0));
- const auto& res = context.get_type(v.left_ty);
- if( H::type_is_num(left) && H::type_is_num(right) ) {
- DEBUG("- Magic inferrence link for binops on numerics");
- context.equate_types(sp, left, res);
+
+ // MAGIC! Have special handling for operator overloads
+ if( v.is_operator ) {
+ if( v.params.m_types.size() == 0 )
+ {
+ // Uni ops = If the value is a primitive, the output is the same type
+ const auto& ty = context.get_type(v.impl_ty);
+ const auto& res = context.get_type(v.left_ty);
+ if( H::type_is_num(ty) ) {
+ DEBUG("- Magic inferrence link for uniops on numerics");
+ context.equate_types(sp, res, ty);
+ }
+ }
+ else if( v.params.m_types.size() == 1 )
+ {
+ // Binary operations - If both types are primitives, the output is the lefthand side
+ const auto& left = context.get_type(v.impl_ty); // yes, impl = LHS of binop
+ const auto& right = context.get_type(v.params.m_types.at(0));
+ const auto& res = context.get_type(v.left_ty);
+ if( H::type_is_num(left) && H::type_is_num(right) ) {
+ DEBUG("- Magic inferrence link for binops on numerics");
+ context.equate_types(sp, res, left);
+ }
+ }
+ else
+ {
+ BUG(sp, "");
}
}
@@ -2809,8 +2829,8 @@ namespace {
DEBUG("- (fail) bounded impl " << v.trait << v.params << " (ty_right = " << context.m_ivars.fmt_type(v.impl_ty));
return false;
}
- if( v.name != "" && assoc.count(v.name) == 0 )
- BUG(sp, "Getting associated type '" << v.name << "' which isn't in list");
+ if( v.name != "" && assoc.count(v.name) == 0 )
+ BUG(sp, "Getting associated type '" << v.name << "' which isn't in " << v.trait);
const auto& out_ty = (v.name == "" ? v.left_ty : assoc.at(v.name));
// - If we're looking for an associated type, allow it to eliminate impossible impls
@@ -2834,6 +2854,8 @@ namespace {
possible_params = args.clone();
}
+ DEBUG("- (possible) " << v.trait << args << " for " << impl_ty);
+
return false;
}
});