summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hir_typeck/helpers.cpp296
-rw-r--r--src/hir_typeck/helpers.hpp1
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,