diff options
author | John Hodge <tpg@mutabah.net> | 2016-12-30 10:09:06 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-12-30 10:09:06 +0800 |
commit | eaacd862ba4942334e15b8cea90b7efec49dd382 (patch) | |
tree | ce80074f1152ef8b80f9d99d69f3b4a87630e85e | |
parent | ea1bde177c33bdd734294ed1616f9fd67ce4b28e (diff) | |
download | mrust-eaacd862ba4942334e15b8cea90b7efec49dd382.tar.gz |
HIR - Hack in more specialisation rules
-rw-r--r-- | src/hir/hir.cpp | 58 |
1 files changed, 51 insertions, 7 deletions
diff --git a/src/hir/hir.cpp b/src/hir/hir.cpp index 18b09fac..8d519f41 100644 --- a/src/hir/hir.cpp +++ b/src/hir/hir.cpp @@ -530,19 +530,63 @@ bool ::HIR::TraitImpl::more_specific_than(const ::HIR::TraitImpl& other) const return false; auto it_t = bounds_t.begin(); - for(auto it_o = bounds_o.begin(); it_o != bounds_o.end(); ++it_o) + auto it_o = bounds_o.begin(); + while( it_t != bounds_t.end() && it_o != bounds_o.end() ) { - // TODO: `T: Foo<T>` is more specific than `T: Foo<U>`, this method doesn't pick that. - while( ::ord(*it_t, *it_o) == OrdLess && it_t != bounds_t.end() ) + auto cmp = ::ord(*it_t, *it_o); + if( cmp == OrdEqual ) + { + ++it_t; + ++it_o; + continue ; + } + + // If the two bounds are similar + if( it_t->tag() == it_o->tag() && it_t->is_TraitBound() ) + { + const auto& b_t = it_t->as_TraitBound(); + const auto& b_o = it_o->as_TraitBound(); + // Check if the type is equal + if( b_t.type == b_o.type && b_t.trait.m_path.m_path == b_o.trait.m_path.m_path ) + { + const auto& params_t = b_t.trait.m_path.m_params; + const auto& params_o = b_o.trait.m_path.m_params; + switch( typelist_ord_specific(sp, params_t.m_types, params_o.m_types) ) + { + case ::OrdLess: return false; + case ::OrdGreater: return true; + case ::OrdEqual: break; + } + // TODO: Find cases where there's `T: Foo<T>` and `T: Foo<U>` + for(unsigned int i = 0; i < params_t.m_types.size(); i ++ ) + { + if( params_t.m_types[i] != params_o.m_types[i] && params_t.m_types[i] == b_t.type ) + { + return true; + } + } + TODO(sp, *it_t << " ?= " << *it_o); + } + } + + if( cmp == OrdLess ) + { ++ it_t; - if( it_t == bounds_t.end() || ::ord(*it_t, *it_o) > OrdEqual ) { - TODO(Span(), "Error when an impl is missing a bound - " << *it_t << " != " << *it_o); + } + else + { + //++ it_o; return false; } } - if( bounds_t.size() <= bounds_o.size() ) + if( it_t != bounds_t.end() ) + { + return true; + } + else + { return false; - return true; + } } |