summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hir_typeck/helpers.cpp196
-rw-r--r--src/hir_typeck/helpers.hpp2
-rw-r--r--src/trans/enumerate.cpp6
3 files changed, 116 insertions, 88 deletions
diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp
index f3604917..3ff39c63 100644
--- a/src/hir_typeck/helpers.cpp
+++ b/src/hir_typeck/helpers.cpp
@@ -1120,6 +1120,107 @@ bool TraitResolution::iterate_aty_bounds(const Span& sp, const ::HIR::Path::Data
return false;
}
+bool TraitResolution::find_trait_impls_magic(const Span& sp,
+ const ::HIR::SimplePath& trait, const ::HIR::PathParams& params,
+ const ::HIR::TypeRef& ty,
+ t_cb_trait_impl_r callback
+ ) const
+{
+ static ::HIR::PathParams null_params;
+ static ::std::map< ::std::string, ::HIR::TypeRef> null_assoc;
+
+ const auto& lang_Sized = this->m_crate.get_lang_item_path(sp, "sized");
+ const auto& lang_Copy = this->m_crate.get_lang_item_path(sp, "copy");
+ //const auto& lang_Clone = this->m_crate.get_lang_item_path(sp, "clone");
+ const auto& lang_Unsize = this->m_crate.get_lang_item_path(sp, "unsize");
+ const auto& lang_CoerceUnsized = this->m_crate.get_lang_item_path(sp, "coerce_unsized");
+
+ const auto& type = this->m_ivars.get_type(ty);
+ TRACE_FUNCTION_F("trait = " << trait << params << ", type = " << type);
+
+ if( trait == lang_Sized ) {
+ auto cmp = type_is_sized(sp, type);
+ if( cmp != ::HIR::Compare::Unequal ) {
+ return callback( ImplRef(&type, &null_params, &null_assoc), cmp );
+ }
+ else {
+ return false;
+ }
+ }
+
+ if( trait == lang_Copy ) {
+ auto cmp = this->type_is_copy(sp, type);
+ if( cmp != ::HIR::Compare::Unequal ) {
+ return callback( ImplRef(&type, &null_params, &null_assoc), cmp );
+ }
+ else {
+ return false;
+ }
+ }
+
+ if( TARGETVER_1_29 && trait == this->m_crate.get_lang_item_path(sp, "clone") )
+ {
+ auto cmp = this->type_is_clone(sp, type);
+ if( cmp != ::HIR::Compare::Unequal ) {
+ return callback( ImplRef(&type, &null_params, &null_assoc), cmp );
+ }
+ else {
+ return false;
+ }
+ }
+
+ // Magic Unsize impls to trait objects
+ if( trait == lang_Unsize )
+ {
+ ASSERT_BUG(sp, params.m_types.size() == 1, "Unsize trait requires a single type param");
+ const auto& dst_ty = this->m_ivars.get_type(params.m_types[0]);
+
+ if( find_trait_impls_bound(sp, trait, params, type, callback) )
+ return true;
+
+ bool rv = false;
+ auto cb = [&](auto new_dst) {
+ ::HIR::PathParams real_params { mv$(new_dst) };
+ rv = callback( ImplRef(type.clone(), mv$(real_params), {}), ::HIR::Compare::Fuzzy );
+ };
+ //if( dst_ty.m_data.is_Infer() || type.m_data.is_Infer() )
+ //{
+ // rv = callback( ImplRef(type.clone(), params.clone(), {}), ::HIR::Compare::Fuzzy );
+ // return rv;
+ //}
+ auto cmp = this->can_unsize(sp, dst_ty, type, cb);
+ if( cmp == ::HIR::Compare::Equal )
+ {
+ assert(!rv);
+ rv = callback( ImplRef(type.clone(), params.clone(), {}), ::HIR::Compare::Equal );
+ }
+ return rv;
+ }
+
+ // Magical CoerceUnsized impls for various types
+ if( trait == lang_CoerceUnsized ) {
+ const auto& dst_ty = params.m_types.at(0);
+ // - `*mut T => *const T`
+ TU_IFLET( ::HIR::TypeRef::Data, type.m_data, Pointer, e,
+ TU_IFLET( ::HIR::TypeRef::Data, dst_ty.m_data, Pointer, de,
+ if( de.type < e.type ) {
+ auto cmp = e.inner->compare_with_placeholders(sp, *de.inner, this->m_ivars.callback_resolve_infer());
+ if( cmp != ::HIR::Compare::Unequal )
+ {
+ ::HIR::PathParams pp;
+ pp.m_types.push_back( dst_ty.clone() );
+ if( callback( ImplRef(type.clone(), mv$(pp), {}), cmp ) ) {
+ return true;
+ }
+ }
+ }
+ )
+ )
+ }
+
+ return false;
+}
+
bool TraitResolution::find_trait_impls(const Span& sp,
const ::HIR::SimplePath& trait, const ::HIR::PathParams& params,
const ::HIR::TypeRef& ty,
@@ -1143,11 +1244,6 @@ bool TraitResolution::find_trait_impls(const Span& sp,
}
#endif
- const auto& lang_Sized = this->m_crate.get_lang_item_path(sp, "sized");
- const auto& lang_Copy = this->m_crate.get_lang_item_path(sp, "copy");
- //const auto& lang_Clone = this->m_crate.get_lang_item_path(sp, "clone");
- const auto& lang_Unsize = this->m_crate.get_lang_item_path(sp, "unsize");
- const auto& lang_CoerceUnsized = this->m_crate.get_lang_item_path(sp, "coerce_unsized");
const auto& trait_fn = this->m_crate.get_lang_item_path(sp, "fn");
const auto& trait_fn_mut = this->m_crate.get_lang_item_path(sp, "fn_mut");
const auto& trait_fn_once = this->m_crate.get_lang_item_path(sp, "fn_once");
@@ -1156,35 +1252,8 @@ bool TraitResolution::find_trait_impls(const Span& sp,
if( magic_trait_impls )
{
- if( trait == lang_Sized ) {
- auto cmp = type_is_sized(sp, type);
- if( cmp != ::HIR::Compare::Unequal ) {
- return callback( ImplRef(&type, &null_params, &null_assoc), cmp );
- }
- else {
- return false;
- }
- }
-
- if( trait == lang_Copy ) {
- auto cmp = this->type_is_copy(sp, type);
- if( cmp != ::HIR::Compare::Unequal ) {
- return callback( ImplRef(&type, &null_params, &null_assoc), cmp );
- }
- else {
- return false;
- }
- }
-
- if( TARGETVER_1_29 && trait == this->m_crate.get_lang_item_path(sp, "clone") )
- {
- auto cmp = this->type_is_clone(sp, type);
- if( cmp != ::HIR::Compare::Unequal ) {
- return callback( ImplRef(&type, &null_params, &null_assoc), cmp );
- }
- else {
- return false;
- }
+ if( find_trait_impls_magic(sp, trait, params, ty, callback) ) {
+ return true;
}
}
@@ -1468,58 +1537,6 @@ bool TraitResolution::find_trait_impls(const Span& sp,
}
)
- if( magic_trait_impls )
- {
- // Magic Unsize impls to trait objects
- if( trait == lang_Unsize )
- {
- ASSERT_BUG(sp, params.m_types.size() == 1, "Unsize trait requires a single type param");
- const auto& dst_ty = this->m_ivars.get_type(params.m_types[0]);
-
- if( find_trait_impls_bound(sp, trait, params, type, callback) )
- return true;
-
- bool rv = false;
- auto cb = [&](auto new_dst) {
- ::HIR::PathParams real_params { mv$(new_dst) };
- rv = callback( ImplRef(type.clone(), mv$(real_params), {}), ::HIR::Compare::Fuzzy );
- };
- //if( dst_ty.m_data.is_Infer() || type.m_data.is_Infer() )
- //{
- // rv = callback( ImplRef(type.clone(), params.clone(), {}), ::HIR::Compare::Fuzzy );
- // return rv;
- //}
- auto cmp = this->can_unsize(sp, dst_ty, type, cb);
- if( cmp == ::HIR::Compare::Equal )
- {
- assert(!rv);
- rv = callback( ImplRef(type.clone(), params.clone(), {}), ::HIR::Compare::Equal );
- }
- return rv;
- }
-
- // Magical CoerceUnsized impls for various types
- if( trait == lang_CoerceUnsized ) {
- const auto& dst_ty = params.m_types.at(0);
- // - `*mut T => *const T`
- TU_IFLET( ::HIR::TypeRef::Data, type.m_data, Pointer, e,
- TU_IFLET( ::HIR::TypeRef::Data, dst_ty.m_data, Pointer, de,
- if( de.type < e.type ) {
- auto cmp = e.inner->compare_with_placeholders(sp, *de.inner, this->m_ivars.callback_resolve_infer());
- if( cmp != ::HIR::Compare::Unequal )
- {
- ::HIR::PathParams pp;
- pp.m_types.push_back( dst_ty.clone() );
- if( callback( ImplRef(type.clone(), mv$(pp), {}), cmp ) ) {
- return true;
- }
- }
- }
- )
- )
- }
- }
-
// 1. Search generic params
if( find_trait_impls_bound(sp, trait, params, type, callback) )
return true;
@@ -4169,7 +4186,12 @@ bool TraitResolution::find_method(const Span& sp,
bool magic_found = false;
bool crate_impl_found = false;
- // NOTE: THis just detects the presence of a trait impl, not the specifics
+
+ crate_impl_found = find_trait_impls_magic(sp, *trait_ref.first, trait_params, self_ty, [&](auto impl, auto cmp) {
+ return true;
+ });
+
+ // NOTE: This just detects the presence of a trait impl, not the specifics
find_trait_impls_crate(sp, *trait_ref.first, &trait_params, self_ty, [&](auto impl, auto cmp) {
DEBUG("[find_method] " << impl << ", cmp = " << cmp);
magic_found = true;
diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp
index cb95c94f..fcd17cfb 100644
--- a/src/hir_typeck/helpers.hpp
+++ b/src/hir_typeck/helpers.hpp
@@ -225,6 +225,8 @@ public:
}
/// Search for a trait implementation in the crate (allows nullptr to ignore params)
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;
+ /// Check for magic (automatically determined) trait implementations
+ bool find_trait_impls_magic(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;
diff --git a/src/trans/enumerate.cpp b/src/trans/enumerate.cpp
index ce3eb53a..a94e302c 100644
--- a/src/trans/enumerate.cpp
+++ b/src/trans/enumerate.cpp
@@ -1376,7 +1376,11 @@ void Trans_Enumerate_FillFrom_Path(EnumState& state, const ::HIR::Path& path, co
// Must have been a dynamic dispatch request, just leave as-is
}
// - <fn(...) as Fn*>::call*
- else if( path_mono.m_data.is_UfcsKnown() && path_mono.m_data.as_UfcsKnown().type->m_data.is_Function() )
+ else if( path_mono.m_data.is_UfcsKnown() && path_mono.m_data.as_UfcsKnown().type->m_data.is_Function() && (
+ path_mono.m_data.as_UfcsKnown().trait.m_path == state.crate.get_lang_item_path_opt("fn")
+ || path_mono.m_data.as_UfcsKnown().trait.m_path == state.crate.get_lang_item_path_opt("fn_mut")
+ || path_mono.m_data.as_UfcsKnown().trait.m_path == state.crate.get_lang_item_path_opt("fn_once")
+ ) )
{
// Must have been a dynamic dispatch request, just leave as-is
}