diff options
author | John Hodge <tpg@mutabah.net> | 2016-07-03 19:48:23 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-07-03 19:48:23 +0800 |
commit | 08290af3aa179c24e34b6d516265c1b789514893 (patch) | |
tree | e08c3b3ff334d7a9f36717744661c3fe3a0c4a05 | |
parent | b602f1e0fe87c2d11120e0ab7e556db9276b9a78 (diff) | |
download | mrust-08290af3aa179c24e34b6d516265c1b789514893.tar.gz |
HIR Typecheck - Move trait-related logic to a common class
-rw-r--r-- | src/hir_typeck/expr_context.cpp | 389 | ||||
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 12 | ||||
-rw-r--r-- | src/hir_typeck/expr_simple.cpp | 2 | ||||
-rw-r--r-- | src/hir_typeck/expr_simple.hpp | 147 | ||||
-rw-r--r-- | src/hir_typeck/helpers.cpp | 258 | ||||
-rw-r--r-- | src/hir_typeck/helpers.hpp | 36 |
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; }; |