summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@ucc.asn.au>2017-05-06 15:01:24 +0800
committerJohn Hodge <tpg@ucc.asn.au>2017-05-06 15:01:24 +0800
commit916c8650efcb0224c580bb7d30b358caa67497db (patch)
treecec884cce080de6129a9111f3041bd6c0b5b0e6a /src
parentdbcfef417cf056b5e466ad9e1d3afc90fbdccb62 (diff)
downloadmrust-916c8650efcb0224c580bb7d30b358caa67497db.tar.gz
Typecheck Expressions - Fix broken associated type unsize
Diffstat (limited to 'src')
-rw-r--r--src/hir_typeck/expr_cs.cpp2
-rw-r--r--src/hir_typeck/helpers.cpp128
-rw-r--r--src/hir_typeck/helpers.hpp1
3 files changed, 74 insertions, 57 deletions
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index 1ac3b2f0..54c63ccd 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -4263,6 +4263,7 @@ namespace {
// Deref coercions
// - If right can be dereferenced to left
+ DEBUG("-- Deref coercions");
{
::HIR::TypeRef tmp_ty;
const ::HIR::TypeRef* out_ty = &ty_src;
@@ -4414,6 +4415,7 @@ namespace {
// Search for Unsize
// - If `right`: ::core::marker::Unsize<`left`>
+ DEBUG("-- Unsize trait");
{
auto cmp = context.m_resolve.can_unsize(sp, ty_dst, ty_src, [&](auto new_dst) {
// Equate these two types
diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp
index f1183157..1c7fbd66 100644
--- a/src/hir_typeck/helpers.cpp
+++ b/src/hir_typeck/helpers.cpp
@@ -1020,6 +1020,41 @@ bool TraitResolution::iterate_bounds( ::std::function<bool(const ::HIR::GenericB
}
return false;
}
+bool TraitResolution::iterate_aty_bounds(const Span& sp, const ::HIR::Path::Data::Data_UfcsKnown& pe, ::std::function<bool(const ::HIR::TraitPath&)> cb) const
+{
+ const auto& trait_ref = m_crate.get_trait_by_path(sp, pe.trait.m_path);
+ ASSERT_BUG(sp, trait_ref.m_types.count( pe.item ) != 0, "Trait " << pe.trait.m_path << " doesn't contain an associated type " << pe.item);
+ const auto& aty_def = trait_ref.m_types.find(pe.item)->second;
+
+ for(const auto& bound : aty_def.m_trait_bounds)
+ {
+ if( cb(bound) )
+ return true;
+ }
+ // Search `<Self as Trait>::Name` bounds on the trait itself
+ for(const auto& bound : trait_ref.m_params.m_bounds)
+ {
+ if( ! bound.is_TraitBound() ) continue ;
+ const auto& be = bound.as_TraitBound();
+
+ if( ! be.type.m_data.is_Path() ) continue ;
+ if( ! be.type.m_data.as_Path().binding.is_Opaque() ) continue ;
+
+ const auto& be_type_pe = be.type.m_data.as_Path().path.m_data.as_UfcsKnown();
+ if( *be_type_pe.type != ::HIR::TypeRef("Self", 0xFFFF) )
+ continue ;
+ if( be_type_pe.trait.m_path != pe.trait.m_path )
+ continue ;
+ if( be_type_pe.item != pe.item )
+ continue ;
+
+ if( cb(be.trait) )
+ return true;
+ }
+
+ return false;
+}
+
bool TraitResolution::find_trait_impls(const Span& sp,
const ::HIR::SimplePath& trait, const ::HIR::PathParams& params,
const ::HIR::TypeRef& ty,
@@ -1343,15 +1378,9 @@ bool TraitResolution::find_trait_impls(const Span& sp,
ASSERT_BUG(sp, e.path.m_data.is_UfcsKnown(), "Opaque bound type wasn't UfcsKnown - " << type);
const auto& pe = e.path.m_data.as_UfcsKnown();
- // If this associated type has a bound of the desired trait, return it.
- const auto& trait_ref = m_crate.get_trait_by_path(sp, pe.trait.m_path);
- ASSERT_BUG(sp, trait_ref.m_types.count( pe.item ) != 0, "Trait " << pe.trait.m_path << " doesn't contain an associated type " << pe.item);
- const auto& aty_def = trait_ref.m_types.find(pe.item)->second;
-
auto monomorph_cb = monomorphise_type_get_cb(sp, &*pe.type, &pe.trait.m_params, nullptr, nullptr);
- for(const auto& bound : aty_def.m_trait_bounds)
- {
+ auto rv = this->iterate_aty_bounds(sp, pe, [&](const auto& bound) {
const auto& b_params = bound.m_path.m_params;
::HIR::PathParams params_mono_o;
const auto& b_params_mono = (monomorphise_pathparams_needed(b_params) ? params_mono_o = monomorphise_path_params_with(sp, b_params, monomorph_cb, false) : b_params);
@@ -1382,58 +1411,14 @@ bool TraitResolution::find_trait_impls(const Span& sp,
return cmp != ::HIR::Compare::Unequal && callback( ImplRef(i_ty.clone(), i_params.clone(), {}), cmp );
});
if( ret )
- return true;
- }
- // TODO: Search `<Self as Trait>::Name` bounds on the trait itself
- for(const auto& bound : trait_ref.m_params.m_bounds)
- {
- if( ! bound.is_TraitBound() ) continue ;
- const auto& be = bound.as_TraitBound();
-
- if( ! be.type.m_data.is_Path() ) continue ;
- if( ! be.type.m_data.as_Path().binding.is_Opaque() ) continue ;
-
- const auto& be_type_pe = be.type.m_data.as_Path().path.m_data.as_UfcsKnown();
- if( *be_type_pe.type != ::HIR::TypeRef("Self", 0xFFFF) )
- continue ;
- if( be_type_pe.trait.m_path != pe.trait.m_path )
- continue ;
- if( be_type_pe.item != pe.item )
- continue ;
-
- // TODO: Merge the below code with the code from the above loop.
- const auto& b_params = be.trait.m_path.m_params;
- ::HIR::PathParams params_mono_o;
- const auto& b_params_mono = (monomorphise_pathparams_needed(b_params) ? params_mono_o = monomorphise_path_params_with(sp, b_params, monomorph_cb, false) : b_params);
-
- if( be.trait.m_path.m_path == trait )
{
- auto cmp = this->compare_pp(sp, b_params_mono, params);
- if( cmp != ::HIR::Compare::Unequal )
- {
- if( &b_params_mono == &params_mono_o )
- {
- if( callback( ImplRef(type.clone(), mv$(params_mono_o), {}), cmp ) )
- return true;
- params_mono_o = monomorphise_path_params_with(sp, b_params, monomorph_cb, false);
- }
- else
- {
- if( callback( ImplRef(&type, &b_params, &null_assoc), cmp ) )
- return true;
- }
- }
- }
-
- bool ret = this->find_named_trait_in_trait(sp, trait, params, *be.trait.m_trait_ptr, be.trait.m_path.m_path, b_params_mono, type,
- [&](const auto& i_ty, const auto& i_params, const auto& i_assoc) {
- auto cmp = this->compare_pp(sp, i_params, params);
- DEBUG("cmp=" << cmp << ", impl " << trait << i_params << " for " << i_ty << " -- desired " << trait << params);
- return cmp != ::HIR::Compare::Unequal && callback( ImplRef(i_ty.clone(), i_params.clone(), {}), cmp );
- });
- if( ret )
+ // NOTE: Callback called in closure's return statement
return true;
- }
+ }
+ return false;
+ });
+ if( rv )
+ return true;
}
)
@@ -3081,6 +3066,35 @@ bool TraitResolution::trait_contains_type(const Span& sp, const ::HIR::GenericPa
}
}
+ // Associated types, check the bounds in the trait.
+ if( src_ty.m_data.is_Path() && src_ty.m_data.as_Path().path.m_data.is_UfcsKnown() )
+ {
+ ::HIR::Compare rv = ::HIR::Compare::Equal;
+ const auto& pe = src_ty.m_data.as_Path().path.m_data.as_UfcsKnown();
+ auto monomorph_cb = monomorphise_type_get_cb(sp, &*pe.type, &pe.trait.m_params, nullptr, nullptr);
+ auto found_bound = this->iterate_aty_bounds(sp, pe, [&](const ::HIR::TraitPath& bound) {
+ if( bound.m_path.m_path != lang_Unsize )
+ return false;
+ const auto& be_dst_tpl = bound.m_path.m_params.m_types.at(0);
+ ::HIR::TypeRef tmp_ty;
+ const auto& be_dst = (monomorphise_type_needed(be_dst_tpl) ? tmp_ty = monomorphise_type_with(sp, be_dst_tpl, monomorph_cb) : be_dst_tpl);
+
+ auto cmp = dst_ty.compare_with_placeholders(sp, be_dst, m_ivars.callback_resolve_infer());
+ if(cmp == ::HIR::Compare::Unequal) return false;
+
+ if( cmp != ::HIR::Compare::Equal )
+ {
+ DEBUG("> Found bound (fuzzy) " << dst_ty << "=" << be_dst << " <- " << src_ty);
+ rv = ::HIR::Compare::Fuzzy;
+ }
+ return true;
+ });
+ if( found_bound )
+ {
+ return rv;
+ }
+ }
+
// Struct<..., T, ...>: Unsize<Struct<..., U, ...>>
if( dst_ty.m_data.is_Path() && src_ty.m_data.is_Path() )
{
diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp
index 1f63dbf4..b7e6ca38 100644
--- a/src/hir_typeck/helpers.hpp
+++ b/src/hir_typeck/helpers.hpp
@@ -201,6 +201,7 @@ public:
/// Iterate over in-scope bounds (function then top)
bool iterate_bounds( ::std::function<bool(const ::HIR::GenericBound&)> cb) const;
+ bool iterate_aty_bounds(const Span& sp, const ::HIR::Path::Data::Data_UfcsKnown& pe, ::std::function<bool(const ::HIR::TraitPath&)> cb) const;
typedef ::std::function<bool(const ::HIR::TypeRef&, const ::HIR::PathParams&, const ::std::map< ::std::string,::HIR::TypeRef>&)> t_cb_trait_impl;
typedef ::std::function<bool(ImplRef, ::HIR::Compare)> t_cb_trait_impl_r;