diff options
-rw-r--r-- | src/hir_typeck/helpers.cpp | 296 | ||||
-rw-r--r-- | src/hir_typeck/helpers.hpp | 1 |
2 files changed, 155 insertions, 142 deletions
diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index 727e41ba..e27d2b00 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -2078,148 +2078,15 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp, return false; } - // HELPER: Search for an impl of this trait for an inner type, and return the match type - auto type_impls_trait = [&](const auto& inner_ty) -> ::HIR::Compare { - auto l_res = ::HIR::Compare::Unequal; - this->find_trait_impls(sp, trait, *params_ptr, inner_ty, [&](auto, auto cmp){ l_res = cmp; return (cmp == ::HIR::Compare::Equal); }); - DEBUG("[type_impls_auto_trait] " << inner_ty << " - " << l_res); - return l_res; - }; - - static ::std::map< ::std::string, ::HIR::TypeRef> null_assoc; - // - If the type is a path (struct/enum/...), search for impls for all contained types. - TU_IFLET( ::HIR::TypeRef::Data, type.m_data, Path, e, - TU_MATCH( ::HIR::Path::Data, (e.path.m_data), (pe), - (Generic, - ::HIR::TypeRef tmp; - auto monomorph_cb = [&](const auto& gt)->const auto& { - const auto& ge = gt.m_data.as_Generic(); - if( ge.binding == 0xFFFF ) { - BUG(sp, "Self type in struct/enum generics"); - } - else if( ge.binding >> 8 == 0 ) { - auto idx = ge.binding & 0xFF; - ASSERT_BUG(sp, idx < pe.m_params.m_types.size(), "Type parameter out of range - " << gt); - return pe.m_params.m_types[idx]; - } - else { - BUG(sp, "Unexpected type parameter - " << gt << " in content of " << type); - } - }; - // HELPER: Get a possibily monomorphised version of the input type (stored in `tmp` if needed) - auto monomorph_get = [&](const auto& ty)->const auto& { - if( monomorphise_type_needed(ty) ) { - return (tmp = monomorphise_type_with(sp, ty, monomorph_cb)); - } - else { - return ty; - } - }; - - ::HIR::Compare res = ::HIR::Compare::Equal; - TU_MATCH( ::HIR::TypeRef::TypePathBinding, (e.binding), (tpb), - (Opaque, - BUG(sp, "Opaque binding on generic path - " << type); - ), - (Unbound, - BUG(sp, "Unbound binding on generic path - " << type); - ), - (Struct, - const auto& str = *tpb; - - // TODO: Somehow store a ruleset for auto traits on the type - // - Map of trait->does_impl for local fields? - // - Problems occur with type parameters - TU_MATCH( ::HIR::Struct::Data, (str.m_data), (se), - (Unit, - ), - (Tuple, - for(const auto& fld : se) - { - const auto& fld_ty_mono = monomorph_get(fld.ent); - res &= type_impls_trait(fld_ty_mono); - if( res == ::HIR::Compare::Unequal ) - return false; - } - ), - (Named, - for(const auto& fld : se) - { - const auto& fld_ty_mono = monomorph_get(fld.second.ent); - - res &= type_impls_trait(fld_ty_mono); - if( res == ::HIR::Compare::Unequal ) - return false; - } - ) - ) - ), - (Enum, - const auto& enm = *tpb; - - for(const auto& var : enm.m_variants) - { - TU_MATCH(::HIR::Enum::Variant, (var.second), (ve), - (Unit, - ), - (Value, - ), - (Tuple, - for(const auto& fld : ve) - { - const auto& fld_ty_mono = monomorph_get(fld.ent); - res &= type_impls_trait(fld_ty_mono); - if( res == ::HIR::Compare::Unequal ) - return false; - } - ), - (Struct, - for(const auto& fld : ve) - { - const auto& fld_ty_mono = monomorph_get(fld.second.ent); - - res &= type_impls_trait(fld_ty_mono); - if( res == ::HIR::Compare::Unequal ) - return false; - } - ) - ) - } - ) - ) - DEBUG("- Nothing failed, calling callback"); - return callback( ImplRef(&type, params_ptr, &null_assoc), res ); - ), - (UfcsUnknown, - BUG(sp, "UfcsUnknown in typeck - " << type); - ), - (UfcsKnown, - TODO(sp, "Check trait bounds for bound on " << type); - ), - (UfcsInherent, - TODO(sp, "Auto trait lookup on UFCS Inherent type"); - ) - ) - ) - else TU_IFLET( ::HIR::TypeRef::Data, type.m_data, Tuple, e, - ::HIR::Compare res = ::HIR::Compare::Equal; - for(const auto& sty : e) - { - res &= type_impls_trait(sty); - if( res == ::HIR::Compare::Unequal ) - return false; - } - return callback( ImplRef(&type, params_ptr, &null_assoc), res ); - ) - else TU_IFLET( ::HIR::TypeRef::Data, type.m_data, Array, e, - auto res = type_impls_trait(*e.inner); - if( res == ::HIR::Compare::Unequal ) - return false; - return callback( ImplRef(&type, params_ptr, &null_assoc), res ); - ) - // Otherwise, there's no negative so it must be positive - else { - return callback( ImplRef(&type, params_ptr, &null_assoc), ::HIR::Compare::Equal ); + auto cmp = this->check_auto_trait_impl_destructure(sp, trait, params_ptr, type); + if( cmp != ::HIR::Compare::Unequal ) + { + static ::std::map< ::std::string, ::HIR::TypeRef> null_assoc; + return callback( ImplRef(&type, params_ptr, &null_assoc), cmp ); + } + else + { + return false; } } @@ -2265,6 +2132,151 @@ bool TraitResolution::find_trait_impls_crate(const Span& sp, } ); } + +::HIR::Compare TraitResolution::check_auto_trait_impl_destructure(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams* params_ptr, const ::HIR::TypeRef& type) const +{ + TRACE_FUNCTION_F("trait = " << trait << ", type = " << type); + // HELPER: Search for an impl of this trait for an inner type, and return the match type + auto type_impls_trait = [&](const auto& inner_ty) -> ::HIR::Compare { + auto l_res = ::HIR::Compare::Unequal; + this->find_trait_impls(sp, trait, *params_ptr, inner_ty, [&](auto, auto cmp){ l_res = cmp; return (cmp == ::HIR::Compare::Equal); }); + DEBUG("[type_impls_auto_trait] " << inner_ty << " - " << l_res); + return l_res; + }; + + // - If the type is a path (struct/enum/...), search for impls for all contained types. + TU_IFLET( ::HIR::TypeRef::Data, type.m_data, Path, e, + ::HIR::Compare res = ::HIR::Compare::Equal; + TU_MATCH( ::HIR::Path::Data, (e.path.m_data), (pe), + (Generic, + ::HIR::TypeRef tmp; + auto monomorph_cb = [&](const auto& gt)->const auto& { + const auto& ge = gt.m_data.as_Generic(); + if( ge.binding == 0xFFFF ) { + BUG(sp, "Self type in struct/enum generics"); + } + else if( ge.binding >> 8 == 0 ) { + auto idx = ge.binding & 0xFF; + ASSERT_BUG(sp, idx < pe.m_params.m_types.size(), "Type parameter out of range - " << gt); + return pe.m_params.m_types[idx]; + } + else { + BUG(sp, "Unexpected type parameter - " << gt << " in content of " << type); + } + }; + // HELPER: Get a possibily monomorphised version of the input type (stored in `tmp` if needed) + auto monomorph_get = [&](const auto& ty)->const auto& { + if( monomorphise_type_needed(ty) ) { + return (tmp = monomorphise_type_with(sp, ty, monomorph_cb)); + } + else { + return ty; + } + }; + + TU_MATCH( ::HIR::TypeRef::TypePathBinding, (e.binding), (tpb), + (Opaque, + BUG(sp, "Opaque binding on generic path - " << type); + ), + (Unbound, + BUG(sp, "Unbound binding on generic path - " << type); + ), + (Struct, + const auto& str = *tpb; + + // TODO: Somehow store a ruleset for auto traits on the type + // - Map of trait->does_impl for local fields? + // - Problems occur with type parameters + TU_MATCH( ::HIR::Struct::Data, (str.m_data), (se), + (Unit, + ), + (Tuple, + for(const auto& fld : se) + { + const auto& fld_ty_mono = monomorph_get(fld.ent); + res &= type_impls_trait(fld_ty_mono); + if( res == ::HIR::Compare::Unequal ) + return ::HIR::Compare::Unequal; + } + ), + (Named, + for(const auto& fld : se) + { + const auto& fld_ty_mono = monomorph_get(fld.second.ent); + + res &= type_impls_trait(fld_ty_mono); + if( res == ::HIR::Compare::Unequal ) + return ::HIR::Compare::Unequal; + } + ) + ) + ), + (Enum, + const auto& enm = *tpb; + + for(const auto& var : enm.m_variants) + { + TU_MATCH(::HIR::Enum::Variant, (var.second), (ve), + (Unit, + ), + (Value, + ), + (Tuple, + for(const auto& fld : ve) + { + const auto& fld_ty_mono = monomorph_get(fld.ent); + res &= type_impls_trait(fld_ty_mono); + if( res == ::HIR::Compare::Unequal ) + return ::HIR::Compare::Unequal; + } + ), + (Struct, + for(const auto& fld : ve) + { + const auto& fld_ty_mono = monomorph_get(fld.second.ent); + + res &= type_impls_trait(fld_ty_mono); + if( res == ::HIR::Compare::Unequal ) + return ::HIR::Compare::Unequal; + } + ) + ) + } + ) + ) + DEBUG("- Nothing failed, calling callback"); + ), + (UfcsUnknown, + BUG(sp, "UfcsUnknown in typeck - " << type); + ), + (UfcsKnown, + TODO(sp, "Check trait bounds for bound on " << type); + ), + (UfcsInherent, + TODO(sp, "Auto trait lookup on UFCS Inherent type"); + ) + ) + return res; + ) + else TU_IFLET( ::HIR::TypeRef::Data, type.m_data, Tuple, e, + ::HIR::Compare res = ::HIR::Compare::Equal; + for(const auto& sty : e) + { + res &= type_impls_trait(sty); + if( res == ::HIR::Compare::Unequal ) + return ::HIR::Compare::Unequal; + } + return res; + ) + else TU_IFLET( ::HIR::TypeRef::Data, type.m_data, Array, e, + return type_impls_trait(*e.inner); + ) + // Otherwise, there's no negative so it must be positive + else { + return ::HIR::Compare::Equal; + } +} + ::HIR::Compare TraitResolution::ftic_check_params(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams* params_ptr, const ::HIR::TypeRef& type, const ::HIR::GenericParams& impl_params_def, const ::HIR::PathParams& impl_trait_args, const ::HIR::TypeRef& impl_ty, diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp index daedf062..fe196dce 100644 --- a/src/hir_typeck/helpers.hpp +++ b/src/hir_typeck/helpers.hpp @@ -209,6 +209,7 @@ public: bool find_trait_impls_crate(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams* params, const ::HIR::TypeRef& type, t_cb_trait_impl_r callback) const; private: + ::HIR::Compare check_auto_trait_impl_destructure(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams* params_ptr, const ::HIR::TypeRef& type) const; ::HIR::Compare ftic_check_params(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::PathParams* params, const ::HIR::TypeRef& type, const ::HIR::GenericParams& impl_params_def, const ::HIR::PathParams& impl_trait_args, const ::HIR::TypeRef& impl_ty, |