summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-07-03 19:48:23 +0800
committerJohn Hodge <tpg@mutabah.net>2016-07-03 19:48:23 +0800
commit08290af3aa179c24e34b6d516265c1b789514893 (patch)
treee08c3b3ff334d7a9f36717744661c3fe3a0c4a05
parentb602f1e0fe87c2d11120e0ab7e556db9276b9a78 (diff)
downloadmrust-08290af3aa179c24e34b6d516265c1b789514893.tar.gz
HIR Typecheck - Move trait-related logic to a common class
-rw-r--r--src/hir_typeck/expr_context.cpp389
-rw-r--r--src/hir_typeck/expr_cs.cpp12
-rw-r--r--src/hir_typeck/expr_simple.cpp2
-rw-r--r--src/hir_typeck/expr_simple.hpp147
-rw-r--r--src/hir_typeck/helpers.cpp258
-rw-r--r--src/hir_typeck/helpers.hpp36
6 files changed, 451 insertions, 393 deletions
diff --git a/src/hir_typeck/expr_context.cpp b/src/hir_typeck/expr_context.cpp
index a957a6f5..3c81dd04 100644
--- a/src/hir_typeck/expr_context.cpp
+++ b/src/hir_typeck/expr_context.cpp
@@ -5,19 +5,6 @@
#include <algorithm> // std::find_if
#include "helpers.hpp"
-struct FmtType {
- const typeck::TypecheckContext& ctxt;
- const ::HIR::TypeRef& ty;
- FmtType(const typeck::TypecheckContext& ctxt, const ::HIR::TypeRef& ty):
- ctxt(ctxt),
- ty(ty)
- {}
- friend ::std::ostream& operator<<(::std::ostream& os, const FmtType& x) {
- x.ctxt.print_type(os, x.ty);
- return os;
- }
-};
-
void typeck::TypecheckContext::push_traits(const ::std::vector<::std::pair< const ::HIR::SimplePath*, const ::HIR::Trait* > >& list)
{
this->m_traits.insert( this->m_traits.end(), list.begin(), list.end() );
@@ -94,268 +81,7 @@ const ::HIR::TypeRef& typeck::TypecheckContext::get_var_type(const Span& sp, uns
}
-bool typeck::TypecheckContext::pathparams_contain_ivars(const ::HIR::PathParams& pps) const {
- for( const auto& ty : pps.m_types ) {
- if(this->type_contains_ivars(ty))
- return true;
- }
- return false;
-}
-bool typeck::TypecheckContext::type_contains_ivars(const ::HIR::TypeRef& ty) const {
- TU_MATCH(::HIR::TypeRef::Data, (this->get_type(ty).m_data), (e),
- (Infer, return true; ),
- (Primitive, return false; ),
- (Diverge, return false; ),
- (Generic, return false; ),
- (Path,
- TU_MATCH(::HIR::Path::Data, (e.path.m_data), (pe),
- (Generic,
- return pathparams_contain_ivars(pe.m_params);
- ),
- (UfcsKnown,
- if( type_contains_ivars(*pe.type) )
- return true;
- if( pathparams_contain_ivars(pe.trait.m_params) )
- return true;
- return pathparams_contain_ivars(pe.params);
- ),
- (UfcsInherent,
- if( type_contains_ivars(*pe.type) )
- return true;
- return pathparams_contain_ivars(pe.params);
- ),
- (UfcsUnknown,
- BUG(Span(), "UfcsUnknown");
- )
- )
- ),
- (Borrow,
- return type_contains_ivars(*e.inner);
- ),
- (Pointer,
- return type_contains_ivars(*e.inner);
- ),
- (Slice,
- return type_contains_ivars(*e.inner);
- ),
- (Array,
- return type_contains_ivars(*e.inner);
- ),
- (Closure,
- for(const auto& arg : e.m_arg_types)
- if( type_contains_ivars(arg) )
- return true;
- return type_contains_ivars(*e.m_rettype);
- ),
- (Function,
- for(const auto& arg : e.m_arg_types)
- if( type_contains_ivars(arg) )
- return true;
- return type_contains_ivars(*e.m_rettype);
- ),
- (TraitObject,
- for(const auto& marker : e.m_markers)
- if( pathparams_contain_ivars(marker.m_params) )
- return true;
- return pathparams_contain_ivars(e.m_trait.m_path.m_params);
- ),
- (Tuple,
- for(const auto& st : e)
- if( type_contains_ivars(st) )
- return true;
- return false;
- )
- )
- throw "";
-}
-
-namespace {
- bool type_list_equal(const typeck::TypecheckContext& context, const ::std::vector< ::HIR::TypeRef>& l, const ::std::vector< ::HIR::TypeRef>& r)
- {
- if( l.size() != r.size() )
- return false;
-
- for( unsigned int i = 0; i < l.size(); i ++ ) {
- if( !context.types_equal(l[i], r[i]) )
- return false;
- }
- return true;
- }
-}
-bool typeck::TypecheckContext::pathparams_equal(const ::HIR::PathParams& pps_l, const ::HIR::PathParams& pps_r) const
-{
- return type_list_equal(*this, pps_l.m_types, pps_r.m_types);
-}
-bool typeck::TypecheckContext::types_equal(const ::HIR::TypeRef& rl, const ::HIR::TypeRef& rr) const
-{
- const auto& l = this->get_type(rl);
- const auto& r = this->get_type(rr);
- if( l.m_data.tag() != r.m_data.tag() )
- return false;
-
- TU_MATCH(::HIR::TypeRef::Data, (l.m_data, r.m_data), (le, re),
- (Infer, return le.index == re.index; ),
- (Primitive, return le == re; ),
- (Diverge, return true; ),
- (Generic, return le.binding == re.binding; ),
- (Path,
- if( le.path.m_data.tag() != re.path.m_data.tag() )
- return false;
- TU_MATCH(::HIR::Path::Data, (le.path.m_data, re.path.m_data), (lpe, rpe),
- (Generic,
- if( lpe.m_path != rpe.m_path )
- return false;
- return pathparams_equal(lpe.m_params, rpe.m_params);
- ),
- (UfcsKnown,
- if( lpe.item != rpe.item )
- return false;
- if( types_equal(*lpe.type, *rpe.type) )
- return false;
- if( pathparams_equal(lpe.trait.m_params, rpe.trait.m_params) )
- return false;
- return pathparams_equal(lpe.params, rpe.params);
- ),
- (UfcsInherent,
- if( lpe.item != rpe.item )
- return false;
- if( types_equal(*lpe.type, *rpe.type) )
- return false;
- return pathparams_equal(lpe.params, rpe.params);
- ),
- (UfcsUnknown,
- BUG(Span(), "UfcsUnknown");
- )
- )
- ),
- (Borrow,
- if( le.type != re.type )
- return false;
- return types_equal(*le.inner, *re.inner);
- ),
- (Pointer,
- if( le.type != re.type )
- return false;
- return types_equal(*le.inner, *re.inner);
- ),
- (Slice,
- return types_equal(*le.inner, *re.inner);
- ),
- (Array,
- if( le.size_val != re.size_val )
- return false;
- return types_equal(*le.inner, *re.inner);
- ),
- (Closure,
- if( !type_list_equal(*this, le.m_arg_types, re.m_arg_types) )
- return false;
- return types_equal(*le.m_rettype, *re.m_rettype);
- ),
- (Function,
- if( !type_list_equal(*this, le.m_arg_types, re.m_arg_types) )
- return false;
- return types_equal(*le.m_rettype, *re.m_rettype);
- ),
- (TraitObject,
- if( le.m_markers.size() != re.m_markers.size() )
- return false;
- for(unsigned int i = 0; i < le.m_markers.size(); i ++) {
- const auto& lm = le.m_markers[i];
- const auto& rm = re.m_markers[i];
- if( lm.m_path != rm.m_path )
- return false;
- if( ! pathparams_equal(lm.m_params, rm.m_params) )
- return false;
- }
- if( le.m_trait.m_path.m_path != re.m_trait.m_path.m_path )
- return false;
- return pathparams_equal(le.m_trait.m_path.m_params, re.m_trait.m_path.m_params);
- ),
- (Tuple,
- return type_list_equal(*this, le, re);
- )
- )
- throw "";
-}
-
-void typeck::TypecheckContext::print_type(::std::ostream& os, const ::HIR::TypeRef& tr) const
-{
- m_ivars.print_type(os, tr);
-}
-///
-/// Add inferrence variables to the provided type (if they're not already set)
-///
-void typeck::TypecheckContext::add_ivars(::HIR::TypeRef& type)
-{
- TU_MATCH(::HIR::TypeRef::Data, (type.m_data), (e),
- (Infer,
- if( e.index == ~0u ) {
- e.index = this->new_ivar();
- this->get_type(type).m_data.as_Infer().ty_class = e.ty_class;
- this->mark_change();
- }
- ),
- (Diverge,
- ),
- (Primitive,
- ),
- (Path,
- // Iterate all arguments
- TU_MATCH(::HIR::Path::Data, (e.path.m_data), (e2),
- (Generic,
- this->add_ivars_params(e2.m_params);
- ),
- (UfcsKnown,
- this->add_ivars(*e2.type);
- this->add_ivars_params(e2.trait.m_params);
- this->add_ivars_params(e2.params);
- ),
- (UfcsUnknown,
- this->add_ivars(*e2.type);
- this->add_ivars_params(e2.params);
- ),
- (UfcsInherent,
- this->add_ivars(*e2.type);
- this->add_ivars_params(e2.params);
- )
- )
- ),
- (Generic,
- ),
- (TraitObject,
- // Iterate all paths
- ),
- (Array,
- add_ivars(*e.inner);
- ),
- (Slice,
- add_ivars(*e.inner);
- ),
- (Tuple,
- for(auto& ty : e)
- add_ivars(ty);
- ),
- (Borrow,
- add_ivars(*e.inner);
- ),
- (Pointer,
- add_ivars(*e.inner);
- ),
- (Function,
- // No ivars allowed
- // TODO: Check?
- ),
- (Closure,
- // Shouldn't be possible
- )
- )
-}
-void typeck::TypecheckContext::add_ivars_params(::HIR::PathParams& params)
-{
- for(auto& arg : params.m_types)
- add_ivars(arg);
-}
void typeck::TypecheckContext::add_pattern_binding(const ::HIR::PatternBinding& pb, ::HIR::TypeRef type)
{
@@ -1002,8 +728,8 @@ void typeck::TypecheckContext::apply_equality(const Span& sp, const ::HIR::TypeR
}
}
- DEBUG("CoerceUnsized - " << this->type_contains_ivars(l_t) << this->type_contains_ivars(r_t) << this->types_equal(l_t, r_t));
- if( !this->type_contains_ivars(l_t) && !this->type_contains_ivars(r_t) && !this->types_equal(l_t, r_t) )
+ DEBUG("CoerceUnsized - " << this->m_ivars.type_contains_ivars(l_t) << this->m_ivars.type_contains_ivars(r_t) << this->m_ivars.types_equal(l_t, r_t));
+ if( !this->m_ivars.type_contains_ivars(l_t) && !this->m_ivars.type_contains_ivars(r_t) && !this->m_ivars.types_equal(l_t, r_t) )
{
// TODO: If the types are fully known, and not equal. Search for CoerceUnsized
::HIR::PathParams pp;
@@ -1029,7 +755,7 @@ void typeck::TypecheckContext::apply_equality(const Span& sp, const ::HIR::TypeR
if( e.path.m_data.is_Generic() ) {
return false;
}
- return context.type_contains_ivars(ty);
+ return context.m_ivars.type_contains_ivars(ty);
)
return false;
}
@@ -1046,13 +772,13 @@ void typeck::TypecheckContext::apply_equality(const Span& sp, const ::HIR::TypeR
// - If right has a deref chain to left, build it
DEBUG("Trying deref coercion " << l_t << " " << r_t);
- if( !l_t.m_data.is_Borrow() && ! this->type_contains_ivars(l_t) && ! this->type_contains_ivars(r_t) )
+ if( !l_t.m_data.is_Borrow() && ! this->m_ivars.type_contains_ivars(l_t) && ! this->m_ivars.type_contains_ivars(r_t) )
{
DEBUG("Trying deref coercion (2)");
::HIR::TypeRef tmp_ty;
const ::HIR::TypeRef* out_ty = &r_t;
unsigned int count = 0;
- while( (out_ty = this->autoderef(sp, *out_ty, tmp_ty)) )
+ while( (out_ty = this->m_resolve.autoderef(sp, *out_ty, tmp_ty)) )
{
count += 1;
@@ -1283,7 +1009,7 @@ void typeck::TypecheckContext::apply_equality(const Span& sp, const ::HIR::TypeR
if(!succ) {
// XXX: Debugging - Resolves to the correct type in a failing case
//auto ty2 = this->expand_associated_types(sp, this->expand_associated_types(sp, right_inner_res.clone()) );
- ERROR(sp, E0000, "Trait " << e.m_trait << " isn't implemented for " << FmtType(*this, right_inner_res) << " (converting to TraitObject) - (r="<<r<<")" );
+ ERROR(sp, E0000, "Trait " << e.m_trait << " isn't implemented for " << m_ivars.fmt_type(right_inner_res) << " (converting to TraitObject) - (r="<<r<<")" );
}
for(const auto& marker : e.m_markers)
{
@@ -1375,41 +1101,11 @@ void typeck::TypecheckContext::apply_equality(const Span& sp, const ::HIR::TypeR
}
}
-// -------------------------------------------------------------------------------------------------------------------
-//
-// -------------------------------------------------------------------------------------------------------------------
-bool typeck::TypecheckContext::check_trait_bound(const Span& sp, const ::HIR::TypeRef& type, const ::HIR::GenericPath& trait, ::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> placeholder) const
-{
- if( this->find_trait_impls_bound(sp, trait.m_path, trait.m_params, placeholder(type), [&](const auto& args, const auto& _){
- DEBUG("TODO: Check args for " << trait.m_path << args << " against " << trait);
- return true;
- })
- )
- {
- // Satisfied by generic
- return true;
- }
- else if( this->m_crate.find_trait_impls(trait.m_path, type, placeholder, [&](const auto& impl) {
- DEBUG("- Bound " << type << " : " << trait << " satisfied by impl" << impl.m_params.fmt_args());
- // TODO: Recursively check
- return true;
- })
- )
- {
- // Match!
- return true;
- }
- else {
- DEBUG("- Bound " << type << " ("<<placeholder(type)<<") : " << trait << " failed");
- return false;
- }
-}
-
// -------------------------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------------------------
-bool typeck::TypecheckContext::iterate_bounds( ::std::function<bool(const ::HIR::GenericBound&)> cb) const
+bool typeck::TraitResolution::iterate_bounds( ::std::function<bool(const ::HIR::GenericBound&)> cb) const
{
const ::HIR::GenericParams* v[2] = { m_item_params, m_impl_params };
for(auto p : v)
@@ -1420,7 +1116,7 @@ bool typeck::TypecheckContext::iterate_bounds( ::std::function<bool(const ::HIR:
}
return false;
}
-bool typeck::TypecheckContext::find_trait_impls(const Span& sp,
+bool typeck::TraitResolution::find_trait_impls(const Span& sp,
const ::HIR::SimplePath& trait, const ::HIR::PathParams& params,
const ::HIR::TypeRef& type,
t_cb_trait_impl callback
@@ -1471,12 +1167,12 @@ bool typeck::TypecheckContext::find_trait_impls(const Span& sp,
// -------------------------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------------------------
-::HIR::TypeRef typeck::TypecheckContext::expand_associated_types(const Span& sp, ::HIR::TypeRef input) const
+::HIR::TypeRef typeck::TraitResolution::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);
+ auto& ty = this->m_ivars.get_type(input);
if( ty != input ) {
input = expand_associated_types(sp, ty.clone());
return input;
@@ -1708,7 +1404,7 @@ bool typeck::TypecheckContext::find_trait_impls(const Span& sp,
}
// TODO: If there are no ivars in this path, set its binding to Opaque
- if( !this->type_contains_ivars(input) ) {
+ if( !this->m_ivars.type_contains_ivars(input) ) {
e.binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({});
}
@@ -1755,7 +1451,7 @@ bool typeck::TypecheckContext::find_trait_impls(const Span& sp,
// -------------------------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------------------------
-bool typeck::TypecheckContext::find_named_trait_in_trait(const Span& sp,
+bool typeck::TraitResolution::find_named_trait_in_trait(const Span& sp,
const ::HIR::SimplePath& des, const ::HIR::PathParams& des_params,
const ::HIR::Trait& trait_ptr, const ::HIR::SimplePath& trait_path, const ::HIR::PathParams& pp,
const ::HIR::TypeRef& target_type,
@@ -1788,7 +1484,7 @@ bool typeck::TypecheckContext::find_named_trait_in_trait(const Span& sp,
}
return false;
}
-bool typeck::TypecheckContext::find_trait_impls_bound(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl callback) const
+bool typeck::TraitResolution::find_trait_impls_bound(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl callback) const
{
return this->iterate_bounds([&](const auto& b) {
TU_IFLET(::HIR::GenericBound, b, TraitBound, e,
@@ -1806,7 +1502,7 @@ bool typeck::TypecheckContext::find_trait_impls_bound(const Span& sp, const ::HI
bool is_fuzzy = false;
// Check against `params`
for(unsigned int i = 0; i < params.m_types.size(); i ++) {
- auto ord = b_params.m_types[i].compare_with_placeholders(sp, params.m_types[i], this->callback_resolve_infer());
+ auto ord = b_params.m_types[i].compare_with_placeholders(sp, params.m_types[i], this->m_ivars.callback_resolve_infer());
if( ord == ::HIR::Compare::Unequal )
return false;
if( ord == ::HIR::Compare::Fuzzy )
@@ -1827,7 +1523,7 @@ bool typeck::TypecheckContext::find_trait_impls_bound(const Span& sp, const ::HI
return false;
});
}
-bool typeck::TypecheckContext::find_trait_impls_crate(const Span& sp,
+bool typeck::TraitResolution::find_trait_impls_crate(const Span& sp,
const ::HIR::SimplePath& trait, const ::HIR::PathParams& params,
const ::HIR::TypeRef& type,
t_cb_trait_impl callback
@@ -1835,7 +1531,7 @@ bool typeck::TypecheckContext::find_trait_impls_crate(const Span& sp,
{
return this->m_crate.find_trait_impls(trait, type, [&](const auto& ty)->const auto&{
if( ty.m_data.is_Infer() )
- return this->get_type(ty);
+ return this->m_ivars.get_type(ty);
else
return ty;
},
@@ -1860,10 +1556,9 @@ bool typeck::TypecheckContext::find_trait_impls_crate(const Span& sp,
}
};
assert( impl.m_trait_args.m_types.size() == params.m_types.size() );
- // TODO: Use a fuzzy-able generic match
- match &= impl.m_type.match_test_generics_fuzz(sp, type , this->callback_resolve_infer(), cb);
+ match &= impl.m_type.match_test_generics_fuzz(sp, type , this->m_ivars.callback_resolve_infer(), cb);
for(unsigned int i = 0; i < impl.m_trait_args.m_types.size(); i ++)
- match &= impl.m_trait_args.m_types[i].match_test_generics_fuzz(sp, params.m_types[i], this->callback_resolve_infer(), cb);
+ match &= impl.m_trait_args.m_types[i].match_test_generics_fuzz(sp, params.m_types[i], this->m_ivars.callback_resolve_infer(), cb);
if( match == ::HIR::Compare::Unequal ) {
DEBUG("- Failed to match parameters - " << impl.m_trait_args << " != " << params);
return false;
@@ -1905,14 +1600,14 @@ bool typeck::TypecheckContext::find_trait_impls_crate(const Span& sp,
if( ty2 == assoc_bound.second ) {
return true;
}
- this->dump();
+ this->m_ivars.dump();
TODO(sp, "Check type bound (fuzz) " << ty2 << " = " << assoc_bound.second);
}
else {
- if( this->get_type(it->second) == assoc_bound.second ) {
+ if( this->m_ivars.get_type(it->second) == assoc_bound.second ) {
return true;
}
- this->dump();
+ this->m_ivars.dump();
TODO(sp, "Check type bound (fuzz) " << it->second << " = " << assoc_bound.second);
}
}
@@ -1944,7 +1639,7 @@ bool typeck::TypecheckContext::find_trait_impls_crate(const Span& sp,
);
}
-bool typeck::TypecheckContext::trait_contains_method(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::std::string& name, ::HIR::GenericPath& out_path) const
+bool typeck::TraitResolution::trait_contains_method(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::std::string& name, ::HIR::GenericPath& out_path) const
{
auto it = trait_ptr.m_values.find(name);
if( it != trait_ptr.m_values.end() ) {
@@ -1970,7 +1665,7 @@ bool typeck::TypecheckContext::trait_contains_method(const Span& sp, const ::HIR
}
return false;
}
-bool typeck::TypecheckContext::trait_contains_type(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::std::string& name, ::HIR::GenericPath& out_path) const
+bool typeck::TraitResolution::trait_contains_type(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::std::string& name, ::HIR::GenericPath& out_path) const
{
auto it = trait_ptr.m_types.find(name);
if( it != trait_ptr.m_types.end() ) {
@@ -2001,7 +1696,7 @@ bool typeck::TypecheckContext::trait_contains_type(const Span& sp, const ::HIR::
// -------------------------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------------------------
-const ::HIR::TypeRef* typeck::TypecheckContext::autoderef(const Span& sp, const ::HIR::TypeRef& ty, ::HIR::TypeRef& tmp_type) const
+const ::HIR::TypeRef* typeck::TraitResolution::autoderef(const Span& sp, const ::HIR::TypeRef& ty, ::HIR::TypeRef& tmp_type) const
{
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Borrow, e,
DEBUG("Deref " << ty << " into " << *e.inner);
@@ -2026,23 +1721,23 @@ const ::HIR::TypeRef* typeck::TypecheckContext::autoderef(const Span& sp, const
}
}
}
-unsigned int typeck::TypecheckContext::autoderef_find_method(const Span& sp, const ::HIR::TypeRef& top_ty, const ::std::string& method_name, /* Out -> */::HIR::Path& fcn_path) const
+unsigned int typeck::TraitResolution::autoderef_find_method(const Span& sp, const HIR::t_trait_list& traits, const ::HIR::TypeRef& top_ty, const ::std::string& method_name, /* Out -> */::HIR::Path& fcn_path) const
{
unsigned int deref_count = 0;
::HIR::TypeRef tmp_type; // Temporary type used for handling Deref
const auto* current_ty = &top_ty;
- TU_IFLET(::HIR::TypeRef::Data, this->get_type(top_ty).m_data, Borrow, e,
+ TU_IFLET(::HIR::TypeRef::Data, this->m_ivars.get_type(top_ty).m_data, Borrow, e,
current_ty = &*e.inner;
deref_count += 1;
)
do {
- const auto& ty = this->get_type(*current_ty);
+ const auto& ty = this->m_ivars.get_type(*current_ty);
if( ty.m_data.is_Infer() ) {
return ~0u;
}
- if( find_method(sp, ty, method_name, fcn_path) ) {
+ if( this->find_method(sp, traits, ty, method_name, fcn_path) ) {
return deref_count;
}
@@ -2051,20 +1746,20 @@ unsigned int typeck::TypecheckContext::autoderef_find_method(const Span& sp, con
current_ty = this->autoderef(sp, ty, tmp_type);
} while( current_ty );
- TU_IFLET(::HIR::TypeRef::Data, this->get_type(top_ty).m_data, Borrow, e,
- const auto& ty = this->get_type(top_ty);
+ TU_IFLET(::HIR::TypeRef::Data, this->m_ivars.get_type(top_ty).m_data, Borrow, e,
+ const auto& ty = this->m_ivars.get_type(top_ty);
- if( find_method(sp, ty, method_name, fcn_path) ) {
+ if( find_method(sp, traits, ty, method_name, fcn_path) ) {
return 0;
}
)
// Dereference failed! This is a hard error (hitting _ is checked above and returns ~0)
- this->dump();
+ this->m_ivars.dump();
TODO(sp, "Error when no method could be found, but type is known - (: " << top_ty << ")." << method_name);
}
-bool typeck::TypecheckContext::find_method(const Span& sp, const ::HIR::TypeRef& ty, const ::std::string& method_name, /* Out -> */::HIR::Path& fcn_path) const
+bool typeck::TraitResolution::find_method(const Span& sp, const HIR::t_trait_list& traits, const ::HIR::TypeRef& ty, const ::std::string& method_name, /* Out -> */::HIR::Path& fcn_path) const
{
TRACE_FUNCTION_F("ty=" << ty << ", name=" << method_name);
// 1. Search generic bounds for a match
@@ -2169,7 +1864,7 @@ bool typeck::TypecheckContext::find_method(const Span& sp, const ::HIR::TypeRef&
}
}
// 3. Search for trait methods (using currently in-scope traits)
- for(const auto& trait_ref : ::reverse(m_traits))
+ for(const auto& trait_ref : ::reverse(traits))
{
if( trait_ref.first == nullptr )
break;
@@ -2183,7 +1878,7 @@ bool typeck::TypecheckContext::find_method(const Span& sp, const ::HIR::TypeRef&
DEBUG("Search for impl of " << *trait_ref.first);
// TODO: Need a "don't care" marker for the PathParams
if( find_trait_impls_crate(sp, *trait_ref.first, ::HIR::PathParams{}, ty, [](const auto&,const auto&) { return true; }) ) {
- DEBUG("Found trait impl " << *trait_ref.first << " (" /*<< FmtType(*this, *trait_ref.first)*/ << ") for " << ty << " ("<<FmtType(*this, ty)<<")");
+ DEBUG("Found trait impl " << *trait_ref.first << " (" /*<< m_ivars.fmt_type(*trait_ref.first)*/ << ") for " << ty << " ("<<m_ivars.fmt_type(ty)<<")");
fcn_path = ::HIR::Path( ::HIR::Path::Data::make_UfcsKnown({
box$( ty.clone() ),
trait_ref.first->clone(),
@@ -2198,18 +1893,18 @@ bool typeck::TypecheckContext::find_method(const Span& sp, const ::HIR::TypeRef&
return false;
}
-unsigned int typeck::TypecheckContext::autoderef_find_field(const Span& sp, const ::HIR::TypeRef& top_ty, const ::std::string& field_name, /* Out -> */::HIR::TypeRef& field_type) const
+unsigned int typeck::TraitResolution::autoderef_find_field(const Span& sp, const ::HIR::TypeRef& top_ty, const ::std::string& field_name, /* Out -> */::HIR::TypeRef& field_type) const
{
unsigned int deref_count = 0;
::HIR::TypeRef tmp_type; // Temporary type used for handling Deref
const auto* current_ty = &top_ty;
- TU_IFLET(::HIR::TypeRef::Data, this->get_type(top_ty).m_data, Borrow, e,
+ TU_IFLET(::HIR::TypeRef::Data, this->m_ivars.get_type(top_ty).m_data, Borrow, e,
current_ty = &*e.inner;
deref_count += 1;
)
do {
- const auto& ty = this->get_type(*current_ty);
+ const auto& ty = this->m_ivars.get_type(*current_ty);
if( ty.m_data.is_Infer() ) {
return ~0u;
}
@@ -2223,8 +1918,8 @@ unsigned int typeck::TypecheckContext::autoderef_find_field(const Span& sp, cons
current_ty = this->autoderef(sp, ty, tmp_type);
} while( current_ty );
- TU_IFLET(::HIR::TypeRef::Data, this->get_type(top_ty).m_data, Borrow, e,
- const auto& ty = this->get_type(top_ty);
+ TU_IFLET(::HIR::TypeRef::Data, this->m_ivars.get_type(top_ty).m_data, Borrow, e,
+ const auto& ty = this->m_ivars.get_type(top_ty);
if( find_field(sp, ty, field_name, field_type) ) {
return 0;
@@ -2232,10 +1927,10 @@ unsigned int typeck::TypecheckContext::autoderef_find_field(const Span& sp, cons
)
// Dereference failed! This is a hard error (hitting _ is checked above and returns ~0)
- this->dump();
+ this->m_ivars.dump();
TODO(sp, "Error when no field could be found, but type is known - (: " << top_ty << ")." << field_name);
}
-bool typeck::TypecheckContext::find_field(const Span& sp, const ::HIR::TypeRef& ty, const ::std::string& name, /* Out -> */::HIR::TypeRef& field_ty) const
+bool typeck::TraitResolution::find_field(const Span& sp, const ::HIR::TypeRef& ty, const ::std::string& name, /* Out -> */::HIR::TypeRef& field_ty) const
{
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Path, e,
TU_MATCH(::HIR::TypeRef::TypePathBinding, (e.binding), (be),
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index 7e24c1c2..d306f89e 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -1115,7 +1115,17 @@ namespace {
TODO(node.span(), "ExprNode_CallValue - revisit");
}
void visit(::HIR::ExprNode_CallMethod& node) override {
- // TODO:
+ const auto& ty = this->context.get_type(node.m_value->m_res_type);
+ //const auto ty = this->context.expand_associated_types(node.span(), this->context.get_type(node.m_value->m_res_type).clone());
+ DEBUG("(CallMethod) ty = " << ty);
+ // Using autoderef, locate this method on the type
+ #if 0
+ ::HIR::Path fcn_path { ::HIR::SimplePath() };
+ unsigned int deref_count = this->context.autoderef_find_method(node.span(), ty, node.m_method, fcn_path);
+ if( deref_count != ~0u )
+ {
+ }
+ #endif
TODO(node.span(), "ExprNode_CallMethod - revisit");
}
void visit(::HIR::ExprNode_Field& node) override {
diff --git a/src/hir_typeck/expr_simple.cpp b/src/hir_typeck/expr_simple.cpp
index 1185d6b9..a3012a99 100644
--- a/src/hir_typeck/expr_simple.cpp
+++ b/src/hir_typeck/expr_simple.cpp
@@ -1998,7 +1998,7 @@ void Typecheck_Code(typeck::TypecheckContext context, const ::HIR::TypeRef& resu
void Typecheck_Code_Simple(const typeck::ModuleState& ms, t_args& args, const ::HIR::TypeRef& result_type, ::HIR::ExprPtr& expr)
{
typeck::TypecheckContext typeck_context { ms.m_crate, ms.m_impl_generics, ms.m_item_generics };
- typeck_context.m_traits = ms.m_traits;
+ typeck_context.init_traits( ms.m_traits );
for( auto& arg : args ) {
typeck_context.add_binding( Span(), arg.first, arg.second );
}
diff --git a/src/hir_typeck/expr_simple.hpp b/src/hir_typeck/expr_simple.hpp
index a8a96fa9..9f9585a5 100644
--- a/src/hir_typeck/expr_simple.hpp
+++ b/src/hir_typeck/expr_simple.hpp
@@ -13,6 +13,68 @@ namespace typeck {
extern void check_type_class_primitive(const Span& sp, const ::HIR::TypeRef& type, ::HIR::InferClass ic, ::HIR::CoreType ct);
+class TraitResolution
+{
+ const HMTypeInferrence& m_ivars;
+
+ const ::HIR::Crate& m_crate;
+ const ::HIR::GenericParams* m_impl_params;
+ const ::HIR::GenericParams* m_item_params;
+
+public:
+ TraitResolution(const HMTypeInferrence& ivars, const ::HIR::Crate& crate, const ::HIR::GenericParams* impl_params, const ::HIR::GenericParams* item_params):
+ m_ivars(ivars),
+ m_crate(crate),
+ m_impl_params( impl_params ),
+ m_item_params( item_params )
+ {
+ }
+
+ typedef ::std::function<bool(const ::HIR::PathParams&, const ::std::map< ::std::string,::HIR::TypeRef>&)> t_cb_trait_impl;
+
+ /// Check if a trait bound applies, using the passed function to expand Generic/Infer types
+ bool check_trait_bound(const Span& sp, const ::HIR::TypeRef& type, const ::HIR::GenericPath& trait, t_cb_generic placeholder) const;
+
+ /// Expand any located associated types in the input, operating in-place and returning the result
+ ::HIR::TypeRef expand_associated_types(const Span& sp, ::HIR::TypeRef input) const;
+
+ /// Iterate over in-scope bounds (function then top)
+ bool iterate_bounds( ::std::function<bool(const ::HIR::GenericBound&)> cb) const;
+
+ /// Searches for a trait impl that matches the provided trait name and type
+ bool find_trait_impls(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl callback) const;
+
+ /// Locate a named trait in the provied trait (either itself or as a parent trait)
+ bool find_named_trait_in_trait(const Span& sp,
+ const ::HIR::SimplePath& des, const ::HIR::PathParams& params,
+ const ::HIR::Trait& trait_ptr, const ::HIR::SimplePath& trait_path, const ::HIR::PathParams& pp,
+ const ::HIR::TypeRef& self_type,
+ t_cb_trait_impl callback
+ ) const;
+ /// Search for a trait implementation in current bounds
+ bool find_trait_impls_bound(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl callback) const;
+ /// Search for a trait implementation in the crate
+ bool find_trait_impls_crate(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl callback) const;
+
+ /// Locate the named method by applying auto-dereferencing.
+ /// \return Number of times deref was applied (or ~0 if _ was hit)
+ unsigned int autoderef_find_method(const Span& sp, const HIR::t_trait_list& traits, const ::HIR::TypeRef& top_ty, const ::std::string& method_name, /* Out -> */::HIR::Path& fcn_path) const;
+ /// Locate the named field by applying auto-dereferencing.
+ /// \return Number of times deref was applied (or ~0 if _ was hit)
+ unsigned int autoderef_find_field(const Span& sp, const ::HIR::TypeRef& top_ty, const ::std::string& name, /* Out -> */::HIR::TypeRef& field_type) const;
+
+ /// Apply an automatic dereference
+ const ::HIR::TypeRef* autoderef(const Span& sp, const ::HIR::TypeRef& ty, ::HIR::TypeRef& tmp_type) const;
+
+private:
+ bool find_method(const Span& sp, const HIR::t_trait_list& traits, const ::HIR::TypeRef& ty, const ::std::string& method_name, /* Out -> */::HIR::Path& fcn_path) const;
+ bool find_field(const Span& sp, const ::HIR::TypeRef& ty, const ::std::string& name, /* Out -> */::HIR::TypeRef& field_type) const;
+
+ /// Locates a named method in a trait, and returns the path of the trait that contains it (with fixed parameters)
+ bool trait_contains_method(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::std::string& name, ::HIR::GenericPath& out_path) const;
+ bool trait_contains_type(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::std::string& name, ::HIR::GenericPath& out_path) const;
+};
+
class TypecheckContext
{
struct Variable
@@ -32,19 +94,16 @@ class TypecheckContext
};
public:
const ::HIR::Crate& m_crate;
- ::std::vector< ::std::pair< const ::HIR::SimplePath*, const ::HIR::Trait* > > m_traits;
private:
+ ::std::vector< ::std::pair< const ::HIR::SimplePath*, const ::HIR::Trait* > > m_traits;
::std::vector< Variable> m_locals;
HMTypeInferrence m_ivars;
-
- const ::HIR::GenericParams* m_impl_params;
- const ::HIR::GenericParams* m_item_params;
+ TraitResolution m_resolve;
public:
TypecheckContext(const ::HIR::Crate& crate, const ::HIR::GenericParams* impl_params, const ::HIR::GenericParams* item_params):
m_crate(crate),
- m_impl_params( impl_params ),
- m_item_params( item_params )
+ m_resolve(m_ivars, crate, impl_params, item_params)
{
}
@@ -56,7 +115,11 @@ public:
void mark_change() {
m_ivars.mark_change();
}
-
+
+ void init_traits(const ::std::vector<::std::pair< const ::HIR::SimplePath*, const ::HIR::Trait* > >& list) {
+ assert(m_traits.size() == 0);
+ m_traits = list;
+ }
void push_traits(const ::std::vector<::std::pair< const ::HIR::SimplePath*, const ::HIR::Trait* > >& list);
void pop_traits(const ::std::vector<::std::pair< const ::HIR::SimplePath*, const ::HIR::Trait* > >& list);
@@ -64,12 +127,12 @@ public:
/// Apply defaults (i32 or f64), returns true if a default was applied
bool apply_defaults();
- bool pathparams_contain_ivars(const ::HIR::PathParams& pps) const;
- bool type_contains_ivars(const ::HIR::TypeRef& ty) const;
- bool pathparams_equal(const ::HIR::PathParams& pps_l, const ::HIR::PathParams& pps_r) const;
- bool types_equal(const ::HIR::TypeRef& l, const ::HIR::TypeRef& r) const;
+ //bool pathparams_contain_ivars(const ::HIR::PathParams& pps) const;
+ //bool type_contains_ivars(const ::HIR::TypeRef& ty) const;
+ //bool pathparams_equal(const ::HIR::PathParams& pps_l, const ::HIR::PathParams& pps_r) const;
+ //bool types_equal(const ::HIR::TypeRef& l, const ::HIR::TypeRef& r) const;
- void print_type(::std::ostream& os, const ::HIR::TypeRef& tr) const;
+ //void print_type(::std::ostream& os, const ::HIR::TypeRef& tr) const;
/// Adds a local variable binding (type is mutable so it can be inferred if required)
void add_local(unsigned int index, const ::std::string& name, ::HIR::TypeRef type);
@@ -78,9 +141,13 @@ public:
const ::HIR::TypeRef& get_var_type(const Span& sp, unsigned int index);
/// Add (and bind) all '_' types in `type`
- void add_ivars(::HIR::TypeRef& type);
+ void add_ivars(::HIR::TypeRef& type) {
+ m_ivars.add_ivars(type);
+ }
// (helper) Add ivars to path parameters
- void add_ivars_params(::HIR::PathParams& params);
+ void add_ivars_params(::HIR::PathParams& params) {
+ m_ivars.add_ivars_params(params);
+ }
// (helper) Add a new local based on the pattern binding
void add_pattern_binding(const ::HIR::PatternBinding& pb, ::HIR::TypeRef type);
@@ -95,9 +162,6 @@ public:
apply_equality(sp, left, [](const auto& x)->const auto&{return x;}, right, [](const auto& x)->const auto&{return x;}, node_ptr_ptr);
}
- /// (helper) Expands a top-level associated type into `tmp_t`, returning either `t` or `tmp_t`
- const ::HIR::TypeRef& expand_associated_types_to(const Span& sp, const ::HIR::TypeRef& t, ::HIR::TypeRef& tmp_t) const;
-
/// Equates the two types, checking that they are equal (and binding ivars)
/// \note !! The ordering DOES matter, as the righthand side will get unsizing/deref coercions applied if possible (using node_ptr_ptr)
/// \param sp Span for reporting errors
@@ -106,44 +170,47 @@ public:
/// \param node_ptr Pointer to ExprNodeP, updated with new nodes for coercions
void apply_equality(const Span& sp, const ::HIR::TypeRef& left, t_cb_generic cb_left, const ::HIR::TypeRef& right, t_cb_generic cb_right, ::HIR::ExprNodeP* node_ptr_ptr);
- /// Check if a trait bound applies, using the passed function to expand Generic/Infer types
- bool check_trait_bound(const Span& sp, const ::HIR::TypeRef& type, const ::HIR::GenericPath& trait, t_cb_generic placeholder) const;
+ /// (helper) Expands a top-level associated type into `tmp_t`, returning either `t` or `tmp_t`
+ const ::HIR::TypeRef& expand_associated_types_to(const Span& sp, const ::HIR::TypeRef& t, ::HIR::TypeRef& tmp_t) const;
/// Expand any located associated types in the input, operating in-place and returning the result
- ::HIR::TypeRef expand_associated_types(const Span& sp, ::HIR::TypeRef input) const;
+ ::HIR::TypeRef expand_associated_types(const Span& sp, ::HIR::TypeRef input) const {
+ return m_resolve.expand_associated_types(sp, mv$(input));
+ }
/// Iterate over in-scope bounds (function then top)
- bool iterate_bounds( ::std::function<bool(const ::HIR::GenericBound&)> cb) const;
+ bool iterate_bounds( ::std::function<bool(const ::HIR::GenericBound&)> cb) const {
+ return m_resolve.iterate_bounds(cb);
+ }
typedef ::std::function<bool(const ::HIR::PathParams&, const ::std::map< ::std::string,::HIR::TypeRef>&)> t_cb_trait_impl;
/// Searches for a trait impl that matches the provided trait name and type
- bool find_trait_impls(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl callback) const;
+ bool find_trait_impls(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl callback) const {
+ return m_resolve.find_trait_impls(sp, trait, params, type, callback);
+ }
- /// Locate a named trait in the provied trait (either itself or as a parent trait)
- bool find_named_trait_in_trait(const Span& sp,
- const ::HIR::SimplePath& des, const ::HIR::PathParams& params,
- const ::HIR::Trait& trait_ptr, const ::HIR::SimplePath& trait_path, const ::HIR::PathParams& pp,
- const ::HIR::TypeRef& self_type,
- t_cb_trait_impl callback
- ) const;
/// Search for a trait implementation in current bounds
- bool find_trait_impls_bound(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl callback) const;
+ bool find_trait_impls_bound(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl callback) const {
+ return m_resolve.find_trait_impls_bound(sp, trait, params, type, callback);
+ }
/// Search for a trait implementation in the crate
- bool find_trait_impls_crate(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl callback) const;
-
- /// Locates a named method in a trait, and returns the path of the trait that contains it (with fixed parameters)
- bool trait_contains_method(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::std::string& name, ::HIR::GenericPath& out_path) const;
- bool trait_contains_type(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::std::string& name, ::HIR::GenericPath& out_path) const;
+ bool find_trait_impls_crate(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams& params, const ::HIR::TypeRef& type, t_cb_trait_impl callback) const {
+ return m_resolve.find_trait_impls_crate(sp, trait, params, type, callback);
+ }
- const ::HIR::TypeRef* autoderef(const Span& sp, const ::HIR::TypeRef& ty, ::HIR::TypeRef& tmp_type) const;
/// Locate the named method by applying auto-dereferencing.
/// \return Number of times deref was applied (or ~0 if _ was hit)
- unsigned int autoderef_find_method(const Span& sp, const ::HIR::TypeRef& top_ty, const ::std::string& method_name, /* Out -> */::HIR::Path& fcn_path) const;
- bool find_method(const Span& sp, const ::HIR::TypeRef& ty, const ::std::string& method_name, /* Out -> */::HIR::Path& fcn_path) const;
+ unsigned int autoderef_find_method(const Span& sp, const ::HIR::TypeRef& top_ty, const ::std::string& method_name, /* Out -> */::HIR::Path& fcn_path) const {
+ return m_resolve.autoderef_find_method(sp, m_traits, top_ty, method_name, fcn_path);
+ }
- unsigned int autoderef_find_field(const Span& sp, const ::HIR::TypeRef& top_ty, const ::std::string& name, /* Out -> */::HIR::TypeRef& field_type) const;
- bool find_field(const Span& sp, const ::HIR::TypeRef& ty, const ::std::string& name, /* Out -> */::HIR::TypeRef& field_type) const;
+ unsigned int autoderef_find_field(const Span& sp, const ::HIR::TypeRef& top_ty, const ::std::string& name, /* Out -> */::HIR::TypeRef& field_type) const {
+ return m_resolve.autoderef_find_field(sp, /*m_traits,*/ top_ty, name, field_type);
+ }
+ const ::HIR::TypeRef* autoderef(const Span& sp, const ::HIR::TypeRef& ty, ::HIR::TypeRef& tmp_type) const {
+ return m_resolve.autoderef(sp, ty, tmp_type);
+ }
public:
::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> callback_resolve_infer() const {
diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp
index 5095cf7c..e560d2e7 100644
--- a/src/hir_typeck/helpers.cpp
+++ b/src/hir_typeck/helpers.cpp
@@ -416,6 +416,80 @@ void HMTypeInferrence::print_type(::std::ostream& os, const ::HIR::TypeRef& tr)
)
)
}
+
+void HMTypeInferrence::add_ivars(::HIR::TypeRef& type)
+{
+ TU_MATCH(::HIR::TypeRef::Data, (type.m_data), (e),
+ (Infer,
+ if( e.index == ~0u ) {
+ e.index = this->new_ivar();
+ this->get_type(type).m_data.as_Infer().ty_class = e.ty_class;
+ this->mark_change();
+ }
+ ),
+ (Diverge,
+ ),
+ (Primitive,
+ ),
+ (Path,
+ // Iterate all arguments
+ TU_MATCH(::HIR::Path::Data, (e.path.m_data), (e2),
+ (Generic,
+ this->add_ivars_params(e2.m_params);
+ ),
+ (UfcsKnown,
+ this->add_ivars(*e2.type);
+ this->add_ivars_params(e2.trait.m_params);
+ this->add_ivars_params(e2.params);
+ ),
+ (UfcsUnknown,
+ this->add_ivars(*e2.type);
+ this->add_ivars_params(e2.params);
+ ),
+ (UfcsInherent,
+ this->add_ivars(*e2.type);
+ this->add_ivars_params(e2.params);
+ )
+ )
+ ),
+ (Generic,
+ ),
+ (TraitObject,
+ // Iterate all paths
+ ),
+ (Array,
+ add_ivars(*e.inner);
+ ),
+ (Slice,
+ add_ivars(*e.inner);
+ ),
+ (Tuple,
+ for(auto& ty : e)
+ add_ivars(ty);
+ ),
+ (Borrow,
+ add_ivars(*e.inner);
+ ),
+ (Pointer,
+ add_ivars(*e.inner);
+ ),
+ (Function,
+ // No ivars allowed
+ // TODO: Check?
+ ),
+ (Closure,
+ // Shouldn't be possible
+ )
+ )
+}
+void HMTypeInferrence::add_ivars_params(::HIR::PathParams& params)
+{
+ for(auto& arg : params.m_types)
+ add_ivars(arg);
+}
+
+
+
unsigned int HMTypeInferrence::new_ivar()
{
m_ivars.push_back( IVar() );
@@ -549,3 +623,187 @@ HMTypeInferrence::IVar& HMTypeInferrence::get_pointed_ivar(unsigned int slot) co
}
return const_cast<IVar&>(m_ivars.at(index));
}
+
+bool HMTypeInferrence::pathparams_contain_ivars(const ::HIR::PathParams& pps) const {
+ for( const auto& ty : pps.m_types ) {
+ if(this->type_contains_ivars(ty))
+ return true;
+ }
+ return false;
+}
+bool HMTypeInferrence::type_contains_ivars(const ::HIR::TypeRef& ty) const {
+ TU_MATCH(::HIR::TypeRef::Data, (this->get_type(ty).m_data), (e),
+ (Infer, return true; ),
+ (Primitive, return false; ),
+ (Diverge, return false; ),
+ (Generic, return false; ),
+ (Path,
+ TU_MATCH(::HIR::Path::Data, (e.path.m_data), (pe),
+ (Generic,
+ return pathparams_contain_ivars(pe.m_params);
+ ),
+ (UfcsKnown,
+ if( type_contains_ivars(*pe.type) )
+ return true;
+ if( pathparams_contain_ivars(pe.trait.m_params) )
+ return true;
+ return pathparams_contain_ivars(pe.params);
+ ),
+ (UfcsInherent,
+ if( type_contains_ivars(*pe.type) )
+ return true;
+ return pathparams_contain_ivars(pe.params);
+ ),
+ (UfcsUnknown,
+ BUG(Span(), "UfcsUnknown");
+ )
+ )
+ ),
+ (Borrow,
+ return type_contains_ivars(*e.inner);
+ ),
+ (Pointer,
+ return type_contains_ivars(*e.inner);
+ ),
+ (Slice,
+ return type_contains_ivars(*e.inner);
+ ),
+ (Array,
+ return type_contains_ivars(*e.inner);
+ ),
+ (Closure,
+ for(const auto& arg : e.m_arg_types)
+ if( type_contains_ivars(arg) )
+ return true;
+ return type_contains_ivars(*e.m_rettype);
+ ),
+ (Function,
+ for(const auto& arg : e.m_arg_types)
+ if( type_contains_ivars(arg) )
+ return true;
+ return type_contains_ivars(*e.m_rettype);
+ ),
+ (TraitObject,
+ for(const auto& marker : e.m_markers)
+ if( pathparams_contain_ivars(marker.m_params) )
+ return true;
+ return pathparams_contain_ivars(e.m_trait.m_path.m_params);
+ ),
+ (Tuple,
+ for(const auto& st : e)
+ if( type_contains_ivars(st) )
+ return true;
+ return false;
+ )
+ )
+ throw "";
+}
+
+namespace {
+ bool type_list_equal(const HMTypeInferrence& context, const ::std::vector< ::HIR::TypeRef>& l, const ::std::vector< ::HIR::TypeRef>& r)
+ {
+ if( l.size() != r.size() )
+ return false;
+
+ for( unsigned int i = 0; i < l.size(); i ++ ) {
+ if( !context.types_equal(l[i], r[i]) )
+ return false;
+ }
+ return true;
+ }
+}
+bool HMTypeInferrence::pathparams_equal(const ::HIR::PathParams& pps_l, const ::HIR::PathParams& pps_r) const
+{
+ return type_list_equal(*this, pps_l.m_types, pps_r.m_types);
+}
+bool HMTypeInferrence::types_equal(const ::HIR::TypeRef& rl, const ::HIR::TypeRef& rr) const
+{
+ const auto& l = this->get_type(rl);
+ const auto& r = this->get_type(rr);
+ if( l.m_data.tag() != r.m_data.tag() )
+ return false;
+
+ TU_MATCH(::HIR::TypeRef::Data, (l.m_data, r.m_data), (le, re),
+ (Infer, return le.index == re.index; ),
+ (Primitive, return le == re; ),
+ (Diverge, return true; ),
+ (Generic, return le.binding == re.binding; ),
+ (Path,
+ if( le.path.m_data.tag() != re.path.m_data.tag() )
+ return false;
+ TU_MATCH(::HIR::Path::Data, (le.path.m_data, re.path.m_data), (lpe, rpe),
+ (Generic,
+ if( lpe.m_path != rpe.m_path )
+ return false;
+ return pathparams_equal(lpe.m_params, rpe.m_params);
+ ),
+ (UfcsKnown,
+ if( lpe.item != rpe.item )
+ return false;
+ if( types_equal(*lpe.type, *rpe.type) )
+ return false;
+ if( pathparams_equal(lpe.trait.m_params, rpe.trait.m_params) )
+ return false;
+ return pathparams_equal(lpe.params, rpe.params);
+ ),
+ (UfcsInherent,
+ if( lpe.item != rpe.item )
+ return false;
+ if( types_equal(*lpe.type, *rpe.type) )
+ return false;
+ return pathparams_equal(lpe.params, rpe.params);
+ ),
+ (UfcsUnknown,
+ BUG(Span(), "UfcsUnknown");
+ )
+ )
+ ),
+ (Borrow,
+ if( le.type != re.type )
+ return false;
+ return types_equal(*le.inner, *re.inner);
+ ),
+ (Pointer,
+ if( le.type != re.type )
+ return false;
+ return types_equal(*le.inner, *re.inner);
+ ),
+ (Slice,
+ return types_equal(*le.inner, *re.inner);
+ ),
+ (Array,
+ if( le.size_val != re.size_val )
+ return false;
+ return types_equal(*le.inner, *re.inner);
+ ),
+ (Closure,
+ if( !type_list_equal(*this, le.m_arg_types, re.m_arg_types) )
+ return false;
+ return types_equal(*le.m_rettype, *re.m_rettype);
+ ),
+ (Function,
+ if( !type_list_equal(*this, le.m_arg_types, re.m_arg_types) )
+ return false;
+ return types_equal(*le.m_rettype, *re.m_rettype);
+ ),
+ (TraitObject,
+ if( le.m_markers.size() != re.m_markers.size() )
+ return false;
+ for(unsigned int i = 0; i < le.m_markers.size(); i ++) {
+ const auto& lm = le.m_markers[i];
+ const auto& rm = re.m_markers[i];
+ if( lm.m_path != rm.m_path )
+ return false;
+ if( ! pathparams_equal(lm.m_params, rm.m_params) )
+ return false;
+ }
+ if( le.m_trait.m_path.m_path != re.m_trait.m_path.m_path )
+ return false;
+ return pathparams_equal(le.m_trait.m_path.m_params, re.m_trait.m_path.m_params);
+ ),
+ (Tuple,
+ return type_list_equal(*this, le, re);
+ )
+ )
+ throw "";
+}
diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp
index 0a744c32..93833f48 100644
--- a/src/hir_typeck/helpers.hpp
+++ b/src/hir_typeck/helpers.hpp
@@ -1,3 +1,5 @@
+/*
+ */
#pragma once
#include <hir/type.hpp>
@@ -20,6 +22,19 @@ extern ::HIR::TypeRef monomorphise_type(const Span& sp, const ::HIR::GenericPara
class HMTypeInferrence
{
public:
+ struct FmtType {
+ const HMTypeInferrence& ctxt;
+ const ::HIR::TypeRef& ty;
+ FmtType(const HMTypeInferrence& ctxt, const ::HIR::TypeRef& ty):
+ ctxt(ctxt),
+ ty(ty)
+ {}
+ friend ::std::ostream& operator<<(::std::ostream& os, const FmtType& x) {
+ x.ctxt.print_type(os, x.ty);
+ return os;
+ }
+ };
+
struct IVar
{
unsigned int alias; // If not ~0, this points to another ivar
@@ -51,10 +66,15 @@ public:
}
void compact_ivars();
- void dump() const;
bool apply_defaults();
+ void dump() const;
+
void print_type(::std::ostream& os, const ::HIR::TypeRef& tr) const;
+ FmtType fmt_type(const ::HIR::TypeRef& tr) const {
+ return FmtType(*this, tr);
+ }
+
/// Add (and bind) all '_' types in `type`
void add_ivars(::HIR::TypeRef& type);
// (helper) Add ivars to path parameters
@@ -69,13 +89,21 @@ public:
};
}
+ // Mutation
unsigned int new_ivar();
::HIR::TypeRef new_ivar_tr();
- ::HIR::TypeRef& get_type(::HIR::TypeRef& type);
- const ::HIR::TypeRef& get_type(const ::HIR::TypeRef& type) const;
-
void set_ivar_to(unsigned int slot, ::HIR::TypeRef type);
void ivar_unify(unsigned int left_slot, unsigned int right_slot);
+
+ // Lookup
+ ::HIR::TypeRef& get_type(::HIR::TypeRef& type);
+ const ::HIR::TypeRef& get_type(const ::HIR::TypeRef& type) const;
+
+ // Helpers
+ bool pathparams_contain_ivars(const ::HIR::PathParams& pps) const;
+ bool type_contains_ivars(const ::HIR::TypeRef& ty) const;
+ bool pathparams_equal(const ::HIR::PathParams& pps_l, const ::HIR::PathParams& pps_r) const;
+ bool types_equal(const ::HIR::TypeRef& l, const ::HIR::TypeRef& r) const;
private:
IVar& get_pointed_ivar(unsigned int slot) const;
};