diff options
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 29 | ||||
-rw-r--r-- | src/hir_typeck/helpers.cpp | 127 | ||||
-rw-r--r-- | src/hir_typeck/helpers.hpp | 11 |
3 files changed, 88 insertions, 79 deletions
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index ec172d0a..981468e3 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -2626,16 +2626,21 @@ namespace { } // Using autoderef, locate this method on the type - ::HIR::Path fcn_path { ::HIR::SimplePath() }; - TraitResolution::AutoderefBorrow ad_borrow; // TODO: Obtain a list of avaliable methods at that level? // - If running in a mode after stablise (before defaults), fall // back to trait if the inherent is still ambigious. - unsigned int deref_count = this->context.m_resolve.autoderef_find_method(node.span(), node.m_traits, node.m_trait_param_ivars, ty, node.m_method, fcn_path, ad_borrow); - //::std::vector<::std::pair<TraitResolution::AutoderefBorrow, ::HIR::Path>> possible_methods; - //unsigned int deref_count = this->context.m_resolve.autoderef_find_method(node.span(), node.m_traits, node.m_trait_param_ivars, ty, node.m_method, possible_methods); + ::std::vector<::std::pair<TraitResolution::AutoderefBorrow, ::HIR::Path>> possible_methods; + unsigned int deref_count = this->context.m_resolve.autoderef_find_method(node.span(), node.m_traits, node.m_trait_param_ivars, ty, node.m_method, possible_methods); + try_again: if( deref_count != ~0u ) { + DEBUG("possible_methods = " << possible_methods); + if( possible_methods.empty() ) + { + ERROR(sp, E0000, "No applicable methods for {" << ty << "}." << node.m_method); + } + auto& ad_borrow = possible_methods.front().first; + auto& fcn_path = possible_methods.front().second; DEBUG("- deref_count = " << deref_count << ", fcn_path = " << fcn_path); node.m_method_path = mv$(fcn_path); @@ -2654,6 +2659,8 @@ namespace { //fix_param_count(sp, this->context, node.m_method_path, fcn.m_params, e.params); ) ) + + // TODO: If this is ambigious, and it's an inherent, and in fallback mode - fall down to the next trait method. if( !visit_call_populate_cache(this->context, node.span(), node.m_method_path, node.m_cache) ) { DEBUG("- AMBIGUOUS - Trying again later"); // Move the params back @@ -2667,6 +2674,18 @@ namespace { node.m_params = mv$(e.params); ) ) + if( this->m_is_fallback && fcn_path.m_data.is_UfcsInherent() ) + { + while( !possible_methods.empty() && possible_methods.front().second.m_data.is_UfcsInherent() ) + { + possible_methods.erase(possible_methods.begin()); + } + if( !possible_methods.empty() ) + { + DEBUG("Infference stall, try again with " << possible_methods.front().second); + goto try_again; + } + } return ; } DEBUG("> m_method_path = " << node.m_method_path); diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index 0c8b87c5..39324ea6 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -3464,8 +3464,10 @@ const ::HIR::TypeRef* TraitResolution::autoderef(const Span& sp, const ::HIR::Ty } } -//unsigned int TraitResolution::autoderef_find_method(const Span& sp, const HIR::t_trait_list& traits, const ::std::vector<unsigned>& ivars, const ::HIR::TypeRef& top_ty, const ::std::string& method_name, /* Out -> */::std::vector<AutoderefBorrow,::HIR::Path>& possibilities) const -unsigned int TraitResolution::autoderef_find_method(const Span& sp, const HIR::t_trait_list& traits, const ::std::vector<unsigned>& ivars, const ::HIR::TypeRef& top_ty, const ::std::string& method_name, /* Out -> */::HIR::Path& fcn_path, AutoderefBorrow& borrow) const +unsigned int TraitResolution::autoderef_find_method(const Span& sp, + const HIR::t_trait_list& traits, const ::std::vector<unsigned>& ivars, const ::HIR::TypeRef& top_ty, const ::std::string& method_name, + /* Out -> */::std::vector<::std::pair<AutoderefBorrow,::HIR::Path>>& possibilities + ) const { TRACE_FUNCTION_F("{" << top_ty << "}." << method_name); unsigned int deref_count = 0; @@ -3505,32 +3507,29 @@ unsigned int TraitResolution::autoderef_find_method(const Span& sp, const HIR::t DEBUG(deref_count << ": " << ty); // Non-referenced - if( this->find_method(sp, traits, ivars, ty, method_name, cur_access, fcn_path) ) + if( this->find_method(sp, traits, ivars, ty, method_name, cur_access, AutoderefBorrow::None, possibilities) ) { - borrow = AutoderefBorrow::None; - return deref_count; + DEBUG("FOUND *{" << deref_count << "}, fcn_path = " << possibilities.back().second); } // Auto-ref auto borrow_ty = ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared, ty.clone()); - if( this->find_method(sp, traits, ivars, borrow_ty, method_name, MethodAccess::Move, fcn_path) ) + if( this->find_method(sp, traits, ivars, borrow_ty, method_name, MethodAccess::Move, AutoderefBorrow::Shared, possibilities) ) { - DEBUG("FOUND & *{" << deref_count << "}, fcn_path = " << fcn_path); - borrow = AutoderefBorrow::Shared; - return deref_count; + DEBUG("FOUND & *{" << deref_count << "}, fcn_path = " << possibilities.back().second); } borrow_ty.m_data.as_Borrow().type = ::HIR::BorrowType::Unique; - if( cur_access >= MethodAccess::Unique && this->find_method(sp, traits, ivars, borrow_ty, method_name, MethodAccess::Move, fcn_path) ) + if( cur_access >= MethodAccess::Unique && this->find_method(sp, traits, ivars, borrow_ty, method_name, MethodAccess::Move, AutoderefBorrow::Unique, possibilities) ) { - DEBUG("FOUND &mut *{" << deref_count << "}, fcn_path = " << fcn_path); - borrow = AutoderefBorrow::Unique; - return deref_count; + DEBUG("FOUND &mut *{" << deref_count << "}, fcn_path = " << possibilities.back().second); } borrow_ty.m_data.as_Borrow().type = ::HIR::BorrowType::Owned; - if( cur_access >= MethodAccess::Move && this->find_method(sp, traits, ivars, borrow_ty, method_name, MethodAccess::Move, fcn_path) ) + if( cur_access >= MethodAccess::Move && this->find_method(sp, traits, ivars, borrow_ty, method_name, MethodAccess::Move, AutoderefBorrow::Owned, possibilities) ) + { + DEBUG("FOUND &move *{" << deref_count << "}, fcn_path = " << possibilities.back().second); + } + if( !possibilities.empty() ) { - DEBUG("FOUND &move *{" << deref_count << "}, fcn_path = " << fcn_path); - borrow = AutoderefBorrow::Owned; return deref_count; } @@ -3553,6 +3552,17 @@ unsigned int TraitResolution::autoderef_find_method(const Span& sp, const HIR::t ERROR(sp, E0000, "Could not find method `" << method_name << "` on type `" << top_ty << "`"); } +::std::ostream& operator<<(::std::ostream& os, const TraitResolution::AutoderefBorrow& x) +{ + switch(x) + { + case TraitResolution::AutoderefBorrow::None: os << "None"; break; + case TraitResolution::AutoderefBorrow::Shared: os << "Shared"; break; + case TraitResolution::AutoderefBorrow::Unique: os << "Unique"; break; + case TraitResolution::AutoderefBorrow::Owned: os << "Owned"; break; + } + return os; +} ::std::ostream& operator<<(::std::ostream& os, const TraitResolution::AllowedReceivers& x) { switch(x) @@ -3643,12 +3653,12 @@ const ::HIR::TypeRef* TraitResolution::check_method_receiver(const Span& sp, ::H return nullptr; } -bool TraitResolution::find_method( - const Span& sp, - const HIR::t_trait_list& traits, const ::std::vector<unsigned>& ivars, - const ::HIR::TypeRef& ty, const ::std::string& method_name, MethodAccess access, - /* Out -> */::HIR::Path& fcn_path) const +bool TraitResolution::find_method(const Span& sp, + const HIR::t_trait_list& traits, const ::std::vector<unsigned>& ivars, const ::HIR::TypeRef& ty, const ::std::string& method_name, MethodAccess access, + AutoderefBorrow borrow_type, /* Out -> */::std::vector<::std::pair<AutoderefBorrow,::HIR::Path>>& possibilities + ) const { + bool rv = false; TRACE_FUNCTION_F("ty=" << ty << ", name=" << method_name << ", access=" << access); auto cb_infer = m_ivars.callback_resolve_infer(); @@ -3684,13 +3694,15 @@ bool TraitResolution::find_method( // - Could collide with legitimate uses of `Self` // Found the method, return the UFCS path for it - fcn_path = ::HIR::Path( ::HIR::Path::Data::make_UfcsKnown({ - box$( self_ty->clone() ), - mv$(final_trait_path), - method_name, - {} - }) ); - return true; + possibilities.push_back(::std::make_pair( borrow_type, + ::HIR::Path( ::HIR::Path::Data::make_UfcsKnown({ + box$( self_ty->clone() ), + mv$(final_trait_path), + method_name, + {} + }) ) )); + rv = true; + break; } else if( cmp == ::HIR::Compare::Fuzzy ) { @@ -3749,13 +3761,8 @@ bool TraitResolution::find_method( // - If the receiver is valid, then it's correct (no need to check the type again) if(const auto* self_ty_p = check_method_receiver(sp, receiver, ty, access)) { - fcn_path = ::HIR::Path( ::HIR::Path::Data::Data_UfcsKnown({ - box$( self_ty_p->clone() ), - mv$(final_trait_path), - method_name, - {} - }) ); - return true; + possibilities.push_back(::std::make_pair(borrow_type, ::HIR::Path(self_ty_p->clone(), mv$(final_trait_path), method_name, {}) )); + rv = true; } } } @@ -3777,13 +3784,8 @@ bool TraitResolution::find_method( if(const auto* self_ty_p = check_method_receiver(sp, receiver, ty, access)) { - fcn_path = ::HIR::Path( ::HIR::Path::Data::Data_UfcsKnown({ - box$( self_ty_p->clone() ), - mv$(final_trait_path), - method_name, - {} - }) ); - return true; + possibilities.push_back(::std::make_pair(borrow_type, ::HIR::Path(self_ty_p->clone(), mv$(final_trait_path), method_name, {}) )); + rv = true; } } } @@ -3840,13 +3842,8 @@ bool TraitResolution::find_method( } // Found the method, return the UFCS path for it - fcn_path = ::HIR::Path( ::HIR::Path::Data::make_UfcsKnown({ - box$( self_ty_p->clone() ), - mv$(final_trait_path), - method_name, - {} - }) ); - return true; + possibilities.push_back(::std::make_pair( borrow_type, ::HIR::Path(self_ty_p->clone(), mv$(final_trait_path), method_name, {}) )); + rv = true; } } @@ -3883,13 +3880,8 @@ bool TraitResolution::find_method( } // Found the method, return the UFCS path for it - fcn_path = ::HIR::Path( ::HIR::Path::Data::make_UfcsKnown({ - box$( self_ty_p->clone() ), - mv$(final_trait_path), - method_name, - {} - }) ); - return true; + possibilities.push_back(::std::make_pair( borrow_type, ::HIR::Path(self_ty_p->clone(), mv$(final_trait_path), method_name, {}) )); + rv = true; } } } @@ -3914,11 +3906,7 @@ bool TraitResolution::find_method( DEBUG("Found `impl" << impl.m_params.fmt_args() << " " << impl.m_type << "` fn " << method_name/* << " - " << top_ty*/); if( *self_ty_p == *cur_check_ty ) { - fcn_path = ::HIR::Path( ::HIR::Path::Data::make_UfcsInherent({ - box$(self_ty_p->clone()), - method_name, - {} - }) ); + possibilities.push_back(::std::make_pair( borrow_type, ::HIR::Path(self_ty_p->clone(), method_name, {}) )); return true; } } @@ -3927,17 +3915,17 @@ bool TraitResolution::find_method( }; if( m_crate.find_type_impls(ty, m_ivars.callback_resolve_infer(), find_type_impls_cb) ) { - return true; + rv = true; } cur_check_ty = (ty.m_data.is_Borrow() ? &*ty.m_data.as_Borrow().inner : nullptr); if( cur_check_ty && m_crate.find_type_impls(*cur_check_ty, m_ivars.callback_resolve_infer(), find_type_impls_cb) ) { - return true; + rv = true; } cur_check_ty = this->type_is_owned_box(sp, ty); if( cur_check_ty && m_crate.find_type_impls(*cur_check_ty, m_ivars.callback_resolve_infer(), find_type_impls_cb) ) { - return true; + rv = true; } } @@ -3974,13 +3962,8 @@ bool TraitResolution::find_method( //if( find_trait_impls(sp, *trait_ref.first, trait_params, self_ty, [](auto , auto ) { return true; }) ) { if( find_trait_impls_crate(sp, *trait_ref.first, &trait_params, self_ty, [](auto , auto ) { return true; }) ) { DEBUG("Found trait impl " << *trait_ref.first << trait_params << " for " << self_ty << " ("<<m_ivars.fmt_type(self_ty)<<")"); - fcn_path = ::HIR::Path( ::HIR::Path::Data::make_UfcsKnown({ - box$( self_ty.clone() ), - ::HIR::GenericPath( *trait_ref.first, mv$(trait_params) ), - method_name, - {} - }) ); - return true; + possibilities.push_back(::std::make_pair( borrow_type, ::HIR::Path(self_ty.clone(), ::HIR::GenericPath( *trait_ref.first, mv$(trait_params) ), method_name, {}) )); + rv = true; } } else @@ -3989,7 +3972,7 @@ bool TraitResolution::find_method( } } - return false; + return rv; } unsigned int TraitResolution::autoderef_find_field(const Span& sp, const ::HIR::TypeRef& top_ty, const ::std::string& field_name, /* Out -> */::HIR::TypeRef& field_type) const diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp index ab0ea93d..335875a5 100644 --- a/src/hir_typeck/helpers.hpp +++ b/src/hir_typeck/helpers.hpp @@ -240,9 +240,13 @@ public: Unique, Owned, }; + friend ::std::ostream& operator<<(::std::ostream& os, const AutoderefBorrow& x); /// Locate the named method by applying auto-dereferencing. /// \return Number of times deref was applied (or ~0 if _ was hit) - unsigned int autoderef_find_method(const Span& sp, const HIR::t_trait_list& traits, const ::std::vector<unsigned>& ivars, const ::HIR::TypeRef& top_ty, const ::std::string& method_name, /* Out -> */::HIR::Path& fcn_path, AutoderefBorrow& borrow) const; + unsigned int autoderef_find_method(const Span& sp, + const HIR::t_trait_list& traits, const ::std::vector<unsigned>& ivars, const ::HIR::TypeRef& top_ty, const ::std::string& method_name, + /* Out -> */::std::vector<::std::pair<AutoderefBorrow,::HIR::Path>>& possibilities + ) const; /// Locate the named field by applying auto-dereferencing. /// \return Number of times deref was applied (or ~0 if _ was hit) unsigned int autoderef_find_field(const Span& sp, const ::HIR::TypeRef& top_ty, const ::std::string& name, /* Out -> */::HIR::TypeRef& field_type) const; @@ -268,7 +272,10 @@ public: Box, }; friend ::std::ostream& operator<<(::std::ostream& os, const AllowedReceivers& x); - bool find_method(const Span& sp, const HIR::t_trait_list& traits, const ::std::vector<unsigned>& ivars, const ::HIR::TypeRef& ty, const ::std::string& method_name, MethodAccess access, /* Out -> */::HIR::Path& fcn_path) const; + bool find_method(const Span& sp, + const HIR::t_trait_list& traits, const ::std::vector<unsigned>& ivars, const ::HIR::TypeRef& ty, const ::std::string& method_name, MethodAccess access, + AutoderefBorrow borrow_type, /* Out -> */::std::vector<::std::pair<AutoderefBorrow,::HIR::Path>>& possibilities + ) const; /// Locates a named method in a trait, and returns the path of the trait that contains it (with fixed parameters) bool trait_contains_method(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::HIR::TypeRef& self, const ::std::string& name, ::HIR::Function::Receiver& out_receiver, ::HIR::GenericPath& out_path) const; |