summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2018-11-03 22:08:03 +0800
committerJohn Hodge <tpg@mutabah.net>2018-11-03 22:08:03 +0800
commit76757341622b747074be74cc75aa5f4f51665f15 (patch)
treee0c7562fc49810c81b915636ad56121508a88970
parentf31020b3f3aeb299e68af9c4790bb591dcfc2aca (diff)
downloadmrust-76757341622b747074be74cc75aa5f4f51665f15.tar.gz
HIR Typecheck - Fixing holes from 1.29 compiler_builtins
-rw-r--r--src/hir/hir.cpp2
-rw-r--r--src/hir/type.cpp60
-rw-r--r--src/hir_typeck/expr_check.cpp4
-rw-r--r--src/hir_typeck/expr_cs.cpp7
-rw-r--r--src/hir_typeck/helpers.cpp260
-rw-r--r--src/hir_typeck/helpers.hpp1
-rw-r--r--src/hir_typeck/impl_ref.cpp19
-rw-r--r--src/include/tagged_union.hpp5
-rw-r--r--src/trans/codegen_c.cpp6
9 files changed, 205 insertions, 159 deletions
diff --git a/src/hir/hir.cpp b/src/hir/hir.cpp
index 9f9bc1c3..fb0cdbd3 100644
--- a/src/hir/hir.cpp
+++ b/src/hir/hir.cpp
@@ -344,7 +344,7 @@ bool ::HIR::TraitImpl::matches_type(const ::HIR::TypeRef& type, ::HIR::t_cb_reso
{
// NOTE: Don't return any impls when the type is an unbouned ivar. Wouldn't be able to pick anything anyway
// TODO: For `Unbound`, it could be valid, if the target is a generic.
- if( is_unbounded_infer(type) || TU_TEST1(type.m_data, Path, .binding.is_Unbound()) ) {
+ if( /*is_unbounded_infer(type) ||*/ TU_TEST1(type.m_data, Path, .binding.is_Unbound()) ) {
return false;
}
return matches_type_int(m_params, m_type, type, ty_res, true);
diff --git a/src/hir/type.cpp b/src/hir/type.cpp
index 6f826111..434d471b 100644
--- a/src/hir/type.cpp
+++ b/src/hir/type.cpp
@@ -58,8 +58,8 @@ namespace HIR {
void ::HIR::TypeRef::fmt(::std::ostream& os) const
{
- TU_MATCH(::HIR::TypeRef::Data, (m_data), (e),
- (Infer,
+ TU_MATCH_HDR( (m_data), { )
+ TU_ARM(m_data, Infer, e) {
os << "_";
if( e.index != ~0u || e.ty_class != ::HIR::InferClass::None ) {
os << "/*";
@@ -73,14 +73,14 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const
}
os << "*/";
}
- ),
- (Diverge,
+ }
+ TU_ARM(m_data, Diverge, e) {
os << "!";
- ),
- (Primitive,
+ }
+ TU_ARM(m_data, Primitive, e) {
os << e;
- ),
- (Path,
+ }
+ TU_ARM(m_data, Path, e) {
os << e.path;
TU_MATCH(::HIR::TypeRef::TypePathBinding, (e.binding), (be),
(Unbound, os << "/*?*/";),
@@ -89,8 +89,8 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const
(Union, os << "/*U*/";),
(Enum, os << "/*E*/";)
)
- ),
- (Generic,
+ }
+ TU_ARM(m_data, Generic, e) {
os << e.name << "/*";
if( e.binding == 0xFFFF )
os << "";
@@ -103,8 +103,8 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const
else
os << e.binding;
os << "*/";
- ),
- (TraitObject,
+ }
+ TU_ARM(m_data, TraitObject, e) {
os << "dyn (";
if( e.m_trait.m_path != ::HIR::GenericPath() )
{
@@ -115,8 +115,8 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const
if( e.m_lifetime != LifetimeRef::new_static() )
os << "+" << e.m_lifetime;
os << ")";
- ),
- (ErasedType,
+ }
+ TU_ARM(m_data, ErasedType, e) {
os << "impl ";
for(const auto& tr : e.m_traits) {
if( &tr != &e.m_traits[0] )
@@ -126,25 +126,25 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const
if( e.m_lifetime != LifetimeRef::new_static() )
os << "+ '" << e.m_lifetime;
os << "/*" << e.m_origin << "#" << e.m_index << "*/";
- ),
- (Array,
+ }
+ TU_ARM(m_data, Array, e) {
os << "[" << *e.inner << "; ";
if( e.size_val != ~0u )
os << e.size_val;
else
os << "/*sz*/";
os << "]";
- ),
- (Slice,
+ }
+ TU_ARM(m_data, Slice, e) {
os << "[" << *e.inner << "]";
- ),
- (Tuple,
+ }
+ TU_ARM(m_data, Tuple, e) {
os << "(";
for(const auto& t : e)
os << t << ", ";
os << ")";
- ),
- (Borrow,
+ }
+ TU_ARM(m_data, Borrow, e) {
switch(e.type)
{
case ::HIR::BorrowType::Shared: os << "&"; break;
@@ -152,8 +152,8 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const
case ::HIR::BorrowType::Owned: os << "&move "; break;
}
os << *e.inner;
- ),
- (Pointer,
+ }
+ TU_ARM(m_data, Pointer, e) {
switch(e.type)
{
case ::HIR::BorrowType::Shared: os << "*const "; break;
@@ -161,8 +161,8 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const
case ::HIR::BorrowType::Owned: os << "*move "; break;
}
os << *e.inner;
- ),
- (Function,
+ }
+ TU_ARM(m_data, Function, e) {
if( e.is_unsafe ) {
os << "unsafe ";
}
@@ -173,8 +173,8 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const
for(const auto& t : e.m_arg_types)
os << t << ", ";
os << ") -> " << *e.m_rettype;
- ),
- (Closure,
+ }
+ TU_ARM(m_data, Closure, e) {
os << "closure["<<e.node<<"]";
/*
os << "(";
@@ -182,8 +182,8 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const
os << t << ", ";
os << ") -> " << *e.m_rettype;
*/
- )
- )
+ }
+ }
}
bool ::HIR::TypeRef::operator==(const ::HIR::TypeRef& x) const
diff --git a/src/hir_typeck/expr_check.cpp b/src/hir_typeck/expr_check.cpp
index 8a199557..6d2feaba 100644
--- a/src/hir_typeck/expr_check.cpp
+++ b/src/hir_typeck/expr_check.cpp
@@ -177,8 +177,8 @@ namespace {
case ::HIR::ExprNode_Assign::Op::And: lang_item = "bitand_assign"; break;
case ::HIR::ExprNode_Assign::Op::Or : lang_item = "bitor_assign" ; break;
case ::HIR::ExprNode_Assign::Op::Xor: lang_item = "bitxor_assign"; break;
- case ::HIR::ExprNode_Assign::Op::Shr: lang_item = "shl_assign"; break;
- case ::HIR::ExprNode_Assign::Op::Shl: lang_item = "shr_assign"; break;
+ case ::HIR::ExprNode_Assign::Op::Shr: lang_item = "shr_assign"; break;
+ case ::HIR::ExprNode_Assign::Op::Shl: lang_item = "shl_assign"; break;
}
assert(lang_item);
const auto& trait_path = this->get_lang_item_path(node.span(), lang_item);
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index e7748115..a236c818 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -846,8 +846,8 @@ namespace {
case ::HIR::ExprNode_Assign::Op::And: lang_item = "bitand_assign"; break;
case ::HIR::ExprNode_Assign::Op::Or : lang_item = "bitor_assign" ; break;
case ::HIR::ExprNode_Assign::Op::Xor: lang_item = "bitxor_assign"; break;
- case ::HIR::ExprNode_Assign::Op::Shr: lang_item = "shl_assign"; break;
- case ::HIR::ExprNode_Assign::Op::Shl: lang_item = "shr_assign"; break;
+ case ::HIR::ExprNode_Assign::Op::Shr: lang_item = "shr_assign"; break;
+ case ::HIR::ExprNode_Assign::Op::Shl: lang_item = "shl_assign"; break;
}
assert(lang_item);
const auto& trait_path = this->context.m_crate.get_lang_item_path(node.span(), lang_item);
@@ -5294,7 +5294,6 @@ namespace {
auto out_ty_o = impl.get_type(v.name.c_str());
if( out_ty_o == ::HIR::TypeRef() )
{
- //BUG(sp, "Getting associated type '" << v.name << "' which isn't in " << v.trait << " (" << ty << ")");
out_ty_o = ::HIR::TypeRef(::HIR::Path( v.impl_ty.clone(), ::HIR::GenericPath(v.trait, v.params.clone()), v.name, ::HIR::PathParams() ));
}
out_ty_o = context.m_resolve.expand_associated_types(sp, mv$(out_ty_o));
@@ -5450,6 +5449,8 @@ namespace {
if( TU_TEST1(impl_ty.m_data, Infer, .is_lit() == false) )
{
DEBUG("Unbounded ivar, waiting - TODO: Add possibility " << impl_ty << " == " << possible_impl_ty);
+ context.possible_equate_type_coerce_to(impl_ty.m_data.as_Infer().index, possible_impl_ty);
+ context.possible_equate_type_coerce_from(impl_ty.m_data.as_Infer().index, possible_impl_ty);
return false;
}
// Only one possible impl
diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp
index 6860de41..4d3ea82d 100644
--- a/src/hir_typeck/helpers.cpp
+++ b/src/hir_typeck/helpers.cpp
@@ -914,8 +914,8 @@ bool HMTypeInferrence::types_equal(const ::HIR::TypeRef& rl, const ::HIR::TypeRe
return pathparams_equal(le.m_trait.m_path.m_params, re.m_trait.m_path.m_params);
),
(ErasedType,
+ ASSERT_BUG(Span(), le.m_origin != ::HIR::SimplePath(), "Erased type with unset origin");
return H::compare_path(*this, le.m_origin, re.m_origin);
- //TODO(Span(), "ErasedType");
),
(Tuple,
return type_list_equal(*this, le, re);
@@ -932,12 +932,17 @@ void TraitResolution::prep_indexes()
static Span sp_AAA;
const Span& sp = sp_AAA;
+ // TODO: Create a list of all known type rules in this scope (recursively)
+ // - What if there's recursive bounds (e.g. on ATYs)
+
auto add_equality = [&](::HIR::TypeRef long_ty, ::HIR::TypeRef short_ty){
DEBUG("[prep_indexes] ADD " << long_ty << " => " << short_ty);
// TODO: Sort the two types by "complexity" (most of the time long >= short)
this->m_type_equalities.insert(::std::make_pair( mv$(long_ty), mv$(short_ty) ));
};
+ // Obtain type equality bounds.
+ // TODO: Also flatten the bounds list into known trait bounds?
this->iterate_bounds([&](const auto& b)->bool {
if(const auto* bep = b.opt_TraitBound())
{
@@ -1047,6 +1052,31 @@ bool TraitResolution::iterate_bounds( ::std::function<bool(const ::HIR::GenericB
}
return false;
}
+bool TraitResolution::iterate_bounds_traits(const Span& sp, ::std::function<bool(const ::HIR::TypeRef&, const ::HIR::TraitPath& trait)> cb) const
+{
+ // Iterate all bounds, finding trait
+ return this->iterate_bounds([&](const auto& gb) {
+ if( const auto* be = gb.opt_TraitBound() )
+ {
+ // TODO: Type filter (to avoid the cost of checking parent bounds)
+ if( cb(be->type, be->trait) )
+ return true;
+
+ assert(be->trait.m_trait_ptr);
+ const auto& trait_ref = *be->trait.m_trait_ptr;
+ auto monomorph_cb = monomorphise_type_get_cb(sp, &be->type, &be->trait.m_path.m_params, nullptr, nullptr);
+ for(const auto& parent_tp : trait_ref.m_all_parent_traits)
+ {
+ ::HIR::TraitPath tp_mono_o;
+ const auto& tp_mono = (monomorphise_traitpath_needed(parent_tp) ? tp_mono_o = monomorphise_traitpath_with(sp, parent_tp, monomorph_cb, false) : parent_tp);
+ // TODO: Monomorphise the bound
+ if( cb(be->type, tp_mono) )
+ return true;
+ }
+ }
+ 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
{
::HIR::GenericPath trait_path;
@@ -2241,136 +2271,127 @@ bool TraitResolution::find_trait_impls_bound(const Span& sp, const ::HIR::Simple
)
)
-#if 0
- if( m_ivars.get_type(type).m_data.is_Infer() )
- return false;
- if( TU_TEST1(m_ivars.get_type(type).m_data, Path, .binding.is_Unbound()) )
- return false;
-#endif
+ // NOTE: Even if the type is completely unknown (infer or unbound UFCS), search the bound list.
// TODO: A bound can imply something via its associated types. How deep can this go?
// E.g. `T: IntoIterator<Item=&u8>` implies `<T as IntoIterator>::IntoIter : Iterator<Item=&u8>`
- return this->iterate_bounds([&](const auto& b)->bool {
- DEBUG(b);
- if( b.is_TraitBound() )
- {
- const auto& e = b.as_TraitBound();
- const auto& b_params = e.trait.m_path.m_params;
+ // > Would maybe want a list of all explicit and implied bounds instead.
+ return this->iterate_bounds_traits(sp, [&](const auto& bound_ty, const ::HIR::TraitPath& bound_trait)->bool {
+ const auto& b_params = bound_trait.m_path.m_params;
- auto cmp = e.type .compare_with_placeholders(sp, type, m_ivars.callback_resolve_infer());
- DEBUG("cmp = " << cmp);
- if( cmp == ::HIR::Compare::Unequal )
- return false;
+ auto cmp = bound_ty .compare_with_placeholders(sp, type, m_ivars.callback_resolve_infer());
+ DEBUG("cmp = " << cmp);
+ if( cmp == ::HIR::Compare::Unequal )
+ return false;
- if( e.trait.m_path.m_path == trait ) {
- // Check against `params`
- DEBUG("[find_trait_impls_bound] Checking params " << params << " vs " << b_params);
- auto ord = cmp;
- ord &= this->compare_pp(sp, b_params, params);
- if( ord == ::HIR::Compare::Unequal )
- return false;
- if( ord == ::HIR::Compare::Fuzzy ) {
- DEBUG("Fuzzy match");
- }
- DEBUG("[find_trait_impls_bound] Match " << b);
- // Hand off to the closure, and return true if it does
- // TODO: The type bounds are only the types that are specified.
- if( callback( ImplRef(&e.type, &e.trait.m_path.m_params, &e.trait.m_type_bounds), ord) ) {
- return true;
- }
+ if( bound_trait.m_path.m_path == trait ) {
+ // Check against `params`
+ DEBUG("[find_trait_impls_bound] Checking params " << params << " vs " << b_params);
+ auto ord = cmp;
+ ord &= this->compare_pp(sp, b_params, params);
+ if( ord == ::HIR::Compare::Unequal )
+ return false;
+ if( ord == ::HIR::Compare::Fuzzy ) {
+ DEBUG("Fuzzy match");
+ }
+ DEBUG("[find_trait_impls_bound] Match " << bound_ty << " : " << bound_trait);
+ // Hand off to the closure, and return true if it does
+ // TODO: The type bounds are only the types that are specified.
+ auto b = bound_trait.clone();
+ if( callback( ImplRef(bound_ty.clone(), mv$(b.m_path.m_params), mv$(b.m_type_bounds)), ord) ) {
+ return true;
}
+ }
- // TODO: Allow fuzzy equality?
- if( cmp == ::HIR::Compare::Equal )
- {
- // HACK: The wrapping closure takes associated types from this bound and applies them to the returned set
- // - XXX: This is actually wrong (false-positive) in many cases. FIXME
- bool rv = this->find_named_trait_in_trait(sp,
- trait,params,
- *e.trait.m_trait_ptr, e.trait.m_path.m_path,e.trait.m_path.m_params,
- type,
- [&](const auto& ty, const auto& params, const auto& assoc) {
- // TODO: Avoid duplicating this map every time
- ::std::map< ::std::string,::HIR::TypeRef> assoc2;
- for(const auto& i : assoc) {
+ // TODO: Allow fuzzy equality?
+ if( cmp == ::HIR::Compare::Equal )
+ {
+ // HACK: The wrapping closure takes associated types from this bound and applies them to the returned set
+ // - XXX: This is actually wrong (false-positive) in many cases. FIXME
+ bool rv = this->find_named_trait_in_trait(sp,
+ trait,params,
+ *bound_trait.m_trait_ptr, bound_trait.m_path.m_path,bound_trait.m_path.m_params,
+ type,
+ [&](const auto& ty, const auto& params, const auto& assoc) {
+ // TODO: Avoid duplicating this map every time
+ ::std::map< ::std::string,::HIR::TypeRef> assoc2;
+ for(const auto& i : assoc) {
+ assoc2.insert( ::std::make_pair(i.first, i.second.clone()) );
+ }
+ for(const auto& i : bound_trait.m_type_bounds) {
+ // TODO: Only include from above when needed
+ //if( des_trait_ref.m_types.count(i.first) ) {
assoc2.insert( ::std::make_pair(i.first, i.second.clone()) );
- }
- for(const auto& i : e.trait.m_type_bounds) {
- // TODO: Only include from above when needed
- //if( des_trait_ref.m_types.count(i.first) ) {
- assoc2.insert( ::std::make_pair(i.first, i.second.clone()) );
- //}
- }
- return callback( ImplRef(ty.clone(), params.clone(), mv$(assoc2)), ::HIR::Compare::Equal );
- });
- if( rv ) {
- return true;
- }
+ //}
+ }
+ return callback( ImplRef(ty.clone(), params.clone(), mv$(assoc2)), ::HIR::Compare::Equal );
+ });
+ if( rv ) {
+ return true;
}
+ }
- // If the input type is an associated type controlled by this trait bound, check for added bounds.
- // TODO: This just checks a single layer, but it's feasable that there could be multiple layers
- if( assoc_info && e.trait.m_path.m_path == assoc_info->trait.m_path && e.type == *assoc_info->type )
- {
- // Check the trait params
- auto ord = this->compare_pp(sp, b_params, assoc_info->trait.m_params);
- if( ord == ::HIR::Compare::Fuzzy ) {
- //TODO(sp, "Handle fuzzy matches searching for associated type bounds");
- }
- else if( ord == ::HIR::Compare::Unequal ) {
- return false;
- }
- auto outer_ord = ord;
+ // If the input type is an associated type controlled by this trait bound, check for added bounds.
+ // TODO: This just checks a single layer, but it's feasable that there could be multiple layers
+ if( assoc_info && bound_trait.m_path.m_path == assoc_info->trait.m_path && bound_ty == *assoc_info->type )
+ {
+ // Check the trait params
+ auto ord = this->compare_pp(sp, b_params, assoc_info->trait.m_params);
+ if( ord == ::HIR::Compare::Fuzzy ) {
+ //TODO(sp, "Handle fuzzy matches searching for associated type bounds");
+ }
+ else if( ord == ::HIR::Compare::Unequal ) {
+ return false;
+ }
+ auto outer_ord = ord;
- const auto& trait_ref = *e.trait.m_trait_ptr;
- const auto& at = trait_ref.m_types.at(assoc_info->item);
- for(const auto& bound : at.m_trait_bounds) {
- if( bound.m_path.m_path == trait )
- {
- auto monomorph_cb = [&](const auto& gt)->const ::HIR::TypeRef& {
- const auto& ge = gt.m_data.as_Generic();
- if( ge.binding == 0xFFFF ) {
- return *assoc_info->type;
- }
- else {
- if( ge.binding >= assoc_info->trait.m_params.m_types.size() )
- BUG(sp, "find_trait_impls_bound - Generic #" << ge.binding << " " << ge.name << " out of range");
- return assoc_info->trait.m_params.m_types[ge.binding];
- }
- };
-
- DEBUG("- Found an associated type bound for this trait via another bound");
- ::HIR::Compare ord = outer_ord;
- if( monomorphise_pathparams_needed(bound.m_path.m_params) ) {
- // TODO: Use a compare+callback method instead
- auto b_params_mono = monomorphise_path_params_with(sp, bound.m_path.m_params, monomorph_cb, false);
- ord &= this->compare_pp(sp, b_params_mono, params);
+ const auto& trait_ref = *bound_trait.m_trait_ptr;
+ const auto& at = trait_ref.m_types.at(assoc_info->item);
+ for(const auto& bound : at.m_trait_bounds) {
+ if( bound.m_path.m_path == trait )
+ {
+ auto monomorph_cb = [&](const auto& gt)->const ::HIR::TypeRef& {
+ const auto& ge = gt.m_data.as_Generic();
+ if( ge.binding == 0xFFFF ) {
+ return *assoc_info->type;
}
else {
- ord &= this->compare_pp(sp, bound.m_path.m_params, params);
- }
- if( ord == ::HIR::Compare::Unequal )
- return false;
- if( ord == ::HIR::Compare::Fuzzy ) {
- DEBUG("Fuzzy match");
+ if( ge.binding >= assoc_info->trait.m_params.m_types.size() )
+ BUG(sp, "find_trait_impls_bound - Generic #" << ge.binding << " " << ge.name << " out of range");
+ return assoc_info->trait.m_params.m_types[ge.binding];
}
+ };
- auto tp_mono = monomorphise_traitpath_with(sp, bound, monomorph_cb, false);
- // - Expand associated types
- for(auto& ty : tp_mono.m_type_bounds) {
- ty.second = this->expand_associated_types(sp, mv$(ty.second));
- }
- DEBUG("- tp_mono = " << tp_mono);
- // TODO: Instead of using `type` here, build the real type
- if( callback( ImplRef(type.clone(), mv$(tp_mono.m_path.m_params), mv$(tp_mono.m_type_bounds)), ord ) ) {
- return true;
- }
+ DEBUG("- Found an associated type bound for this trait via another bound");
+ ::HIR::Compare ord = outer_ord;
+ if( monomorphise_pathparams_needed(bound.m_path.m_params) ) {
+ // TODO: Use a compare+callback method instead
+ auto b_params_mono = monomorphise_path_params_with(sp, bound.m_path.m_params, monomorph_cb, false);
+ ord &= this->compare_pp(sp, b_params_mono, params);
+ }
+ else {
+ ord &= this->compare_pp(sp, bound.m_path.m_params, params);
+ }
+ if( ord == ::HIR::Compare::Unequal )
+ return false;
+ if( ord == ::HIR::Compare::Fuzzy ) {
+ DEBUG("Fuzzy match");
+ }
+
+ auto tp_mono = monomorphise_traitpath_with(sp, bound, monomorph_cb, false);
+ // - Expand associated types
+ for(auto& ty : tp_mono.m_type_bounds) {
+ ty.second = this->expand_associated_types(sp, mv$(ty.second));
+ }
+ DEBUG("- tp_mono = " << tp_mono);
+ // TODO: Instead of using `type` here, build the real type
+ if( callback( ImplRef(type.clone(), mv$(tp_mono.m_path.m_params), mv$(tp_mono.m_type_bounds)), ord ) ) {
+ return true;
}
}
}
-
- return false;
}
+
return false;
});
}
@@ -3843,7 +3864,8 @@ bool TraitResolution::find_method(const Span& sp,
// 2. Compare the receiver of the above to this type and the bound.
if(const auto* self_ty = check_method_receiver(sp, *fcn_ptr, ty, access))
{
- if( self_ty->m_data.is_Infer() )
+ // If the type is an unbounded ivar, don't check.
+ if( TU_TEST1(self_ty->m_data, Infer, .is_lit() == false) )
return false;
// TODO: Do a fuzzy match here?
auto cmp = self_ty->compare_with_placeholders(sp, e.type, cb_infer);
@@ -3864,7 +3886,17 @@ bool TraitResolution::find_method(const Span& sp,
}
else if( cmp == ::HIR::Compare::Fuzzy )
{
- TODO(sp, "Fuzzy match checking bounded method - " << *self_ty << " != " << e.type);
+ DEBUG("Fuzzy match checking bounded method - " << *self_ty << " != " << e.type);
+
+ // Found the method, return the UFCS path for it
+ possibilities.push_back(::std::make_pair( borrow_type,
+ ::HIR::Path( ::HIR::Path::Data::make_UfcsKnown({
+ box$( self_ty->clone() ),
+ mv$(final_trait_path),
+ method_name,
+ {}
+ }) ) ));
+ rv = true;
}
else
{
diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp
index 7868b93f..cb95c94f 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_bounds_traits(const Span& sp, ::std::function<bool(const ::HIR::TypeRef&, const ::HIR::TraitPath& trait)> 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;
diff --git a/src/hir_typeck/impl_ref.cpp b/src/hir_typeck/impl_ref.cpp
index e8966b38..d2dc9fe6 100644
--- a/src/hir_typeck/impl_ref.cpp
+++ b/src/hir_typeck/impl_ref.cpp
@@ -219,8 +219,8 @@ bool ImplRef::type_is_specialisable(const char* name) const
::std::ostream& operator<<(::std::ostream& os, const ImplRef& x)
{
- TU_MATCH(ImplRef::Data, (x.m_data), (e),
- (TraitImpl,
+ TU_MATCH_HDR( (x.m_data), { )
+ TU_ARM(x.m_data, TraitImpl, e) {
if( e.impl == nullptr ) {
os << "none";
}
@@ -258,13 +258,16 @@ bool ImplRef::type_is_specialisable(const char* name) const
}
os << "}";
}
- ),
- (BoundedPtr,
+ }
+ TU_ARM(x.m_data, BoundedPtr, e) {
+ assert(e.type);
+ assert(e.trait_args);
+ assert(e.assoc);
os << "bound (ptr) " << *e.type << " : ?" << *e.trait_args << " + {" << *e.assoc << "}";
- ),
- (Bounded,
+ }
+ TU_ARM(x.m_data, Bounded, e) {
os << "bound " << e.type << " : ?" << e.trait_args << " + {"<<e.assoc<<"}";
- )
- )
+ }
+ }
return os;
}
diff --git a/src/include/tagged_union.hpp b/src/include/tagged_union.hpp
index bcc9eb3d..93dc6980 100644
--- a/src/include/tagged_union.hpp
+++ b/src/include/tagged_union.hpp
@@ -116,8 +116,11 @@
#define TU_IFLET(CLASS, VAR, TAG, NAME, ...) if(VAR.tag() == CLASS::TAG_##TAG) { auto& NAME = VAR.as_##TAG(); (void)&NAME; __VA_ARGS__ }
+#define TU_MATCH_HDR(VARS, brace) TU_MATCH_HDR_(::std::remove_reference<decltype(TU_FIRST VARS)>::type, VARS, brace)
+#define TU_MATCH_HDR_(CLASS, VARS, brace) switch( (TU_FIRST VARS).tag() ) brace case CLASS::TAGDEAD: assert(!"ERROR: destructed tagged union used");
+
// Evil hack: two for loops, the inner stops the outer after it's done.
-#define TU_ARM(VAR, TAG, NAME) case ::std::remove_reference<decltype(VAR)>::type::TAG_##TAG: for(bool tu_lc = true; tu_lc; tu_lc=false) for(auto& NAME = VAR.as_##TAG(); (void)NAME, tu_lc; tu_lc=false)
+#define TU_ARM(VAR, TAG, NAME) break; case ::std::remove_reference<decltype(VAR)>::type::TAG_##TAG: for(bool tu_lc = true; tu_lc; tu_lc=false) for(auto& NAME = VAR.as_##TAG(); (void)NAME, tu_lc; tu_lc=false)
//#define TU_TEST(VAL, ...) (VAL.is_##TAG() && VAL.as_##TAG() TEST)
#define TU_TEST1(VAL, TAG1, TEST) (VAL.is_##TAG1() && VAL.as_##TAG1() TEST)
diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp
index 86bbdddc..1bbafcd2 100644
--- a/src/trans/codegen_c.cpp
+++ b/src/trans/codegen_c.cpp
@@ -1776,6 +1776,9 @@ namespace {
};
TU_MATCHA( (lit), (e),
(Invalid, m_of << "/* INVALID */"; ),
+ (Defer,
+ MIR_BUG(*m_mir_res, "Defer literal encountered");
+ ),
(List,
m_of << "{";
if( ty.m_data.is_Array() )
@@ -5285,6 +5288,9 @@ namespace {
(Invalid,
m_of << "/* INVALID */";
),
+ (Defer,
+ MIR_BUG(*m_mir_res, "Defer literal encountered");
+ ),
(List,
if( ty.m_data.is_Array() )
{