summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/hir/hir.hpp2
-rw-r--r--src/hir/type.cpp64
-rw-r--r--src/hir/type.hpp6
-rw-r--r--src/hir_typeck/expr.cpp95
4 files changed, 132 insertions, 35 deletions
diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp
index c6dec6c8..3447aaa0 100644
--- a/src/hir/hir.hpp
+++ b/src/hir/hir.hpp
@@ -204,8 +204,6 @@ TAGGED_UNION(ValueItem, Import,
// --------------------------------------------------------------------
-typedef ::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> t_cb_resolve_type;
-
class TypeImpl
{
public:
diff --git a/src/hir/type.cpp b/src/hir/type.cpp
index dfaf9d1d..e4931dbf 100644
--- a/src/hir/type.cpp
+++ b/src/hir/type.cpp
@@ -241,17 +241,38 @@ bool ::HIR::TypeRef::operator==(const ::HIR::TypeRef& x) const
)
throw "";
}
-void ::HIR::TypeRef::match_generics(const Span& sp, const ::HIR::TypeRef& x, ::std::function<void(unsigned int, const ::HIR::TypeRef&)> callback) const
+
+
+typedef ::std::function<void(unsigned int, const ::HIR::TypeRef&)> t_cb_match_generics;
+
+namespace {
+ bool match_generics_pp(const Span& sp, const ::HIR::PathParams& t, const ::HIR::PathParams& x, ::HIR::t_cb_resolve_type resolve_placeholder, t_cb_match_generics callback)
+ {
+ if( t.m_types.size() != x.m_types.size() ) {
+ return false;
+ }
+
+ for(unsigned int i = 0; i < t.m_types.size(); i ++ )
+ {
+ t.m_types[i].match_generics( sp, x.m_types[i], resolve_placeholder, callback );
+ }
+
+ return true;
+ }
+}
+
+void ::HIR::TypeRef::match_generics(const Span& sp, const ::HIR::TypeRef& x_in, t_cb_resolve_type resolve_placeholder, t_cb_match_generics callback) const
{
if( m_data.is_Infer() ) {
- BUG(sp, "");
+ BUG(sp, "Encountered '_' as this - " << *this);
}
if( m_data.is_Generic() ) {
- callback(m_data.as_Generic().binding, x);
+ callback(m_data.as_Generic().binding, x_in);
return ;
}
+ const auto& x = (x_in.m_data.is_Infer() || x_in.m_data.is_Generic() ? resolve_placeholder(x_in) : x_in);
if( m_data.tag() != x.m_data.tag() ) {
- BUG(sp, "");
+ BUG(sp, "TypeRef::match_generics with mismatched forms - " << *this << " and " << x);
}
TU_MATCH(::HIR::TypeRef::Data, (m_data, x.m_data), (te, xe),
(Infer, throw "";),
@@ -261,29 +282,50 @@ void ::HIR::TypeRef::match_generics(const Span& sp, const ::HIR::TypeRef& x, ::s
(Diverge,
),
(Path,
- TODO(sp, "Path");
+ if( te.path.m_data.tag() != xe.path.m_data.tag() ) {
+ BUG(sp, "TypeRef::match_generics with mismatched forms - " << *this << " and " << x);
+ }
+ TU_MATCH(::HIR::Path::Data, (te.path.m_data, xe.path.m_data), (tpe, xpe),
+ (Generic,
+ if( tpe.m_path != xpe.m_path ) {
+ BUG(sp, "TypeRef::match_generics with mismatched forms - " << *this << " and " << x);
+ }
+ if( !match_generics_pp(sp, tpe.m_params, xpe.m_params, resolve_placeholder, callback) ) {
+ BUG(sp, "TypeRef::match_generics with mismatched forms - " << *this << " and " << x);
+ }
+ ),
+ (UfcsKnown,
+ TODO(sp, "Path UfcsKnown - " << *this << " and " << x);
+ ),
+ (UfcsUnknown,
+ TODO(sp, "Path UfcsUnknown - " << *this << " and " << x);
+ ),
+ (UfcsInherent,
+ TODO(sp, "Path UfcsInherent - " << *this << " and " << x);
+ )
+ )
),
(TraitObject,
TODO(sp, "TraitObject");
),
(Array,
- te.inner->match_generics( sp, *xe.inner, callback );
+ te.inner->match_generics( sp, *xe.inner, resolve_placeholder, callback );
),
(Slice,
- te.inner->match_generics( sp, *xe.inner, callback );
+ te.inner->match_generics( sp, *xe.inner, resolve_placeholder, callback );
),
(Tuple,
if( te.size() != xe.size() ) {
- BUG(sp, "");
+ BUG(sp, "TypeRef::match_generics with mismatched forms - " << *this << " and " << x);
}
for(unsigned int i = 0; i < te.size(); i ++ )
- te[i].match_generics( sp, xe[i], callback );
+ te[i].match_generics( sp, xe[i], resolve_placeholder, callback );
),
(Pointer,
- te.inner->match_generics( sp, *xe.inner, callback );
+ te.inner->match_generics( sp, *xe.inner, resolve_placeholder, callback );
),
(Borrow,
- te.inner->match_generics( sp, *xe.inner, callback );
+ te.inner->match_generics( sp, *xe.inner, resolve_placeholder, callback );
),
(Function,
TODO(sp, "Function");
diff --git a/src/hir/type.hpp b/src/hir/type.hpp
index 75cf4485..adb48df0 100644
--- a/src/hir/type.hpp
+++ b/src/hir/type.hpp
@@ -15,6 +15,8 @@ class Enum;
class TypeRef;
+typedef ::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> t_cb_resolve_type;
+
enum class InferClass
{
None,
@@ -168,7 +170,7 @@ public:
// Match generics in `this` with types from `x`
// Raises a bug against `sp` if there is a form mismatch or `this` has an infer
- void match_generics(const Span& sp, const ::HIR::TypeRef& x, ::std::function<void(unsigned int, const ::HIR::TypeRef&)> callback) const;
+ void match_generics(const Span& sp, const ::HIR::TypeRef& x, t_cb_resolve_type resolve_placeholder, ::std::function<void(unsigned int, const ::HIR::TypeRef&)> callback) const;
enum Compare {
Equal,
@@ -176,7 +178,7 @@ public:
Unequal,
};
// Compares this type with another, using `resolve_placeholder` to get replacements for generics/infers in `x`
- Compare compare_with_paceholders(const Span& sp, const ::HIR::TypeRef& x, ::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> resolve_placeholder) const;
+ Compare compare_with_paceholders(const Span& sp, const ::HIR::TypeRef& x, t_cb_resolve_type resolve_placeholder) const;
};
extern ::std::ostream& operator<<(::std::ostream& os, const ::HIR::TypeRef& ty);
diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp
index 19dfdda7..5446a299 100644
--- a/src/hir_typeck/expr.cpp
+++ b/src/hir_typeck/expr.cpp
@@ -1117,8 +1117,11 @@ namespace {
::HIR::TypeRef expand_associated_types(const Span& sp, ::HIR::TypeRef input) const
{
+ TRACE_FUNCTION_F(input);
TU_MATCH(::HIR::TypeRef::Data, (input.m_data), (e),
(Infer,
+ //auto& ty = this->get_type(input);
+ //return ty.clone();
),
(Diverge,
),
@@ -1127,27 +1130,89 @@ namespace {
(Path,
TU_MATCH(::HIR::Path::Data, (e.path.m_data), (e2),
(Generic,
+ for(auto& arg : e2.m_params.m_types)
+ arg = expand_associated_types(sp, mv$(arg));
),
(UfcsInherent,
TODO(sp, "Path - UfcsInherent - " << e.path);
),
(UfcsKnown,
+ DEBUG("Checking UFCS types for " << e.path);
// HACK - Shortcut to prevent expensive search if the type is a parameter
if( e2.type->m_data.is_Generic() ) {
return input;
}
+ *e2.type = expand_associated_types(sp, mv$(*e2.type));
+
// Search for a matching trait impl
const ::HIR::TraitImpl* impl_ptr = nullptr;
- bool rv = this->m_crate.find_trait_impls(e2.trait.m_path, *e2.type,
- [&](const auto& ty)->const auto& {
+ ::std::vector< const ::HIR::TypeRef*> impl_args;
+
+ auto cb_get_infer = [&](const auto& ty)->const auto& {
if( ty.m_data.is_Infer() )
return this->get_type(ty);
else
return ty;
- },
+ };
+
+ bool rv = this->m_crate.find_trait_impls(e2.trait.m_path, *e2.type, cb_get_infer,
[&](const auto& impl) {
- DEBUG("Found impl - " << e2.trait.m_path << impl.m_trait_args << " for " << impl.m_type);
+ DEBUG("Found impl" << impl.m_params.fmt_args() << " " << e2.trait.m_path << impl.m_trait_args << " for " << impl.m_type);
+ // - Populate the impl's type arguments
+ impl_args.clear();
+ impl_args.resize( impl.m_params.m_types.size() );
+ // - Match with `Self`
+ auto cb_res = [&](unsigned int slot, const ::HIR::TypeRef& ty) {
+ DEBUG("Set " << slot << " = " << ty);
+ if( slot >= impl_args.size() ) {
+ BUG(sp, "Impl parameter out of range - " << slot);
+ }
+ auto& slot_r = impl_args.at(slot);
+ if( slot_r != nullptr ) {
+ DEBUG("- Match " << slot_r << " == " << ty);
+ }
+ else {
+ slot_r = &ty;
+ }
+ };
+ impl.m_type.match_generics(sp, *e2.type, cb_get_infer, cb_res);
+ for( unsigned int i = 0; i < impl.m_trait_args.m_types.size(); i ++ )
+ {
+ impl.m_trait_args.m_types[i].match_generics(sp, e2.trait.m_params.m_types.at(i), cb_get_infer, cb_res);
+ }
+ for( const auto& bound : impl.m_params.m_bounds )
+ {
+ TU_MATCH_DEF(::HIR::GenericBound, (bound), (be),
+ (
+ ),
+ (TraitBound,
+ bool rv2 = this->m_crate.find_trait_impls(be.trait.m_path.m_path, be.type,
+ [&](const auto& ty)->const auto& {
+ if( ty.m_data.is_Infer() )
+ return this->get_type(ty);
+ else TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Generic, e,
+ assert( impl_args.at(e.binding) );
+ return *impl_args.at(e.binding);
+ )
+ else
+ return ty;
+ },
+ [&](const auto& impl) {
+ DEBUG("- Bound " << be.type << " : " << be.trait.m_path << " satisfied by impl" << impl.m_params.fmt_args());
+ // TODO: Recursively check
+ return true;
+ }
+ );
+ if( !rv2 ) {
+ DEBUG("- Bound " << be.type << " : " << be.trait.m_path << " failed");
+ return false;
+ }
+ )
+ )
+ }
+ // TODO: Bounds check? (here or elsewhere?)
+ // - Need to check bounds before picking this impl, because the bound could be preventing false matches
if( impl.m_trait_args.m_types.size() > 0 )
{
TODO(sp, "Check trait type parameters in expand_associated_types");
@@ -1160,19 +1225,6 @@ namespace {
// An impl was found:
assert(impl_ptr);
- // - Populate the impl's type arguments
- ::std::vector< const ::HIR::TypeRef*> impl_args;
- impl_args.resize( impl_ptr->m_params.m_types.size() );
-
- // 1. Match impl_ptr->m_type with *e2.type
- impl_ptr->m_type.match_generics(sp, *e2.type, [&](unsigned int slot, const ::HIR::TypeRef& ty) {
- DEBUG("Set " << slot << " = " << ty);
- if( slot >= impl_args.size() ) {
- BUG(sp, "Impl parameter out of range - " << slot);
- }
- impl_args.at(slot) = &ty;
- });
- // 2. Match impl_ptr->m_trait_args with e2.trait.m_params
// - Monomorphise the output type
auto new_type = monomorphise_type_with(sp, impl_ptr->m_types.at( e2.item ), [&](const auto& ty)->const auto& {
@@ -1180,7 +1232,7 @@ namespace {
assert(ge.binding < impl_args.size());
return *impl_args[ge.binding];
});
- DEBUG("Converted UfcsKnown - " << e.path << " = " << new_type);
+ DEBUG("Converted UfcsKnown - " << e.path << " = " << new_type << " using " << e2.item << " = " << impl_ptr->m_types.at( e2.item ));
return new_type;
),
(UfcsUnknown,
@@ -1229,7 +1281,6 @@ namespace {
for(const auto& b : p->m_bounds)
{
TU_IFLET(::HIR::GenericBound, b, TraitBound, e,
- DEBUG("Bound " << e.type << " : " << e.trait.m_path);
if( e.type == type && e.trait.m_path.m_path == trait ) {
if( callback(e.trait.m_path.m_params) ) {
return true;
@@ -1352,6 +1403,7 @@ namespace {
}
} while( current_ty );
// Dereference failed! This is a hard error (hitting _ is checked above and returns ~0)
+ this->dump();
TODO(sp, "Error when no method could be found, but type is known - (: " << top_ty << ")." << method_name);
}
@@ -2203,7 +2255,7 @@ namespace {
//}
//else {
//}
- TODO(sp, "Monomorphise for trait method - " << ge.name << " " << ge.binding);
+ TODO(sp, "Monomorphise for trait method "<<path<<" - Param " << ge.name << " (" << ge.binding << ")");
};
),
(UfcsUnknown,
@@ -2280,6 +2332,9 @@ namespace {
this->context.apply_equality(sp, arg_ty, arg_expr_ptr->m_res_type, &arg_expr_ptr);
}
+ // HACK: Expand UFCS again
+ arg_types.back() = this->context.expand_associated_types(sp, mv$(arg_types.back()));
+
DEBUG("RV " << arg_types.back());
this->context.apply_equality(sp, res_type, arg_types.back(), &this_node_ptr);
}