summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hir/hir.cpp14
-rw-r--r--src/hir/hir.hpp3
-rw-r--r--src/hir_typeck/expr.cpp54
3 files changed, 64 insertions, 7 deletions
diff --git a/src/hir/hir.cpp b/src/hir/hir.cpp
index 756e4b7b..29d7e975 100644
--- a/src/hir/hir.cpp
+++ b/src/hir/hir.cpp
@@ -259,7 +259,7 @@ const ::HIR::Function& ::HIR::Crate::get_function_by_path(const Span& sp, const
}
}
-const bool ::HIR::Crate::find_trait_impls(const ::HIR::SimplePath& trait, const ::HIR::TypeRef& type, t_cb_resolve_type ty_res, ::std::function<bool(const ::HIR::TraitImpl&)> callback) const
+bool ::HIR::Crate::find_trait_impls(const ::HIR::SimplePath& trait, const ::HIR::TypeRef& type, t_cb_resolve_type ty_res, ::std::function<bool(const ::HIR::TraitImpl&)> callback) const
{
auto its = this->m_trait_impls.equal_range( trait );
for( auto it = its.first; it != its.second; ++ it )
@@ -273,3 +273,15 @@ const bool ::HIR::Crate::find_trait_impls(const ::HIR::SimplePath& trait, const
}
return false;
}
+bool ::HIR::Crate::find_type_impls(const ::HIR::TypeRef& type, t_cb_resolve_type ty_res, ::std::function<bool(const ::HIR::TypeImpl&)> callback) const
+{
+ for( const auto& impl : this->m_type_impls )
+ {
+ if( impl.matches_type(type, ty_res) ) {
+ if( callback(impl) ) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp
index 73e7b1af..c6dec6c8 100644
--- a/src/hir/hir.hpp
+++ b/src/hir/hir.hpp
@@ -275,7 +275,8 @@ public:
const ::HIR::ValueItem& get_valitem_by_path(const Span& sp, const ::HIR::SimplePath& path) const;
const ::HIR::Function& get_function_by_path(const Span& sp, const ::HIR::SimplePath& path) const;
- const bool find_trait_impls(const ::HIR::SimplePath& path, const ::HIR::TypeRef& type, t_cb_resolve_type ty_res, ::std::function<bool(const ::HIR::TraitImpl&)> callback) const;
+ bool find_trait_impls(const ::HIR::SimplePath& path, const ::HIR::TypeRef& type, t_cb_resolve_type ty_res, ::std::function<bool(const ::HIR::TraitImpl&)> callback) const;
+ bool find_type_impls(const ::HIR::TypeRef& type, t_cb_resolve_type ty_res, ::std::function<bool(const ::HIR::TypeImpl&)> callback) const;
};
} // namespace HIR
diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp
index 6a05ff52..3834d812 100644
--- a/src/hir_typeck/expr.cpp
+++ b/src/hir_typeck/expr.cpp
@@ -267,6 +267,7 @@ namespace {
return rv;
}
void mark_change() {
+ DEBUG("- CHANGE");
m_has_changed = true;
}
@@ -913,15 +914,22 @@ namespace {
if( l_t.m_data.is_Pointer() && r_t.m_data.is_Borrow() ) {
const auto& l_e = l_t.m_data.as_Pointer();
const auto& r_e = r_t.m_data.as_Borrow();
+ if( l_e.type != r_e.type ) {
+ ERROR(sp, E0000, "Type mismatch between " << l_t << " and " << r_t << " (pointer type mismatch)");
+ }
+ // 1. Equate inner types
+ this->apply_equality(sp, *l_e.inner, cb_left, *r_e.inner, cb_right, nullptr);
+
+ // 2. If that succeeds, add a coerce
if( node_ptr_ptr != nullptr )
{
- // 1. Equate inner types
- this->apply_equality(sp, *l_e.inner, cb_left, *r_e.inner, cb_right, nullptr);
- // 2. If that succeeds, add a coerce
auto span = (**node_ptr_ptr).span();
+ // - Override the existing result type (to prevent infinite recursion)
+ (*node_ptr_ptr)->m_res_type = r_t.clone();
*node_ptr_ptr = ::HIR::ExprNodeP(new ::HIR::ExprNode_Cast( mv$(span), mv$(*node_ptr_ptr), l_t.clone() ));
(*node_ptr_ptr)->m_res_type = l_t.clone();
+ DEBUG("- Borrow->Pointer cast added - " << l_t << " <- " << r_t);
this->mark_change();
return ;
}
@@ -1949,7 +1957,7 @@ namespace {
(UfcsKnown,
const auto& trait = this->context.m_crate.get_trait_by_path(sp, e.trait.m_path);
this->fix_param_count(sp, path, trait.m_params, e.trait.m_params);
- const auto& fcn = trait.m_values.find(e.item)->second.as_Function();
+ const auto& fcn = trait.m_values.at(e.item).as_Function();
this->fix_param_count(sp, path, fcn.m_params, e.params);
fcn_ptr = &fcn;
@@ -1973,7 +1981,40 @@ namespace {
TODO(sp, "Hit a UfcsUnknown (" << path << ") - Is this an error?");
),
(UfcsInherent,
- TODO(sp, "Locate functions in UFCS inherent - " << path);
+ const ::HIR::TypeImpl* impl_ptr = nullptr;
+ this->context.m_crate.find_type_impls(*e.type, [&](const auto& ty)->const auto& {
+ if( ty.m_data.is_Infer() )
+ return this->context.get_type(ty);
+ else
+ return ty;
+ },
+ [&](const auto& impl) {
+ auto it = impl.m_methods.find(e.item);
+ if( it == impl.m_methods.end() )
+ return false;
+ fcn_ptr = &it->second;
+ impl_ptr = &impl;
+ return true;
+ });
+ if( !fcn_ptr ) {
+ ERROR(sp, E0000, "Failed to locate function " << path);
+ }
+ assert(impl_ptr);
+ this->fix_param_count(sp, path, fcn_ptr->m_params, e.params);
+
+ monomorph_cb = [&](const auto& gt)->const auto& {
+ const auto& ge = gt.m_data.as_Generic();
+ if( ge.binding == 0xFFFF ) {
+ return *e.type;
+ }
+ // TODO: Don't the function-level params use 256-511?
+ //else if( ge.binding < 256 ) {
+ // return path_params.m_types[ge.binding];
+ //}
+ //else {
+ //}
+ TODO(sp, "Monomorphise for type method - " << ge.name << " " << ge.binding);
+ };
)
)
@@ -2216,8 +2257,11 @@ void Typecheck_Code(TypecheckContext context, const ::HIR::TypeRef& result_type,
// 2. Iterate through nodes applying rules until nothing changes
{
ExprVisitor_Run visitor { context };
+ unsigned int count = 0;
do {
visitor.visit_node_ptr(root_ptr);
+ count += 1;
+ assert(count < 1000);
} while( context.take_changed() );
}