diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 21 | ||||
-rw-r--r-- | src/hir_typeck/helpers.cpp | 34 |
2 files changed, 48 insertions, 7 deletions
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 8011e0a8..7312bb3b 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -2523,14 +2523,25 @@ namespace { this->context.equate_types(sp, node.m_res_type, node.m_cache.m_arg_types.back()); // Add derefs - if( deref_count >= ~3u ) + 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(deref_count) + switch(borrow_ty) { - case ~1u: bt = ::HIR::BorrowType::Shared; break; - case ~2u: bt = ::HIR::BorrowType::Unique; break; - case ~3u: bt = ::HIR::BorrowType::Owned ; break; + 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); } diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index 245b6320..a8c7ddfa 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -2945,7 +2945,10 @@ unsigned int TraitResolution::autoderef_find_method(const Span& sp, const HIR::t return ~0u; } - // TODO: Insert a single reference and try again (only allowing by-value methods), returning a magic value (e.g. ~1u) + // 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()); @@ -2961,9 +2964,36 @@ unsigned int TraitResolution::autoderef_find_method(const Span& sp, const HIR::t 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 ~2u; + return ~3u; } + // 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(); ERROR(sp, E0000, "Could not find method `" << method_name << "` on type `" << top_ty << "`"); |