summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hir_typeck/expr_cs.cpp29
-rw-r--r--src/hir_typeck/helpers.cpp127
-rw-r--r--src/hir_typeck/helpers.hpp11
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;