diff options
author | John Hodge <tpg@mutabah.net> | 2017-01-14 17:01:36 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2017-01-14 17:01:36 +0800 |
commit | 63fb307fb112dcf3abb73c1da0dfb5a27935f4eb (patch) | |
tree | 5473ed81b50a4571ab7eca0da9dbcbaf53092ee0 /src/hir_conv/markings.cpp | |
parent | 53983bf333143560ef4b161eaa2f46c55bcd517b (diff) | |
download | mrust-63fb307fb112dcf3abb73c1da0dfb5a27935f4eb.tar.gz |
HIR - Build up a flattened list of parent traits early to save time later
Diffstat (limited to 'src/hir_conv/markings.cpp')
-rw-r--r-- | src/hir_conv/markings.cpp | 157 |
1 files changed, 156 insertions, 1 deletions
diff --git a/src/hir_conv/markings.cpp b/src/hir_conv/markings.cpp index e40ce537..d867fc06 100644 --- a/src/hir_conv/markings.cpp +++ b/src/hir_conv/markings.cpp @@ -3,7 +3,7 @@ * - By John Hodge (Mutabah/thePowersGang) * * hir_conv/markings.cpp - * - Fills the TraitMarkings structure on types + * - Fills the TraitMarkings structure on types as well as other metadata */ #include "main_bindings.hpp" #include <hir/visitor.hpp> @@ -45,6 +45,161 @@ public: } } + void visit_trait(::HIR::ItemPath ip, ::HIR::Trait& tr) override + { + static Span sp; + TRACE_FUNCTION_F(ip); + + // Enumerate supertraits and save for later stages + struct Enumerate + { + ::std::vector< ::HIR::TraitPath> supertraits; + + void enum_supertraits_in(const ::HIR::Trait& tr, ::HIR::GenericPath path, ::std::function<::HIR::TypeRef(const char*)> get_aty) + { + TRACE_FUNCTION_F(path); + + // Fill defaulted parameters. + // NOTE: Doesn't do much error checking. + if( path.m_params.m_types.size() != tr.m_params.m_types.size() ) + { + ASSERT_BUG(sp, path.m_params.m_types.size() < tr.m_params.m_types.size(), ""); + for(unsigned int i = path.m_params.m_types.size(); i < tr.m_params.m_types.size(); i ++) + { + const auto& def = tr.m_params.m_types[i]; + path.m_params.m_types.push_back( def.m_default.clone() ); + } + } + + ::HIR::TypeRef ty_self { "Self", 0xFFFF }; + auto monomorph_cb = monomorphise_type_get_cb(sp, &ty_self, &path.m_params, nullptr); + // Recurse into parent traits + for(const auto& pt : tr.m_parent_traits) + { + auto get_aty_this = [&](const char* name) { + auto it = pt.m_type_bounds.find(name); + if( it != pt.m_type_bounds.end() ) + return monomorphise_type_with(sp, it->second, monomorph_cb); + return get_aty(name); + }; + enum_supertraits_in(*pt.m_trait_ptr, monomorphise_genericpath_with(sp, pt.m_path, monomorph_cb, false), get_aty_this); + } + // - Bound parent traits + for(const auto& b : tr.m_params.m_bounds) + { + if( !b.is_TraitBound() ) + continue; + const auto& be = b.as_TraitBound(); + if( be.type != ::HIR::TypeRef("Self", 0xFFFF) ) + continue; + const auto& pt = be.trait; + if( pt.m_path.m_path == path.m_path ) + continue ; + + auto get_aty_this = [&](const char* name) { + auto it = pt.m_type_bounds.find(name); + if( it != pt.m_type_bounds.end() ) + return monomorphise_type_with(sp, it->second, monomorph_cb); + return get_aty(name); + }; + + enum_supertraits_in(*pt.m_trait_ptr, monomorphise_genericpath_with(sp, pt.m_path, monomorph_cb, false), get_aty_this); + } + + + // Build output path. + ::HIR::TraitPath out_path; + out_path.m_path = mv$(path); + out_path.m_trait_ptr = &tr; + // - Locate associated types for this trait + for(const auto& ty : tr.m_types) + { + auto v = get_aty(ty.first.c_str()); + if( v != ::HIR::TypeRef() ) + { + out_path.m_type_bounds.insert( ::std::make_pair(ty.first, mv$(v)) ); + } + } + // TODO: HRLs? + supertraits.push_back( mv$(out_path) ); + } + }; + + auto this_path = ip.get_simple_path(); + this_path.m_crate_name = m_crate.m_crate_name; + + Enumerate e; + for(const auto& pt : tr.m_parent_traits) + { + auto get_aty = [&](const char* name) { + auto it = pt.m_type_bounds.find(name); + if( it != pt.m_type_bounds.end() ) + return it->second.clone(); + return ::HIR::TypeRef(); + }; + e.enum_supertraits_in(*pt.m_trait_ptr, pt.m_path.clone(), get_aty); + } + for(const auto& b : tr.m_params.m_bounds) + { + if( !b.is_TraitBound() ) + continue; + const auto& be = b.as_TraitBound(); + if( be.type != ::HIR::TypeRef("Self", 0xFFFF) ) + continue; + const auto& pt = be.trait; + + // TODO: Remove this along with the from_ast.cpp hack + if( pt.m_path.m_path == this_path ) + { + // TODO: Should this restrict based on the parameters + continue ; + } + + auto get_aty = [&](const char* name) { + auto it = be.trait.m_type_bounds.find(name); + if( it != be.trait.m_type_bounds.end() ) + return it->second.clone(); + return ::HIR::TypeRef(); + }; + e.enum_supertraits_in(*be.trait.m_trait_ptr, be.trait.m_path.clone(), get_aty); + } + + ::std::sort(e.supertraits.begin(), e.supertraits.end()); + DEBUG("supertraits = " << e.supertraits); + if( e.supertraits.size() > 0 ) + { + bool dedeup_done = false; + auto prev = e.supertraits.begin(); + for(auto it = e.supertraits.begin()+1; it != e.supertraits.end(); ) + { + if( prev->m_path == it->m_path ) + { + if( *prev == *it ) { + } + else if( prev->m_type_bounds.size() == 0 ) { + ::std::swap(*prev, *it); + } + else if( it->m_type_bounds.size() == 0 ) { + } + else { + TODO(sp, "Merge associated types from " << *prev << " and " << *it); + } + it = e.supertraits.erase(it); + dedeup_done = true; + } + else + { + ++ it; + ++ prev; + } + } + if( dedeup_done ) { + DEBUG("supertraits dd = " << e.supertraits); + } + } + tr.m_all_parent_traits = mv$(e.supertraits); + } + ::HIR::TraitMarkings::DstType get_field_dst_type(const ::HIR::TypeRef& ty, const ::HIR::GenericParams& inner_def, const ::HIR::GenericParams& params_def, const ::HIR::PathParams* params) { // If the type is generic, and the pointed-to parameters is ?Sized, record as needing unsize |