From 3bf9a102de5421864863c26626f667ab2429e8bc Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 21 Apr 2019 19:18:20 +0800 Subject: [PATCH] Typecheck Expessions - Improved handling of overlapping bounds, diverging ivars --- src/hir_typeck/expr_cs.cpp | 27 +++++++++++++++++++++------ src/hir_typeck/helpers.cpp | 9 +++++++-- src/hir_typeck/helpers.hpp | 1 + src/hir_typeck/impl_ref.cpp | 31 +++++++++++++++++++++++++++++-- 4 files changed, 58 insertions(+), 10 deletions(-) diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 9b1b35b51..3bc7cfe58 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -84,12 +84,15 @@ struct Context bool is_operator; friend ::std::ostream& operator<<(::std::ostream& os, const Associated& v) { + os << "R" << v.rule_idx << " "; if( v.name == "" ) { - os << "R" << v.rule_idx << " " << "req ty " << v.impl_ty << " impl " << v.trait << v.params; + os << "req ty " << v.impl_ty << " impl " << v.trait << v.params; } else { - os << "R" << v.rule_idx << " " << v.left_ty << " = " << "< `" << v.impl_ty << "` as `" << v.trait << v.params << "` >::" << v.name; + os << v.left_ty << " = " << "< `" << v.impl_ty << "` as `" << v.trait << v.params << "` >::" << v.name; } + if( v.is_operator ) + os << " - op"; return os; } }; @@ -5802,13 +5805,23 @@ namespace { unsigned int count = 0; ::HIR::PathParams pp { dst.clone() }; - bool found = context.m_resolve.find_trait_impls(sp, lang_Unsize, pp, src, [&best_impl,&count](auto impl, auto cmp){ + bool found = context.m_resolve.find_trait_impls(sp, lang_Unsize, pp, src, [&best_impl,&count,&context](auto impl, auto cmp){ DEBUG("[check_unsize_tys] Found impl " << impl << (cmp == ::HIR::Compare::Fuzzy ? " (fuzzy)" : "")); - if( impl.more_specific_than(best_impl) ) + if( !impl.overlaps_with(context.m_crate, best_impl) ) { - best_impl = mv$(impl); + // No overlap, count it as a new possibility + if( count == 0 ) + best_impl = mv$(impl); count ++; } + else if( impl.more_specific_than(best_impl) ) + { + best_impl = mv$(impl); + } + else + { + // Less specific + } // TODO: Record the best impl (if fuzzy) and equate params return cmp != ::HIR::Compare::Fuzzy; }); @@ -5830,6 +5843,7 @@ namespace { { // TODO: Fuzzy? //context.equate_types(sp, *e.inner, *s_e.inner); + DEBUG("Multiple impls"); } } @@ -6814,7 +6828,8 @@ namespace { return false; } - // Don't attempt to guess literalS + // Don't attempt to guess literals + // - What about if they're bounded? if( ty_l.m_data.as_Infer().is_lit() ) { DEBUG(i << ": Literal " << ty_l); diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index 529d2727f..053aab4dd 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -619,8 +619,12 @@ void HMTypeInferrence::set_ivar_to(unsigned int slot, ::HIR::TypeRef type) } #if 1 - if( type.m_data.is_Diverge() ) { - root_ivar.type->m_data.as_Infer().ty_class = ::HIR::InferClass::Diverge; + if( type.m_data.is_Diverge() ) + { + if( root_ivar.type->m_data.as_Infer().ty_class == ::HIR::InferClass::None ) + { + root_ivar.type->m_data.as_Infer().ty_class = ::HIR::InferClass::Diverge; + } } else #endif @@ -2276,6 +2280,7 @@ bool TraitResolution::find_named_trait_in_trait(const Span& sp, //DEBUG(pt << " => " << pt_mono); if( pt.m_path.m_path == des ) { + //DEBUG("Found potential " << pt_mono); // NOTE: Doesn't quite work... //auto cmp = this->compare_pp(sp, pt_mono.m_path.m_params, des_params); //if( cmp != ::HIR::Compare::Unequal ) diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp index fcd17cfb4..651a36c86 100644 --- a/src/hir_typeck/helpers.hpp +++ b/src/hir_typeck/helpers.hpp @@ -57,6 +57,7 @@ class HMTypeInferrence public: // ?? - Needed once, anymore? struct IVar { + //bool could_be_diverge; // TODO: use this instead of InferClass::Diverge unsigned int alias; // If not ~0, this points to another ivar ::std::unique_ptr< ::HIR::TypeRef> type; // Type (only nullptr if alias!=0) diff --git a/src/hir_typeck/impl_ref.cpp b/src/hir_typeck/impl_ref.cpp index 86f886482..910a3c5eb 100644 --- a/src/hir_typeck/impl_ref.cpp +++ b/src/hir_typeck/impl_ref.cpp @@ -32,10 +32,24 @@ bool ImplRef::more_specific_than(const ImplRef& other) const ) ), (BoundedPtr, - return true; + if( !other.m_data.is_BoundedPtr() ) + return false; + const auto& oe = other.m_data.as_BoundedPtr(); + assert( *te.type == *oe.type ); + assert( *te.trait_args == *oe.trait_args ); + if( te.assoc->size() > oe.assoc->size() ) + return true; + return false; ), (Bounded, - return true; + if( !other.m_data.is_Bounded() ) + return false; + const auto& oe = other.m_data.as_Bounded(); + assert( te.type == oe.type ); + assert( te.trait_args == oe.trait_args ); + if( te.assoc.size() > oe.assoc.size() ) + return true; + return false; ) ) throw ""; @@ -50,8 +64,21 @@ bool ImplRef::overlaps_with(const ::HIR::Crate& crate, const ImplRef& other) con return te.impl->overlaps_with( crate, *oe.impl ); ), (BoundedPtr, + // TODO: Bounded and BoundedPtr are compatible + if( *te.type != *oe.type ) + return false; + if( *te.trait_args != *oe.trait_args ) + return false; + // Don't check associated types + return true; ), (Bounded, + if( te.type != oe.type ) + return false; + if( te.trait_args != oe.trait_args ) + return false; + // Don't check associated types + return true; ) ) return false;