diff options
author | John Hodge <tpg@mutabah.net> | 2016-07-03 22:25:30 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-07-03 22:25:30 +0800 |
commit | 744a4e5bb4b11c61e4588d08fd82fc47fc276632 (patch) | |
tree | 8901b5f088615879731bee9056dbb328fe6a46d1 /src | |
parent | edba362fab65f2aac3d21711a359e3456f93a829 (diff) | |
download | mrust-744a4e5bb4b11c61e4588d08fd82fc47fc276632.tar.gz |
HIR Typecheck CS - Methods and rough coercions
Diffstat (limited to 'src')
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 177 |
1 files changed, 165 insertions, 12 deletions
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 4fcc4468..0e960c07 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -28,7 +28,7 @@ struct Context struct Coercion { ::HIR::TypeRef left_ty; - ::HIR::ExprNodeP& right_node_ptr; + ::HIR::ExprNodeP* right_node_ptr; }; struct Associated { @@ -1126,7 +1126,22 @@ namespace { unsigned int deref_count = this->context.m_resolve.autoderef_find_method(node.span(), node.m_traits, ty, node.m_method, fcn_path); if( deref_count != ~0u ) { - TODO(node.span(), "ExprNode_CallMethod - Found method " << fcn_path); + visit_call_populate_cache(this->context, node.span(), fcn_path, node.m_cache); + assert( node.m_cache.m_arg_types.size() >= 1); + + if( node.m_args.size()+1 != node.m_cache.m_arg_types.size() - 1 ) { + ERROR(node.span(), E0000, "Incorrect number of arguments to " << fcn_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[1+i], node.m_args[i]); + } + this->context.equate_types(node.span(), node.m_res_type, node.m_cache.m_arg_types.back()); + + node.m_method_path = mv$(fcn_path); + this->m_completed = true; } } void visit(::HIR::ExprNode_Field& node) override { @@ -1175,7 +1190,7 @@ void Context::dump() const { m_ivars.dump(); DEBUG("CS Context - " << link_coerce.size() << " Coercions, " << link_assoc.size() << " associated, " << to_visit.size() << " nodes"); for(const auto& v : link_coerce) { - DEBUG(v.left_ty << " := " << &*v.right_node_ptr << " (" << v.right_node_ptr->m_res_type << ")"); + DEBUG(v.left_ty << " := " << &**v.right_node_ptr << " (" << (*v.right_node_ptr)->m_res_type << ")"); } for(const auto& v : link_assoc) { DEBUG(v.left_ty << " = " << "<" << v.impl_ty << " as " << v.trait << "<" << v.params << ">>::" << v.name); @@ -1556,7 +1571,7 @@ void Context::equate_types_coerce(const Span& sp, const ::HIR::TypeRef& l, ::HIR { // - Just record the equality this->link_coerce.push_back(Coercion { - l.clone(), node_ptr + l.clone(), &node_ptr }); } 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) @@ -1628,9 +1643,123 @@ void fix_param_count(const Span& sp, Context& context, const ::HIR::GenericPath& fix_param_count_(sp, context, path, param_defs, params); } +namespace { + bool check_coerce(Context& context, const Context::Coercion& v) { + const ::HIR::ExprNodeP& node_ptr = *v.right_node_ptr; + const auto& sp = node_ptr->span(); + const auto& ty = context.m_ivars.get_type(v.left_ty); + const auto& ty_r = context.m_ivars.get_type(node_ptr->m_res_type); + // 1. Check target type is a valid coercion + // - Otherwise - Force equality + TU_MATCH( ::HIR::TypeRef::Data, (ty.m_data), (e), + (Infer, + // TODO: If the righthand side cannot ever coerce, equate + ), + (Diverge, + return true; + ), + (Primitive, + // TODO: `str` is a coercion target? (but only via &str) + context.equate_types(sp, ty, node_ptr->m_res_type); + return true; + ), + (Path, + TODO(Span(), "check_coerce - Coercion to " << ty); + ), + (Generic, + TODO(Span(), "check_coerce - Coercion to " << ty); + ), + (TraitObject, + // TODO: Can bare trait objects coerce? + context.equate_types(sp, ty, node_ptr->m_res_type); + return true; + ), + (Array, + context.equate_types(sp, ty, node_ptr->m_res_type); + return true; + ), + (Slice, + context.equate_types(sp, ty, node_ptr->m_res_type); + return true; + ), + (Tuple, + context.equate_types(sp, ty, node_ptr->m_res_type); + return true; + ), + (Borrow, + // TODO: Borrows can have unsizing and deref coercions applied + ), + (Pointer, + // TODO: Pointers coerce from borrows and similar pointers + ), + (Function, + TODO(sp, "check_coerce - Coercion to " << ty); + ), + (Closure, + context.equate_types(sp, ty, node_ptr->m_res_type); + return true; + ) + ) + + TU_MATCH( ::HIR::TypeRef::Data, (ty_r.m_data), (e), + (Infer, + ), + (Diverge, + return true; + ), + (Primitive, + context.equate_types(sp, ty, node_ptr->m_res_type); + return true; + ), + (Path, + TODO(Span(), "check_coerce - Coercion from " << ty_r); + ), + (Generic, + TODO(Span(), "check_coerce - Coercion from " << ty_r); + ), + (TraitObject, + // TODO: Can bare trait objects coerce? + context.equate_types(sp, ty, node_ptr->m_res_type); + return true; + ), + (Array, + // TODO: Can raw arrays coerce to anything? + context.equate_types(sp, ty, node_ptr->m_res_type); + return true; + ), + (Slice, + context.equate_types(sp, ty, node_ptr->m_res_type); + return true; + ), + (Tuple, + context.equate_types(sp, ty, node_ptr->m_res_type); + return true; + ), + (Borrow, + // TODO: Borrows can have unsizing and deref coercions applied + ), + (Pointer, + // TODO: Pointers coerce from borrows and similar pointers + ), + (Function, + TODO(sp, "check_coerce - Coercion from " << ty_r); + ), + (Closure, + TODO(sp, "check_coerce - Coercion from " << ty_r); + ) + ) + + TODO(sp, "Typecheck_Code_CS - Coercion " << context.m_ivars.fmt_type(ty) << " from " << context.m_ivars.fmt_type(node_ptr->m_res_type)); + return false; + } +} + void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR::TypeRef& result_type, ::HIR::ExprPtr& expr) { + TRACE_FUNCTION; + + auto root_ptr = expr.into_unique(); Context context { ms.m_crate, ms.m_impl_generics, ms.m_item_generics }; for( auto& arg : args ) { @@ -1640,29 +1769,44 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR: // - 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.add_ivars(root_ptr->m_res_type); + root_ptr->visit(visitor); - context.equate_types(expr->span(), result_type, expr->m_res_type); + //context.equate_types(expr->span(), result_type, root_ptr->m_res_type); + context.equate_types_coerce(expr->span(), result_type, root_ptr); } - context.dump(); - const unsigned int MAX_ITERATIONS = 100; unsigned int count = 0; while( context.take_changed() && context.has_rules() && count < MAX_ITERATIONS ) { + DEBUG("=== PASS " << count << " ==="); + context.dump(); + // 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) + for(auto it = context.link_coerce.begin(); it != context.link_coerce.end(); ) { + if( check_coerce(context, *it) ) { + it = context.link_coerce.erase(it); + } + else { + ++ it; + } + } // 3. Check associated type rules - // - Find trait impl + for(const auto& v : context.link_assoc) { + // - Find trait impl + TODO(Span(), "Typecheck_Code_CS - Associated " << v.left_ty); + } // 4. Revisit nodes that require revisiting for( auto it = context.to_visit.begin(); it != context.to_visit.end(); ) { + ::HIR::ExprNode& node = **it; ExprVisitor_Revisit visitor { context }; - (*it)->visit( visitor ); + node.visit( visitor ); // - If the node is completed, remove it if( visitor.node_completed() ) { + DEBUG("- Completed " << &node << " - " << typeid(node).name()); it = context.to_visit.erase(it); } else { @@ -1670,8 +1814,17 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR: } } - TODO(Span(), "Typecheck_Code_CS"); count ++; } + + // - Validate typeck + expr = ::HIR::ExprPtr( mv$(root_ptr) ); + { + DEBUG("==== VALIDATE ===="); + context.dump(); + + //typeck::ExprVisitor_Apply visitor { context }; + //expr->visit( visitor ); + } } |