diff options
author | John Hodge <tpg@mutabah.net> | 2016-11-03 12:15:49 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-11-03 12:15:49 +0800 |
commit | 01dc9ba84fab3200d3db551857e40f9df7c2fcac (patch) | |
tree | f9aaae2dbb6e1193959102174cda71365671ffaf | |
parent | de3d219f998e854091a0663c7e57cb1b3334e995 (diff) | |
download | mrust-01dc9ba84fab3200d3db551857e40f9df7c2fcac.tar.gz |
HIR Typecheck Expr - Slightly better handling of Box receivers
-rw-r--r-- | src/hir_typeck/helpers.cpp | 51 | ||||
-rw-r--r-- | src/hir_typeck/helpers.hpp | 5 |
2 files changed, 44 insertions, 12 deletions
diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index 8406d1db..245b6320 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -2680,7 +2680,7 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp, return match; } -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, bool allow_move, ::HIR::GenericPath& out_path) const +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 { auto it = trait_ptr.m_values.find(name); if( it != trait_ptr.m_values.end() ) { @@ -2691,9 +2691,12 @@ bool TraitResolution::trait_contains_method(const Span& sp, const ::HIR::Generic case ::HIR::Function::Receiver::Free: break; case ::HIR::Function::Receiver::Value: - if( !allow_move ) { + if( ar != AllowedReceivers::All && ar != AllowedReceivers::Value ) + break; + if(0) + case ::HIR::Function::Receiver::Box: + if( ar != AllowedReceivers::Box ) break; - } default: out_path = trait_path.clone(); return true; @@ -2705,7 +2708,7 @@ bool TraitResolution::trait_contains_method(const Span& sp, const ::HIR::Generic for(const auto& st : trait_ptr.m_parent_traits) { auto& st_ptr = this->m_crate.get_trait_by_path(sp, st.m_path.m_path); - if( trait_contains_method(sp, st.m_path, st_ptr, self, name, allow_move, out_path) ) { + if( trait_contains_method(sp, st.m_path, st_ptr, self, name, ar, out_path) ) { out_path.m_params = monomorphise_path_params_with(sp, mv$(out_path.m_params), [&](const auto& gt)->const auto& { const auto& ge = gt.m_data.as_Generic(); if( ge.binding == 0xFFFF ) { @@ -2887,6 +2890,24 @@ 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); + 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. @@ -2971,7 +2992,7 @@ bool TraitResolution::find_method( DEBUG("Bound `" << e.type << " : " << e.trait.m_path << "` - Matches " << ty); ::HIR::GenericPath final_trait_path; assert(e.trait.m_trait_ptr); - if( !this->trait_contains_method(sp, e.trait.m_path, *e.trait.m_trait_ptr, ty, method_name, ar != AllowedReceivers::AnyBorrow, final_trait_path) ) + if( !this->trait_contains_method(sp, e.trait.m_path, *e.trait.m_trait_ptr, ty, method_name, ar, final_trait_path) ) continue ; DEBUG("- Found trait " << final_trait_path); // TODO: Re-monomorphise final trait using `ty`? @@ -3007,6 +3028,9 @@ bool TraitResolution::find_method( // Only accept by-value methods if not dereferencing to them if( ar == AllowedReceivers::AnyBorrow ) break; + case ::HIR::Function::Receiver::Box: + if( ar != AllowedReceivers::Box ) + break; default: fcn_path = ::HIR::Path( ::HIR::Path::Data::Data_UfcsKnown({ box$( ty.clone() ), @@ -3035,7 +3059,7 @@ bool TraitResolution::find_method( { ASSERT_BUG(sp, bound.m_trait_ptr, "Pointer to trait " << bound.m_path << " not set in " << e.trait.m_path); ::HIR::GenericPath final_trait_path; - if( !this->trait_contains_method(sp, bound.m_path, *bound.m_trait_ptr, ::HIR::TypeRef("Self", 0xFFFF), method_name, ar != AllowedReceivers::AnyBorrow, final_trait_path) ) + if( !this->trait_contains_method(sp, bound.m_path, *bound.m_trait_ptr, ::HIR::TypeRef("Self", 0xFFFF), method_name, ar, final_trait_path) ) continue ; DEBUG("- Found trait " << final_trait_path); @@ -3087,8 +3111,12 @@ bool TraitResolution::find_method( if( ar == AllowedReceivers::AnyBorrow ) break; if( 0 ) + case ::HIR::Function::Receiver::Box: + if( ar != AllowedReceivers::Box ) + break; + if(0) default: - if( ar == AllowedReceivers::Value ) + if( ar == AllowedReceivers::Value || ar == AllowedReceivers::Box ) break; DEBUG("Matching `impl" << impl.m_params.fmt_args() << " " << impl.m_type << "`"/* << " - " << top_ty*/); fcn_path = ::HIR::Path( ::HIR::Path::Data::make_UfcsInherent({ @@ -3131,11 +3159,12 @@ bool TraitResolution::find_method( if( ar == AllowedReceivers::AnyBorrow ) break; if(0) - default: - if( ar == AllowedReceivers::Value ) + case ::HIR::Function::Receiver::Box: + if( ar != AllowedReceivers::Box ) break; - // NOTE: Only allow picking a `self: Box<Self>` method if we've been through a deref. - if( v.m_receiver == ::HIR::Function::Receiver::Box && ar != AllowedReceivers::AnyBorrow ) + if(0) + default: + if( ar == AllowedReceivers::Value || ar == AllowedReceivers::Box || (v.m_receiver == ::HIR::Function::Receiver::Box && ar != AllowedReceivers::AnyBorrow) ) break; DEBUG("Search for impl of " << *trait_ref.first); diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp index 47669985..a2a08ca2 100644 --- a/src/hir_typeck/helpers.hpp +++ b/src/hir_typeck/helpers.hpp @@ -138,6 +138,7 @@ class TraitResolution ::std::map< ::HIR::TypeRef, ::HIR::TypeRef> m_type_equalities; + ::HIR::SimplePath m_lang_Box; mutable ::std::vector< ::HIR::TypeRef> m_eat_active_stack; public: TraitResolution(const HMTypeInferrence& ivars, const ::HIR::Crate& crate, const ::HIR::GenericParams* impl_params, const ::HIR::GenericParams* item_params): @@ -147,6 +148,7 @@ public: m_item_params( item_params ) { prep_indexes(); + m_lang_Box = crate.get_lang_item_path_opt("owned_box"); } const ::HIR::GenericParams& impl_params() const { @@ -233,11 +235,12 @@ public: All, AnyBorrow, Value, + Box, }; 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, AllowedReceivers ar, /* Out -> */::HIR::Path& fcn_path) 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, bool allow_move, ::HIR::GenericPath& out_path) const; + 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, AllowedReceivers ar, ::HIR::GenericPath& out_path) const; 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; |