diff options
author | John Hodge <tpg@mutabah.net> | 2016-07-19 19:41:01 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-07-19 19:41:01 +0800 |
commit | 3fab1f6071718b5456d4c6b33fa5afe8f9a43f71 (patch) | |
tree | 8d6c97418b3d97b076a8b70c63d3f157494e9a3b | |
parent | 394fb3ccec788e2c3abff511d142a9573bc783a6 (diff) | |
download | mrust-3fab1f6071718b5456d4c6b33fa5afe8f9a43f71.tar.gz |
HIR - Very rough impl specialisation support in outer typeck
-rw-r--r-- | src/hir/type.cpp | 68 | ||||
-rw-r--r-- | src/hir/type.hpp | 1 | ||||
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 1 | ||||
-rw-r--r-- | src/hir_typeck/outer.cpp | 35 | ||||
-rw-r--r-- | src/hir_typeck/static.cpp | 47 | ||||
-rw-r--r-- | src/hir_typeck/static.hpp | 40 |
6 files changed, 170 insertions, 22 deletions
diff --git a/src/hir/type.cpp b/src/hir/type.cpp index 7695f066..a27d5dd0 100644 --- a/src/hir/type.cpp +++ b/src/hir/type.cpp @@ -351,6 +351,74 @@ Ordering HIR::TypeRef::ord(const ::HIR::TypeRef& x) const ) throw ""; } +bool ::HIR::TypeRef::contains_generics() const +{ + struct H { + static bool vec_contains_generics(const ::std::vector<TypeRef>& v) { + for( const auto& t : v ) + if( t.contains_generics() ) + return true; + return false; + } + }; + TU_MATCH(::HIR::TypeRef::Data, (m_data), (te), + (Infer, + return false; + ), + (Diverge, + return false; + ), + (Primitive, + return false; + ), + (Path, + TU_MATCH(::HIR::Path::Data, (te.path.m_data), (tpe), + (Generic, + return H::vec_contains_generics( tpe.m_params.m_types ); + ), + (UfcsInherent, + if( tpe.type->contains_generics() ) + return true; + TODO(Span(), "UfcsInherent"); + ), + (UfcsKnown, + TODO(Span(), "UfcsKnown"); + ), + (UfcsUnknown, + TODO(Span(), "UfcsUnknown"); + ) + ) + ), + (Generic, + return true; + ), + (TraitObject, + TODO(Span(), "TraitObject"); + ), + (Array, + return te.inner->contains_generics(); + ), + (Slice, + return te.inner->contains_generics(); + ), + (Tuple, + return H::vec_contains_generics(te); + ), + (Borrow, + return te.inner->contains_generics(); + ), + (Pointer, + return te.inner->contains_generics(); + ), + (Function, + return H::vec_contains_generics(te.m_arg_types) || te.m_rettype->contains_generics(); + ), + (Closure, + return H::vec_contains_generics(te.m_arg_types) || te.m_rettype->contains_generics(); + ) + ) + throw ""; +} namespace { diff --git a/src/hir/type.hpp b/src/hir/type.hpp index c5d08c5f..f01c0f1d 100644 --- a/src/hir/type.hpp +++ b/src/hir/type.hpp @@ -222,6 +222,7 @@ public: bool operator<(const ::HIR::TypeRef& x) const { return ord(x) == OrdLess; } Ordering ord(const ::HIR::TypeRef& x) const; + bool contains_generics() const; // Match generics in `this` with types from `x` // Raises a bug against `sp` if there is a form mismatch or `this` has an infer diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 195e5e66..86304b4a 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -834,6 +834,7 @@ namespace { const auto& des_ty_r = it->second.ent; auto& des_ty_cache = node.m_value_types[it - fields.begin()]; + DEBUG(name << " : " << des_ty_r); if( monomorphise_type_needed(des_ty_r) ) { if( des_ty_cache == ::HIR::TypeRef() ) { des_ty_cache = monomorphise_type_with(node.span(), des_ty_r, monomorph_cb); diff --git a/src/hir_typeck/outer.cpp b/src/hir_typeck/outer.cpp index 22dcaa43..2baa6ec5 100644 --- a/src/hir_typeck/outer.cpp +++ b/src/hir_typeck/outer.cpp @@ -251,19 +251,30 @@ namespace { e.binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({}); } else { - ::HIR::TypeRef new_ty; - bool found = m_resolve.find_impl(sp, pe.trait.m_path, pe.trait.m_params, *pe.type, [&](const auto& impl) { - DEBUG("TODO - Extract associated type '"<<pe.item<<"' from " << impl); - new_ty = impl.get_type(pe.item.c_str()); - if( new_ty == ::HIR::TypeRef() ) { - ERROR(sp, E0000, "Associated type '"<<pe.item<<"' could not be found in " << pe.trait); - } - return true; + StaticTraitResolve::ImplRef best_impl; + m_resolve.find_impl(sp, pe.trait.m_path, pe.trait.m_params, *pe.type, [&](auto impl) { + DEBUG("[visit_type] Found " << impl); + if( best_impl.more_specific_than(impl) ) + return false; + best_impl = mv$(impl); + if( ! best_impl.type_is_specializable(pe.item.c_str()) ) + return true; + return false; }); - if( found ) { - assert( new_ty != ::HIR::TypeRef() ); - DEBUG("Replaced " << ty << " with " << new_ty); - ty = mv$(new_ty); + if( best_impl.is_valid() ) { + // If the type is still specialisable, and there's geerics in the type. + if( best_impl.type_is_specializable(pe.item.c_str()) && pe.type->contains_generics() ) { + // Mark it as opaque (because monomorphisation could change things) + e.binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({}); + } + else { + auto new_ty = best_impl.get_type(pe.item.c_str()); + if( new_ty == ::HIR::TypeRef() ) { + ERROR(sp, E0000, "Associated type '"<<pe.item<<"' could not be found in " << pe.trait); + } + DEBUG("Replaced " << ty << " with " << new_ty); + ty = mv$(new_ty); + } } else { ERROR(sp, E0000, "Couldn't find an impl of " << pe.trait << " for " << *pe.type); diff --git a/src/hir_typeck/static.cpp b/src/hir_typeck/static.cpp index 4a7de82e..1ee20dfd 100644 --- a/src/hir_typeck/static.cpp +++ b/src/hir_typeck/static.cpp @@ -53,7 +53,7 @@ bool StaticTraitResolve::find_impl( return false; } // Hand off to the closure, and return true if it does - if( found_cb(ImplRef(e.type, e.trait.m_path.m_params, e.trait.m_type_bounds)) ) { + if( found_cb(ImplRef(&e.type, &e.trait.m_path.m_params, &e.trait.m_type_bounds)) ) { return true; } } @@ -71,7 +71,7 @@ bool StaticTraitResolve::find_impl( assoc.insert( ::std::make_pair(i.first, i.second.clone()) ); //} } - return found_cb( ImplRef(type, params, assoc) ); + return found_cb( ImplRef(type.clone(), params.clone(), mv$(assoc)) ); }); if( rv ) { return true; @@ -106,7 +106,7 @@ bool StaticTraitResolve::find_impl( } DEBUG("- tp_mono = " << tp_mono); // TODO: Instead of using `type` here, build the real type - if( found_cb( ImplRef(type, tp_mono.m_path.m_params, tp_mono.m_type_bounds) ) ) { + if( found_cb( ImplRef(type.clone(), mv$(tp_mono.m_path.m_params), mv$(tp_mono.m_type_bounds)) ) ) { return true; } } @@ -547,6 +547,44 @@ bool StaticTraitResolve::trait_contains_type(const Span& sp, const ::HIR::Generi return false; } +bool StaticTraitResolve::ImplRef::more_specific_than(const ImplRef& other) const +{ + TU_MATCH(Data, (this->m_data), (e), + (TraitImpl, + if( e.impl == nullptr ) { + return false; + } + TODO(Span(), "more_specific_than - TraitImpl (" << *this << " '>' " << other << ")"); + ), + (BoundedPtr, + return true; + ), + (Bounded, + return true; + ) + ) + throw ""; +} +bool StaticTraitResolve::ImplRef::type_is_specializable(const char* name) const +{ + TU_MATCH(Data, (this->m_data), (e), + (TraitImpl, + if( e.impl == nullptr ) { + // No impl yet? This type is specialisable. + return true; + } + //TODO(Span(), "type_is_specializable - Impl = " << *this << ", Type = " << name); + return true; + ), + (BoundedPtr, + return false; + ), + (Bounded, + return false; + ) + ) + throw ""; +} ::HIR::TypeRef StaticTraitResolve::ImplRef::get_type(const char* name) const { static Span sp; @@ -570,6 +608,9 @@ bool StaticTraitResolve::trait_contains_type(const Span& sp, const ::HIR::Generi return it->second.clone(); } ), + (BoundedPtr, + TODO(Span(), *this); + ), (Bounded, TODO(Span(), *this); ) diff --git a/src/hir_typeck/static.hpp b/src/hir_typeck/static.hpp index 22f1e4bd..8c9989f6 100644 --- a/src/hir_typeck/static.hpp +++ b/src/hir_typeck/static.hpp @@ -57,29 +57,55 @@ public: ::std::vector<const ::HIR::TypeRef*> params; const ::HIR::TraitImpl* impl; }), + (BoundedPtr, struct { + const ::HIR::TypeRef* type; + const ::HIR::PathParams* trait_args; + const ::std::map< ::std::string, ::HIR::TypeRef>* assoc; + }), (Bounded, struct { - const ::HIR::TypeRef* type; - const ::HIR::PathParams* trait_args; - const ::std::map< ::std::string, ::HIR::TypeRef>* assoc; + ::HIR::TypeRef type; + ::HIR::PathParams trait_args; + ::std::map< ::std::string, ::HIR::TypeRef> assoc; }) ); Data m_data; + ImplRef(): + m_data(Data::make_TraitImpl({ {}, nullptr })) + {} ImplRef(::std::vector<const ::HIR::TypeRef*> params, const ::HIR::TraitImpl& impl): m_data(Data::make_TraitImpl({ mv$(params), &impl })) {} - ImplRef(const ::HIR::TypeRef& type, const ::HIR::PathParams& args, const ::std::map< ::std::string, ::HIR::TypeRef>& assoc): - m_data(Data::make_Bounded({ &type, &args, &assoc })) + ImplRef(const ::HIR::TypeRef* type, const ::HIR::PathParams* args, const ::std::map< ::std::string, ::HIR::TypeRef>* assoc): + m_data(Data::make_BoundedPtr({ type, mv$(args), mv$(assoc) })) {} + ImplRef(::HIR::TypeRef type, ::HIR::PathParams args, ::std::map< ::std::string, ::HIR::TypeRef> assoc): + m_data(Data::make_Bounded({ mv$(type), mv$(args), mv$(assoc) })) + {} + + bool is_valid() const { + return !(m_data.is_TraitImpl() && m_data.as_TraitImpl().impl == nullptr); + } + + bool more_specific_than(const ImplRef& other) const; + bool type_is_specializable(const char* name) const; ::HIR::TypeRef get_type(const char* name) const; friend ::std::ostream& operator<<(::std::ostream& os, const ImplRef& x) { TU_MATCH(Data, (x.m_data), (e), (TraitImpl, - os << "impl" << e.impl->m_params.fmt_args() << " ?" << e.impl->m_trait_args << " for " << e.impl->m_type << e.impl->m_params.fmt_bounds(); + if( e.impl == nullptr ) { + os << "none"; + } + else { + os << "impl" << e.impl->m_params.fmt_args() << " ?" << e.impl->m_trait_args << " for " << e.impl->m_type << e.impl->m_params.fmt_bounds(); + } + ), + (BoundedPtr, + os << "bound"; ), (Bounded, os << "bound"; @@ -91,7 +117,7 @@ public: /// \brief Lookups /// \{ - typedef ::std::function<bool(const ImplRef&)> t_cb_find_impl; + typedef ::std::function<bool(ImplRef)> t_cb_find_impl; bool find_impl( const Span& sp, |