summaryrefslogtreecommitdiff
path: root/src/hir_conv/markings.cpp
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2017-01-14 17:01:36 +0800
committerJohn Hodge <tpg@mutabah.net>2017-01-14 17:01:36 +0800
commit63fb307fb112dcf3abb73c1da0dfb5a27935f4eb (patch)
tree5473ed81b50a4571ab7eca0da9dbcbaf53092ee0 /src/hir_conv/markings.cpp
parent53983bf333143560ef4b161eaa2f46c55bcd517b (diff)
downloadmrust-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.cpp157
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