summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/hir_typeck/impl_ref.cpp18
-rw-r--r--src/hir_typeck/impl_ref.hpp1
2 files changed, 17 insertions, 2 deletions
diff --git a/src/hir_typeck/impl_ref.cpp b/src/hir_typeck/impl_ref.cpp
index 7b3dfe60..abda820e 100644
--- a/src/hir_typeck/impl_ref.cpp
+++ b/src/hir_typeck/impl_ref.cpp
@@ -72,8 +72,22 @@ bool ImplRef::type_is_specialisable(const char* name) const
const auto& e = this->m_data.as_TraitImpl();
return [this,&e,&sp](const auto& gt)->const auto& {
const auto& ge = gt.m_data.as_Generic();
- assert(ge.binding < 256);
- assert(ge.binding < e.params.size());
+ if( ge.binding == 0xFFFF ) {
+ // Store (or cache) a monomorphisation of Self, and error if this recurses
+ if( e.self_cache == ::HIR::TypeRef() ) {
+ e.self_cache = ::HIR::TypeRef::new_diverge();
+ e.self_cache = monomorphise_type_with(sp, e.impl->m_type, this->get_cb_monomorph_traitimpl(sp));
+ }
+ else if( e.self_cache == ::HIR::TypeRef::new_diverge() ) {
+ // BUG!
+ BUG(sp, "Use of `Self` in expansion of `Self`");
+ }
+ else {
+ }
+ return e.self_cache;
+ }
+ ASSERT_BUG(sp, ge.binding < 256, "Binding in " << gt << " out of range (>=256)");
+ ASSERT_BUG(sp, ge.binding < e.params.size(), "Binding in " << gt << " out of range (>= " << e.params.size() << ")");
if( e.params[ge.binding] ) {
return *e.params[ge.binding];
}
diff --git a/src/hir_typeck/impl_ref.hpp b/src/hir_typeck/impl_ref.hpp
index 3135b4cc..dd31a7e3 100644
--- a/src/hir_typeck/impl_ref.hpp
+++ b/src/hir_typeck/impl_ref.hpp
@@ -16,6 +16,7 @@ struct ImplRef
::std::vector<::HIR::TypeRef> params_ph;
const ::HIR::SimplePath* trait_path;
const ::HIR::TraitImpl* impl;
+ mutable ::HIR::TypeRef self_cache;
}),
(BoundedPtr, struct {
const ::HIR::TypeRef* type;