summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2017-01-25 19:40:58 +0800
committerJohn Hodge <tpg@mutabah.net>2017-01-25 19:40:58 +0800
commiteeae19a128b93a41e33ca59f82808bc779f2666b (patch)
tree1cf195299f9fd2c0ea04ec9931b6af07da64ad4a
parent4c7add8f0e160123cde2c454ad96ba7170a8af7c (diff)
downloadmrust-eeae19a128b93a41e33ca59f82808bc779f2666b.tar.gz
HIR Typecheck - Box autoderef quirk fixes
-rw-r--r--src/hir_typeck/helpers.cpp70
-rw-r--r--src/hir_typeck/helpers.hpp16
2 files changed, 62 insertions, 24 deletions
diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp
index f7aaa2a5..c29bc64b 100644
--- a/src/hir_typeck/helpers.cpp
+++ b/src/hir_typeck/helpers.cpp
@@ -2956,7 +2956,7 @@ namespace {
bool TraitResolution::trait_contains_method(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::HIR::TypeRef& self, const ::std::string& name, AllowedReceivers ar, ::HIR::GenericPath& out_path) const
{
- TRACE_FUNCTION_FR(trait_path << " has " << name, out_path);
+ TRACE_FUNCTION_FR("trait_path=" << trait_path << ",name=" << name << ",ar=" << ar, out_path);
if( trait_contains_method_(trait_ptr, name, ar) )
{
@@ -3109,6 +3109,18 @@ bool TraitResolution::trait_contains_type(const Span& sp, const ::HIR::GenericPa
)
)
}
+const ::HIR::TypeRef* TraitResolution::type_is_owned_box(const Span& sp, const ::HIR::TypeRef& ty) const
+{
+ TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Path, e,
+ TU_IFLET(::HIR::Path::Data, e.path.m_data, Generic, pe,
+ if( pe.m_path == m_lang_Box )
+ {
+ return &this->m_ivars.get_type( pe.m_params.m_types.at(0) );
+ }
+ )
+ )
+ return nullptr;
+}
// -------------------------------------------------------------------------------------------------------------------
@@ -3165,32 +3177,13 @@ unsigned int TraitResolution::autoderef_find_method(const Span& sp, const HIR::t
deref_count += 1;
)
- // 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) );
- if( ! ty.m_data.is_Infer() )
- {
- // 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;
- }
- }
- }
- )
- )
-
// TODO: This appears to dereference a &mut to call a `self: Self` method, where it should use the trait impl on &mut Self.
// - Shouldn't deref to get a by-value receiver.// unless it's via a &move.
-
+ bool can_move = unconditional_allow_move;
do {
// TODO: Update `unconditional_allow_move` based on the current type.
const auto& ty = this->m_ivars.get_type(*current_ty);
- if( ty.m_data.is_Infer() ) {
+ if( type_is_unbounded_infer(ty) ) {
DEBUG("- Ivar, pausing");
return ~0u;
}
@@ -3198,14 +3191,33 @@ unsigned int TraitResolution::autoderef_find_method(const Span& sp, const HIR::t
DEBUG("- Unbound type path " << ty << ", pausing");
return ~0u;
}
+ DEBUG("ty = " << ty);
- auto allowed_receivers = (unconditional_allow_move || (deref_count == 0) ? AllowedReceivers::All : AllowedReceivers::AnyBorrow);
+ auto allowed_receivers = (can_move ? 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;
}
+ // Handle `self: Box<Self>` methods by detecting m_lang_Box and searchig for box receiver methods
+ // - Only possible if we can move the receiver
+ if( allowed_receivers == AllowedReceivers::All )
+ {
+ if( const auto* typ = this->type_is_owned_box(sp, ty) )
+ {
+ if( ! type_is_unbounded_infer(*typ) )
+ {
+ // Search for methods on the inner type with Receiver::Box
+ if( this->find_method(sp, traits, ivars, *typ, method_name, AllowedReceivers::Box, fcn_path) ) {
+ DEBUG("FOUND Box, fcn_path = " << fcn_path);
+ borrow = AutoderefBorrow::None;
+ return deref_count+1;
+ }
+ }
+ }
+ }
+
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) ) {
@@ -3228,7 +3240,16 @@ unsigned int TraitResolution::autoderef_find_method(const Span& sp, const HIR::t
// 3. Dereference and try again
deref_count += 1;
- current_ty = this->autoderef(sp, ty, tmp_type);
+ if( const auto* typ = this->type_is_owned_box(sp, ty) )
+ {
+ current_ty = typ;
+ }
+ else
+ {
+ current_ty = this->autoderef(sp, ty, tmp_type);
+ if( current_ty )
+ can_move = this->type_is_copy(sp, *current_ty) == ::HIR::Compare::Equal;
+ }
} while( current_ty );
// If the top is a borrow, search for methods on &/&mut
@@ -3513,6 +3534,7 @@ bool TraitResolution::find_method(
{
if( trait_ref.first == nullptr )
break;
+ DEBUG("Search " << *trait_ref.first);
//::HIR::GenericPath final_trait_path;
//if( !this->trait_contains_method(sp, *trait_ref.first, *trait_ref.second, method_name, final_trait_path) )
diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp
index 19235a8e..a1db0af9 100644
--- a/src/hir_typeck/helpers.hpp
+++ b/src/hir_typeck/helpers.hpp
@@ -12,6 +12,20 @@
#include "common.hpp"
+static inline bool type_is_unbounded_infer(const ::HIR::TypeRef& ty)
+{
+ if( const auto* te = ty.m_data.opt_Infer() ) {
+ switch( te->ty_class )
+ {
+ case ::HIR::InferClass::Integer: return false;
+ case ::HIR::InferClass::Float: return false;
+ case ::HIR::InferClass::None: return true;
+ case ::HIR::InferClass::Diverge:return true;
+ }
+ }
+ return false;
+}
+
class HMTypeInferrence
{
public:
@@ -251,6 +265,8 @@ public:
bool trait_contains_type(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::std::string& name, ::HIR::GenericPath& out_path) const;
::HIR::Compare type_is_copy(const Span& sp, const ::HIR::TypeRef& ty) const;
+ const ::HIR::TypeRef* type_is_owned_box(const Span& sp, const ::HIR::TypeRef& ty) const;
+
private:
void expand_associated_types_inplace(const Span& sp, ::HIR::TypeRef& input, LList<const ::HIR::TypeRef*> stack) const;
void expand_associated_types_inplace__UfcsKnown(const Span& sp, ::HIR::TypeRef& input, LList<const ::HIR::TypeRef*> stack) const;