summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hir_typeck/expr_cs.cpp50
-rw-r--r--src/hir_typeck/helpers.cpp68
-rw-r--r--src/hir_typeck/helpers.hpp8
3 files changed, 59 insertions, 67 deletions
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index a4be26aa..74e879f6 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -2509,7 +2509,8 @@ namespace {
// Using autoderef, locate this method on the type
::HIR::Path fcn_path { ::HIR::SimplePath() };
- 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);
+ TraitResolution::AutoderefBorrow ad_borrow;
+ 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);
if( deref_count != ~0u )
{
DEBUG("- deref_count = " << deref_count << ", fcn_path = " << fcn_path);
@@ -2555,35 +2556,7 @@ namespace {
this->context.equate_types(sp, node.m_res_type, node.m_cache.m_arg_types.back());
// Add derefs
- if( deref_count >= ~6u )
- {
- auto inv = ~deref_count;
- bool is_box_deref = (inv > 3);
- auto borrow_ty = inv % 3;
-
- if( is_box_deref ) {
- const auto& ity = this->context.get_type(node.m_value->m_res_type).m_data.as_Path().path.m_data.as_Generic().m_params.m_types.at(0);
- auto span = node.m_value->span();
- DEBUG("- Deref Box " << &*node.m_value << " -> " << ity);
- node.m_value = NEWNODE(ity.clone(), span, _Deref, mv$(node.m_value));
- }
-
- ::HIR::BorrowType bt = ::HIR::BorrowType::Shared;
- switch(borrow_ty)
- {
- case 1: bt = ::HIR::BorrowType::Shared; break;
- case 2: bt = ::HIR::BorrowType::Unique; break;
- case 0: bt = ::HIR::BorrowType::Owned ; break;
- default:
- BUG(sp, "Invalid deref return count - " << deref_count);
- }
-
- auto ty = ::HIR::TypeRef::new_borrow(bt, node.m_value->m_res_type.clone());
- DEBUG("- Ref " << &*node.m_value << " -> " << ty);
- auto span = node.m_value->span();
- node.m_value = NEWNODE(mv$(ty), span, _Borrow, bt, mv$(node.m_value) );
- }
- else if( deref_count > 0 )
+ if( deref_count > 0 )
{
assert( deref_count < (1<<16) ); // Just some sanity.
DEBUG("- Inserting " << deref_count << " dereferences");
@@ -2603,6 +2576,23 @@ namespace {
}
// Autoref
+ if( ad_borrow != TraitResolution::AutoderefBorrow::None )
+ {
+ ::HIR::BorrowType bt = ::HIR::BorrowType::Shared;
+ switch(ad_borrow)
+ {
+ case TraitResolution::AutoderefBorrow::None: throw "";
+ case TraitResolution::AutoderefBorrow::Shared: bt = ::HIR::BorrowType::Shared; break;
+ case TraitResolution::AutoderefBorrow::Unique: bt = ::HIR::BorrowType::Unique; break;
+ case TraitResolution::AutoderefBorrow::Owned : bt = ::HIR::BorrowType::Owned ; break;
+ }
+
+ auto ty = ::HIR::TypeRef::new_borrow(bt, node.m_value->m_res_type.clone());
+ DEBUG("- Ref (cmd) " << &*node.m_value << " -> " << ty);
+ auto span = node.m_value->span();
+ node.m_value = NEWNODE(mv$(ty), span, _Borrow, bt, mv$(node.m_value) );
+ }
+ else
{
auto receiver_class = node.m_cache.m_fcn->m_receiver;
::HIR::BorrowType bt;
diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp
index 2ce2e7ac..77985336 100644
--- a/src/hir_typeck/helpers.cpp
+++ b/src/hir_typeck/helpers.cpp
@@ -3075,7 +3075,7 @@ 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 -> */::HIR::Path& fcn_path) 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 deref_count = 0;
::HIR::TypeRef tmp_type; // Temporary type used for handling Deref
@@ -3111,6 +3111,7 @@ unsigned int TraitResolution::autoderef_find_method(const Span& sp, const HIR::t
// Search for methods on the inner type with Receiver::Box
if( this->find_method(sp, traits, ivars, ty, method_name, AllowedReceivers::Box, fcn_path) ) {
DEBUG("FOUND Box, fcn_path = " << fcn_path);
+ borrow = AutoderefBorrow::None;
return 1;
}
}
@@ -3131,6 +3132,27 @@ unsigned int TraitResolution::autoderef_find_method(const Span& sp, const HIR::t
auto allowed_receivers = (unconditional_allow_move || (deref_count == 0) ? AllowedReceivers::All : AllowedReceivers::AnyBorrow);
if( this->find_method(sp, traits, ivars, ty, method_name, allowed_receivers, fcn_path) ) {
DEBUG("FOUND " << deref_count << ", fcn_path = " << fcn_path);
+ borrow = AutoderefBorrow::None;
+ return deref_count;
+ }
+
+
+ auto borrow_ty = ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared, ty.clone());
+ if( find_method(sp, traits, ivars, borrow_ty, method_name, AllowedReceivers::Value, fcn_path) ) {
+ DEBUG("FOUND &*" << deref_count << ", fcn_path = " << fcn_path);
+ borrow = AutoderefBorrow::Shared;
+ return deref_count;
+ }
+ borrow_ty.m_data.as_Borrow().type = ::HIR::BorrowType::Unique;
+ if( find_method(sp, traits, ivars, borrow_ty, method_name, AllowedReceivers::Value, fcn_path) ) {
+ DEBUG("FOUND &mut*" << deref_count << ", fcn_path = " << fcn_path);
+ borrow = AutoderefBorrow::Unique;
+ return deref_count;
+ }
+ borrow_ty.m_data.as_Borrow().type = ::HIR::BorrowType::Owned;
+ if( find_method(sp, traits, ivars, borrow_ty, method_name, AllowedReceivers::Value, fcn_path) ) {
+ DEBUG("FOUND &mut*" << deref_count << ", fcn_path = " << fcn_path);
+ borrow = AutoderefBorrow::Owned;
return deref_count;
}
@@ -3145,6 +3167,7 @@ unsigned int TraitResolution::autoderef_find_method(const Span& sp, const HIR::t
if( find_method(sp, traits, ivars, ty, method_name, AllowedReceivers::All, fcn_path) ) {
DEBUG("FOUND " << 0 << ", fcn_path = " << fcn_path);
+ borrow = AutoderefBorrow::None;
return 0;
}
)
@@ -3155,57 +3178,30 @@ unsigned int TraitResolution::autoderef_find_method(const Span& sp, const HIR::t
return ~0u;
}
- // TODO: Try the following after dereferencing a Box? - Requires indiciating via the return that the caller should deref+ref
- // - Should refactor to change searching to search for functions taking the current type as a receiver (not method searching as is currently done)
-
// Insert a single reference and try again (only allowing by-value methods), returning a magic value (e.g. ~1u)
// - Required for calling `(self[..]: str).into_searcher(haystack)` - Which invokes `<&str as Pattern>::into_searcher(&self[..], haystack)`
// - Have to do several tries, each with different borrow classes.
auto borrow_ty = ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared, top_ty.clone());
if( find_method(sp, traits, ivars, borrow_ty, method_name, AllowedReceivers::Value, fcn_path) ) {
DEBUG("FOUND &, fcn_path = " << fcn_path);
- return ~1u;
+ borrow = AutoderefBorrow::Shared;
+ return 0;
}
borrow_ty.m_data.as_Borrow().type = ::HIR::BorrowType::Unique;
if( find_method(sp, traits, ivars, borrow_ty, method_name, AllowedReceivers::Value, fcn_path) ) {
DEBUG("FOUND &mut, fcn_path = " << fcn_path);
- return ~2u;
+ borrow = AutoderefBorrow::Unique;
+ return 0;
}
borrow_ty.m_data.as_Borrow().type = ::HIR::BorrowType::Owned;
if( find_method(sp, traits, ivars, borrow_ty, method_name, AllowedReceivers::Value, fcn_path) ) {
- DEBUG("FOUND &mut, fcn_path = " << fcn_path);
- return ~3u;
+ DEBUG("FOUND &move, fcn_path = " << fcn_path);
+ borrow = AutoderefBorrow::Owned;
+ return 0;
}
- // Handle `self: Box<Self>` methods by detecting m_lang_Box and searchig for box receiver methods
- TU_IFLET(::HIR::TypeRef::Data, top_ty_r.m_data, Path, e,
- TU_IFLET(::HIR::Path::Data, e.path.m_data, Generic, pe,
- if( pe.m_path == m_lang_Box )
- {
- const auto& ty = this->m_ivars.get_type( pe.m_params.m_types.at(0) );
- assert( ! ty.m_data.is_Infer() );
-
- auto borrow_ty = ::HIR::TypeRef::new_borrow(::HIR::BorrowType::Shared, ty.clone());
- if( find_method(sp, traits, ivars, borrow_ty, method_name, AllowedReceivers::Value, fcn_path) ) {
- DEBUG("FOUND &*box, fcn_path = " << fcn_path);
- return ~4u;
- }
- borrow_ty.m_data.as_Borrow().type = ::HIR::BorrowType::Unique;
- if( find_method(sp, traits, ivars, borrow_ty, method_name, AllowedReceivers::Value, fcn_path) ) {
- DEBUG("FOUND &mut*box, fcn_path = " << fcn_path);
- return ~5u;
- }
- borrow_ty.m_data.as_Borrow().type = ::HIR::BorrowType::Owned;
- if( find_method(sp, traits, ivars, borrow_ty, method_name, AllowedReceivers::Value, fcn_path) ) {
- DEBUG("FOUND &mut*box, fcn_path = " << fcn_path);
- return ~6u;
- }
- }
- )
- )
-
// Dereference failed! This is a hard error (hitting _ is checked above and returns ~0)
- this->m_ivars.dump();
+ //this->m_ivars.dump();
ERROR(sp, E0000, "Could not find method `" << method_name << "` on type `" << top_ty << "`");
}
diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp
index 76487140..9bf8d4d9 100644
--- a/src/hir_typeck/helpers.hpp
+++ b/src/hir_typeck/helpers.hpp
@@ -219,9 +219,15 @@ private:
) const ;
public:
+ enum class AutoderefBorrow {
+ None,
+ Shared,
+ Unique,
+ Owned,
+ };
/// 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) 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 -> */::HIR::Path& fcn_path, AutoderefBorrow& borrow) 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;