diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/expand/derive.cpp | 2 | ||||
-rw-r--r-- | src/hir/from_ast.cpp | 20 | ||||
-rw-r--r-- | src/hir_typeck/expr.cpp | 93 | ||||
-rw-r--r-- | src/hir_typeck/expr.hpp | 8 | ||||
-rw-r--r-- | src/hir_typeck/expr_context.cpp | 28 | ||||
-rw-r--r-- | src/hir_typeck/outer.cpp | 2 | ||||
-rw-r--r-- | src/resolve/absolute.cpp | 4 |
7 files changed, 128 insertions, 29 deletions
diff --git a/src/expand/derive.cpp b/src/expand/derive.cpp index fdb8088b..aec3de51 100644 --- a/src/expand/derive.cpp +++ b/src/expand/derive.cpp @@ -112,7 +112,7 @@ public: AST::GenericParams(), ret_type, vec$( - ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef(TypeRef::TagReference(), sp, false, TypeRef("Self")) ), + ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef(TypeRef::TagReference(), sp, false, TypeRef("Self", 0xFFFF)) ), ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "f"), f_type ) ) ); diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp index 4b52cd22..d7f95d81 100644 --- a/src/hir/from_ast.cpp +++ b/src/hir/from_ast.cpp @@ -733,20 +733,34 @@ const ::HIR::SimplePath path_Sized = ::HIR::SimplePath("", {"marker", "Sized"}); } ::HIR::Trait LowerHIR_Trait(::HIR::SimplePath trait_path, const ::AST::Trait& f) { - ::std::string lifetime; + bool trait_reqires_sized = false; + auto params = LowerHIR_GenericParams(f.params(), &trait_reqires_sized); + ::std::string lifetime; ::std::vector< ::HIR::GenericPath> supertraits; for(const auto& st : f.supertraits()) { if( st.ent.is_valid() ) { supertraits.push_back( LowerHIR_GenericPath(st.sp, st.ent) ); + const auto& atype_bounds = st.ent.nodes().back().args().m_assoc; + for(const auto& atype : atype_bounds) + { + params.m_bounds.push_back( ::HIR::GenericBound::make_TypeEquality({ + ::HIR::TypeRef(::HIR::Path(::HIR::Path::Data::make_UfcsKnown({ + box$( ::HIR::TypeRef("Self",0xFFFF) ), + supertraits.back().clone(), + atype.first, + {} + }))), + LowerHIR_Type(atype.second) + }) ); + } } else { lifetime = "static"; } } - bool trait_reqires_sized = false; ::HIR::Trait rv { - LowerHIR_GenericParams(f.params(), &trait_reqires_sized), + mv$(params), mv$(lifetime), mv$(supertraits) }; diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp index 269d0850..a41dfe93 100644 --- a/src/hir_typeck/expr.cpp +++ b/src/hir_typeck/expr.cpp @@ -353,6 +353,7 @@ namespace typeck { ::HIR::ExprVisitorDef::visit(node); this->context.apply_equality( node.span(), node.m_res_type, ::HIR::TypeRef::new_array(node.m_val->m_res_type.clone(), node.m_size_val) ); + this->context.apply_equality( node.span(), node.m_size->m_res_type, ::HIR::TypeRef(::HIR::CoreType::Usize) ); } void visit(::HIR::ExprNode_Tuple& node) override { @@ -557,6 +558,7 @@ namespace typeck { // - BinOp: Look for overload or primitive void visit(::HIR::ExprNode_BinOp& node) override { + const auto& sp = node.span(); ::HIR::ExprVisitorDef::visit(node); const auto& ty_left = this->context.get_type(node.m_left->m_res_type ); const auto& ty_right = this->context.get_type(node.m_right->m_res_type); @@ -693,15 +695,40 @@ namespace typeck { // Search for ops trait impl const ::HIR::TraitImpl* impl_ptr = nullptr; + ::HIR::TypeRef possible_right_type; unsigned int count = 0; const auto& ops_trait = this->context.m_crate.get_lang_item_path(node.span(), item_name); - DEBUG("Searching for impl " << ops_trait << "< " << ty_left << "> for " << ty_right); - bool found_exact = this->context.m_crate.find_trait_impls(ops_trait, ty_left, this->context.callback_resolve_infer(), + DEBUG("Searching for impl " << ops_trait << "< " << ty_right << "> for " << ty_left); + bool found_bound = this->context.find_trait_impls_bound(sp, ops_trait, ty_left, + [&](const auto& args) { + assert(args.m_types.size() == 1); + const auto& arg_type = args.m_types[0]; + // TODO: if arg_type mentions Self? + auto cmp = arg_type.compare_with_paceholders(node.span(), ty_right, this->context.callback_resolve_infer()); + if( cmp == ::HIR::Compare::Unequal ) { + DEBUG("- (fail) bounded impl " << ops_trait << "<" << arg_type << ">"); + return false; + } + count += 1; + if( cmp == ::HIR::Compare::Equal ) { + return true; + } + else { + if( possible_right_type == ::HIR::TypeRef() ) { + DEBUG("- Set possibility for " << ty_right << " - " << arg_type); + possible_right_type = arg_type.clone(); + } + + return false; + } + }); + // - Only set found_exact if either found_bound returned true, XOR this returns true + bool found_exact = found_bound ^ this->context.m_crate.find_trait_impls(ops_trait, ty_left, this->context.callback_resolve_infer(), [&](const auto& impl) { - // TODO: Check how concretely the types matched assert( impl.m_trait_args.m_types.size() == 1 ); const auto& arg_type = impl.m_trait_args.m_types[0]; + // TODO: Abstract the below code into a method on TypecheckContext // 1. Match arg_type with ty_right into impl block params bool fail = false; ::std::vector< const ::HIR::TypeRef*> impl_params; @@ -725,7 +752,8 @@ namespace typeck { DEBUG("- (fail) impl" << impl.m_params.fmt_args() << " " << ops_trait << "<" << arg_type << "> for " << impl.m_type); return false; } - // TODO: handle a generic somehow + + // TODO: handle a generic righthand type by using the above parameters if( monomorphise_type_needed(arg_type) ) { return true; //TODO(node.span(), "Compare ops trait type when it contains generics - " << arg_type << " == " << ty_right); @@ -742,23 +770,47 @@ namespace typeck { } else { DEBUG("Operator impl fuzzy match - '"<<item_name<<"' - " << arg_type << " == " << ty_right); + if( possible_right_type == ::HIR::TypeRef() ) { + DEBUG("- Set possibility for " << ty_right << " - " << arg_type); + possible_right_type = arg_type.clone(); + } return false; } } ); // If there wasn't an exact match, BUT there was one partial match - assume the partial match is what we want if( !found_exact && count == 1 ) { - assert(impl_ptr); - this->context.apply_equality(node.span(), impl_ptr->m_trait_args.m_types[0], ty_right); + assert( possible_right_type != ::HIR::TypeRef() ); + this->context.apply_equality(node.span(), possible_right_type, ty_right); } - if( impl_ptr ) { + if( count > 0 ) { + // - If the output type is variable if( has_output ) { - const auto& type = impl_ptr->m_types.at("Output"); - if( monomorphise_type_needed(type) ) { - TODO(node.span(), "BinOp output = " << type); + // - If an impl block was found + if( impl_ptr ) + { + const auto& type = impl_ptr->m_types.at("Output"); + if( monomorphise_type_needed(type) ) { + TODO(node.span(), "BinOp output = " << type); + } + else { + this->context.apply_equality(node.span(), node.m_res_type, type); + } } - else { + else + { + const auto& ty_right = this->context.get_type(node.m_right->m_res_type); + + ::HIR::PathParams tpp; + DEBUG("- ty_right = " << ty_right); + tpp.m_types.push_back( ty_right.clone() ); + auto type = ::HIR::TypeRef( ::HIR::Path::Data::make_UfcsKnown({ + box$( ty_left.clone() ), + ::HIR::GenericPath( ops_trait, mv$(tpp) ), + "Output", + {} + }) ); this->context.apply_equality(node.span(), node.m_res_type, type); } } @@ -910,9 +962,13 @@ namespace typeck { void visit(::HIR::ExprNode_Deref& node) override { const auto& ty = this->context.get_type( node.m_value->m_res_type ); + TRACE_FUNCTION_FR("Deref *{" << ty << "}", this->context.get_type(node.m_res_type)); TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Borrow, e, this->context.apply_equality(node.span(), node.m_res_type, *e.inner); ) + else TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, e, + this->context.apply_equality(node.span(), node.m_res_type, ::HIR::TypeRef::new_slice(e.inner->clone())); + ) else { // TODO: Search for Deref impl } @@ -1571,10 +1627,12 @@ namespace typeck { context(context) { } - void visit_node(::HIR::ExprNode& node) override { - DEBUG(typeid(node).name() << " : " << node.m_res_type); - this->check_type_resolved(node.span(), node.m_res_type, node.m_res_type); - DEBUG(typeid(node).name() << " : = " << node.m_res_type); + void visit_node_ptr(::HIR::ExprNodeP& node) override { + const char* node_ty = typeid(*node).name(); + TRACE_FUNCTION_FR(node_ty << " : " << node->m_res_type, node_ty); + this->check_type_resolved(node->span(), node->m_res_type, node->m_res_type); + DEBUG(node_ty << " : = " << node->m_res_type); + ::HIR::ExprVisitorDef::visit_node_ptr(node); } private: @@ -1660,14 +1718,17 @@ void Typecheck_Code(typeck::TypecheckContext context, const ::HIR::TypeRef& resu unsigned int count = 0; do { count += 1; + assert(count < 1000); DEBUG("==== PASS " << count << " ===="); visitor.visit_node_ptr(root_ptr); - assert(count < 1000); + context.compact_ivars(); } while( context.take_changed() ); + DEBUG("==== STOPPED: " << count << " passes ===="); } // 3. Check that there's no unresolved types left expr = ::HIR::ExprPtr( mv$(root_ptr) ); + context.compact_ivars(); context.dump(); { DEBUG("==== VALIDATE ===="); diff --git a/src/hir_typeck/expr.hpp b/src/hir_typeck/expr.hpp index 83469264..5fa558a3 100644 --- a/src/hir_typeck/expr.hpp +++ b/src/hir_typeck/expr.hpp @@ -80,6 +80,8 @@ public: m_has_changed = true; } + void compact_ivars(); + /// Adds a local variable binding (type is mutable so it can be inferred if required) void add_local(unsigned int index, const ::std::string& name, ::HIR::TypeRef type); @@ -127,7 +129,11 @@ public: /// Searches for a trait impl that matches the provided trait name and type bool find_trait_impls(const ::HIR::SimplePath& trait, const ::HIR::TypeRef& type, ::std::function<bool(const ::HIR::PathParams&)> callback) const; /// Locate a named trait in the provied trait (either itself or as a parent trait) - bool find_named_trait_in_trait(const Span& sp, const ::HIR::SimplePath& des, const ::HIR::Trait& trait_ptr, const ::HIR::PathParams& pp, ::std::function<bool(const ::HIR::PathParams&)> callback) const; + bool find_named_trait_in_trait(const Span& sp, + const ::HIR::SimplePath& des, const ::HIR::Trait& trait_ptr, + const ::HIR::PathParams& pp, const ::HIR::TypeRef& self_type, + ::std::function<bool(const ::HIR::PathParams&)> callback + ) const; /// Search for a trait implementation in current bounds bool find_trait_impls_bound(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::TypeRef& type, ::std::function<bool(const ::HIR::PathParams&)> callback) const; /// Search for a trait implementation in the crate diff --git a/src/hir_typeck/expr_context.cpp b/src/hir_typeck/expr_context.cpp index 13e52674..eea61da7 100644 --- a/src/hir_typeck/expr_context.cpp +++ b/src/hir_typeck/expr_context.cpp @@ -23,6 +23,20 @@ void typeck::TypecheckContext::dump() const i ++; } } +void typeck::TypecheckContext::compact_ivars() +{ + TRACE_FUNCTION; + unsigned int i = 0; + for(auto& v : m_ivars) + { + if( !v.is_alias() ) { + auto nt = this->expand_associated_types(Span(), v.type->clone()); + DEBUG("- " << i << " " << *v.type << " -> " << nt); + *v.type = mv$(nt); + } + i ++; + } +} void typeck::TypecheckContext::add_local(unsigned int index, const ::std::string& name, ::HIR::TypeRef type) { @@ -1037,7 +1051,12 @@ bool typeck::TypecheckContext::find_trait_impls(const ::HIR::SimplePath& trait, TU_MATCH(::HIR::TypeRef::Data, (input.m_data), (e), (Infer, auto& ty = this->get_type(input); - return ty.clone(); + if( ty != input ) { + return expand_associated_types(sp, ty.clone()); + } + else { + return input; + } ), (Diverge, ), @@ -1297,17 +1316,18 @@ bool typeck::TypecheckContext::find_trait_impls(const ::HIR::SimplePath& trait, // ------------------------------------------------------------------------------------------------------------------- bool typeck::TypecheckContext::find_named_trait_in_trait(const Span& sp, const ::HIR::SimplePath& des, const ::HIR::Trait& trait_ptr, - const ::HIR::PathParams& pp, + const ::HIR::PathParams& pp, const ::HIR::TypeRef& target_type, ::std::function<bool(const ::HIR::PathParams&)> callback ) const { + TRACE_FUNCTION_F(des << pp); assert( pp.m_types.size() == trait_ptr.m_params.m_types.size() ); for( const auto& pt : trait_ptr.m_parent_traits ) { auto pt_pp = monomorphise_path_params_with(Span(), pt.m_params.clone(), [&](const auto& gt)->const auto& { const auto& ge = gt.m_data.as_Generic(); if( ge.binding == 0xFFFF ) { - return gt; + return target_type; } else { if( ge.binding >= pp.m_types.size() ) @@ -1335,7 +1355,7 @@ bool typeck::TypecheckContext::find_trait_impls_bound(const Span& sp, const ::HI return true; } } - if( this->find_named_trait_in_trait(sp, trait, *e.trait.m_trait_ptr, e.trait.m_path.m_params, callback) ) { + if( this->find_named_trait_in_trait(sp, trait, *e.trait.m_trait_ptr, e.trait.m_path.m_params, type, callback) ) { return true; } ) diff --git a/src/hir_typeck/outer.cpp b/src/hir_typeck/outer.cpp index 211f9007..8f33f120 100644 --- a/src/hir_typeck/outer.cpp +++ b/src/hir_typeck/outer.cpp @@ -266,7 +266,7 @@ namespace { void visit_trait(::HIR::PathChain p, ::HIR::Trait& item) override { - ::HIR::TypeRef tr { "Self", 0 }; + ::HIR::TypeRef tr { "Self", 0xFFFF }; m_self_types.push_back(&tr); ::HIR::Visitor::visit_trait(p, item); m_self_types.pop_back(); diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp index 84a6b191..2a5b5561 100644 --- a/src/resolve/absolute.cpp +++ b/src/resolve/absolute.cpp @@ -154,9 +154,7 @@ struct Context return e->clone(); } else { - auto rv = ::TypeRef("Self"); - rv.m_data.as_Generic().index = 0xFFFF; - return rv; + return ::TypeRef("Self", 0xFFFF); } ) ) |