summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2018-12-16 16:53:46 +0800
committerJohn Hodge <tpg@mutabah.net>2018-12-16 16:53:46 +0800
commitf4c39e95caf3c9a8ccd302dbd9eca92b32564c27 (patch)
tree4311eda5b198f8ef9ade0ecf6ab130bb01559e5c /src
parent937b161b40dd6dfdaa0a55c1399b3af2d23227d7 (diff)
downloadmrust-f4c39e95caf3c9a8ccd302dbd9eca92b32564c27.tar.gz
Typecheck Expressions - Extended possibility checking, fallback default (HACK)
Diffstat (limited to 'src')
-rw-r--r--src/hir_typeck/common.cpp21
-rw-r--r--src/hir_typeck/common.hpp1
-rw-r--r--src/hir_typeck/expr_cs.cpp94
-rw-r--r--src/hir_typeck/helpers.cpp22
4 files changed, 110 insertions, 28 deletions
diff --git a/src/hir_typeck/common.cpp b/src/hir_typeck/common.cpp
index 4b0328e7..1bb21f99 100644
--- a/src/hir_typeck/common.cpp
+++ b/src/hir_typeck/common.cpp
@@ -144,7 +144,7 @@ bool monomorphise_type_needed(const ::HIR::TypeRef& tpl)
}
-::HIR::PathParams clone_ty_with__path_params(const Span& sp, const ::HIR::PathParams& tpl, t_cb_clone_ty callback) {
+::HIR::PathParams clone_path_params_with(const Span& sp, const ::HIR::PathParams& tpl, t_cb_clone_ty callback) {
::HIR::PathParams rv;
rv.m_types.reserve( tpl.m_types.size() );
for( const auto& ty : tpl.m_types)
@@ -152,7 +152,7 @@ bool monomorphise_type_needed(const ::HIR::TypeRef& tpl)
return rv;
}
::HIR::GenericPath clone_ty_with__generic_path(const Span& sp, const ::HIR::GenericPath& tpl, t_cb_clone_ty callback) {
- return ::HIR::GenericPath( tpl.m_path, clone_ty_with__path_params(sp, tpl.m_params, callback) );
+ return ::HIR::GenericPath( tpl.m_path, clone_path_params_with(sp, tpl.m_params, callback) );
}
::HIR::TraitPath clone_ty_with__trait_path(const Span& sp, const ::HIR::TraitPath& tpl, t_cb_clone_ty callback) {
::HIR::TraitPath rv {
@@ -181,22 +181,22 @@ bool monomorphise_type_needed(const ::HIR::TypeRef& tpl)
box$( clone_ty_with(sp, *e2.type, callback) ),
clone_ty_with__generic_path(sp, e2.trait, callback),
e2.item,
- clone_ty_with__path_params(sp, e2.params, callback)
+ clone_path_params_with(sp, e2.params, callback)
});
),
(UfcsUnknown,
return ::HIR::Path::Data::make_UfcsUnknown({
box$( clone_ty_with(sp, *e2.type, callback) ),
e2.item,
- clone_ty_with__path_params(sp, e2.params, callback)
+ clone_path_params_with(sp, e2.params, callback)
});
),
(UfcsInherent,
return ::HIR::Path::Data::make_UfcsInherent({
box$( clone_ty_with(sp, *e2.type, callback) ),
e2.item,
- clone_ty_with__path_params(sp, e2.params, callback),
- clone_ty_with__path_params(sp, e2.impl_params, callback)
+ clone_path_params_with(sp, e2.params, callback),
+ clone_path_params_with(sp, e2.impl_params, callback)
});
)
)
@@ -207,7 +207,7 @@ bool monomorphise_type_needed(const ::HIR::TypeRef& tpl)
::HIR::TypeRef rv;
if( callback(tpl, rv) ) {
- DEBUG(tpl << " => " << rv);
+ //DEBUG(tpl << " => " << rv);
return rv;
}
@@ -226,8 +226,9 @@ bool monomorphise_type_needed(const ::HIR::TypeRef& tpl)
clone_ty_with__path(sp, e.path, callback),
e.binding.clone()
} );
- // If the input binding was Opaque, clear it back to Unbound
- if( e.binding.is_Opaque() ) {
+ // If the input binding was Opaque, AND the type changed, clear it back to Unbound
+ if( e.binding.is_Opaque() /*&& rv != tpl*/ ) {
+ // NOTE: The replacement can be Self=Self, which should trigger a binding clear.
rv.m_data.as_Path().binding = ::HIR::TypeRef::TypePathBinding();
}
),
@@ -323,7 +324,7 @@ namespace {
::HIR::PathParams monomorphise_path_params_with(const Span& sp, const ::HIR::PathParams& tpl, t_cb_generic callback, bool allow_infer)
{
- return clone_ty_with__path_params(sp, tpl, monomorphise_type_with__closure(sp, tpl, callback, allow_infer));
+ return clone_path_params_with(sp, tpl, monomorphise_type_with__closure(sp, tpl, callback, allow_infer));
}
::HIR::GenericPath monomorphise_genericpath_with(const Span& sp, const ::HIR::GenericPath& tpl, t_cb_generic callback, bool allow_infer)
{
diff --git a/src/hir_typeck/common.hpp b/src/hir_typeck/common.hpp
index 14d9162f..c0e495a6 100644
--- a/src/hir_typeck/common.hpp
+++ b/src/hir_typeck/common.hpp
@@ -38,6 +38,7 @@ extern bool visit_path_tys_with(const ::HIR::Path& ty, t_cb_visit_ty callback);
typedef ::std::function<bool(const ::HIR::TypeRef&, ::HIR::TypeRef&)> t_cb_clone_ty;
/// Clones a type, calling the provided callback on every type (optionally providing a replacement)
extern ::HIR::TypeRef clone_ty_with(const Span& sp, const ::HIR::TypeRef& tpl, t_cb_clone_ty callback);
+extern ::HIR::PathParams clone_path_params_with(const Span& sp, const ::HIR::PathParams& tpl, t_cb_clone_ty callback);
// Helper for passing a group of params around
struct MonomorphState
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index 23ac0afd..a7c5ddee 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -2713,6 +2713,13 @@ namespace {
// ivars (node.m_trait_param_ivars)
for(auto it_1 = possible_methods.begin(); it_1 != possible_methods.end(); ++ it_1)
{
+ if( it_1->first != possible_methods.front().first )
+ {
+ it_1 = possible_methods.erase(it_1) - 1;
+ }
+ }
+ for(auto it_1 = possible_methods.begin(); it_1 != possible_methods.end(); ++ it_1)
+ {
if( !it_1->second.m_data.is_UfcsKnown() )
continue;
bool was_found = false;
@@ -2727,10 +2734,17 @@ namespace {
}
const auto& e2 = it_2->second.m_data.as_UfcsKnown();
+ // TODO: If the trait is the same, but the type differs, pick the first?
+ if( e1.trait == e2.trait ) {
+ DEBUG("Duplicate trait, different type - " << e1.trait << " for " << *e1.type << " or " << *e2.type << ", picking the first");
+ it_2 = possible_methods.erase(it_2) - 1;
+ continue ;
+ }
if( *e1.type != *e2.type )
continue;
if( e1.trait.m_path != e2.trait.m_path )
continue;
+ assert( !(e1.trait.m_params == e2.trait.m_params) );
DEBUG("Duplicate trait in possible_methods - " << it_1->second << " and " << it_2->second);
if( !was_found )
@@ -2745,11 +2759,8 @@ namespace {
trait_params.m_types.push_back( ::HIR::TypeRef::new_infer(ivars[i], ::HIR::InferClass::None) );
//ASSERT_BUG(sp, m_ivars.get_type( trait_params.m_types.back() ).m_data.as_Infer().index == ivars[i], "A method selection ivar was bound");
}
- // If one of these was already using the placeholder ivars, then maintain the other one?
- if( e2.trait.m_params == trait_params )
- {
- }
- else
+ // If one of these was already using the placeholder ivars, then maintain the one with the palceholders
+ if( e1.trait.m_params != trait_params )
{
e1.trait.m_params = mv$(trait_params);
}
@@ -2759,6 +2770,12 @@ namespace {
}
}
}
+ assert( !possible_methods.empty() );
+ if( possible_methods.size() != 1 && possible_methods.front().second.m_data.is_UfcsKnown() )
+ {
+ DEBUG("- Multiple options, deferring");
+ return;
+ }
auto& ad_borrow = possible_methods.front().first;
auto& fcn_path = possible_methods.front().second;
DEBUG("- deref_count = " << deref_count << ", fcn_path = " << fcn_path);
@@ -4261,7 +4278,6 @@ void Context::possible_equate_type(unsigned int ivar_index, const ::HIR::TypeRef
list.push_back( t.clone() );
}
void Context::possible_equate_type_bound(unsigned int ivar_index, const ::HIR::TypeRef& t) {
- DEBUG(ivar_index << " bounded as " << t << " " << this->m_ivars.get_type(t));
{
::HIR::TypeRef ty_l;
ty_l.m_data.as_Infer().index = ivar_index;
@@ -4278,9 +4294,21 @@ void Context::possible_equate_type_bound(unsigned int ivar_index, const ::HIR::T
}
auto& ent = possible_ivar_vals[ivar_index];
for(const auto& e : ent.bounded)
+ {
if( e == t )
+ {
+ if( t.m_data.is_Infer() )
+ DEBUG(ivar_index << " duplicate bounded " << t << " " << this->m_ivars.get_type(t));
+ else
+ DEBUG(ivar_index << " duplicate bounded " << t);
return ;
+ }
+ }
ent.bounded.push_back( t.clone() );
+ if( t.m_data.is_Infer() )
+ DEBUG(ivar_index << " bounded as " << t << " " << this->m_ivars.get_type(t));
+ else
+ DEBUG(ivar_index << " bounded as " << t);
}
void Context::possible_equate_type_disable(unsigned int ivar_index, bool is_to) {
DEBUG(ivar_index << " ?= ?? (" << (is_to ? "to" : "from") << ")");
@@ -5593,17 +5621,49 @@ namespace {
{
for(const auto& bound : context.link_assoc)
{
- // TODO: Monomorphise this type replacing mentions of the current ivar with the replacement?
- if( bound.impl_ty != ty_l )
- continue ;
+ bool used_ty = false;
+ auto cb = [&](const ::HIR::TypeRef& ty, ::HIR::TypeRef& out_ty){ if( ty == ty_l ) { out_ty = new_ty.clone(); used_ty = true; return true; } else { return false; }};
+ auto t = clone_ty_with(sp, bound.impl_ty, cb);
+ auto p = clone_path_params_with(sp, bound.params, cb);
+ if(!used_ty)
+ continue;
+ // - Run EAT on t and p
+ t = context.m_resolve.expand_associated_types( sp, mv$(t) );
+ // TODO: EAT on `p`
+ DEBUG("Check " << t << " : " << bound.trait << p);
+ DEBUG("- From " << bound.impl_ty << " : " << bound.trait << bound.params);
// Search for any trait impl that could match this,
- bool has = context.m_resolve.find_trait_impls(sp, bound.trait, bound.params, new_ty, [&](const auto , auto){return true;});
- if( !has ) {
+ bool bound_failed = true;
+ context.m_resolve.find_trait_impls(sp, bound.trait, p, t, [&](const auto impl, auto cmp){
+ // If this bound specifies an associated type, then check that that type could match
+ if( bound.name != "" )
+ {
+ auto aty = impl.get_type(bound.name.c_str());
+ if( aty == ::HIR::TypeRef() ) {
+ // A possible match was found, so don't delete just yet
+ bound_failed = false;
+ // - Return false to keep searching
+ return false;
+ }
+ else if( aty.compare_with_placeholders(sp, bound.left_ty, context.m_ivars.callback_resolve_infer()) == HIR::Compare::Unequal ) {
+ bound_failed = true;
+ // - Bail instantly
+ return true;
+ }
+ else {
+ }
+ }
+ bound_failed = false;
+ return true;
+ });
+ if( bound_failed ) {
// If none was found, remove from the possibility list
DEBUG("Remove possibility " << new_ty << " because it failed a bound");
return true;
}
+
+ // TODO: Check for the resultant associated type
}
// Handle methods
@@ -6276,8 +6336,9 @@ namespace {
if( !ivar_ent.bounded.empty() )
{
// TODO: Search know possibilties and check if they satisfy the bounds for this ivar
+ DEBUG("Options: " << ivar_ent.bounded);
unsigned int n_good = 0;
- const ::HIR::TypeRef* only_good;
+ const ::HIR::TypeRef* only_good = nullptr;
for(const auto& new_ty : ivar_ent.bounded)
{
DEBUG("- Test " << new_ty << " against current rules");
@@ -6287,11 +6348,14 @@ namespace {
else
{
n_good ++;
- only_good = &new_ty;
+ if( !only_good )
+ only_good = &new_ty;
DEBUG("> " << new_ty << " feasible");
}
}
- if(n_good == 1
+ // Picks the first if in fallback mode (which is signalled by `honour_disable` being false)
+ // - This handles the case where there's multiple valid options (needed for libcompiler_builtins)
+ if( (honour_disable ? n_good == 1 : n_good > 0)
&& ivar_ent.types_coerce_from.size() == 0 && ivar_ent.types_coerce_to.size() == 0
&& ivar_ent.types_unsize_from.size() == 0 && ivar_ent.types_unsize_to.size() == 0
)
@@ -6635,7 +6699,7 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR:
const auto& sp = node->span();
if( const auto* np = dynamic_cast<::HIR::ExprNode_CallMethod*>(node) )
{
- WARNING(sp, W0000, "Spare Rule - {" << context.m_ivars.fmt_type(np->m_value->m_res_type) << "}." << np->m_method);
+ WARNING(sp, W0000, "Spare Rule - {" << context.m_ivars.fmt_type(np->m_value->m_res_type) << "}." << np->m_method << " -> " << context.m_ivars.fmt_type(np->m_res_type));
}
else
{
diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp
index 27728dbe..b353e6a7 100644
--- a/src/hir_typeck/helpers.cpp
+++ b/src/hir_typeck/helpers.cpp
@@ -2247,7 +2247,7 @@ bool TraitResolution::find_named_trait_in_trait(const Span& sp,
{
auto pt_mono = monomorphise_traitpath_with(sp, pt, monomorph_cb, false);
- DEBUG(pt << " => " << pt_mono);
+ //DEBUG(pt << " => " << pt_mono);
if( pt.m_path.m_path == des ) {
// NOTE: Doesn't quite work...
//auto cmp = this->compare_pp(sp, pt_mono.m_path.m_params, des_params);
@@ -3890,6 +3890,7 @@ bool TraitResolution::find_method(const Span& sp,
method_name,
{}
}) ) ));
+ DEBUG("++ " << possibilities.back());
rv = true;
}
else if( cmp == ::HIR::Compare::Fuzzy )
@@ -3904,6 +3905,7 @@ bool TraitResolution::find_method(const Span& sp,
method_name,
{}
}) ) ));
+ DEBUG("++ " << possibilities.back());
rv = true;
}
else
@@ -3959,6 +3961,7 @@ bool TraitResolution::find_method(const Span& sp,
if(const auto* self_ty_p = check_method_receiver(sp, *fcn_ptr, ty, access))
{
possibilities.push_back(::std::make_pair(borrow_type, ::HIR::Path(self_ty_p->clone(), mv$(final_trait_path), method_name, {}) ));
+ DEBUG("++ " << possibilities.back());
rv = true;
}
}
@@ -3981,6 +3984,7 @@ bool TraitResolution::find_method(const Span& sp,
if(const auto* self_ty_p = check_method_receiver(sp, *fcn_ptr, ty, access))
{
possibilities.push_back(::std::make_pair(borrow_type, ::HIR::Path(self_ty_p->clone(), mv$(final_trait_path), method_name, {}) ));
+ DEBUG("++ " << possibilities.back());
rv = true;
}
}
@@ -4039,6 +4043,7 @@ bool TraitResolution::find_method(const Span& sp,
// Found the method, return the UFCS path for it
possibilities.push_back(::std::make_pair( borrow_type, ::HIR::Path(self_ty_p->clone(), mv$(final_trait_path), method_name, {}) ));
+ DEBUG("++ " << possibilities.back());
rv = true;
}
}
@@ -4077,6 +4082,7 @@ bool TraitResolution::find_method(const Span& sp,
// Found the method, return the UFCS path for it
possibilities.push_back(::std::make_pair( borrow_type, ::HIR::Path(self_ty_p->clone(), mv$(final_trait_path), method_name, {}) ));
+ DEBUG("++ " << possibilities.back());
rv = true;
}
}
@@ -4104,6 +4110,7 @@ bool TraitResolution::find_method(const Span& sp,
if( *self_ty_p == *cur_check_ty )
{
possibilities.push_back(::std::make_pair( borrow_type, ::HIR::Path(self_ty_p->clone(), method_name, {}) ));
+ DEBUG("++ " << possibilities.back());
return true;
}
}
@@ -4156,10 +4163,19 @@ bool TraitResolution::find_method(const Span& sp,
// TODO: Re-monomorphise the trait path!
- //if( find_trait_impls(sp, *trait_ref.first, trait_params, self_ty, [](auto , auto ) { return true; }) ) {
- if( find_trait_impls_crate(sp, *trait_ref.first, &trait_params, self_ty, [](auto , auto ) { return true; }) ) {
+ bool magic_found = false;
+ bool crate_impl_found = false;
+ // 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;
+ crate_impl_found = true;
+ return true;
+ });
+ if( crate_impl_found ) {
DEBUG("Found trait impl " << *trait_ref.first << trait_params << " for " << self_ty << " ("<<m_ivars.fmt_type(self_ty)<<")");
possibilities.push_back(::std::make_pair( borrow_type, ::HIR::Path(self_ty.clone(), ::HIR::GenericPath( *trait_ref.first, mv$(trait_params) ), method_name, {}) ));
+ DEBUG("++ " << possibilities.back());
rv = true;
}
}