diff options
author | John Hodge <tpg@ucc.asn.au> | 2019-06-04 07:35:15 +0800 |
---|---|---|
committer | John Hodge <tpg@ucc.asn.au> | 2019-06-04 07:35:15 +0800 |
commit | 6343f85577b2a28fe2476860420a6d7f394a98d1 (patch) | |
tree | ed77d5e7392520dc1125fc582e7895f961e5891f /src | |
parent | 2f2f8f04b081f89de411f9b9b2ad40ace3733983 (diff) | |
download | mrust-6343f85577b2a28fe2476860420a6d7f394a98d1.tar.gz |
HIR - Use maps-of-vectors for impl lists for faster lookup, optimise Trans_Enumerate
Diffstat (limited to 'src')
-rw-r--r-- | src/hir/deserialise.cpp | 41 | ||||
-rw-r--r-- | src/hir/from_ast.cpp | 16 | ||||
-rw-r--r-- | src/hir/hir.hpp | 14 | ||||
-rw-r--r-- | src/hir/hir_ops.cpp | 162 | ||||
-rw-r--r-- | src/hir/serialise.cpp | 48 | ||||
-rw-r--r-- | src/hir/visitor.cpp | 27 | ||||
-rw-r--r-- | src/hir_conv/resolve_ufcs_outer.cpp | 43 | ||||
-rw-r--r-- | src/hir_expand/closures.cpp | 103 | ||||
-rw-r--r-- | src/hir_typeck/outer.cpp | 13 | ||||
-rw-r--r-- | src/trans/auto_impls.cpp | 11 | ||||
-rw-r--r-- | src/trans/enumerate.cpp | 281 | ||||
-rw-r--r-- | src/trans/trans_list.cpp | 2 | ||||
-rw-r--r-- | src/trans/trans_list.hpp | 4 |
13 files changed, 477 insertions, 288 deletions
diff --git a/src/hir/deserialise.cpp b/src/hir/deserialise.cpp index 35aeacca..9d5b6cd2 100644 --- a/src/hir/deserialise.cpp +++ b/src/hir/deserialise.cpp @@ -123,6 +123,20 @@ } return rv; } + template<typename V> + ::std::map< ::HIR::SimplePath,V> deserialise_pathmap() + { + TRACE_FUNCTION_F("<" << typeid(V).name() << ">"); + size_t n = m_in.read_count(); + ::std::map< ::HIR::SimplePath, V> rv; + //rv.reserve(n); + for(size_t i = 0; i < n; i ++) + { + auto s = deserialise_simplepath(); + rv.insert( ::std::make_pair( mv$(s), D<V>::des(*this) ) ); + } + return rv; + } template<typename T> ::std::vector<T> deserialise_vec() @@ -779,6 +793,9 @@ DEF_D( ::std::unique_ptr<T>, return d.deserialise_ptr<T>(); ) + template<typename T> + DEF_D( ::std::vector<T>, + return d.deserialise_vec<T>(); ) template<typename T, typename U> struct D< ::std::pair<T,U> > { static ::std::pair<T,U> des(HirDeserialiser& d) { auto a = D<T>::des(d); @@ -817,6 +834,8 @@ template<> DEF_D( ::HIR::ProcMacro, return d.deserialise_procmacro(); ) template<> DEF_D( ::HIR::TypeImpl, return d.deserialise_typeimpl(); ) + template<> DEF_D( ::HIR::TraitImpl, return d.deserialise_traitimpl(); ) + template<> DEF_D( ::HIR::MarkerImpl, return d.deserialise_markerimpl(); ) template<> DEF_D( ::MacroRulesPtr, return d.deserialise_macrorulesptr(); ) template<> DEF_D( unsigned int, return static_cast<unsigned int>(d.deserialise_count()); ) @@ -1306,24 +1325,12 @@ rv.m_crate_name = this->m_crate_name; rv.m_root_module = deserialise_module(); - rv.m_type_impls = deserialise_vec< ::HIR::TypeImpl>(); + rv.m_named_type_impls = deserialise_pathmap< ::std::vector<::HIR::TypeImpl>>(); + rv.m_primitive_type_impls = deserialise_vec< ::HIR::TypeImpl>(); + rv.m_generic_type_impls = deserialise_vec< ::HIR::TypeImpl>(); - { - size_t n = m_in.read_count(); - for(size_t i = 0; i < n; i ++) - { - auto p = deserialise_simplepath(); - rv.m_trait_impls.insert( ::std::make_pair( mv$(p), deserialise_traitimpl() ) ); - } - } - { - size_t n = m_in.read_count(); - for(size_t i = 0; i < n; i ++) - { - auto p = deserialise_simplepath(); - rv.m_marker_impls.insert( ::std::make_pair( mv$(p), deserialise_markerimpl() ) ); - } - } + rv.m_trait_impls = deserialise_pathmap< ::std::vector<::HIR::TraitImpl>>(); + rv.m_marker_impls = deserialise_pathmap< ::std::vector<::HIR::MarkerImpl>>(); rv.m_exported_macros = deserialise_istrumap< ::MacroRulesPtr>(); rv.m_lang_items = deserialise_strumap< ::HIR::SimplePath>(); diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp index 84980818..cb8438bf 100644 --- a/src/hir/from_ast.cpp +++ b/src/hir/from_ast.cpp @@ -1615,6 +1615,7 @@ void LowerHIR_Module_Impls(const ::AST::Module& ast_mod, ::HIR::Crate& hir_crat { if( !i.data.is_Impl() ) continue; const auto& impl = i.data.as_Impl(); + const Span impl_span; auto params = LowerHIR_GenericParams(impl.def().params(), nullptr); TRACE_FUNCTION_F("IMPL " << impl.def()); @@ -1675,7 +1676,7 @@ void LowerHIR_Module_Impls(const ::AST::Module& ast_mod, ::HIR::Crate& hir_crat ) } - hir_crate.m_trait_impls.insert( ::std::make_pair(mv$(trait_name), ::HIR::TraitImpl { + hir_crate.m_trait_impls.insert( ::std::make_pair(mv$(trait_name), ::std::vector<::HIR::TraitImpl>()) ).first->second.push_back( ::HIR::TraitImpl { mv$(params), mv$(trait_args), mv$(type), @@ -1686,7 +1687,7 @@ void LowerHIR_Module_Impls(const ::AST::Module& ast_mod, ::HIR::Crate& hir_crat mv$(types), LowerHIR_SimplePath(Span(), ast_mod.path()) - }) ); + } ); } else if( impl.def().type().m_data.is_None() ) { @@ -1695,14 +1696,14 @@ void LowerHIR_Module_Impls(const ::AST::Module& ast_mod, ::HIR::Crate& hir_crat else { auto type = LowerHIR_Type(impl.def().type()); - hir_crate.m_marker_impls.insert( ::std::make_pair( mv$(trait_name), ::HIR::MarkerImpl { + hir_crate.m_marker_impls.insert( ::std::make_pair(mv$(trait_name), ::std::vector<::HIR::MarkerImpl>()) ).first->second.push_back(::HIR::MarkerImpl { mv$(params), mv$(trait_args), true, mv$(type), LowerHIR_SimplePath(Span(), ast_mod.path()) - } ) ); + } ); } } else @@ -1748,7 +1749,8 @@ void LowerHIR_Module_Impls(const ::AST::Module& ast_mod, ::HIR::Crate& hir_crat ) } - hir_crate.m_type_impls.push_back( ::HIR::TypeImpl { + // Sorted later on + hir_crate.m_generic_type_impls.push_back( ::HIR::TypeImpl { mv$(params), mv$(type), mv$(methods), @@ -1769,14 +1771,14 @@ void LowerHIR_Module_Impls(const ::AST::Module& ast_mod, ::HIR::Crate& hir_crat auto trait_name = mv$(trait.m_path); auto trait_args = mv$(trait.m_params); - hir_crate.m_marker_impls.insert( ::std::make_pair( mv$(trait_name), ::HIR::MarkerImpl { + hir_crate.m_marker_impls.insert( ::std::make_pair(mv$(trait_name), ::std::vector<::HIR::MarkerImpl>()) ).first->second.push_back(::HIR::MarkerImpl { mv$(params), mv$(trait_args), false, mv$(type), LowerHIR_SimplePath(Span(), ast_mod.path()) - } ) ); + } ); } } diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp index 3f045dd2..12b874a7 100644 --- a/src/hir/hir.hpp +++ b/src/hir/hir.hpp @@ -527,11 +527,17 @@ public: Module m_root_module; - /// Impl blocks on just a type - ::std::vector< ::HIR::TypeImpl > m_type_impls; + /// Impl blocks on just a type, split into three groups + // - Named type (sorted on the path) + // - Primitive types + // - Unsorted (generics, and everything before outer type resolution) + ::std::map<::HIR::SimplePath, ::std::vector<::HIR::TypeImpl>> m_named_type_impls; + ::std::vector< ::HIR::TypeImpl> m_primitive_type_impls; + ::std::vector< ::HIR::TypeImpl> m_generic_type_impls; + /// Impl blocks - ::std::multimap< ::HIR::SimplePath, ::HIR::TraitImpl > m_trait_impls; - ::std::multimap< ::HIR::SimplePath, ::HIR::MarkerImpl > m_marker_impls; + ::std::map< ::HIR::SimplePath, ::std::vector<::HIR::TraitImpl> > m_trait_impls; + ::std::map< ::HIR::SimplePath, ::std::vector<::HIR::MarkerImpl> > m_marker_impls; /// Macros exported by this crate ::std::unordered_map< RcString, ::MacroRulesPtr > m_exported_macros; diff --git a/src/hir/hir_ops.cpp b/src/hir/hir_ops.cpp index 32c70a72..a484b5eb 100644 --- a/src/hir/hir_ops.cpp +++ b/src/hir/hir_ops.cpp @@ -15,9 +15,9 @@ #include <mir/main_bindings.hpp> namespace { - bool matches_genericpath(const ::HIR::GenericParams& params, const ::HIR::GenericPath& left, const ::HIR::GenericPath& right, ::HIR::t_cb_resolve_type ty_res, bool expand_generic); + bool matches_genericpath(const ::HIR::GenericPath& left, const ::HIR::GenericPath& right, ::HIR::t_cb_resolve_type ty_res, bool expand_generic); - bool matches_type_int(const ::HIR::GenericParams& params, const ::HIR::TypeRef& left, const ::HIR::TypeRef& right_in, ::HIR::t_cb_resolve_type ty_res, bool expand_generic) + bool matches_type_int(const ::HIR::TypeRef& left, const ::HIR::TypeRef& right_in, ::HIR::t_cb_resolve_type ty_res, bool expand_generic) { assert(! left.m_data.is_Infer() ); const auto& right = (right_in.m_data.is_Infer() || (right_in.m_data.is_Generic() && expand_generic) ? ty_res(right_in) : right_in); @@ -97,7 +97,7 @@ namespace { return false; ), (Generic, - return matches_genericpath(params, ple, pre, ty_res, expand_generic); + return matches_genericpath( ple, pre, ty_res, expand_generic); ) ) ), @@ -105,7 +105,7 @@ namespace { throw ""; ), (TraitObject, - if( !matches_genericpath(params, le.m_trait.m_path, re.m_trait.m_path, ty_res, expand_generic) ) + if( !matches_genericpath(le.m_trait.m_path, re.m_trait.m_path, ty_res, expand_generic) ) return false; if( le.m_markers.size() != re.m_markers.size() ) return false; @@ -113,7 +113,7 @@ namespace { { const auto& lm = le.m_markers[i]; const auto& rm = re.m_markers[i]; - if( !matches_genericpath(params, lm, rm, ty_res, expand_generic) ) + if( !matches_genericpath(lm, rm, ty_res, expand_generic) ) return false; } return true; @@ -122,32 +122,32 @@ namespace { throw "Unexpected ErasedType in matches_type_int"; ), (Array, - if( ! matches_type_int(params, *le.inner, *re.inner, ty_res, expand_generic) ) + if( ! matches_type_int(*le.inner, *re.inner, ty_res, expand_generic) ) return false; if( le.size_val != re.size_val ) return false; return true; ), (Slice, - return matches_type_int(params, *le.inner, *re.inner, ty_res, expand_generic); + return matches_type_int(*le.inner, *re.inner, ty_res, expand_generic); ), (Tuple, if( le.size() != re.size() ) return false; for( unsigned int i = 0; i < le.size(); i ++ ) - if( !matches_type_int(params, le[i], re[i], ty_res, expand_generic) ) + if( !matches_type_int(le[i], re[i], ty_res, expand_generic) ) return false; return true; ), (Borrow, if( le.type != re.type ) return false; - return matches_type_int(params, *le.inner, *re.inner, ty_res, expand_generic); + return matches_type_int(*le.inner, *re.inner, ty_res, expand_generic); ), (Pointer, if( le.type != re.type ) return false; - return matches_type_int(params, *le.inner, *re.inner, ty_res, expand_generic); + return matches_type_int(*le.inner, *re.inner, ty_res, expand_generic); ), (Function, if( le.is_unsafe != re.is_unsafe ) @@ -157,9 +157,9 @@ namespace { if( le.m_arg_types.size() != re.m_arg_types.size() ) return false; for( unsigned int i = 0; i < le.m_arg_types.size(); i ++ ) - if( !matches_type_int(params, le.m_arg_types[i], re.m_arg_types[i], ty_res, expand_generic) ) + if( !matches_type_int(le.m_arg_types[i], re.m_arg_types[i], ty_res, expand_generic) ) return false; - return matches_type_int(params, *le.m_rettype, *re.m_rettype, ty_res, expand_generic); + return matches_type_int(*le.m_rettype, *re.m_rettype, ty_res, expand_generic); ), (Closure, return le.node == re.node; @@ -167,7 +167,7 @@ namespace { ) return false; } - bool matches_genericpath(const ::HIR::GenericParams& params, const ::HIR::GenericPath& left, const ::HIR::GenericPath& right, ::HIR::t_cb_resolve_type ty_res, bool expand_generic) + bool matches_genericpath(const ::HIR::GenericPath& left, const ::HIR::GenericPath& right, ::HIR::t_cb_resolve_type ty_res, bool expand_generic) { if( left.m_path.m_crate_name != right.m_path.m_crate_name ) return false; @@ -188,7 +188,7 @@ namespace { } for( unsigned int i = 0; i < right.m_params.m_types.size(); i ++ ) { - if( ! matches_type_int(params, left.m_params.m_types[i], right.m_params.m_types[i], ty_res, expand_generic) ) + if( ! matches_type_int(left.m_params.m_types[i], right.m_params.m_types[i], ty_res, expand_generic) ) return false; } } @@ -196,23 +196,6 @@ namespace { } } -//::HIR::TypeRef HIR::Function::make_ty(const Span& sp, const ::HIR::PathParams& params) const -//{ -// // TODO: Obtain function type for this function (i.e. a type that is specifically for this function) -// auto fcn_ty_data = ::HIR::FunctionType { -// m_is_unsafe, -// m_abi, -// box$( monomorphise_type(sp, m_params, params, m_return) ), -// {} -// }; -// fcn_ty_data.m_arg_types.reserve( m_args.size() ); -// for(const auto& arg : m_args) -// { -// fcn_ty_data.m_arg_types.push_back( monomorphise_type(sp, m_params, params, arg.second) ); -// } -// return ::HIR::TypeRef( mv$(fcn_ty_data) ); -//} - namespace { bool is_unbounded_infer(const ::HIR::TypeRef& type) { if( const auto* e = type.m_data.opt_Infer() ) { @@ -234,21 +217,21 @@ bool ::HIR::TraitImpl::matches_type(const ::HIR::TypeRef& type, ::HIR::t_cb_reso if( is_unbounded_infer(type) || TU_TEST1(type.m_data, Path, .binding.is_Unbound()) ) { return false; } - return matches_type_int(m_params, m_type, type, ty_res, true); + return matches_type_int(m_type, type, ty_res, true); } bool ::HIR::TypeImpl::matches_type(const ::HIR::TypeRef& type, ::HIR::t_cb_resolve_type ty_res) const { if( is_unbounded_infer(type) || TU_TEST1(type.m_data, Path, .binding.is_Unbound()) ) { return false; } - return matches_type_int(m_params, m_type, type, ty_res, true); + return matches_type_int(m_type, type, ty_res, true); } bool ::HIR::MarkerImpl::matches_type(const ::HIR::TypeRef& type, ::HIR::t_cb_resolve_type ty_res) const { if( is_unbounded_infer(type) || TU_TEST1(type.m_data, Path, .binding.is_Unbound()) ) { return false; } - return matches_type_int(m_params, m_type, type, ty_res, true); + return matches_type_int(m_type, type, ty_res, true); } namespace { @@ -954,13 +937,15 @@ bool ::HIR::TraitImpl::overlaps_with(const Crate& crate, const ::HIR::TraitImpl& bool ::HIR::Crate::find_trait_impls(const ::HIR::SimplePath& trait, const ::HIR::TypeRef& type, t_cb_resolve_type ty_res, ::std::function<bool(const ::HIR::TraitImpl&)> callback) const { - auto its = this->m_trait_impls.equal_range( trait ); - for( auto it = its.first; it != its.second; ++ it ) + auto it = this->m_trait_impls.find( trait ); + if( it != this->m_trait_impls.end() ) { - const auto& impl = it->second; - if( impl.matches_type(type, ty_res) ) { - if( callback(impl) ) { - return true; + for(const auto& impl : it->second) + { + if( impl.matches_type(type, ty_res) ) { + if( callback(impl) ) { + return true; + } } } } @@ -974,13 +959,15 @@ bool ::HIR::Crate::find_trait_impls(const ::HIR::SimplePath& trait, const ::HIR: } bool ::HIR::Crate::find_auto_trait_impls(const ::HIR::SimplePath& trait, const ::HIR::TypeRef& type, t_cb_resolve_type ty_res, ::std::function<bool(const ::HIR::MarkerImpl&)> callback) const { - auto its = this->m_marker_impls.equal_range( trait ); - for( auto it = its.first; it != its.second; ++ it ) + auto it = this->m_marker_impls.find( trait ); + if( it != this->m_marker_impls.end() ) { - const auto& impl = it->second; - if( impl.matches_type(type, ty_res) ) { - if( callback(impl) ) { - return true; + for(const auto& impl : it->second) + { + if( impl.matches_type(type, ty_res) ) { + if( callback(impl) ) { + return true; + } } } } @@ -992,21 +979,90 @@ bool ::HIR::Crate::find_auto_trait_impls(const ::HIR::SimplePath& trait, const : } return false; } -bool ::HIR::Crate::find_type_impls(const ::HIR::TypeRef& type, t_cb_resolve_type ty_res, ::std::function<bool(const ::HIR::TypeImpl&)> callback) const +namespace { - // TODO: Restrict which crate is searched based on the type. - for( const auto& impl : this->m_type_impls ) + bool find_type_impls_list(const ::std::vector<HIR::TypeImpl>& impl_list, const ::HIR::TypeRef& type, ::HIR::t_cb_resolve_type ty_res, ::std::function<bool(const ::HIR::TypeImpl&)> callback) { - if( impl.matches_type(type, ty_res) ) { - if( callback(impl) ) { - return true; + for(const auto& impl : impl_list) + { + if( impl.matches_type(type, ty_res) ) + { + if( callback(impl) ) + { + return true; + } } } + return false; + } + bool find_type_impls_int(const ::HIR::Crate& crate, const ::HIR::SimplePath* sort_path, const ::HIR::TypeRef& type, ::HIR::t_cb_resolve_type ty_res, ::std::function<bool(const ::HIR::TypeImpl&)> callback) + { + // 1. Find named impls (associated with named types) + if( sort_path ) + { + // TODO: This fails if the type is marked as #[fundamental] + //if( sort_path->m_crate_name != crate.m_crate_name ) { + // return false; + //} + + auto impl_list_it = crate.m_named_type_impls.find(*sort_path); + if( impl_list_it != crate.m_named_type_impls.end() ) + { + if( find_type_impls_list(impl_list_it->second, type, ty_res, callback) ) + return true; + } + } + // - If this type has no associated path, look in the primitives list + else + { + if( find_type_impls_list(crate.m_primitive_type_impls, type, ty_res, callback) ) + return true; + } + + // 2. Search fully generic list? + if( find_type_impls_list(crate.m_generic_type_impls, type, ty_res, callback) ) + return true; + + return false; + } +} +bool ::HIR::Crate::find_type_impls(const ::HIR::TypeRef& type, t_cb_resolve_type ty_res, ::std::function<bool(const ::HIR::TypeImpl&)> callback) const +{ + const ::HIR::SimplePath* path = nullptr; + // - Generic paths get sorted + if( TU_TEST1(type.m_data, Path, .path.m_data.is_Generic()) ) + { + path = &type.m_data.as_Path().path.m_data.as_Generic().m_path; + } + // - So do trait objects + else if( type.m_data.is_TraitObject() ) + { + path = &type.m_data.as_TraitObject().m_trait.m_path.m_path; + } + else + { + // Keep as nullptr, will search primitive list + } + + if( path ) + { + DEBUG(type << ", path=" << *path); + } + else + { + DEBUG(type << ", no path"); + } + + // > Current crate + if( find_type_impls_int(*this, path, type, ty_res, callback) ) + { + return true; } for( const auto& ec : this->m_ext_crates ) { //DEBUG("- " << ec.first); - if( ec.second.m_data->find_type_impls(type, ty_res, callback) ) { + if( find_type_impls_int(*ec.second.m_data, path, type, ty_res, callback) ) + { return true; } } diff --git a/src/hir/serialise.cpp b/src/hir/serialise.cpp index fc53e245..83e6d016 100644 --- a/src/hir/serialise.cpp +++ b/src/hir/serialise.cpp @@ -39,6 +39,16 @@ } } template<typename V> + void serialise_pathmap(const ::std::map< ::HIR::SimplePath,V>& map) + { + m_out.write_count(map.size()); + for(const auto& v : map) { + DEBUG("- " << v.first); + serialise(v.first); + serialise(v.second); + } + } + template<typename V> void serialise_strmap(const ::std::unordered_map<RcString,V>& map) { m_out.write_count(map.size()); @@ -87,6 +97,11 @@ serialise(i); } template<typename T> + void serialise(const ::std::vector<T>& vec) + { + serialise_vec(vec); + } + template<typename T> void serialise(const ::HIR::VisEnt<T>& e) { m_out.write_bool(e.publicity.is_global()); // At this stage, we only care if the item is visible outside the crate or not @@ -299,20 +314,13 @@ m_out.write_string(crate.m_crate_name); serialise_module(crate.m_root_module); - m_out.write_count(crate.m_type_impls.size()); - for(const auto& impl : crate.m_type_impls) { - serialise_typeimpl(impl); - } - m_out.write_count(crate.m_trait_impls.size()); - for(const auto& tr_impl : crate.m_trait_impls) { - serialise_simplepath(tr_impl.first); - serialise_traitimpl(tr_impl.second); - } - m_out.write_count(crate.m_marker_impls.size()); - for(const auto& tr_impl : crate.m_marker_impls) { - serialise_simplepath(tr_impl.first); - serialise_markerimpl(tr_impl.second); - } + //std::map<HIR::SimplePath,std::vector<TypeImpl>> + serialise_pathmap(crate.m_named_type_impls); + serialise_vec(crate.m_primitive_type_impls); + serialise_vec(crate.m_generic_type_impls); + + serialise_pathmap(crate.m_trait_impls); + serialise_pathmap(crate.m_marker_impls); serialise_strmap(crate.m_exported_macros); { @@ -373,6 +381,10 @@ } // m_src_module doesn't matter after typeck } + void serialise(const ::HIR::TypeImpl& impl) + { + serialise_typeimpl(impl); + } void serialise_traitimpl(const ::HIR::TraitImpl& impl) { TRACE_FUNCTION_F("impl" << impl.m_params.fmt_args() << " ?" << impl.m_trait_args << " for " << impl.m_type); @@ -410,6 +422,10 @@ } // m_src_module doesn't matter after typeck } + void serialise(const ::HIR::TraitImpl& impl) + { + serialise_traitimpl(impl); + } void serialise_markerimpl(const ::HIR::MarkerImpl& impl) { serialise_generics(impl.m_params); @@ -417,6 +433,10 @@ m_out.write_bool(impl.is_positive); serialise_type(impl.m_type); } + void serialise(const ::HIR::MarkerImpl& impl) + { + serialise_markerimpl(impl); + } void serialise(const ::HIR::TypeRef& ty) { serialise_type(ty); diff --git a/src/hir/visitor.cpp b/src/hir/visitor.cpp index f23bae88..8bf674b3 100644 --- a/src/hir/visitor.cpp +++ b/src/hir/visitor.cpp @@ -16,17 +16,34 @@ void ::HIR::Visitor::visit_crate(::HIR::Crate& crate) { this->visit_module(::HIR::ItemPath(crate.m_crate_name), crate.m_root_module ); - for( auto& ty_impl : crate.m_type_impls ) + for( auto& ty_impl_group : crate.m_named_type_impls ) + { + for( auto& ty_impl : ty_impl_group.second ) + { + this->visit_type_impl(ty_impl); + } + } + for( auto& ty_impl : crate.m_primitive_type_impls ) { this->visit_type_impl(ty_impl); } - for( auto& impl : crate.m_trait_impls ) + for( auto& ty_impl : crate.m_generic_type_impls ) { - this->visit_trait_impl(impl.first, impl.second); + this->visit_type_impl(ty_impl); } - for( auto& impl : crate.m_marker_impls ) + for( auto& impl_group : crate.m_trait_impls ) { - this->visit_marker_impl(impl.first, impl.second); + for( auto& impl : impl_group.second ) + { + this->visit_trait_impl(impl_group.first, impl); + } + } + for( auto& impl_group : crate.m_marker_impls ) + { + for( auto& impl : impl_group.second ) + { + this->visit_marker_impl(impl_group.first, impl); + } } } diff --git a/src/hir_conv/resolve_ufcs_outer.cpp b/src/hir_conv/resolve_ufcs_outer.cpp index a8accf4d..285f6e55 100644 --- a/src/hir_conv/resolve_ufcs_outer.cpp +++ b/src/hir_conv/resolve_ufcs_outer.cpp @@ -13,6 +13,7 @@ #include <hir/expr.hpp> #include <hir/visitor.hpp> #include <hir_typeck/common.hpp> // monomorphise_genericpath_needed +#include <algorithm> namespace { class Visitor: @@ -342,4 +343,46 @@ void ConvertHIR_ResolveUFCS_Outer(::HIR::Crate& crate) { Visitor exp { crate }; exp.visit_crate( crate ); + + // Sort impls! + auto new_end = ::std::remove_if(crate.m_generic_type_impls.begin(), crate.m_generic_type_impls.end(), [&crate](::HIR::TypeImpl& ty_impl) { + const auto& type = ty_impl.m_type; + const ::HIR::SimplePath* path = nullptr; + // - Generic paths get sorted + if( TU_TEST1(type.m_data, Path, .path.m_data.is_Generic()) ) + { + path = &type.m_data.as_Path().path.m_data.as_Generic().m_path; + } + // - So do trait objects + else if( type.m_data.is_TraitObject() ) + { + path = &type.m_data.as_TraitObject().m_trait.m_path.m_path; + } + else + { + // Keep as nullptr, will search primitive list + } + + if( path ) + { + auto it = crate.m_named_type_impls.find(*path); + if( it == crate.m_named_type_impls.end() ) + { + it = crate.m_named_type_impls.insert( ::std::make_pair(*path, ::std::vector<::HIR::TypeImpl>()) ).first; + } + it->second.push_back(mv$(ty_impl)); + } + else if( type.m_data.is_Path() || type.m_data.is_Generic() ) + { + return false; + } + else + { + crate.m_primitive_type_impls.push_back(mv$(ty_impl)); + } + return true; + }); + crate.m_generic_type_impls.erase(new_end, crate.m_generic_type_impls.end()); + + DEBUG("Impl counts: " << crate.m_named_type_impls.size() << " path groups, " << crate.m_primitive_type_impls.size() << " primitive, " << crate.m_generic_type_impls.size() << " ungrouped"); } diff --git a/src/hir_expand/closures.cpp b/src/hir_expand/closures.cpp index 94f272f8..b4ab564c 100644 --- a/src/hir_expand/closures.cpp +++ b/src/hir_expand/closures.cpp @@ -46,6 +46,48 @@ namespace { return rv; } + void push_new_impls(const Span& sp, ::HIR::Crate& crate, out_impls_t new_trait_impls) + { + for(auto& impl : new_trait_impls) + { + switch(impl.first) + { + case ::HIR::ExprNode_Closure::Class::Once: + crate.m_trait_impls[crate.get_lang_item_path(sp, "fn_once")].push_back( mv$(impl.second) ); + break; + case ::HIR::ExprNode_Closure::Class::Mut: + crate.m_trait_impls[crate.get_lang_item_path(sp, "fn_mut" )].push_back( mv$(impl.second) ); + break; + case ::HIR::ExprNode_Closure::Class::Shared: + crate.m_trait_impls[crate.get_lang_item_path(sp, "fn" )].push_back( mv$(impl.second) ); + break; + case ::HIR::ExprNode_Closure::Class::NoCapture: { + assert(impl.second.m_methods.size() == 1); + assert(impl.second.m_types.empty()); + assert(impl.second.m_constants.empty()); + // NOTE: This should always have a name + const auto& path = impl.second.m_type.m_data.as_Path().path.m_data.as_Generic().m_path; + DEBUG("Adding type impl " << path); + auto list_it = crate.m_named_type_impls.insert( ::std::make_pair(path, ::std::vector<::HIR::TypeImpl>()) ).first; + list_it->second.push_back( ::HIR::TypeImpl { + mv$(impl.second.m_params), + mv$(impl.second.m_type), + make_map1( + impl.second.m_methods.begin()->first, + ::HIR::TypeImpl::VisImplEnt< ::HIR::Function> { ::HIR::Publicity::new_global(), false, mv$(impl.second.m_methods.begin()->second.data) } + ), + {}, + mv$(impl.second.m_src_module) + } ); + } break; + case ::HIR::ExprNode_Closure::Class::Unknown: + BUG(Span(), "Encountered Unkown closure type in new impls"); + break; + } + } + new_trait_impls.resize(0); + } + /// Mutate the contents of a closure to update captures, variables, and types class ExprVisitor_Mutate: public ::HIR::ExprVisitorDef @@ -1190,37 +1232,8 @@ namespace { ::HIR::Visitor::visit_crate(crate); - for(auto& impl : m_new_trait_impls) - { - switch(impl.first) - { - case ::HIR::ExprNode_Closure::Class::Once: - crate.m_trait_impls.insert( ::std::make_pair(crate.get_lang_item_path(sp, "fn_once"), mv$(impl.second)) ); - break; - case ::HIR::ExprNode_Closure::Class::Mut: - crate.m_trait_impls.insert( ::std::make_pair(crate.get_lang_item_path(sp, "fn_mut" ), mv$(impl.second)) ); - break; - case ::HIR::ExprNode_Closure::Class::Shared: - crate.m_trait_impls.insert( ::std::make_pair(crate.get_lang_item_path(sp, "fn" ), mv$(impl.second)) ); - break; - case ::HIR::ExprNode_Closure::Class::NoCapture: - assert(impl.second.m_methods.size() == 1); - assert(impl.second.m_types.empty()); - assert(impl.second.m_constants.empty()); - crate.m_type_impls.push_back( ::HIR::TypeImpl { - mv$(impl.second.m_params), - mv$(impl.second.m_type), - make_map1(impl.second.m_methods.begin()->first, ::HIR::TypeImpl::VisImplEnt< ::HIR::Function> { ::HIR::Publicity::new_global(), false, mv$(impl.second.m_methods.begin()->second.data) }), - {}, - mv$(impl.second.m_src_module) - } ); - break; - case ::HIR::ExprNode_Closure::Class::Unknown: - BUG(Span(), "Encountered Unkown closure type in new impls"); - break; - } - } - m_new_trait_impls.resize(0); + push_new_impls(sp, crate, mv$(m_new_trait_impls)); + m_new_trait_impls.clear(); } void visit_module(::HIR::ItemPath p, ::HIR::Module& mod) override @@ -1399,34 +1412,8 @@ void HIR_Expand_Closures_Expr(const ::HIR::Crate& crate_ro, ::HIR::ExprPtr& exp) m.second.data.m_code.m_state->stage = ::HIR::ExprState::Stage::Typecheck; } impl.second.m_src_module = exp.m_state->m_mod_path; - switch(impl.first) - { - case ::HIR::ExprNode_Closure::Class::Once: - crate.m_trait_impls.insert( ::std::make_pair(crate.get_lang_item_path(sp, "fn_once"), mv$(impl.second)) ); - break; - case ::HIR::ExprNode_Closure::Class::Mut: - crate.m_trait_impls.insert( ::std::make_pair(crate.get_lang_item_path(sp, "fn_mut" ), mv$(impl.second)) ); - break; - case ::HIR::ExprNode_Closure::Class::Shared: - crate.m_trait_impls.insert( ::std::make_pair(crate.get_lang_item_path(sp, "fn" ), mv$(impl.second)) ); - break; - case ::HIR::ExprNode_Closure::Class::NoCapture: - assert(impl.second.m_methods.size() == 1); - assert(impl.second.m_types.empty()); - assert(impl.second.m_constants.empty()); - crate.m_type_impls.push_back( ::HIR::TypeImpl { - mv$(impl.second.m_params), - mv$(impl.second.m_type), - make_map1(impl.second.m_methods.begin()->first, ::HIR::TypeImpl::VisImplEnt< ::HIR::Function> { ::HIR::Publicity::new_global(), false, mv$(impl.second.m_methods.begin()->second.data) }), - {}, - mv$(impl.second.m_src_module) - } ); - break; - case ::HIR::ExprNode_Closure::Class::Unknown: - BUG(Span(), "Encountered Unkown closure type in new impls"); - break; - } } + push_new_impls(sp, crate, mv$(new_trait_impls)); } void HIR_Expand_Closures(::HIR::Crate& crate) diff --git a/src/hir_typeck/outer.cpp b/src/hir_typeck/outer.cpp index c2b216d4..38c6f652 100644 --- a/src/hir_typeck/outer.cpp +++ b/src/hir_typeck/outer.cpp @@ -506,26 +506,25 @@ namespace { ) else { // 1. Search for applicable inherent methods (COMES FIRST!) - for( const auto& impl : this->crate.m_type_impls ) - { - if( !impl.matches_type(*e.type) ) { - continue ; - } + if( this->crate.find_type_impls(*e.type, [](const auto& ty)->const auto&{return ty;}, [&](const auto& impl) { DEBUG("- matched inherent impl " << *e.type); // Search for item in this block switch( pc ) { case ::HIR::Visitor::PathContext::VALUE: if( impl.m_methods.find(e.item) == impl.m_methods.end() ) { - continue ; + return false; } // Found it, just keep going (don't care about details here) break; case ::HIR::Visitor::PathContext::TRAIT: case ::HIR::Visitor::PathContext::TYPE: - continue ; + return false; } + return true; + }) ) + { auto new_data = ::HIR::Path::Data::make_UfcsInherent({ mv$(e.type), mv$(e.item), mv$(e.params)} ); p.m_data = mv$(new_data); DEBUG("- Resolved, replace with " << p); diff --git a/src/trans/auto_impls.cpp b/src/trans/auto_impls.cpp index ea10c8e2..ced322a4 100644 --- a/src/trans/auto_impls.cpp +++ b/src/trans/auto_impls.cpp @@ -202,7 +202,7 @@ void Trans_AutoImpl_Clone(State& state, ::HIR::TypeRef ty) impl.m_methods.insert(::std::make_pair( RcString::new_interned("clone"), ::HIR::TraitImpl::ImplEnt< ::HIR::Function> { false, ::std::move(fcn) } )); // Add impl to the crate - state.crate.m_trait_impls.insert(::std::make_pair( state.lang_Clone, ::std::move(impl) )); + state.crate.m_trait_impls[state.lang_Clone].push_back( ::std::move(impl) ); } void Trans_AutoImpls(::HIR::Crate& crate, TransList& trans_list) @@ -227,18 +227,19 @@ void Trans_AutoImpls(::HIR::Crate& crate, TransList& trans_list) Trans_AutoImpl_Clone(state, mv$(ty)); } - const auto impl_range = crate.m_trait_impls.equal_range( state.lang_Clone ); + auto impl_list_it = crate.m_trait_impls.find(state.lang_Clone); for(const auto& ty : state.done_list) { + assert(impl_list_it != crate.m_trait_impls.end()); // TODO: Find a way of turning a set into a vector so items can be erased. auto p = ::HIR::Path(ty.clone(), ::HIR::GenericPath(state.lang_Clone), "clone"); //DEBUG("add_function(" << p << ")"); auto e = trans_list.add_function(::std::move(p)); - auto it = ::std::find_if( impl_range.first, impl_range.second, [&](const auto& i){ return i.second.m_type == ty; }); - assert( it->second.m_methods.size() == 1 ); - e->ptr = &it->second.m_methods.begin()->second.data; + auto it = ::std::find_if( impl_list_it->second.begin(), impl_list_it->second.end(), [&](const auto& i){ return i.m_type == ty; }); + assert( it->m_methods.size() == 1 ); + e->ptr = &it->m_methods.begin()->second.data; } } diff --git a/src/trans/enumerate.cpp b/src/trans/enumerate.cpp index dfc566c0..7ef605b9 100644 --- a/src/trans/enumerate.cpp +++ b/src/trans/enumerate.cpp @@ -48,6 +48,7 @@ namespace { TransList Trans_Enumerate_CommonPost(EnumState& state); void Trans_Enumerate_Types(EnumState& state); void Trans_Enumerate_FillFrom_Path(EnumState& state, const ::HIR::Path& path, const Trans_Params& pp); +void Trans_Enumerate_FillFrom_PathMono(EnumState& state, ::HIR::Path path); void Trans_Enumerate_FillFrom(EnumState& state, const ::HIR::Function& function, const Trans_Params& pp); void Trans_Enumerate_FillFrom(EnumState& state, const ::HIR::Static& stat, TransList_Static& stat_out, Trans_Params pp={}); void Trans_Enumerate_FillFrom_VTable (EnumState& state, ::HIR::Path vtable_path, const Trans_Params& pp); @@ -176,100 +177,125 @@ TransList Trans_Enumerate_Public(::HIR::Crate& crate) // Impl blocks StaticTraitResolve resolve { crate }; - for(auto& impl : crate.m_trait_impls) + for(auto& impl_group : crate.m_trait_impls) { - const auto& impl_ty = impl.second.m_type; - TRACE_FUNCTION_F("Impl " << impl.first << impl.second.m_trait_args << " for " << impl_ty); - if( impl.second.m_params.m_types.size() == 0 ) + const auto& trait_path = impl_group.first; + for(auto& impl : impl_group.second) { - auto cb_monomorph = monomorphise_type_get_cb(sp, &impl_ty, &impl.second.m_trait_args, nullptr); - - // Emit each method/static (in the trait itself) - const auto& trait = crate.get_trait_by_path(sp, impl.first); - for(const auto& vi : trait.m_values) + const auto& impl_ty = impl.m_type; + TRACE_FUNCTION_F("Impl " << trait_path << impl.m_trait_args << " for " << impl_ty); + if( impl.m_params.m_types.size() == 0 ) { - TRACE_FUNCTION_F("Item " << vi.first << " : " << vi.second.tag_str()); - // Constant, no codegen - if( vi.second.is_Constant() ) - ; - // Generic method, no codegen - else if( vi.second.is_Function() && vi.second.as_Function().m_params.m_types.size() > 0 ) - ; - // VTable, magic - else if( vi.first == "vtable#" ) - ; - else + auto cb_monomorph = monomorphise_type_get_cb(sp, &impl_ty, &impl.m_trait_args, nullptr); + + // Emit each method/static (in the trait itself) + const auto& trait = crate.get_trait_by_path(sp, trait_path); + for(const auto& vi : trait.m_values) { - // Check bounds before queueing for codegen - if( vi.second.is_Function() ) + TRACE_FUNCTION_F("Item " << vi.first << " : " << vi.second.tag_str()); + // Constant, no codegen + if( vi.second.is_Constant() ) + ; + // Generic method, no codegen + else if( vi.second.is_Function() && vi.second.as_Function().m_params.m_types.size() > 0 ) + ; + // VTable, magic + else if( vi.first == "vtable#" ) + ; + else { - bool rv = true; - for(const auto& b : vi.second.as_Function().m_params.m_bounds) + // Check bounds before queueing for codegen + if( vi.second.is_Function() ) { - if( !b.is_TraitBound() ) continue; - const auto& be = b.as_TraitBound(); + bool rv = true; + for(const auto& b : vi.second.as_Function().m_params.m_bounds) + { + if( !b.is_TraitBound() ) continue; + const auto& be = b.as_TraitBound(); - auto b_ty_mono = monomorphise_type_with(sp, be.type, cb_monomorph); resolve.expand_associated_types(sp, b_ty_mono); - auto b_tp_mono = monomorphise_traitpath_with(sp, be.trait, cb_monomorph, false); - for(auto& ty : b_tp_mono.m_path.m_params.m_types) { - resolve.expand_associated_types(sp, ty); - } - for(auto& assoc_bound : b_tp_mono.m_type_bounds) { - resolve.expand_associated_types(sp, assoc_bound.second); - } + auto b_ty_mono = monomorphise_type_with(sp, be.type, cb_monomorph); resolve.expand_associated_types(sp, b_ty_mono); + auto b_tp_mono = monomorphise_traitpath_with(sp, be.trait, cb_monomorph, false); + for(auto& ty : b_tp_mono.m_path.m_params.m_types) { + resolve.expand_associated_types(sp, ty); + } + for(auto& assoc_bound : b_tp_mono.m_type_bounds) { + resolve.expand_associated_types(sp, assoc_bound.second); + } - rv = resolve.find_impl(sp, b_tp_mono.m_path.m_path, b_tp_mono.m_path.m_params, b_ty_mono, [&](const auto& impl, bool) { - return true; - }); + rv = resolve.find_impl(sp, b_tp_mono.m_path.m_path, b_tp_mono.m_path.m_params, b_ty_mono, [&](const auto& impl, bool) { + return true; + }); + if( !rv ) + break; + } if( !rv ) - break; + continue ; } - if( !rv ) - continue ; + auto path = ::HIR::Path(impl_ty.clone(), ::HIR::GenericPath(trait_path, impl.m_trait_args.clone()), vi.first); + Trans_Enumerate_FillFrom_PathMono(state, mv$(path)); + //state.enum_fcn(mv$(path), fcn.second.data, {}); } - auto p = ::HIR::Path(impl_ty.clone(), ::HIR::GenericPath(impl.first, impl.second.m_trait_args.clone()), vi.first); - Trans_Enumerate_FillFrom_Path(state, p, {}); + } + for(auto& m : impl.m_methods) + { + if( m.second.data.m_params.m_types.size() > 0 ) + m.second.data.m_save_code = true; } } - for(auto& m : impl.second.m_methods) + else { - if( m.second.data.m_params.m_types.size() > 0 ) + for(auto& m : impl.m_methods) + { m.second.data.m_save_code = true; - } - } - else - { - for(auto& m : impl.second.m_methods) - { - m.second.data.m_save_code = true; + } } } } - for(auto& impl : crate.m_type_impls) + struct H1 { - if( impl.m_params.m_types.size() == 0 ) + static void enumerate_type_impl(EnumState& state, ::HIR::TypeImpl& impl) { - for(auto& fcn : impl.m_methods) + TRACE_FUNCTION_F("impl" << impl.m_params.fmt_args() << " " << impl.m_type); + if( impl.m_params.m_types.size() == 0 ) { - if( fcn.second.data.m_params.m_types.size() == 0 ) + for(auto& fcn : impl.m_methods) { - auto p = ::HIR::Path(impl.m_type.clone(), fcn.first); - Trans_Enumerate_FillFrom_Path(state, p, {}); + DEBUG("fn " << fcn.first << fcn.second.data.m_params.fmt_args()); + if( fcn.second.data.m_params.m_types.size() == 0 ) + { + auto path = ::HIR::Path(impl.m_type.clone(), fcn.first); + state.enum_fcn(mv$(path), fcn.second.data, {}); + } + else + { + fcn.second.data.m_save_code = true; + } } - else + } + else + { + for(auto& m : impl.m_methods) { - fcn.second.data.m_save_code = true; + m.second.data.m_save_code = true; } } } - else + }; + for(auto& impl_grp : crate.m_named_type_impls) + { + for(auto& impl : impl_grp.second) { - for(auto& m : impl.m_methods) - { - m.second.data.m_save_code = true; - } + H1::enumerate_type_impl(state, impl); } } + for(auto& impl : crate.m_primitive_type_impls) + { + H1::enumerate_type_impl(state, impl); + } + for(auto& impl : crate.m_generic_type_impls) + { + H1::enumerate_type_impl(state, impl); + } auto rv = Trans_Enumerate_CommonPost(state); @@ -407,7 +433,8 @@ TransList Trans_Enumerate_CommonPost(EnumState& state) return mv$(state.rv); } -namespace { +namespace +{ struct PtrComp { template<typename T> @@ -420,7 +447,8 @@ namespace { ::StaticTraitResolve m_resolve; ::std::vector< ::std::pair< ::HIR::TypeRef, bool> >& out_list; - ::std::map< ::HIR::TypeRef, bool > visited; + // TODO: Have a list of indexes into `out_list`, sorted by typeref ordering + ::std::vector<size_t> visited_map; ::std::set< const ::HIR::TypeRef*, PtrComp> active_set; TypeVisitor(const ::HIR::Crate& crate, ::std::vector< ::std::pair< ::HIR::TypeRef, bool > >& out_list): @@ -429,6 +457,11 @@ namespace { out_list(out_list) {} + ~TypeVisitor() + { + DEBUG("Visited a total of " << visited_map.size()); + } + void visit_struct(const ::HIR::GenericPath& path, const ::HIR::Struct& item) { static Span sp; ::HIR::TypeRef tmp; @@ -506,16 +539,16 @@ namespace { { // If the type has already been visited, AND either this is a shallow visit, or the previous wasn't { - auto it = visited.find(ty); - if( it != visited.end() ) + auto idx_it = ::std::lower_bound(visited_map.begin(), visited_map.end(), ty, [&](size_t i, const ::HIR::TypeRef& t){ return out_list[i].first < t; }); + if( idx_it != visited_map.end() && out_list[*idx_it].first == ty) { + auto it = &out_list[*idx_it]; if( it->second == false || mode == Mode::Shallow ) { // Return early return ; } DEBUG("-- " << ty << " already visited as shallow"); - it->second = false; } } TRACE_FUNCTION_F(ty << " - " << (mode == Mode::Shallow ? "Shallow" : (mode == Mode::Normal ? "Normal" : "Deep"))); @@ -635,37 +668,30 @@ namespace { bool shallow = (mode == Mode::Shallow); { - auto rv = visited.insert( ::std::make_pair(ty.clone(), shallow) ); - if( !rv.second && ! shallow ) + auto idx_it = ::std::lower_bound(visited_map.begin(), visited_map.end(), ty, [&](size_t i, const ::HIR::TypeRef& t){ return out_list[i].first < t; }); + if( idx_it == visited_map.end() || out_list[*idx_it].first != ty ) { - rv.first->second = false; + // Add a new entry + visited_map.insert(idx_it, out_list.size()); + } + else + { + // Previous visit was shallow, but this one isn't + // - Update the entry to the to-be-pushed entry with shallow=false + if( !shallow && out_list[*idx_it].second ) + { + *idx_it = out_list.size(); + } } } out_list.push_back( ::std::make_pair(ty.clone(), shallow) ); DEBUG("Add type " << ty << (shallow ? " (Shallow)": "")); } - }; -} - -// Enumerate types required for the enumerated items -void Trans_Enumerate_Types(EnumState& state) -{ - static Span sp; - TypeVisitor tv { state.crate, state.rv.m_types }; - unsigned int types_count = 0; - bool constructors_added; - do - { - // Visit all functions that haven't been type-visited yet - for(unsigned int i = 0; i < state.fcns_to_type_visit.size(); i++) + void __attribute__ ((noinline)) visit_function(const ::HIR::Path& path, const ::HIR::Function& fcn, const Trans_Params& pp) { - auto* p = state.fcns_to_type_visit[i]; - auto& fcn_path = ::std::find_if(state.rv.m_functions.begin(), state.rv.m_functions.end(), [&](const auto&x){ return x.second.get() == p; })->first; - TRACE_FUNCTION_F("Function " << fcn_path); - assert(p->ptr); - const auto& fcn = *p->ptr; - const auto& pp = p->pp; + Span sp; + auto& tv = *this; ::HIR::TypeRef tmp; auto monomorph = [&](const auto& ty)->const auto& { @@ -909,8 +935,35 @@ void Trans_Enumerate_Types(EnumState& state) } } } + }; // struct TypeVisitor +} // namespace <empty> + +// Enumerate types required for the enumerated items +void Trans_Enumerate_Types(EnumState& state) +{ + static Span sp; + TypeVisitor tv { state.crate, state.rv.m_types }; + + unsigned int types_count = 0; + bool constructors_added; + do + { + // Visit all functions that haven't been type-visited yet + for(unsigned int i = 0; i < state.fcns_to_type_visit.size(); i++) + { + auto* p = state.fcns_to_type_visit[i]; + assert(p->path); + assert(p->ptr); + auto& fcn_path = *p->path; + const auto& fcn = *p->ptr; + const auto& pp = p->pp; + + TRACE_FUNCTION_F("Function " << fcn_path); + tv.visit_function(fcn_path, fcn, pp); + } state.fcns_to_type_visit.clear(); // TODO: Similarly restrict revisiting of statics. + // - Challenging, as they're stored as a std::map for(const auto& ent : state.rv.m_statics) { TRACE_FUNCTION_F("Enumerate static " << ent.first); @@ -957,22 +1010,16 @@ void Trans_Enumerate_Types(EnumState& state) if( ty.m_data.is_Path() ) { const auto& te = ty.m_data.as_Path(); - const ::HIR::TraitMarkings* markings_ptr = nullptr; - TU_MATCHA( (te.binding), (tpb), - (Unbound, ), - (Opaque, ), - (ExternType, markings_ptr = &tpb->m_markings; ), - (Struct, markings_ptr = &tpb->m_markings; ), - (Union, markings_ptr = &tpb->m_markings; ), - (Enum, markings_ptr = &tpb->m_markings; ) - ) - ASSERT_BUG(Span(), markings_ptr, "Path binding not set correctly - " << ty); + ASSERT_BUG(sp, te.path.m_data.is_Generic(), "Non-Generic type path after enumeration - " << ty); + const auto& gp = te.path.m_data.as_Generic(); + const ::HIR::TraitMarkings* markings_ptr = te.binding.get_trait_markings(); + ASSERT_BUG(sp, markings_ptr, "Path binding not set correctly - " << ty); // If the type has a drop impl, and it's either defined in this crate or has params (and thus was monomorphised) - if( markings_ptr->has_drop_impl && (te.path.m_data.as_Generic().m_path.m_crate_name == state.crate.m_crate_name || te.path.m_data.as_Generic().m_params.has_params()) ) + if( markings_ptr->has_drop_impl && (gp.m_path.m_crate_name == state.crate.m_crate_name || gp.m_params.has_params()) ) { // Add the Drop impl to the codegen list - Trans_Enumerate_FillFrom_Path(state, ::HIR::Path( ty.clone(), state.crate.get_lang_item_path(sp, "drop"), "drop"), {}); + Trans_Enumerate_FillFrom_PathMono(state, ::HIR::Path( ty.clone(), state.crate.get_lang_item_path(sp, "drop"), "drop")); constructors_added = true; } } @@ -982,7 +1029,7 @@ void Trans_Enumerate_Types(EnumState& state) // Reqire drop glue for inner type. // - Should that already exist? // Requires box_free lang item - Trans_Enumerate_FillFrom_Path(state, ::HIR::GenericPath( state.crate.get_lang_item_path(sp, "box_free"), { ity->clone() } ), {});; + Trans_Enumerate_FillFrom_PathMono(state, ::HIR::GenericPath( state.crate.get_lang_item_path(sp, "box_free"), { ity->clone() } )); } } types_count = state.rv.m_types.size(); @@ -1278,24 +1325,27 @@ namespace MIR { void Trans_Enumerate_FillFrom_Path(EnumState& state, const ::HIR::Path& path, const Trans_Params& pp) { - TRACE_FUNCTION_F(path); - Span sp; auto path_mono = pp.monomorph(state.crate, path); - DEBUG("- " << path_mono); + Trans_Enumerate_FillFrom_PathMono(state, mv$(path_mono)); +} +void Trans_Enumerate_FillFrom_PathMono(EnumState& state, ::HIR::Path path_mono) +{ + TRACE_FUNCTION_F(path_mono); + Span sp; // TODO: If already in the list, return early - if( state.rv.m_functions.count(path) ) { + if( state.rv.m_functions.count(path_mono) ) { DEBUG("> Already done function"); return ; } - if( state.rv.m_statics.count(path) ) { + if( state.rv.m_statics.count(path_mono) ) { DEBUG("> Already done static"); return ; } - if( state.rv.m_constants.count(path) ) { + if( state.rv.m_constants.count(path_mono) ) { DEBUG("> Already done constant"); return ; } - if( state.rv.m_vtables.count(path) ) { + if( state.rv.m_vtables.count(path_mono) ) { DEBUG("> Already done vtable"); return ; } @@ -1315,7 +1365,7 @@ void Trans_Enumerate_FillFrom_Path(EnumState& state, const ::HIR::Path& path, co sub_pp.self_type = pe.type->clone(); ), (UfcsUnknown, - BUG(sp, "UfcsUnknown - " << path); + BUG(sp, "UfcsUnknown - " << path_mono); ) ) // Get the item type @@ -1368,8 +1418,7 @@ void Trans_Enumerate_FillFrom_Path(EnumState& state, const ::HIR::Path& path, co auto enum_impl = [&](const ::HIR::TypeRef& ity) { if( !resolve.type_is_copy(sp, ity) ) { - auto p = ::HIR::Path(ity.clone(), pe.trait.clone(), pe.item); - Trans_Enumerate_FillFrom_Path(state, p, {}); + Trans_Enumerate_FillFrom_PathMono(state, ::HIR::Path(ity.clone(), pe.trait.clone(), pe.item)); } }; if( const auto* te = inner_ty.m_data.opt_Tuple() ) { @@ -1599,7 +1648,7 @@ void Trans_Enumerate_FillFrom_VTable(EnumState& state, ::HIR::Path vtable_path, { DEBUG("- " << m.second.first << " = " << m.second.second << " :: " << m.first); auto gpath = monomorphise_genericpath_with(sp, m.second.second, monomorph_cb_trait, false); - Trans_Enumerate_FillFrom_Path(state, ::HIR::Path(type.clone(), mv$(gpath), m.first), {}); + Trans_Enumerate_FillFrom_PathMono(state, ::HIR::Path(type.clone(), mv$(gpath), m.first)); } } diff --git a/src/trans/trans_list.cpp b/src/trans/trans_list.cpp index 54ae8011..3d8aa86f 100644 --- a/src/trans/trans_list.cpp +++ b/src/trans/trans_list.cpp @@ -15,7 +15,7 @@ TransList_Function* TransList::add_function(::HIR::Path p) { DEBUG("Function " << rv.first->first); assert( !rv.first->second ); - rv.first->second.reset( new TransList_Function {} ); + rv.first->second.reset( new TransList_Function(rv.first->first) ); return &*rv.first->second; } else diff --git a/src/trans/trans_list.hpp b/src/trans/trans_list.hpp index df550925..7009111f 100644 --- a/src/trans/trans_list.hpp +++ b/src/trans/trans_list.hpp @@ -49,12 +49,14 @@ struct CachedFunction { }; struct TransList_Function { + const ::HIR::Path* path; // Pointer into the list (std::map pointers are stable) const ::HIR::Function* ptr; Trans_Params pp; // If `pp.has_types` is true, the below is valid CachedFunction monomorphised; - TransList_Function(): + TransList_Function(const ::HIR::Path& path): + path(&path), ptr(nullptr) {} }; |