summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-07-03 13:48:16 +0800
committerJohn Hodge <tpg@mutabah.net>2016-07-03 13:48:16 +0800
commitb602f1e0fe87c2d11120e0ab7e556db9276b9a78 (patch)
tree09f5ac2103e9d0775e0ccb7f026fc301f1da34fd /src
parent1626d0a929414a6298bb08edba3ccd6fa98983ff (diff)
downloadmrust-b602f1e0fe87c2d11120e0ab7e556db9276b9a78.tar.gz
HIR Typecheck CS - Prep for running nodes
Diffstat (limited to 'src')
-rw-r--r--src/hir_typeck/expr_cs.cpp1848
1 files changed, 994 insertions, 854 deletions
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index 86058fe9..7e24c1c2 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -94,954 +94,1070 @@ private:
static void fix_param_count(const Span& sp, Context& context, const ::HIR::Path& path, const ::HIR::GenericParams& param_defs, ::HIR::PathParams& params);
static void fix_param_count(const Span& sp, Context& context, const ::HIR::GenericPath& path, const ::HIR::GenericParams& param_defs, ::HIR::PathParams& params);
-class ExprVisitor_Enum:
- public ::HIR::ExprVisitor
-{
- Context& context;
- const ::HIR::TypeRef& ret_type;
-
- // TEMP: List of in-scope traits for buildup
- ::HIR::t_trait_list m_traits;
-public:
- ExprVisitor_Enum(Context& context, ::HIR::t_trait_list base_traits, const ::HIR::TypeRef& ret_type):
- context(context),
- ret_type(ret_type),
- m_traits( mv$(base_traits) )
+namespace {
+ class ExprVisitor_Enum:
+ public ::HIR::ExprVisitor
{
- }
-
- void visit(::HIR::ExprNode_Block& node) override
- {
- TRACE_FUNCTION_F("{ ... }");
- this->push_traits( node.m_traits );
-
- for( unsigned int i = 0; i < node.m_nodes.size(); i ++ )
+ Context& context;
+ const ::HIR::TypeRef& ret_type;
+
+ // TEMP: List of in-scope traits for buildup
+ ::HIR::t_trait_list m_traits;
+ public:
+ ExprVisitor_Enum(Context& context, ::HIR::t_trait_list base_traits, const ::HIR::TypeRef& ret_type):
+ context(context),
+ ret_type(ret_type),
+ m_traits( mv$(base_traits) )
{
- auto& snp = node.m_nodes[i];
- this->context.add_ivars( snp->m_res_type );
- if( i == node.m_nodes.size()-1 ) {
- this->context.equate_types(snp->span(), node.m_res_type, snp->m_res_type);
- }
- else {
- // TODO: Ignore? or force to ()? - Depends on inner
- // - Blocks (and block-likes) are forced to ()
- // - What if they were '({});'? Then they're left dangling
- }
- snp->visit(*this);
}
- this->pop_traits( node.m_traits );
- }
- void visit(::HIR::ExprNode_Return& node) override
- {
- TRACE_FUNCTION_F("return ...");
- this->context.add_ivars( node.m_value->m_res_type );
-
- this->context.equate_types_coerce(node.span(), this->ret_type, node.m_value);
-
- node.m_value->visit( *this );
- }
-
- void visit(::HIR::ExprNode_Loop& node) override
- {
- TRACE_FUNCTION_F("loop { ... }");
-
- this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_unit());
-
- node.m_code->visit( *this );
- }
- void visit(::HIR::ExprNode_LoopControl& node) override
- {
- TRACE_FUNCTION_F((node.m_continue ? "continue" : "break") << " '" << node.m_label);
- // Nothing
- }
-
- void visit(::HIR::ExprNode_Let& node) override
- {
- TRACE_FUNCTION_F("let " << node.m_pattern << ": " << node.m_type);
-
- this->context.add_ivars( node.m_type );
- this->context.add_binding(node.span(), node.m_pattern, node.m_type);
-
- this->context.add_ivars( node.m_value->m_res_type );
- this->context.equate_types_coerce( node.span(), node.m_type, node.m_value );
-
- node.m_value->visit( *this );
- }
- void visit(::HIR::ExprNode_Match& node) override
- {
- TRACE_FUNCTION_F("match ...");
-
- this->context.add_ivars(node.m_value->m_res_type);
-
- for(auto& arm : node.m_arms)
+ void visit(::HIR::ExprNode_Block& node) override
{
- DEBUG("ARM " << arm.m_patterns);
- for(auto& pat : arm.m_patterns)
- {
- this->context.add_binding(node.span(), pat, node.m_value->m_res_type);
- }
+ TRACE_FUNCTION_F("{ ... }");
+ this->push_traits( node.m_traits );
- if( arm.m_cond )
+ for( unsigned int i = 0; i < node.m_nodes.size(); i ++ )
{
- this->context.add_ivars( arm.m_cond->m_res_type );
- this->context.equate_types_coerce(arm.m_cond->span(), ::HIR::TypeRef(::HIR::CoreType::Bool), arm.m_cond);
- arm.m_cond->visit( *this );
+ auto& snp = node.m_nodes[i];
+ this->context.add_ivars( snp->m_res_type );
+ if( i == node.m_nodes.size()-1 ) {
+ this->context.equate_types(snp->span(), node.m_res_type, snp->m_res_type);
+ }
+ else {
+ // TODO: Ignore? or force to ()? - Depends on inner
+ // - Blocks (and block-likes) are forced to ()
+ // - What if they were '({});'? Then they're left dangling
+ }
+ snp->visit(*this);
}
- this->context.add_ivars( arm.m_code->m_res_type );
- this->context.equate_types_coerce(node.span(), node.m_res_type, arm.m_code);
- arm.m_code->visit( *this );
+ this->pop_traits( node.m_traits );
}
-
- node.m_value->visit( *this );
- }
-
- void visit(::HIR::ExprNode_If& node) override
- {
- TRACE_FUNCTION_F("if ...");
-
- this->context.add_ivars( node.m_cond->m_res_type );
- this->context.equate_types_coerce(node.m_cond->span(), ::HIR::TypeRef(::HIR::CoreType::Bool), node.m_cond);
-
- this->context.add_ivars( node.m_true->m_res_type );
- this->context.equate_types_coerce(node.span(), node.m_res_type, node.m_true);
- node.m_true->visit( *this );
-
- if( node.m_false ) {
- this->context.add_ivars( node.m_false->m_res_type );
- this->context.equate_types_coerce(node.span(), node.m_res_type, node.m_false);
- node.m_false->visit( *this );
+ void visit(::HIR::ExprNode_Return& node) override
+ {
+ TRACE_FUNCTION_F("return ...");
+ this->context.add_ivars( node.m_value->m_res_type );
+
+ this->context.equate_types_coerce(node.span(), this->ret_type, node.m_value);
+
+ node.m_value->visit( *this );
}
- else {
+
+ void visit(::HIR::ExprNode_Loop& node) override
+ {
+ TRACE_FUNCTION_F("loop { ... }");
+
this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_unit());
+
+ node.m_code->visit( *this );
+ }
+ void visit(::HIR::ExprNode_LoopControl& node) override
+ {
+ TRACE_FUNCTION_F((node.m_continue ? "continue" : "break") << " '" << node.m_label);
+ // Nothing
}
- }
-
-
- void visit(::HIR::ExprNode_Assign& node) override
- {
- TRACE_FUNCTION_F("... = ...");
- this->context.add_ivars( node.m_slot ->m_res_type );
- this->context.add_ivars( node.m_value->m_res_type );
- // Plain assignment can't be overloaded, requires equal types
- if( node.m_op == ::HIR::ExprNode_Assign::Op::None ) {
- this->context.equate_types_coerce(node.span(), node.m_slot->m_res_type, node.m_value);
+ void visit(::HIR::ExprNode_Let& node) override
+ {
+ TRACE_FUNCTION_F("let " << node.m_pattern << ": " << node.m_type);
+
+ this->context.add_ivars( node.m_type );
+ this->context.add_binding(node.span(), node.m_pattern, node.m_type);
+
+ this->context.add_ivars( node.m_value->m_res_type );
+ this->context.equate_types_coerce( node.span(), node.m_type, node.m_value );
+
+ node.m_value->visit( *this );
}
- else {
- // Type inferrence using the +=
- // - "" as type name to indicate that it's just using the trait magic?
- const char *lang_item = nullptr;
- switch( node.m_op )
+ void visit(::HIR::ExprNode_Match& node) override
+ {
+ TRACE_FUNCTION_F("match ...");
+
+ this->context.add_ivars(node.m_value->m_res_type);
+
+ for(auto& arm : node.m_arms)
{
- case ::HIR::ExprNode_Assign::Op::None: throw "";
- case ::HIR::ExprNode_Assign::Op::Add: lang_item = "add_assign"; break;
- case ::HIR::ExprNode_Assign::Op::Sub: lang_item = "sub_assign"; break;
- case ::HIR::ExprNode_Assign::Op::Mul: lang_item = "mul_assign"; break;
- case ::HIR::ExprNode_Assign::Op::Div: lang_item = "div_assign"; break;
- case ::HIR::ExprNode_Assign::Op::Mod: lang_item = "rem_assign"; break;
- case ::HIR::ExprNode_Assign::Op::And: lang_item = "bitand_assign"; break;
- case ::HIR::ExprNode_Assign::Op::Or : lang_item = "bitor_assign" ; break;
- case ::HIR::ExprNode_Assign::Op::Xor: lang_item = "bitxor_assign"; break;
- case ::HIR::ExprNode_Assign::Op::Shr: lang_item = "shl_assign"; break;
- case ::HIR::ExprNode_Assign::Op::Shl: lang_item = "shr_assign"; break;
+ DEBUG("ARM " << arm.m_patterns);
+ for(auto& pat : arm.m_patterns)
+ {
+ this->context.add_binding(node.span(), pat, node.m_value->m_res_type);
+ }
+
+ if( arm.m_cond )
+ {
+ this->context.add_ivars( arm.m_cond->m_res_type );
+ this->context.equate_types_coerce(arm.m_cond->span(), ::HIR::TypeRef(::HIR::CoreType::Bool), arm.m_cond);
+ arm.m_cond->visit( *this );
+ }
+
+ this->context.add_ivars( arm.m_code->m_res_type );
+ this->context.equate_types_coerce(node.span(), node.m_res_type, arm.m_code);
+ arm.m_code->visit( *this );
}
- assert(lang_item);
- const auto& trait_path = this->context.m_crate.get_lang_item_path(node.span(), lang_item);
- this->context.equate_types_assoc(node.span(), ::HIR::TypeRef(), trait_path, ::make_vec1(node.m_value->m_res_type.clone()), node.m_slot->m_res_type.clone(), "");
+ node.m_value->visit( *this );
}
- node.m_slot->visit( *this );
- node.m_value->visit( *this );
- }
- void visit(::HIR::ExprNode_BinOp& node) override
- {
- TRACE_FUNCTION_F("... "<<::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 );
-
- switch(node.m_op)
+ void visit(::HIR::ExprNode_If& node) override
{
- case ::HIR::ExprNode_BinOp::Op::CmpEqu:
- case ::HIR::ExprNode_BinOp::Op::CmpNEqu:
- case ::HIR::ExprNode_BinOp::Op::CmpLt:
- case ::HIR::ExprNode_BinOp::Op::CmpLtE:
- case ::HIR::ExprNode_BinOp::Op::CmpGt:
- case ::HIR::ExprNode_BinOp::Op::CmpGtE: {
- this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef(::HIR::CoreType::Bool));
+ TRACE_FUNCTION_F("if ...");
- const char* item_name = nullptr;
- switch(node.m_op)
- {
- case ::HIR::ExprNode_BinOp::Op::CmpEqu: item_name = "eq"; break;
- case ::HIR::ExprNode_BinOp::Op::CmpNEqu: item_name = "eq"; break;
- case ::HIR::ExprNode_BinOp::Op::CmpLt: item_name = "ord"; break;
- case ::HIR::ExprNode_BinOp::Op::CmpLtE: item_name = "ord"; break;
- case ::HIR::ExprNode_BinOp::Op::CmpGt: item_name = "ord"; break;
- case ::HIR::ExprNode_BinOp::Op::CmpGtE: item_name = "ord"; break;
- default: break;
+ this->context.add_ivars( node.m_cond->m_res_type );
+ this->context.equate_types_coerce(node.m_cond->span(), ::HIR::TypeRef(::HIR::CoreType::Bool), node.m_cond);
+
+ this->context.add_ivars( node.m_true->m_res_type );
+ this->context.equate_types_coerce(node.span(), node.m_res_type, node.m_true);
+ node.m_true->visit( *this );
+
+ if( node.m_false ) {
+ this->context.add_ivars( node.m_false->m_res_type );
+ this->context.equate_types_coerce(node.span(), node.m_res_type, node.m_false);
+ node.m_false->visit( *this );
}
- 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(), "");
- break; }
+ else {
+ this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_unit());
+ }
+ }
- 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));
- break;
- default: {
- const char* item_name = nullptr;
+
+ void visit(::HIR::ExprNode_Assign& node) override
+ {
+ TRACE_FUNCTION_F("... = ...");
+ this->context.add_ivars( node.m_slot ->m_res_type );
+ this->context.add_ivars( node.m_value->m_res_type );
+
+ // Plain assignment can't be overloaded, requires equal types
+ if( node.m_op == ::HIR::ExprNode_Assign::Op::None ) {
+ this->context.equate_types_coerce(node.span(), node.m_slot->m_res_type, node.m_value);
+ }
+ else {
+ // Type inferrence using the +=
+ // - "" as type name to indicate that it's just using the trait magic?
+ const char *lang_item = nullptr;
+ switch( node.m_op )
+ {
+ case ::HIR::ExprNode_Assign::Op::None: throw "";
+ case ::HIR::ExprNode_Assign::Op::Add: lang_item = "add_assign"; break;
+ case ::HIR::ExprNode_Assign::Op::Sub: lang_item = "sub_assign"; break;
+ case ::HIR::ExprNode_Assign::Op::Mul: lang_item = "mul_assign"; break;
+ case ::HIR::ExprNode_Assign::Op::Div: lang_item = "div_assign"; break;
+ case ::HIR::ExprNode_Assign::Op::Mod: lang_item = "rem_assign"; break;
+ case ::HIR::ExprNode_Assign::Op::And: lang_item = "bitand_assign"; break;
+ case ::HIR::ExprNode_Assign::Op::Or : lang_item = "bitor_assign" ; break;
+ case ::HIR::ExprNode_Assign::Op::Xor: lang_item = "bitxor_assign"; break;
+ case ::HIR::ExprNode_Assign::Op::Shr: lang_item = "shl_assign"; break;
+ case ::HIR::ExprNode_Assign::Op::Shl: lang_item = "shr_assign"; break;
+ }
+ assert(lang_item);
+ const auto& trait_path = this->context.m_crate.get_lang_item_path(node.span(), lang_item);
+
+ this->context.equate_types_assoc(node.span(), ::HIR::TypeRef(), trait_path, ::make_vec1(node.m_value->m_res_type.clone()), node.m_slot->m_res_type.clone(), "");
+ }
+
+ node.m_slot->visit( *this );
+ node.m_value->visit( *this );
+ }
+ void visit(::HIR::ExprNode_BinOp& node) override
+ {
+ TRACE_FUNCTION_F("... "<<::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 );
+
switch(node.m_op)
{
- case ::HIR::ExprNode_BinOp::Op::CmpEqu: throw "";
- case ::HIR::ExprNode_BinOp::Op::CmpNEqu: throw "";
- case ::HIR::ExprNode_BinOp::Op::CmpLt: throw "";
- case ::HIR::ExprNode_BinOp::Op::CmpLtE: throw "";
- case ::HIR::ExprNode_BinOp::Op::CmpGt: throw "";
- case ::HIR::ExprNode_BinOp::Op::CmpGtE: throw "";
- case ::HIR::ExprNode_BinOp::Op::BoolAnd: throw "";
- case ::HIR::ExprNode_BinOp::Op::BoolOr: throw "";
+ case ::HIR::ExprNode_BinOp::Op::CmpEqu:
+ case ::HIR::ExprNode_BinOp::Op::CmpNEqu:
+ case ::HIR::ExprNode_BinOp::Op::CmpLt:
+ case ::HIR::ExprNode_BinOp::Op::CmpLtE:
+ case ::HIR::ExprNode_BinOp::Op::CmpGt:
+ case ::HIR::ExprNode_BinOp::Op::CmpGtE: {
+ this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef(::HIR::CoreType::Bool));
+
+ const char* item_name = nullptr;
+ switch(node.m_op)
+ {
+ case ::HIR::ExprNode_BinOp::Op::CmpEqu: item_name = "eq"; break;
+ case ::HIR::ExprNode_BinOp::Op::CmpNEqu: item_name = "eq"; break;
+ case ::HIR::ExprNode_BinOp::Op::CmpLt: item_name = "ord"; break;
+ case ::HIR::ExprNode_BinOp::Op::CmpLtE: item_name = "ord"; break;
+ case ::HIR::ExprNode_BinOp::Op::CmpGt: item_name = "ord"; break;
+ case ::HIR::ExprNode_BinOp::Op::CmpGtE: item_name = "ord"; break;
+ default: break;
+ }
+ assert(item_name);
+ const auto& op_trait = this->context.m_crate.get_lang_item_path(node.span(), item_name);
- case ::HIR::ExprNode_BinOp::Op::Add: item_name = "add"; break;
- case ::HIR::ExprNode_BinOp::Op::Sub: item_name = "sub"; break;
- case ::HIR::ExprNode_BinOp::Op::Mul: item_name = "mul"; break;
- case ::HIR::ExprNode_BinOp::Op::Div: item_name = "div"; break;
- case ::HIR::ExprNode_BinOp::Op::Mod: item_name = "rem"; break;
-
- case ::HIR::ExprNode_BinOp::Op::And: item_name = "bitand"; break;
- case ::HIR::ExprNode_BinOp::Op::Or: item_name = "bitor"; break;
- case ::HIR::ExprNode_BinOp::Op::Xor: item_name = "bitxor"; break;
+ 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(), "");
+ break; }
- case ::HIR::ExprNode_BinOp::Op::Shr: item_name = "shr"; break;
- case ::HIR::ExprNode_BinOp::Op::Shl: item_name = "shl"; 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));
+ break;
+ default: {
+ const char* item_name = nullptr;
+ switch(node.m_op)
+ {
+ case ::HIR::ExprNode_BinOp::Op::CmpEqu: throw "";
+ case ::HIR::ExprNode_BinOp::Op::CmpNEqu: throw "";
+ case ::HIR::ExprNode_BinOp::Op::CmpLt: throw "";
+ case ::HIR::ExprNode_BinOp::Op::CmpLtE: throw "";
+ case ::HIR::ExprNode_BinOp::Op::CmpGt: throw "";
+ case ::HIR::ExprNode_BinOp::Op::CmpGtE: throw "";
+ case ::HIR::ExprNode_BinOp::Op::BoolAnd: throw "";
+ case ::HIR::ExprNode_BinOp::Op::BoolOr: throw "";
+
+ case ::HIR::ExprNode_BinOp::Op::Add: item_name = "add"; break;
+ case ::HIR::ExprNode_BinOp::Op::Sub: item_name = "sub"; break;
+ case ::HIR::ExprNode_BinOp::Op::Mul: item_name = "mul"; break;
+ case ::HIR::ExprNode_BinOp::Op::Div: item_name = "div"; break;
+ case ::HIR::ExprNode_BinOp::Op::Mod: item_name = "rem"; break;
+
+ case ::HIR::ExprNode_BinOp::Op::And: item_name = "bitand"; break;
+ case ::HIR::ExprNode_BinOp::Op::Or: item_name = "bitor"; break;
+ case ::HIR::ExprNode_BinOp::Op::Xor: item_name = "bitxor"; break;
+
+ case ::HIR::ExprNode_BinOp::Op::Shr: item_name = "shr"; break;
+ case ::HIR::ExprNode_BinOp::Op::Shl: item_name = "shl"; break;
+ }
+ 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(), node.m_res_type, op_trait, ::make_vec1(node.m_right->m_res_type.clone()), node.m_left->m_res_type.clone(), "Output");
+ break; }
}
- 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(), node.m_res_type, op_trait, ::make_vec1(node.m_right->m_res_type.clone()), node.m_left->m_res_type.clone(), "Output");
- break; }
+ node.m_left ->visit( *this );
+ node.m_right->visit( *this );
}
- node.m_left ->visit( *this );
- node.m_right->visit( *this );
- }
- void visit(::HIR::ExprNode_UniOp& node) override
- {
- TRACE_FUNCTION_F(::HIR::ExprNode_UniOp::opname(node.m_op) << "...");
- this->context.add_ivars( node.m_value->m_res_type );
- switch(node.m_op)
+ void visit(::HIR::ExprNode_UniOp& node) override
{
- case ::HIR::ExprNode_UniOp::Op::Ref:
- // TODO: Can Ref/RefMut trigger coercions?
- this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared, node.m_value->m_res_type.clone()));
- break;
- case ::HIR::ExprNode_UniOp::Op::RefMut:
- 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");
- 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(), "minus"), {}, node.m_value->m_res_type.clone(), "Output");
- break;
+ TRACE_FUNCTION_F(::HIR::ExprNode_UniOp::opname(node.m_op) << "...");
+ this->context.add_ivars( node.m_value->m_res_type );
+ switch(node.m_op)
+ {
+ case ::HIR::ExprNode_UniOp::Op::Ref:
+ // TODO: Can Ref/RefMut trigger coercions?
+ this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared, node.m_value->m_res_type.clone()));
+ break;
+ case ::HIR::ExprNode_UniOp::Op::RefMut:
+ 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");
+ 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(), "minus"), {}, node.m_value->m_res_type.clone(), "Output");
+ break;
+ }
+ node.m_value->visit( *this );
}
- node.m_value->visit( *this );
- }
- void visit(::HIR::ExprNode_Cast& node) override
- {
- TRACE_FUNCTION_F("... as " << node.m_res_type);
- this->context.add_ivars( node.m_value->m_res_type );
-
- // TODO: Depending on the form of the result type, it can lead to links between the input and output
-
- node.m_value->visit( *this );
- }
- void visit(::HIR::ExprNode_Unsize& node) override
- {
- BUG(node.span(), "Hit _Unsize");
- }
- void visit(::HIR::ExprNode_Index& node) override
- {
- TRACE_FUNCTION_F("... [ ... ]");
- this->context.add_ivars( node.m_value->m_res_type );
- this->context.add_ivars( node.m_index->m_res_type );
-
- const auto& op_trait = this->context.m_crate.get_lang_item_path(node.span(), "index");
- this->context.equate_types_assoc(node.span(), node.m_res_type, op_trait, ::make_vec1(node.m_index->m_res_type.clone()), node.m_value->m_res_type.clone(), "Output");
-
- node.m_value->visit( *this );
- node.m_index->visit( *this );
- }
- void visit(::HIR::ExprNode_Deref& node) override
- {
- TRACE_FUNCTION_F("*...");
- this->context.add_ivars( node.m_value->m_res_type );
-
- const auto& op_trait = this->context.m_crate.get_lang_item_path(node.span(), "deref");
- this->context.equate_types_assoc(node.span(), node.m_res_type, op_trait, {}, node.m_value->m_res_type.clone(), "Target");
-
- node.m_value->visit( *this );
- }
-
- void add_ivars_generic_path(const Span& sp, ::HIR::GenericPath& gp) {
- for(auto& ty : gp.m_params.m_types)
- this->context.add_ivars(ty);
- }
- void add_ivars_path(const Span& sp, ::HIR::Path& path) {
- TU_MATCH(::HIR::Path::Data, (path.m_data), (e),
- (Generic,
- this->add_ivars_generic_path(sp, e);
- ),
- (UfcsKnown,
- this->context.add_ivars(*e.type);
- this->add_ivars_generic_path(sp, e.trait);
- for(auto& ty : e.params.m_types)
- this->context.add_ivars(ty);
- ),
- (UfcsUnknown,
- TODO(sp, "Hit a UfcsUnknown (" << path << ") - Is this an error?");
- ),
- (UfcsInherent,
- this->context.add_ivars(*e.type);
- for(auto& ty : e.params.m_types)
- this->context.add_ivars(ty);
- )
- )
- }
-
- ::HIR::TypeRef get_structenum_ty(const Span& sp, bool is_struct, ::HIR::GenericPath& gp)
- {
- if( is_struct )
+ void visit(::HIR::ExprNode_Cast& node) override
{
- const auto& str = this->context.m_crate.get_struct_by_path(sp, gp.m_path);
- fix_param_count(sp, this->context, gp, str.m_params, gp.m_params);
+ TRACE_FUNCTION_F("... as " << node.m_res_type);
+ this->context.add_ivars( node.m_value->m_res_type );
+
+ // TODO: Depending on the form of the result type, it can lead to links between the input and output
- return ::HIR::TypeRef::new_path( gp.clone(), ::HIR::TypeRef::TypePathBinding::make_Struct(&str) );
+ node.m_value->visit( *this );
+ }
+ void visit(::HIR::ExprNode_Unsize& node) override
+ {
+ BUG(node.span(), "Hit _Unsize");
}
- else
+ void visit(::HIR::ExprNode_Index& node) override
{
- auto s_path = gp.m_path;
- s_path.m_components.pop_back();
+ TRACE_FUNCTION_F("... [ ... ]");
+ this->context.add_ivars( node.m_value->m_res_type );
+ this->context.add_ivars( node.m_index->m_res_type );
- const auto& enm = this->context.m_crate.get_enum_by_path(sp, s_path);
- fix_param_count(sp, this->context, gp, enm.m_params, gp.m_params);
+ const auto& op_trait = this->context.m_crate.get_lang_item_path(node.span(), "index");
+ this->context.equate_types_assoc(node.span(), node.m_res_type, op_trait, ::make_vec1(node.m_index->m_res_type.clone()), node.m_value->m_res_type.clone(), "Output");
- return ::HIR::TypeRef::new_path( ::HIR::GenericPath(mv$(s_path), gp.m_params.clone()), ::HIR::TypeRef::TypePathBinding::make_Enum(&enm) );
+ node.m_value->visit( *this );
+ node.m_index->visit( *this );
}
- }
-
- void visit(::HIR::ExprNode_TupleVariant& node) override
- {
- TRACE_FUNCTION_F(node.m_path << "(...) [" << (node.m_is_struct ? "struct" : "enum") << "]");
- for( auto& val : node.m_args ) {
- this->context.add_ivars( val->m_res_type );
+ void visit(::HIR::ExprNode_Deref& node) override
+ {
+ TRACE_FUNCTION_F("*...");
+ this->context.add_ivars( node.m_value->m_res_type );
+
+ const auto& op_trait = this->context.m_crate.get_lang_item_path(node.span(), "deref");
+ this->context.equate_types_assoc(node.span(), node.m_res_type, op_trait, {}, node.m_value->m_res_type.clone(), "Target");
+
+ node.m_value->visit( *this );
}
-
- // - Create ivars in path, and set result type
- const auto ty = this->get_structenum_ty(node.span(), node.m_is_struct, node.m_path);
- this->context.equate_types(node.span(), node.m_res_type, ty);
-
- const ::HIR::t_tuple_fields* fields_ptr = nullptr;
- TU_MATCH(::HIR::TypeRef::TypePathBinding, (ty.m_data.as_Path().binding), (e),
- (Unbound, ),
- (Opaque, ),
- (Enum,
- const auto& var_name = node.m_path.m_path.m_components.back();
- const auto& enm = *e;
- auto it = ::std::find_if(enm.m_variants.begin(), enm.m_variants.end(), [&](const auto&v)->auto{ return v.first == var_name; });
- assert(it != enm.m_variants.end());
- fields_ptr = &it->second.as_Tuple();
- ),
- (Struct,
- fields_ptr = &e->m_data.as_Tuple();
+
+ void add_ivars_generic_path(const Span& sp, ::HIR::GenericPath& gp) {
+ for(auto& ty : gp.m_params.m_types)
+ this->context.add_ivars(ty);
+ }
+ void add_ivars_path(const Span& sp, ::HIR::Path& path) {
+ TU_MATCH(::HIR::Path::Data, (path.m_data), (e),
+ (Generic,
+ this->add_ivars_generic_path(sp, e);
+ ),
+ (UfcsKnown,
+ this->context.add_ivars(*e.type);
+ this->add_ivars_generic_path(sp, e.trait);
+ for(auto& ty : e.params.m_types)
+ this->context.add_ivars(ty);
+ ),
+ (UfcsUnknown,
+ TODO(sp, "Hit a UfcsUnknown (" << path << ") - Is this an error?");
+ ),
+ (UfcsInherent,
+ this->context.add_ivars(*e.type);
+ for(auto& ty : e.params.m_types)
+ this->context.add_ivars(ty);
+ )
)
- )
- assert(fields_ptr);
- const ::HIR::t_tuple_fields& fields = *fields_ptr;
- if( fields.size() != node.m_args.size() ) {
- ERROR(node.span(), E0000, "");
}
- // Bind fields with type params (coercable)
- for( unsigned int i = 0; i < node.m_args.size(); i ++ )
+ ::HIR::TypeRef get_structenum_ty(const Span& sp, bool is_struct, ::HIR::GenericPath& gp)
{
- const auto& des_ty_r = fields[i].ent;
- if( monomorphise_type_needed(des_ty_r) ) {
- TODO(node.span(), "Monomorphise tuple variant type");
+ if( is_struct )
+ {
+ const auto& str = this->context.m_crate.get_struct_by_path(sp, gp.m_path);
+ fix_param_count(sp, this->context, gp, str.m_params, gp.m_params);
+
+ return ::HIR::TypeRef::new_path( gp.clone(), ::HIR::TypeRef::TypePathBinding::make_Struct(&str) );
}
- else {
- this->context.equate_types_coerce(node.span(), des_ty_r, node.m_args[i]);
+ else
+ {
+ auto s_path = gp.m_path;
+ s_path.m_components.pop_back();
+
+ const auto& enm = this->context.m_crate.get_enum_by_path(sp, s_path);
+ fix_param_count(sp, this->context, gp, enm.m_params, gp.m_params);
+
+ return ::HIR::TypeRef::new_path( ::HIR::GenericPath(mv$(s_path), gp.m_params.clone()), ::HIR::TypeRef::TypePathBinding::make_Enum(&enm) );
}
}
- for( auto& val : node.m_args ) {
- val->visit( *this );
- }
- }
- void visit(::HIR::ExprNode_StructLiteral& node) override
- {
- TRACE_FUNCTION_F(node.m_path << "{...} [" << (node.m_is_struct ? "struct" : "enum") << "]");
- for( auto& val : node.m_values ) {
- this->context.add_ivars( val.second->m_res_type );
- }
-
- // - Create ivars in path, and set result type
- const auto ty = this->get_structenum_ty(node.span(), node.m_is_struct, node.m_path);
- this->context.equate_types(node.span(), node.m_res_type, ty);
-
- const ::HIR::t_struct_fields* fields_ptr = nullptr;
- TU_MATCH(::HIR::TypeRef::TypePathBinding, (ty.m_data.as_Path().binding), (e),
- (Unbound, ),
- (Opaque, ),
- (Enum,
- const auto& var_name = node.m_path.m_path.m_components.back();
- const auto& enm = *e;
- auto it = ::std::find_if(enm.m_variants.begin(), enm.m_variants.end(), [&](const auto&v)->auto{ return v.first == var_name; });
- assert(it != enm.m_variants.end());
- fields_ptr = &it->second.as_Struct();
- ),
- (Struct,
- fields_ptr = &e->m_data.as_Named();
- )
- )
- assert(fields_ptr);
- const ::HIR::t_struct_fields& fields = *fields_ptr;
-
- // Bind fields with type params (coercable)
- for( auto& val : node.m_values)
+ void visit(::HIR::ExprNode_TupleVariant& node) override
{
- const auto& name = val.first;
- auto it = ::std::find_if(fields.begin(), fields.end(), [&](const auto& v)->bool{ return v.first == name; });
- assert(it != fields.end());
- const auto& des_ty_r = it->second.ent;
+ TRACE_FUNCTION_F(node.m_path << "(...) [" << (node.m_is_struct ? "struct" : "enum") << "]");
+ for( auto& val : node.m_args ) {
+ this->context.add_ivars( val->m_res_type );
+ }
- if( monomorphise_type_needed(des_ty_r) ) {
- TODO(node.span(), "Monomorphise struct variant type");
+ // - Create ivars in path, and set result type
+ const auto ty = this->get_structenum_ty(node.span(), node.m_is_struct, node.m_path);
+ this->context.equate_types(node.span(), node.m_res_type, ty);
+
+ const ::HIR::t_tuple_fields* fields_ptr = nullptr;
+ TU_MATCH(::HIR::TypeRef::TypePathBinding, (ty.m_data.as_Path().binding), (e),
+ (Unbound, ),
+ (Opaque, ),
+ (Enum,
+ const auto& var_name = node.m_path.m_path.m_components.back();
+ const auto& enm = *e;
+ auto it = ::std::find_if(enm.m_variants.begin(), enm.m_variants.end(), [&](const auto&v)->auto{ return v.first == var_name; });
+ assert(it != enm.m_variants.end());
+ fields_ptr = &it->second.as_Tuple();
+ ),
+ (Struct,
+ fields_ptr = &e->m_data.as_Tuple();
+ )
+ )
+ assert(fields_ptr);
+ const ::HIR::t_tuple_fields& fields = *fields_ptr;
+ if( fields.size() != node.m_args.size() ) {
+ ERROR(node.span(), E0000, "");
}
- else {
- this->context.equate_types_coerce(node.span(), des_ty_r, val.second);
+
+ // Bind fields with type params (coercable)
+ for( unsigned int i = 0; i < node.m_args.size(); i ++ )
+ {
+ const auto& des_ty_r = fields[i].ent;
+ if( monomorphise_type_needed(des_ty_r) ) {
+ TODO(node.span(), "Monomorphise tuple variant type");
+ }
+ else {
+ this->context.equate_types_coerce(node.span(), des_ty_r, node.m_args[i]);
+ }
}
- }
-
- for( auto& val : node.m_values ) {
- val.second->visit( *this );
- }
- }
- void visit(::HIR::ExprNode_UnitVariant& node) override
- {
- TRACE_FUNCTION_F(node.m_path << " [" << (node.m_is_struct ? "struct" : "enum") << "]");
-
- // - Create ivars in path, and set result type
- const auto ty = this->get_structenum_ty(node.span(), node.m_is_struct, node.m_path);
- this->context.equate_types(node.span(), node.m_res_type, ty);
- }
-
-private:
- /// (HELPER) Populate the cache for nodes that use visit_call
- void visit_call_populate_cache(const Span& sp, ::HIR::Path& path, ::HIR::ExprCallCache& cache) const
- {
- assert(cache.m_arg_types.size() == 0);
-
- const ::HIR::Function* fcn_ptr = nullptr;
- ::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> monomorph_cb;
-
- TU_MATCH(::HIR::Path::Data, (path.m_data), (e),
- (Generic,
- const auto& fcn = this->context.m_crate.get_function_by_path(sp, e.m_path);
- fix_param_count(sp, this->context, path, fcn.m_params, e.m_params);
- fcn_ptr = &fcn;
- cache.m_fcn_params = &fcn.m_params;
- //const auto& params_def = fcn.m_params;
- const auto& path_params = e.m_params;
- monomorph_cb = [&](const auto& gt)->const auto& {
- const auto& e = gt.m_data.as_Generic();
- if( e.name == "Self" || e.binding == 0xFFFF )
- TODO(sp, "Handle 'Self' when monomorphising");
- if( e.binding < 256 ) {
- BUG(sp, "Impl-level parameter on free function (#" << e.binding << " " << e.name << ")");
- }
- else if( e.binding < 512 ) {
- auto idx = e.binding - 256;
- if( idx >= path_params.m_types.size() ) {
- BUG(sp, "Generic param out of input range - " << idx << " '"<<e.name<<"' >= " << path_params.m_types.size());
- }
- return this->context.get_type(path_params.m_types[idx]);
- }
- else {
- BUG(sp, "Generic bounding out of total range");
- }
- };
- ),
- (UfcsKnown,
- const auto& trait = this->context.m_crate.get_trait_by_path(sp, e.trait.m_path);
- fix_param_count(sp, this->context, path, trait.m_params, e.trait.m_params);
- if( trait.m_values.count(e.item) == 0 ) {
- BUG(sp, "Method '" << e.item << "' of trait " << e.trait.m_path << " doesn't exist");
+ for( auto& val : node.m_args ) {
+ val->visit( *this );
+ }
+ }
+ void visit(::HIR::ExprNode_StructLiteral& node) override
+ {
+ TRACE_FUNCTION_F(node.m_path << "{...} [" << (node.m_is_struct ? "struct" : "enum") << "]");
+ for( auto& val : node.m_values ) {
+ this->context.add_ivars( val.second->m_res_type );
}
- const auto& fcn = trait.m_values.at(e.item).as_Function();
- fix_param_count(sp, this->context, path, fcn.m_params, e.params);
- cache.m_fcn_params = &fcn.m_params;
- cache.m_top_params = &trait.m_params;
- // TODO: Check/apply trait bounds (apply = closure arguments or fixed trait args)
+ // - Create ivars in path, and set result type
+ const auto ty = this->get_structenum_ty(node.span(), node.m_is_struct, node.m_path);
+ this->context.equate_types(node.span(), node.m_res_type, ty);
- fcn_ptr = &fcn;
+ const ::HIR::t_struct_fields* fields_ptr = nullptr;
+ TU_MATCH(::HIR::TypeRef::TypePathBinding, (ty.m_data.as_Path().binding), (e),
+ (Unbound, ),
+ (Opaque, ),
+ (Enum,
+ const auto& var_name = node.m_path.m_path.m_components.back();
+ const auto& enm = *e;
+ auto it = ::std::find_if(enm.m_variants.begin(), enm.m_variants.end(), [&](const auto&v)->auto{ return v.first == var_name; });
+ assert(it != enm.m_variants.end());
+ fields_ptr = &it->second.as_Struct();
+ ),
+ (Struct,
+ fields_ptr = &e->m_data.as_Named();
+ )
+ )
+ assert(fields_ptr);
+ const ::HIR::t_struct_fields& fields = *fields_ptr;
- const auto& trait_params = e.trait.m_params;
- const auto& path_params = e.params;
- monomorph_cb = [&](const auto& gt)->const auto& {
- const auto& ge = gt.m_data.as_Generic();
- if( ge.binding == 0xFFFF ) {
- return *e.type;
- }
- else if( ge.binding < 256 ) {
- auto idx = ge.binding;
- if( idx >= trait_params.m_types.size() ) {
- BUG(sp, "Generic param (impl) out of input range - " << idx << " '"<<ge.name<<"' >= " << trait_params.m_types.size());
- }
- return this->context.get_type(trait_params.m_types[idx]);
- }
- else if( ge.binding < 512 ) {
- auto idx = ge.binding - 256;
- if( idx >= path_params.m_types.size() ) {
- BUG(sp, "Generic param out of input range - " << idx << " '"<<ge.name<<"' >= " << path_params.m_types.size());
- }
- return this->context.get_type(path_params.m_types[idx]);
- }
- else {
- BUG(sp, "Generic bounding out of total range");
- }
- };
- ),
- (UfcsUnknown,
- TODO(sp, "Hit a UfcsUnknown (" << path << ") - Is this an error?");
- ),
- (UfcsInherent,
- // TODO: What if this types has ivars?
- // - Locate function (and impl block)
- const ::HIR::TypeImpl* impl_ptr = nullptr;
- this->context.m_crate.find_type_impls(*e.type, [&](const auto& ty)->const auto& {
- if( ty.m_data.is_Infer() )
- return this->context.get_type(ty);
- else
- return ty;
- },
- [&](const auto& impl) {
- DEBUG("- impl" << impl.m_params.fmt_args() << " " << impl.m_type);
- auto it = impl.m_methods.find(e.item);
- if( it == impl.m_methods.end() )
- return false;
- fcn_ptr = &it->second;
- impl_ptr = &impl;
- return true;
- });
- if( !fcn_ptr ) {
- ERROR(sp, E0000, "Failed to locate function " << path);
+ // Bind fields with type params (coercable)
+ for( auto& val : node.m_values)
+ {
+ const auto& name = val.first;
+ auto it = ::std::find_if(fields.begin(), fields.end(), [&](const auto& v)->bool{ return v.first == name; });
+ assert(it != fields.end());
+ const auto& des_ty_r = it->second.ent;
+
+ if( monomorphise_type_needed(des_ty_r) ) {
+ TODO(node.span(), "Monomorphise struct variant type");
+ }
+ else {
+ this->context.equate_types_coerce(node.span(), des_ty_r, val.second);
+ }
}
- assert(impl_ptr);
- fix_param_count(sp, this->context, path, fcn_ptr->m_params, e.params);
- cache.m_fcn_params = &fcn_ptr->m_params;
-
- // If the impl block has parameters, figure out what types they map to
- // - The function params are already mapped (from fix_param_count)
- auto& impl_params = cache.m_ty_impl_params;
- if( impl_ptr->m_params.m_types.size() > 0 ) {
- impl_params.m_types.resize( impl_ptr->m_params.m_types.size() );
- impl_ptr->m_type.match_generics(sp, *e.type, this->context.m_ivars.callback_resolve_infer(), [&](auto idx, const auto& ty) {
- assert( idx < impl_params.m_types.size() );
- impl_params.m_types[idx] = ty.clone();
- });
- for(const auto& ty : impl_params.m_types)
- assert( !( ty.m_data.is_Infer() && ty.m_data.as_Infer().index == ~0u) );
+ for( auto& val : node.m_values ) {
+ val.second->visit( *this );
}
+ }
+ void visit(::HIR::ExprNode_UnitVariant& node) override
+ {
+ TRACE_FUNCTION_F(node.m_path << " [" << (node.m_is_struct ? "struct" : "enum") << "]");
- // Create monomorphise callback
- const auto& fcn_params = e.params;
- monomorph_cb = [&](const auto& gt)->const auto& {
- const auto& ge = gt.m_data.as_Generic();
- if( ge.binding == 0xFFFF ) {
- return this->context.get_type(*e.type);
- }
- else if( ge.binding < 256 ) {
- auto idx = ge.binding;
- if( idx >= impl_params.m_types.size() ) {
- BUG(sp, "Generic param out of input range - " << idx << " '" << ge.name << "' >= " << impl_params.m_types.size());
+ // - Create ivars in path, and set result type
+ const auto ty = this->get_structenum_ty(node.span(), node.m_is_struct, node.m_path);
+ this->context.equate_types(node.span(), node.m_res_type, ty);
+ }
+
+ private:
+ /// (HELPER) Populate the cache for nodes that use visit_call
+ void visit_call_populate_cache(const Span& sp, ::HIR::Path& path, ::HIR::ExprCallCache& cache) const
+ {
+ assert(cache.m_arg_types.size() == 0);
+
+ const ::HIR::Function* fcn_ptr = nullptr;
+ ::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> monomorph_cb;
+
+ TU_MATCH(::HIR::Path::Data, (path.m_data), (e),
+ (Generic,
+ const auto& fcn = this->context.m_crate.get_function_by_path(sp, e.m_path);
+ fix_param_count(sp, this->context, path, fcn.m_params, e.m_params);
+ fcn_ptr = &fcn;
+ cache.m_fcn_params = &fcn.m_params;
+
+ //const auto& params_def = fcn.m_params;
+ const auto& path_params = e.m_params;
+ monomorph_cb = [&](const auto& gt)->const auto& {
+ const auto& e = gt.m_data.as_Generic();
+ if( e.name == "Self" || e.binding == 0xFFFF )
+ TODO(sp, "Handle 'Self' when monomorphising");
+ if( e.binding < 256 ) {
+ BUG(sp, "Impl-level parameter on free function (#" << e.binding << " " << e.name << ")");
}
- return this->context.get_type(impl_params.m_types[idx]);
- }
- else if( ge.binding < 512 ) {
- auto idx = ge.binding - 256;
- if( idx >= fcn_params.m_types.size() ) {
- BUG(sp, "Generic param out of input range - " << idx << " '" << ge.name << "' >= " << fcn_params.m_types.size());
+ else if( e.binding < 512 ) {
+ auto idx = e.binding - 256;
+ if( idx >= path_params.m_types.size() ) {
+ BUG(sp, "Generic param out of input range - " << idx << " '"<<e.name<<"' >= " << path_params.m_types.size());
+ }
+ return this->context.get_type(path_params.m_types[idx]);
}
- return this->context.get_type(fcn_params.m_types[idx]);
- }
- else {
- BUG(sp, "Generic bounding out of total range");
- }
- };
+ else {
+ BUG(sp, "Generic bounding out of total range");
+ }
+ };
+ ),
+ (UfcsKnown,
+ const auto& trait = this->context.m_crate.get_trait_by_path(sp, e.trait.m_path);
+ fix_param_count(sp, this->context, path, trait.m_params, e.trait.m_params);
+ if( trait.m_values.count(e.item) == 0 ) {
+ BUG(sp, "Method '" << e.item << "' of trait " << e.trait.m_path << " doesn't exist");
+ }
+ const auto& fcn = trait.m_values.at(e.item).as_Function();
+ fix_param_count(sp, this->context, path, fcn.m_params, e.params);
+ cache.m_fcn_params = &fcn.m_params;
+ cache.m_top_params = &trait.m_params;
+
+ // TODO: Check/apply trait bounds (apply = closure arguments or fixed trait args)
+
+ fcn_ptr = &fcn;
+
+ const auto& trait_params = e.trait.m_params;
+ const auto& path_params = e.params;
+ monomorph_cb = [&](const auto& gt)->const auto& {
+ const auto& ge = gt.m_data.as_Generic();
+ if( ge.binding == 0xFFFF ) {
+ return *e.type;
+ }
+ else if( ge.binding < 256 ) {
+ auto idx = ge.binding;
+ if( idx >= trait_params.m_types.size() ) {
+ BUG(sp, "Generic param (impl) out of input range - " << idx << " '"<<ge.name<<"' >= " << trait_params.m_types.size());
+ }
+ return this->context.get_type(trait_params.m_types[idx]);
+ }
+ else if( ge.binding < 512 ) {
+ auto idx = ge.binding - 256;
+ if( idx >= path_params.m_types.size() ) {
+ BUG(sp, "Generic param out of input range - " << idx << " '"<<ge.name<<"' >= " << path_params.m_types.size());
+ }
+ return this->context.get_type(path_params.m_types[idx]);
+ }
+ else {
+ BUG(sp, "Generic bounding out of total range");
+ }
+ };
+ ),
+ (UfcsUnknown,
+ TODO(sp, "Hit a UfcsUnknown (" << path << ") - Is this an error?");
+ ),
+ (UfcsInherent,
+ // TODO: What if this types has ivars?
+ // - Locate function (and impl block)
+ const ::HIR::TypeImpl* impl_ptr = nullptr;
+ this->context.m_crate.find_type_impls(*e.type, [&](const auto& ty)->const auto& {
+ if( ty.m_data.is_Infer() )
+ return this->context.get_type(ty);
+ else
+ return ty;
+ },
+ [&](const auto& impl) {
+ DEBUG("- impl" << impl.m_params.fmt_args() << " " << impl.m_type);
+ auto it = impl.m_methods.find(e.item);
+ if( it == impl.m_methods.end() )
+ return false;
+ fcn_ptr = &it->second;
+ impl_ptr = &impl;
+ return true;
+ });
+ if( !fcn_ptr ) {
+ ERROR(sp, E0000, "Failed to locate function " << path);
+ }
+ assert(impl_ptr);
+ fix_param_count(sp, this->context, path, fcn_ptr->m_params, e.params);
+ cache.m_fcn_params = &fcn_ptr->m_params;
+
+
+ // If the impl block has parameters, figure out what types they map to
+ // - The function params are already mapped (from fix_param_count)
+ auto& impl_params = cache.m_ty_impl_params;
+ if( impl_ptr->m_params.m_types.size() > 0 ) {
+ impl_params.m_types.resize( impl_ptr->m_params.m_types.size() );
+ impl_ptr->m_type.match_generics(sp, *e.type, this->context.m_ivars.callback_resolve_infer(), [&](auto idx, const auto& ty) {
+ assert( idx < impl_params.m_types.size() );
+ impl_params.m_types[idx] = ty.clone();
+ });
+ for(const auto& ty : impl_params.m_types)
+ assert( !( ty.m_data.is_Infer() && ty.m_data.as_Infer().index == ~0u) );
+ }
+
+ // Create monomorphise callback
+ const auto& fcn_params = e.params;
+ monomorph_cb = [&](const auto& gt)->const auto& {
+ const auto& ge = gt.m_data.as_Generic();
+ if( ge.binding == 0xFFFF ) {
+ return this->context.get_type(*e.type);
+ }
+ else if( ge.binding < 256 ) {
+ auto idx = ge.binding;
+ if( idx >= impl_params.m_types.size() ) {
+ BUG(sp, "Generic param out of input range - " << idx << " '" << ge.name << "' >= " << impl_params.m_types.size());
+ }
+ return this->context.get_type(impl_params.m_types[idx]);
+ }
+ else if( ge.binding < 512 ) {
+ auto idx = ge.binding - 256;
+ if( idx >= fcn_params.m_types.size() ) {
+ BUG(sp, "Generic param out of input range - " << idx << " '" << ge.name << "' >= " << fcn_params.m_types.size());
+ }
+ return this->context.get_type(fcn_params.m_types[idx]);
+ }
+ else {
+ BUG(sp, "Generic bounding out of total range");
+ }
+ };
+ )
)
- )
- assert( fcn_ptr );
- const auto& fcn = *fcn_ptr;
-
- // --- Monomorphise the argument/return types (into current context)
- for(const auto& arg : fcn.m_args) {
- if( monomorphise_type_needed(arg.second) ) {
- cache.m_arg_types.push_back( /*this->context.expand_associated_types(sp, */monomorphise_type_with(sp, arg.second, monomorph_cb)/*)*/ );
+ assert( fcn_ptr );
+ const auto& fcn = *fcn_ptr;
+
+ // --- Monomorphise the argument/return types (into current context)
+ for(const auto& arg : fcn.m_args) {
+ if( monomorphise_type_needed(arg.second) ) {
+ cache.m_arg_types.push_back( /*this->context.expand_associated_types(sp, */monomorphise_type_with(sp, arg.second, monomorph_cb)/*)*/ );
+ }
+ else {
+ cache.m_arg_types.push_back( arg.second.clone() );
+ }
+ }
+ if( monomorphise_type_needed(fcn.m_return) ) {
+ cache.m_arg_types.push_back( /*this->context.expand_associated_types(sp, */monomorphise_type_with(sp, fcn.m_return, monomorph_cb)/*)*/ );
}
else {
- cache.m_arg_types.push_back( arg.second.clone() );
+ cache.m_arg_types.push_back( fcn.m_return.clone() );
}
+
+ cache.m_monomorph_cb = mv$(monomorph_cb);
}
- if( monomorphise_type_needed(fcn.m_return) ) {
- cache.m_arg_types.push_back( /*this->context.expand_associated_types(sp, */monomorphise_type_with(sp, fcn.m_return, monomorph_cb)/*)*/ );
- }
- else {
- cache.m_arg_types.push_back( fcn.m_return.clone() );
- }
-
- cache.m_monomorph_cb = mv$(monomorph_cb);
- }
-public:
- void visit(::HIR::ExprNode_CallPath& node) override
- {
- TRACE_FUNCTION_F(node.m_path << "(...)");
- for( auto& val : node.m_args ) {
- this->context.add_ivars( val->m_res_type );
- }
-
- // Populate cache
+ public:
+ void visit(::HIR::ExprNode_CallPath& node) override
{
- this->visit_call_populate_cache(node.span(), node.m_path, node.m_cache);
- assert( node.m_cache.m_arg_types.size() >= 1);
+ TRACE_FUNCTION_F(node.m_path << "(...)");
+ for( auto& val : node.m_args ) {
+ this->context.add_ivars( val->m_res_type );
+ }
- if( node.m_args.size() != node.m_cache.m_arg_types.size() - 1 ) {
- ERROR(node.span(), E0000, "Incorrect number of arguments to " << node.m_path);
+ // Populate cache
+ {
+ this->visit_call_populate_cache(node.span(), node.m_path, node.m_cache);
+ assert( node.m_cache.m_arg_types.size() >= 1);
+
+ if( node.m_args.size() != node.m_cache.m_arg_types.size() - 1 ) {
+ ERROR(node.span(), E0000, "Incorrect number of arguments to " << node.m_path);
+ }
}
- }
-
- // Link arguments
- for(unsigned int i = 0; i < node.m_args.size(); i ++)
- {
- this->context.equate_types_coerce(node.span(), node.m_cache.m_arg_types[i], node.m_args[i]);
- }
- this->context.equate_types(node.span(), node.m_res_type, node.m_cache.m_arg_types.back());
+
+ // Link arguments
+ for(unsigned int i = 0; i < node.m_args.size(); i ++)
+ {
+ this->context.equate_types_coerce(node.span(), node.m_cache.m_arg_types[i], node.m_args[i]);
+ }
+ this->context.equate_types(node.span(), node.m_res_type, node.m_cache.m_arg_types.back());
- for( auto& val : node.m_args ) {
- val->visit( *this );
- }
- }
- void visit(::HIR::ExprNode_CallValue& node) override
- {
- TRACE_FUNCTION_F("...(...)");
- this->context.add_ivars( node.m_value->m_res_type );
- for( auto& val : node.m_args ) {
- this->context.add_ivars( val->m_res_type );
+ for( auto& val : node.m_args ) {
+ val->visit( *this );
+ }
}
-
- // Nothing can be done until type is known
- this->context.add_revisit(node);
+ void visit(::HIR::ExprNode_CallValue& node) override
+ {
+ TRACE_FUNCTION_F("...(...)");
+ this->context.add_ivars( node.m_value->m_res_type );
+ for( auto& val : node.m_args ) {
+ this->context.add_ivars( val->m_res_type );
+ }
+
+ // Nothing can be done until type is known
+ this->context.add_revisit(node);
- node.m_value->visit( *this );
- for( auto& val : node.m_args ) {
- val->visit( *this );
- }
- }
- void visit(::HIR::ExprNode_CallMethod& node) override
- {
- TRACE_FUNCTION_F("(...)."<<node.m_method<<"(...)");
- this->context.add_ivars( node.m_value->m_res_type );
- for( auto& val : node.m_args ) {
- this->context.add_ivars( val->m_res_type );
+ node.m_value->visit( *this );
+ for( auto& val : node.m_args ) {
+ val->visit( *this );
+ }
}
-
- // - Search in-scope trait list for traits that provide a method of this name
- const ::std::string& method_name = node.m_method;
- ::HIR::t_trait_list possible_traits;
- for(const auto& trait_ref : ::reverse(m_traits))
+ void visit(::HIR::ExprNode_CallMethod& node) override
{
- if( trait_ref.first == nullptr )
- break;
+ TRACE_FUNCTION_F("(...)."<<node.m_method<<"(...)");
+ this->context.add_ivars( node.m_value->m_res_type );
+ for( auto& val : node.m_args ) {
+ this->context.add_ivars( val->m_res_type );
+ }
- // TODO: Search supertraits too
- auto it = trait_ref.second->m_values.find(method_name);
- if( it == trait_ref.second->m_values.end() )
- continue ;
- if( !it->second.is_Function() )
- continue ;
- possible_traits.push_back( trait_ref );
- }
- // > Store the possible set of traits for later
- node.m_traits = mv$(possible_traits);
-
- // Resolution can't be done until lefthand type is known.
- // > Has to be done during iteraton
- this->context.add_revisit( node );
-
- node.m_value->visit( *this );
- for( auto& val : node.m_args ) {
- val->visit( *this );
- }
- }
- void visit(::HIR::ExprNode_Field& node) override
- {
- TRACE_FUNCTION_F("(...)."<<node.m_field);
- this->context.add_ivars( node.m_value->m_res_type );
-
- this->context.add_revisit( node );
-
- node.m_value->visit( *this );
- }
-
- void visit(::HIR::ExprNode_Tuple& node) override
- {
- TRACE_FUNCTION_F("(...,)");
- for( auto& val : node.m_vals ) {
- this->context.add_ivars( val->m_res_type );
+ // - Search in-scope trait list for traits that provide a method of this name
+ const ::std::string& method_name = node.m_method;
+ ::HIR::t_trait_list possible_traits;
+ for(const auto& trait_ref : ::reverse(m_traits))
+ {
+ if( trait_ref.first == nullptr )
+ break;
+
+ // TODO: Search supertraits too
+ auto it = trait_ref.second->m_values.find(method_name);
+ if( it == trait_ref.second->m_values.end() )
+ continue ;
+ if( !it->second.is_Function() )
+ continue ;
+ possible_traits.push_back( trait_ref );
+ }
+ // > Store the possible set of traits for later
+ node.m_traits = mv$(possible_traits);
+
+ // Resolution can't be done until lefthand type is known.
+ // > Has to be done during iteraton
+ this->context.add_revisit( node );
+
+ node.m_value->visit( *this );
+ for( auto& val : node.m_args ) {
+ val->visit( *this );
+ }
}
-
- ::std::vector< ::HIR::TypeRef> tuple_tys;
- for(const auto& val : node.m_vals ) {
- // Can these coerce? Assuming not
- tuple_tys.push_back( val->m_res_type.clone() );
+ void visit(::HIR::ExprNode_Field& node) override
+ {
+ TRACE_FUNCTION_F("(...)."<<node.m_field);
+ this->context.add_ivars( node.m_value->m_res_type );
+
+ this->context.add_revisit( node );
+
+ node.m_value->visit( *this );
}
- this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef(mv$(tuple_tys)));
- for( auto& val : node.m_vals ) {
- val->visit( *this );
- }
- }
- void visit(::HIR::ExprNode_ArrayList& node) override
- {
- TRACE_FUNCTION_F("[...,]");
- for( auto& val : node.m_vals ) {
- this->context.add_ivars( val->m_res_type );
+ void visit(::HIR::ExprNode_Tuple& node) override
+ {
+ TRACE_FUNCTION_F("(...,)");
+ for( auto& val : node.m_vals ) {
+ this->context.add_ivars( val->m_res_type );
+ }
+
+ ::std::vector< ::HIR::TypeRef> tuple_tys;
+ for(const auto& val : node.m_vals ) {
+ // Can these coerce? Assuming not
+ tuple_tys.push_back( val->m_res_type.clone() );
+ }
+ this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef(mv$(tuple_tys)));
+
+ for( auto& val : node.m_vals ) {
+ val->visit( *this );
+ }
}
-
- // Cleanly equate into array (with coercions)
- // - Result type already set, just need to extract ivar
- const auto& inner_ty = *node.m_res_type.m_data.as_Array().inner;
- for( auto& val : node.m_vals ) {
- this->context.equate_types_coerce(node.span(), inner_ty, val);
+ void visit(::HIR::ExprNode_ArrayList& node) override
+ {
+ TRACE_FUNCTION_F("[...,]");
+ for( auto& val : node.m_vals ) {
+ this->context.add_ivars( val->m_res_type );
+ }
+
+ // Cleanly equate into array (with coercions)
+ // - Result type already set, just need to extract ivar
+ const auto& inner_ty = *node.m_res_type.m_data.as_Array().inner;
+ for( auto& val : node.m_vals ) {
+ this->context.equate_types_coerce(node.span(), inner_ty, val);
+ }
+
+ for( auto& val : node.m_vals ) {
+ val->visit( *this );
+ }
}
-
- for( auto& val : node.m_vals ) {
- val->visit( *this );
+ void visit(::HIR::ExprNode_ArraySized& node) override
+ {
+ TRACE_FUNCTION_F("[...; "<<node.m_size_val<<"]");
+ this->context.add_ivars( node.m_val->m_res_type );
+ this->context.add_ivars( node.m_size->m_res_type );
+
+ // Create result type (can't be known until after const expansion)
+ // - Should it be created in const expansion?
+ auto ty = ::HIR::TypeRef::new_array( ::HIR::TypeRef(), node.m_size_val );
+ this->context.add_ivars(ty);
+ this->context.equate_types(node.span(), node.m_res_type, ty);
+ // Equate with coercions
+ const auto& inner_ty = *ty.m_data.as_Array().inner;
+ this->context.equate_types_coerce(node.span(), inner_ty, node.m_val);
+ this->context.equate_types(node.span(), ::HIR::TypeRef(::HIR::CoreType::Usize), node.m_size->m_res_type);
+
+ node.m_val->visit( *this );
+ node.m_size->visit( *this );
}
- }
- void visit(::HIR::ExprNode_ArraySized& node) override
- {
- TRACE_FUNCTION_F("[...; "<<node.m_size_val<<"]");
- this->context.add_ivars( node.m_val->m_res_type );
- this->context.add_ivars( node.m_size->m_res_type );
-
- // Create result type (can't be known until after const expansion)
- // - Should it be created in const expansion?
- auto ty = ::HIR::TypeRef::new_array( ::HIR::TypeRef(), node.m_size_val );
- this->context.add_ivars(ty);
- this->context.equate_types(node.span(), node.m_res_type, ty);
- // Equate with coercions
- const auto& inner_ty = *ty.m_data.as_Array().inner;
- this->context.equate_types_coerce(node.span(), inner_ty, node.m_val);
- this->context.equate_types(node.span(), ::HIR::TypeRef(::HIR::CoreType::Usize), node.m_size->m_res_type);
- node.m_val->visit( *this );
- node.m_size->visit( *this );
- }
-
- void visit(::HIR::ExprNode_Literal& node) override
- {
- TU_MATCH(::HIR::ExprNode_Literal::Data, (node.m_data), (e),
- (Integer,
- DEBUG(" (: " << e.m_type << " = " << e.m_value << ")");
- ),
- (Float,
- DEBUG(" (: " << e.m_type << " = " << e.m_value << ")");
- ),
- (Boolean,
- DEBUG(" ( " << (e ? "true" : "false") << ")");
- ),
- (String,
- ),
- (ByteString,
+ void visit(::HIR::ExprNode_Literal& node) override
+ {
+ TU_MATCH(::HIR::ExprNode_Literal::Data, (node.m_data), (e),
+ (Integer,
+ DEBUG(" (: " << e.m_type << " = " << e.m_value << ")");
+ ),
+ (Float,
+ DEBUG(" (: " << e.m_type << " = " << e.m_value << ")");
+ ),
+ (Boolean,
+ DEBUG(" ( " << (e ? "true" : "false") << ")");
+ ),
+ (String,
+ ),
+ (ByteString,
+ )
)
- )
- }
- void visit(::HIR::ExprNode_PathValue& node) override
- {
- const auto& sp = node.span();
- TRACE_FUNCTION_F(node.m_path);
-
- this->add_ivars_path(node.span(), node.m_path);
-
- TU_MATCH(::HIR::Path::Data, (node.m_path.m_data), (e),
- (Generic,
- switch(node.m_target) {
- case ::HIR::ExprNode_PathValue::UNKNOWN:
- BUG(sp, "Unknown target PathValue encountered with Generic path");
- case ::HIR::ExprNode_PathValue::FUNCTION: {
- const auto& f = this->context.m_crate.get_function_by_path(sp, e.m_path);
+ }
+ void visit(::HIR::ExprNode_PathValue& node) override
+ {
+ const auto& sp = node.span();
+ TRACE_FUNCTION_F(node.m_path);
+
+ this->add_ivars_path(node.span(), node.m_path);
+
+ TU_MATCH(::HIR::Path::Data, (node.m_path.m_data), (e),
+ (Generic,
+ switch(node.m_target) {
+ case ::HIR::ExprNode_PathValue::UNKNOWN:
+ BUG(sp, "Unknown target PathValue encountered with Generic path");
+ case ::HIR::ExprNode_PathValue::FUNCTION: {
+ const auto& f = this->context.m_crate.get_function_by_path(sp, e.m_path);
+ ::HIR::FunctionType ft {
+ f.m_unsafe,
+ f.m_abi,
+ box$( f.m_return.clone() ),
+ {}
+ };
+ for( const auto& arg : f.m_args )
+ ft.m_arg_types.push_back( arg.second.clone() );
+ auto ty = ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Function(mv$(ft)) );
+ this->context.equate_types(sp, node.m_res_type, ty);
+ } break;
+ case ::HIR::ExprNode_PathValue::STATIC: {
+ const auto& v = this->context.m_crate.get_static_by_path(sp, e.m_path);
+ DEBUG("static v.m_type = " << v.m_type);
+ this->context.equate_types(sp, node.m_res_type, v.m_type);
+ } break;
+ case ::HIR::ExprNode_PathValue::CONSTANT: {
+ const auto& v = this->context.m_crate.get_constant_by_path(sp, e.m_path);
+ DEBUG("const"<<v.m_params.fmt_args()<<" v.m_type = " << v.m_type);
+ if( v.m_params.m_types.size() > 0 ) {
+ TODO(sp, "Support generic constants in typeck");
+ }
+ this->context.equate_types(sp, node.m_res_type, v.m_type);
+ } break;
+ }
+ ),
+ (UfcsUnknown,
+ BUG(sp, "Encountered UfcsUnknown");
+ ),
+ (UfcsKnown,
+ TODO(sp, "Look up associated constants/statics (trait)");
+ ),
+ (UfcsInherent,
+ // TODO: If ivars are valid within the type of this UFCS, then resolution has to be deferred until iteration
+ // - If they're not valid, then resolution can be done here.
+ TODO(sp, "Handle associated constants/functions in type - Can the type be infer?");
+
+ #if 0
+ // - Locate function (and impl block)
+ const ::HIR::Function* fcn_ptr = nullptr;
+ const ::HIR::TypeImpl* impl_ptr = nullptr;
+ this->context.m_crate.find_type_impls(*e.type, [&](const auto& ty)->const auto& {
+ if( ty.m_data.is_Infer() )
+ return this->context.get_type(ty);
+ else
+ return ty;
+ },
+ [&](const auto& impl) {
+ DEBUG("- impl" << impl.m_params.fmt_args() << " " << impl.m_type);
+ auto it = impl.m_methods.find(e.item);
+ if( it == impl.m_methods.end() )
+ return false;
+ fcn_ptr = &it->second;
+ impl_ptr = &impl;
+ return true;
+ });
+ if( !fcn_ptr ) {
+ ERROR(sp, E0000, "Failed to locate function " << path);
+ }
+ assert(impl_ptr);
+ fix_param_count(sp, this->context, path, fcn_ptr->m_params, e.params);
+
+ // If the impl block has parameters, figure out what types they map to
+ // - The function params are already mapped (from fix_param_count)
+ ::HIR::PathParams impl_params;
+ if( impl_ptr->m_params.m_types.size() > 0 ) {
+ impl_params.m_types.resize( impl_ptr->m_params.m_types.size() );
+ impl_ptr->m_type.match_generics(sp, *e.type, this->context.callback_resolve_infer(), [&](auto idx, const auto& ty) {
+ assert( idx < impl_params.m_types.size() );
+ impl_params.m_types[idx] = ty.clone();
+ });
+ for(const auto& ty : impl_params.m_types)
+ assert( !( ty.m_data.is_Infer() && ty.m_data.as_Infer().index == ~0u) );
+ }
+
+ // Create monomorphise callback
+ const auto& fcn_params = e.params;
+ auto monomorph_cb = [&](const auto& gt)->const auto& {
+ const auto& ge = gt.m_data.as_Generic();
+ if( ge.binding == 0xFFFF ) {
+ return this->context.get_type(*e.type);
+ }
+ else if( ge.binding < 256 ) {
+ auto idx = ge.binding;
+ if( idx >= impl_params.m_types.size() ) {
+ BUG(sp, "Generic param out of input range - " << idx << " '" << ge.name << "' >= " << impl_params.m_types.size());
+ }
+ return this->context.get_type(impl_params.m_types[idx]);
+ }
+ else if( ge.binding < 512 ) {
+ auto idx = ge.binding - 256;
+ if( idx >= fcn_params.m_types.size() ) {
+ BUG(sp, "Generic param out of input range - " << idx << " '" << ge.name << "' >= " << fcn_params.m_types.size());
+ }
+ return this->context.get_type(fcn_params.m_types[idx]);
+ }
+ else {
+ BUG(sp, "Generic bounding out of total range");
+ }
+ };
+
::HIR::FunctionType ft {
- f.m_unsafe,
- f.m_abi,
- box$( f.m_return.clone() ),
+ fcn_ptr->m_unsafe, fcn_ptr->m_abi,
+ box$( monomorphise_type_with(sp, fcn_ptr->m_return, monomorph_cb) ),
{}
};
- for( const auto& arg : f.m_args )
- ft.m_arg_types.push_back( arg.second.clone() );
- auto ty = ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Function(mv$(ft)) );
- this->context.equate_types(sp, node.m_res_type, ty);
- } break;
- case ::HIR::ExprNode_PathValue::STATIC: {
- const auto& v = this->context.m_crate.get_static_by_path(sp, e.m_path);
- DEBUG("static v.m_type = " << v.m_type);
- this->context.equate_types(sp, node.m_res_type, v.m_type);
- } break;
- case ::HIR::ExprNode_PathValue::CONSTANT: {
- const auto& v = this->context.m_crate.get_constant_by_path(sp, e.m_path);
- DEBUG("const"<<v.m_params.fmt_args()<<" v.m_type = " << v.m_type);
- if( v.m_params.m_types.size() > 0 ) {
- TODO(sp, "Support generic constants in typeck");
- }
- this->context.equate_types(sp, node.m_res_type, v.m_type);
- } break;
- }
- ),
- (UfcsUnknown,
- BUG(sp, "Encountered UfcsUnknown");
- ),
- (UfcsKnown,
- TODO(sp, "Look up associated constants/statics (trait)");
- ),
- (UfcsInherent,
- // TODO: If ivars are valid within the type of this UFCS, then resolution has to be deferred until iteration
- // - If they're not valid, then resolution can be done here.
- TODO(sp, "Handle associated constants/functions in type - Can the type be infer?");
+ for(const auto& arg : fcn_ptr->m_args)
+ ft.m_arg_types.push_back( monomorphise_type_with(sp, arg.second, monomorph_cb) );
+ auto ty = ::HIR::TypeRef(mv$(ft));
+
+ this->context.equate_types(node.span(), node.m_res_type, ty);
+ #endif
+ )
+ )
+ }
+ void visit(::HIR::ExprNode_Variable& node) override
+ {
+ TRACE_FUNCTION_F(node.m_name << "{" << node.m_slot << "}");
- #if 0
- // - Locate function (and impl block)
- const ::HIR::Function* fcn_ptr = nullptr;
- const ::HIR::TypeImpl* impl_ptr = nullptr;
- this->context.m_crate.find_type_impls(*e.type, [&](const auto& ty)->const auto& {
- if( ty.m_data.is_Infer() )
- return this->context.get_type(ty);
- else
- return ty;
- },
- [&](const auto& impl) {
- DEBUG("- impl" << impl.m_params.fmt_args() << " " << impl.m_type);
- auto it = impl.m_methods.find(e.item);
- if( it == impl.m_methods.end() )
- return false;
- fcn_ptr = &it->second;
- impl_ptr = &impl;
- return true;
- });
- if( !fcn_ptr ) {
- ERROR(sp, E0000, "Failed to locate function " << path);
+ this->context.equate_types(node.span(), node.m_res_type, this->context.get_var(node.span(), node.m_slot));
+ }
+
+ void visit(::HIR::ExprNode_Closure& node) override
+ {
+ TRACE_FUNCTION_F("|...| ...");
+ for(auto& arg : node.m_args) {
+ this->context.add_ivars( arg.second );
+ this->context.add_binding( node.span(), arg.first, arg.second );
}
- assert(impl_ptr);
- fix_param_count(sp, this->context, path, fcn_ptr->m_params, e.params);
+ this->context.add_ivars( node.m_return );
+ this->context.add_ivars( node.m_code->m_res_type );
- // If the impl block has parameters, figure out what types they map to
- // - The function params are already mapped (from fix_param_count)
- ::HIR::PathParams impl_params;
- if( impl_ptr->m_params.m_types.size() > 0 ) {
- impl_params.m_types.resize( impl_ptr->m_params.m_types.size() );
- impl_ptr->m_type.match_generics(sp, *e.type, this->context.callback_resolve_infer(), [&](auto idx, const auto& ty) {
- assert( idx < impl_params.m_types.size() );
- impl_params.m_types[idx] = ty.clone();
- });
- for(const auto& ty : impl_params.m_types)
- assert( !( ty.m_data.is_Infer() && ty.m_data.as_Infer().index == ~0u) );
+ // Closure result type
+ ::HIR::TypeRef::Data::Data_Closure ty_data;
+ for(auto& arg : node.m_args) {
+ ty_data.m_arg_types.push_back( arg.second.clone() );
}
+ ty_data.m_rettype = box$( node.m_return.clone() );
+ this->context.equate_types( node.span(), node.m_res_type, ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Closure(mv$(ty_data)) ) );
+
+ this->context.equate_types_coerce( node.span(), node.m_return, node.m_code );
- // Create monomorphise callback
- const auto& fcn_params = e.params;
- auto monomorph_cb = [&](const auto& gt)->const auto& {
- const auto& ge = gt.m_data.as_Generic();
- if( ge.binding == 0xFFFF ) {
- return this->context.get_type(*e.type);
- }
- else if( ge.binding < 256 ) {
- auto idx = ge.binding;
- if( idx >= impl_params.m_types.size() ) {
- BUG(sp, "Generic param out of input range - " << idx << " '" << ge.name << "' >= " << impl_params.m_types.size());
- }
- return this->context.get_type(impl_params.m_types[idx]);
- }
- else if( ge.binding < 512 ) {
- auto idx = ge.binding - 256;
- if( idx >= fcn_params.m_types.size() ) {
- BUG(sp, "Generic param out of input range - " << idx << " '" << ge.name << "' >= " << fcn_params.m_types.size());
- }
- return this->context.get_type(fcn_params.m_types[idx]);
- }
- else {
- BUG(sp, "Generic bounding out of total range");
- }
- };
-
- ::HIR::FunctionType ft {
- fcn_ptr->m_unsafe, fcn_ptr->m_abi,
- box$( monomorphise_type_with(sp, fcn_ptr->m_return, monomorph_cb) ),
- {}
- };
- for(const auto& arg : fcn_ptr->m_args)
- ft.m_arg_types.push_back( monomorphise_type_with(sp, arg.second, monomorph_cb) );
- auto ty = ::HIR::TypeRef(mv$(ft));
-
- this->context.equate_types(node.span(), node.m_res_type, ty);
- #endif
- )
- )
- }
- void visit(::HIR::ExprNode_Variable& node) override
- {
- TRACE_FUNCTION_F(node.m_name << "{" << node.m_slot << "}");
+ node.m_code->visit( *this );
+ }
- this->context.equate_types(node.span(), node.m_res_type, this->context.get_var(node.span(), node.m_slot));
- }
-
- void visit(::HIR::ExprNode_Closure& node) override
+ private:
+ void push_traits(const ::HIR::t_trait_list& list) {
+ this->m_traits.insert( this->m_traits.end(), list.begin(), list.end() );
+ }
+ void pop_traits(const ::HIR::t_trait_list& list) {
+ this->m_traits.erase( this->m_traits.end() - list.size(), this->m_traits.end() );
+ }
+ };
+
+
+ class ExprVisitor_Revisit:
+ public ::HIR::ExprVisitor
{
- TRACE_FUNCTION_F("|...| ...");
- for(auto& arg : node.m_args) {
- this->context.add_ivars( arg.second );
- this->context.add_binding( node.span(), arg.first, arg.second );
+ Context& context;
+ bool m_completed;
+ public:
+ ExprVisitor_Revisit(Context& context):
+ context(context),
+ m_completed(false)
+ {}
+
+ bool node_completed() const {
+ return m_completed;
+ }
+
+ void visit(::HIR::ExprNode_Block& node) override {
+ no_revisit(node);
+ }
+ void visit(::HIR::ExprNode_Return& node) override {
+ no_revisit(node);
+ }
+ void visit(::HIR::ExprNode_Let& node) override {
+ no_revisit(node);
+ }
+ void visit(::HIR::ExprNode_Loop& node) override {
+ no_revisit(node);
+ }
+ void visit(::HIR::ExprNode_LoopControl& node) override {
+ no_revisit(node);
+ }
+ void visit(::HIR::ExprNode_Match& node) override {
+ no_revisit(node);
+ }
+ void visit(::HIR::ExprNode_If& node) override {
+ no_revisit(node);
+ }
+
+ void visit(::HIR::ExprNode_Assign& node) override {
+ no_revisit(node);
+ }
+ void visit(::HIR::ExprNode_BinOp& node) override {
+ no_revisit(node);
+ }
+ void visit(::HIR::ExprNode_UniOp& node) override {
+ no_revisit(node);
+ }
+ void visit(::HIR::ExprNode_Cast& node) override {
+ no_revisit(node);
+ }
+ void visit(::HIR::ExprNode_Unsize& node) override {
+ no_revisit(node);
+ }
+ void visit(::HIR::ExprNode_Index& node) override {
+ no_revisit(node);
+ }
+ void visit(::HIR::ExprNode_Deref& node) override {
+ no_revisit(node);
}
- this->context.add_ivars( node.m_return );
- this->context.add_ivars( node.m_code->m_res_type );
- // Closure result type
- ::HIR::TypeRef::Data::Data_Closure ty_data;
- for(auto& arg : node.m_args) {
- ty_data.m_arg_types.push_back( arg.second.clone() );
+ void visit(::HIR::ExprNode_TupleVariant& node) override {
+ no_revisit(node);
+ }
+ void visit(::HIR::ExprNode_CallPath& node) override {
+ no_revisit(node);
+ }
+ void visit(::HIR::ExprNode_CallValue& node) override {
+ // TODO:
+ TODO(node.span(), "ExprNode_CallValue - revisit");
+ }
+ void visit(::HIR::ExprNode_CallMethod& node) override {
+ // TODO:
+ TODO(node.span(), "ExprNode_CallMethod - revisit");
+ }
+ void visit(::HIR::ExprNode_Field& node) override {
+ // TODO:
+ TODO(node.span(), "ExprNode_Field - revisit");
}
- ty_data.m_rettype = box$( node.m_return.clone() );
- this->context.equate_types( node.span(), node.m_res_type, ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Closure(mv$(ty_data)) ) );
- this->context.equate_types_coerce( node.span(), node.m_return, node.m_code );
+ void visit(::HIR::ExprNode_Literal& node) override {
+ no_revisit(node);
+ }
+ void visit(::HIR::ExprNode_UnitVariant& node) override {
+ no_revisit(node);
+ }
+ void visit(::HIR::ExprNode_PathValue& node) override {
+ no_revisit(node);
+ }
+ void visit(::HIR::ExprNode_Variable& node) override {
+ no_revisit(node);
+ }
- node.m_code->visit( *this );
- }
-
-private:
- void push_traits(const ::HIR::t_trait_list& list) {
- this->m_traits.insert( this->m_traits.end(), list.begin(), list.end() );
- }
- void pop_traits(const ::HIR::t_trait_list& list) {
- this->m_traits.erase( this->m_traits.end() - list.size(), this->m_traits.end() );
- }
-};
+ void visit(::HIR::ExprNode_StructLiteral& node) override {
+ no_revisit(node);
+ }
+ void visit(::HIR::ExprNode_Tuple& node) override {
+ no_revisit(node);
+ }
+ void visit(::HIR::ExprNode_ArrayList& node) override {
+ no_revisit(node);
+ }
+ void visit(::HIR::ExprNode_ArraySized& node) override {
+ no_revisit(node);
+ }
+
+ void visit(::HIR::ExprNode_Closure& node) override {
+ no_revisit(node);
+ }
+ private:
+ void no_revisit(::HIR::ExprNode& node) {
+ BUG(node.span(), "Node revisit unexpected - " << typeid(node).name());
+ }
+ };
+}
void Context::dump() const {
@@ -1577,17 +1693,41 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR:
context.add_binding( Span(), arg.first, arg.second );
}
- ExprVisitor_Enum visitor(context, ms.m_traits, result_type);
- context.add_ivars(expr->m_res_type);
- expr->visit(visitor);
-
- context.equate_types(expr->span(), result_type, expr->m_res_type);
+ // - Build up ruleset from node tree
+ {
+ ExprVisitor_Enum visitor(context, ms.m_traits, result_type);
+ context.add_ivars(expr->m_res_type);
+ expr->visit(visitor);
+
+ context.equate_types(expr->span(), result_type, expr->m_res_type);
+ }
context.dump();
- while( context.take_changed() && context.has_rules() )
+
+ const unsigned int MAX_ITERATIONS = 100;
+ unsigned int count = 0;
+ while( context.take_changed() && context.has_rules() && count < MAX_ITERATIONS )
{
- // TODO: Run
+ // 1. Check coercions for ones that cannot coerce due to RHS type (e.g. `str` which doesn't coerce to anything)
+ // 2. (???) Locate coercions that cannot coerce (due to single option)
+ // 3. Check associated type rules
+ // - Find trait impl
+ // 4. Revisit nodes that require revisiting
+ for( auto it = context.to_visit.begin(); it != context.to_visit.end(); )
+ {
+ ExprVisitor_Revisit visitor { context };
+ (*it)->visit( visitor );
+ // - If the node is completed, remove it
+ if( visitor.node_completed() ) {
+ it = context.to_visit.erase(it);
+ }
+ else {
+ ++ it;
+ }
+ }
+
TODO(Span(), "Typecheck_Code_CS");
+ count ++;
}
}