summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-07-19 19:41:01 +0800
committerJohn Hodge <tpg@mutabah.net>2016-07-19 19:41:01 +0800
commit3fab1f6071718b5456d4c6b33fa5afe8f9a43f71 (patch)
tree8d6c97418b3d97b076a8b70c63d3f157494e9a3b
parent394fb3ccec788e2c3abff511d142a9573bc783a6 (diff)
downloadmrust-3fab1f6071718b5456d4c6b33fa5afe8f9a43f71.tar.gz
HIR - Very rough impl specialisation support in outer typeck
-rw-r--r--src/hir/type.cpp68
-rw-r--r--src/hir/type.hpp1
-rw-r--r--src/hir_typeck/expr_cs.cpp1
-rw-r--r--src/hir_typeck/outer.cpp35
-rw-r--r--src/hir_typeck/static.cpp47
-rw-r--r--src/hir_typeck/static.hpp40
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,