diff options
-rw-r--r-- | src/hir/hir.cpp | 1 | ||||
-rw-r--r-- | src/hir/type.cpp | 4 | ||||
-rw-r--r-- | src/hir/type.hpp | 1 | ||||
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 197 | ||||
-rw-r--r-- | src/hir_typeck/expr_simple.cpp | 2 | ||||
-rw-r--r-- | src/hir_typeck/helpers.cpp | 77 |
6 files changed, 222 insertions, 60 deletions
diff --git a/src/hir/hir.cpp b/src/hir/hir.cpp index 09187ae8..e090b795 100644 --- a/src/hir/hir.cpp +++ b/src/hir/hir.cpp @@ -48,6 +48,7 @@ namespace { switch(right.m_data.as_Infer().ty_class) { case ::HIR::InferClass::None: + case ::HIR::InferClass::Diverge: return left.m_data.is_Generic(); case ::HIR::InferClass::Integer: TU_IFLET(::HIR::TypeRef::Data, left.m_data, Primitive, le, diff --git a/src/hir/type.cpp b/src/hir/type.cpp index a27d5dd0..6b90801f 100644 --- a/src/hir/type.cpp +++ b/src/hir/type.cpp @@ -49,6 +49,7 @@ void ::HIR::TypeRef::fmt(::std::ostream& os) const switch(e.ty_class) { case ::HIR::InferClass::None: break; + case ::HIR::InferClass::Diverge:os << ":!"; break; case ::HIR::InferClass::Float: os << ":f"; break; case ::HIR::InferClass::Integer:os << ":i"; break; } @@ -462,6 +463,7 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x switch(xe.ty_class) { case ::HIR::InferClass::None: + case ::HIR::InferClass::Diverge: // - If right is generic infer, assume it's good //return true; return Compare::Fuzzy; @@ -694,6 +696,7 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x switch(e.ty_class) { case ::HIR::InferClass::None: + case ::HIR::InferClass::Diverge: return Compare::Fuzzy; case ::HIR::InferClass::Integer: TU_IFLET( ::HIR::TypeRef::Data, right.m_data, Primitive, le, @@ -735,6 +738,7 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x switch( e.ty_class ) { case ::HIR::InferClass::None: + case ::HIR::InferClass::Diverge: return Compare::Fuzzy; case ::HIR::InferClass::Integer: TU_IFLET( ::HIR::TypeRef::Data, left.m_data, Primitive, le, diff --git a/src/hir/type.hpp b/src/hir/type.hpp index f01c0f1d..4f495fcd 100644 --- a/src/hir/type.hpp +++ b/src/hir/type.hpp @@ -21,6 +21,7 @@ typedef ::std::function< ::HIR::Compare(unsigned int, const ::HIR::TypeRef&) > t enum class InferClass { None, + Diverge, Integer, Float, }; diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 5d566d5a..b8347578 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -358,6 +358,8 @@ namespace { const ::HIR::TypeRef& ret_type; ::std::vector< const ::HIR::TypeRef*> closure_ret_types; + ::std::vector<bool> inner_coerce_enabled_stack; + // TEMP: List of in-scope traits for buildup ::HIR::t_trait_list m_traits; public: @@ -371,42 +373,47 @@ namespace { void visit(::HIR::ExprNode_Block& node) override { TRACE_FUNCTION_F(&node << " { ... }"); - this->push_traits( node.m_traits ); - for( unsigned int i = 0; i < node.m_nodes.size(); i ++ ) + if( node.m_nodes.size() > 0 ) { - auto& snp = node.m_nodes[i]; - this->context.add_ivars( snp->m_res_type ); - if( i == node.m_nodes.size()-1 ) { - this->context.equate_types(snp->span(), node.m_res_type, snp->m_res_type); - } - else { + this->push_traits( node.m_traits ); + + this->push_inner_coerce(false); + for( unsigned int i = 0; i < node.m_nodes.size()-1; i ++ ) + { + auto& snp = node.m_nodes[i]; + this->context.add_ivars( snp->m_res_type ); // TODO: Ignore? or force to ()? - Depends on inner // - Blocks (and block-likes) are forced to () // - What if they were '({});'? Then they're left dangling + snp->visit(*this); } + this->pop_inner_coerce(); + + auto& snp = node.m_nodes.back(); + this->context.add_ivars( snp->m_res_type ); + this->context.equate_types(snp->span(), node.m_res_type, snp->m_res_type); snp->visit(*this); + + this->pop_traits( node.m_traits ); } - - this->pop_traits( node.m_traits ); } void visit(::HIR::ExprNode_Return& node) override { TRACE_FUNCTION_F(&node << " return ..."); this->context.add_ivars( node.m_value->m_res_type ); - if( this->closure_ret_types.size() > 0 ) { - this->context.equate_types_coerce(node.span(), *this->closure_ret_types.back(), node.m_value); - } - else { - this->context.equate_types_coerce(node.span(), this->ret_type, node.m_value); - } + const auto& ret_ty = ( this->closure_ret_types.size() > 0 ? *this->closure_ret_types.back() : this->ret_type ); + this->context.equate_types_coerce(node.span(), ret_ty, node.m_value); + this->push_inner_coerce( true ); node.m_value->visit( *this ); + this->pop_inner_coerce(); } void visit(::HIR::ExprNode_Loop& node) override { + auto _ = this->push_inner_coerce_scoped(false); TRACE_FUNCTION_F(&node << " loop { ... }"); this->context.equate_types(node.span(), node.m_res_type, ::HIR::TypeRef::new_unit()); @@ -436,13 +443,16 @@ namespace { // If the type was omitted or was just `_`, equate if( node.m_type.m_data.is_Infer() ) { this->context.equate_types( node.span(), node.m_type, node.m_value->m_res_type ); + this->push_inner_coerce(false); } // otherwise coercions apply else { this->context.equate_types_coerce( node.span(), node.m_type, node.m_value ); + this->push_inner_coerce(true); } node.m_value->visit( *this ); + this->pop_inner_coerce(); } } void visit(::HIR::ExprNode_Match& node) override @@ -450,9 +460,13 @@ namespace { TRACE_FUNCTION_F(&node << " match ..."); const auto& val_type = node.m_value->m_res_type; - this->context.add_ivars(node.m_value->m_res_type); - // TODO: If a coercion point is placed here, it will allow `match &string { "..." ... }` - node.m_value->visit( *this ); + + { + auto _ = this->push_inner_coerce_scoped(false); + this->context.add_ivars(node.m_value->m_res_type); + // TODO: If a coercion point is placed here, it will allow `match &string { "..." ... }` + node.m_value->visit( *this ); + } for(auto& arm : node.m_arms) { @@ -464,13 +478,14 @@ namespace { if( arm.m_cond ) { + auto _ = this->push_inner_coerce_scoped(false); this->context.add_ivars( arm.m_cond->m_res_type ); - this->context.equate_types_coerce(arm.m_cond->span(), ::HIR::TypeRef(::HIR::CoreType::Bool), arm.m_cond); + this->context.equate_types(arm.m_cond->span(), ::HIR::TypeRef(::HIR::CoreType::Bool), arm.m_cond->m_res_type); arm.m_cond->visit( *this ); } this->context.add_ivars( arm.m_code->m_res_type ); - this->context.equate_types_coerce(node.span(), node.m_res_type, arm.m_code); + this->equate_types_inner_coerce(node.span(), node.m_res_type, arm.m_code); arm.m_code->visit( *this ); } } @@ -480,18 +495,20 @@ namespace { TRACE_FUNCTION_F(&node << " if ..."); this->context.add_ivars( node.m_cond->m_res_type ); - this->context.equate_types_coerce(node.m_cond->span(), ::HIR::TypeRef(::HIR::CoreType::Bool), node.m_cond); - node.m_cond->visit( *this ); + + { + auto _ = this->push_inner_coerce_scoped(false); + this->context.equate_types(node.m_cond->span(), ::HIR::TypeRef(::HIR::CoreType::Bool), node.m_cond->m_res_type); + node.m_cond->visit( *this ); + } this->context.add_ivars( node.m_true->m_res_type ); - this->context.equate_types_coerce(node.span(), node.m_res_type, node.m_true); - //this->context.equate_types(node.span(), node.m_res_type, node.m_true->m_res_type); + this->equate_types_inner_coerce(node.span(), node.m_res_type, node.m_true); node.m_true->visit( *this ); if( node.m_false ) { this->context.add_ivars( node.m_false->m_res_type ); - this->context.equate_types_coerce(node.span(), node.m_res_type, node.m_false); - //this->context.equate_types(node.span(), node.m_res_type, node.m_false->m_res_type); + this->equate_types_inner_coerce(node.span(), node.m_res_type, node.m_false); node.m_false->visit( *this ); } else { @@ -502,6 +519,8 @@ namespace { void visit(::HIR::ExprNode_Assign& node) override { + auto _ = this->push_inner_coerce_scoped(false); + TRACE_FUNCTION_F(&node << "... = ..."); this->context.add_ivars( node.m_slot ->m_res_type ); this->context.add_ivars( node.m_value->m_res_type ); @@ -535,10 +554,14 @@ namespace { } node.m_slot->visit( *this ); + + auto _2 = this->push_inner_coerce_scoped( node.m_op == ::HIR::ExprNode_Assign::Op::None ); node.m_value->visit( *this ); } void visit(::HIR::ExprNode_BinOp& node) override { + auto _ = this->push_inner_coerce_scoped(false); + TRACE_FUNCTION_F(&node << "... "<<::HIR::ExprNode_BinOp::opname(node.m_op)<<" ..."); this->context.add_ivars( node.m_left ->m_res_type ); this->context.add_ivars( node.m_right->m_res_type ); @@ -614,6 +637,8 @@ namespace { } void visit(::HIR::ExprNode_UniOp& node) override { + auto _ = this->push_inner_coerce_scoped(false); + TRACE_FUNCTION_F(&node << " " << ::HIR::ExprNode_UniOp::opname(node.m_op) << "..."); this->context.add_ivars( node.m_value->m_res_type ); switch(node.m_op) @@ -636,6 +661,8 @@ namespace { } void visit(::HIR::ExprNode_Cast& node) override { + auto _ = this->push_inner_coerce_scoped(false); + TRACE_FUNCTION_F(&node << " ... as " << node.m_res_type); this->context.add_ivars( node.m_value->m_res_type ); @@ -650,6 +677,8 @@ namespace { } void visit(::HIR::ExprNode_Index& node) override { + auto _ = this->push_inner_coerce_scoped(false); + TRACE_FUNCTION_F(&node << " ... [ ... ]"); this->context.add_ivars( node.m_value->m_res_type ); this->context.add_ivars( node.m_index->m_res_type ); @@ -661,6 +690,8 @@ namespace { } void visit(::HIR::ExprNode_Deref& node) override { + auto _ = this->push_inner_coerce_scoped(false); + TRACE_FUNCTION_F(&node << " *..."); this->context.add_ivars( node.m_value->m_res_type ); @@ -773,15 +804,16 @@ namespace { for( unsigned int i = 0; i < node.m_args.size(); i ++ ) { const auto& des_ty_r = fields[i].ent; + const auto* des_ty = &des_ty_r; if( monomorphise_type_needed(des_ty_r) ) { node.m_arg_types[i] = monomorphise_type_with(sp, des_ty_r, monomorph_cb); - this->context.equate_types_coerce(node.span(), node.m_arg_types[i], node.m_args[i]); - } - else { - this->context.equate_types_coerce(node.span(), des_ty_r, node.m_args[i]); + des_ty = &node.m_arg_types[i]; } + + this->context.equate_types_coerce(node.span(), *des_ty, node.m_args[i]); } + auto _ = this->push_inner_coerce_scoped(true); for( auto& val : node.m_args ) { val->visit( *this ); } @@ -848,24 +880,27 @@ namespace { assert(it != fields.end()); const auto& des_ty_r = it->second.ent; auto& des_ty_cache = node.m_value_types[it - fields.begin()]; + const auto* des_ty = &des_ty_r; DEBUG(name << " : " << des_ty_r); if( monomorphise_type_needed(des_ty_r) ) { if( des_ty_cache == ::HIR::TypeRef() ) { des_ty_cache = monomorphise_type_with(node.span(), des_ty_r, monomorph_cb); } - // TODO: Is it an error when it's already populated? - this->context.equate_types_coerce(node.span(), des_ty_cache, val.second); - } - else { - this->context.equate_types_coerce(node.span(), des_ty_r, val.second); + else { + // TODO: Is it an error when it's already populated? + } + des_ty = &des_ty_cache; } + this->equate_types_inner_coerce(node.span(), *des_ty, val.second); } + auto _ = this->push_inner_coerce_scoped(true); for( auto& val : node.m_values ) { val.second->visit( *this ); } if( node.m_base_value ) { + auto _ = this->push_inner_coerce_scoped(false); node.m_base_value->visit( *this ); } } @@ -903,6 +938,7 @@ namespace { } this->context.equate_types(node.span(), node.m_res_type, node.m_cache.m_arg_types.back()); + auto _ = this->push_inner_coerce_scoped(true); for( auto& val : node.m_args ) { val->visit( *this ); } @@ -918,7 +954,11 @@ namespace { // Nothing can be done until type is known this->context.add_revisit(node); - node.m_value->visit( *this ); + { + auto _ = this->push_inner_coerce_scoped(false); + node.m_value->visit( *this ); + } + auto _ = this->push_inner_coerce_scoped(true); for( auto& val : node.m_args ) { val->visit( *this ); } @@ -954,13 +994,18 @@ namespace { // > Has to be done during iteraton this->context.add_revisit( node ); - node.m_value->visit( *this ); + { + auto _ = this->push_inner_coerce_scoped(false); + node.m_value->visit( *this ); + } + auto _ = this->push_inner_coerce_scoped(true); for( auto& val : node.m_args ) { val->visit( *this ); } } void visit(::HIR::ExprNode_Field& node) override { + auto _ = this->push_inner_coerce_scoped(false); TRACE_FUNCTION_F(&node << " (...)."<<node.m_field); this->context.add_ivars( node.m_value->m_res_type ); @@ -976,6 +1021,8 @@ namespace { this->context.add_ivars( val->m_res_type ); } + if( can_coerce_inner_result() ) { + } ::std::vector< ::HIR::TypeRef> tuple_tys; for(const auto& val : node.m_vals ) { // Can these coerce? Assuming not @@ -998,7 +1045,7 @@ namespace { // - Result type already set, just need to extract ivar const auto& inner_ty = *node.m_res_type.m_data.as_Array().inner; for( auto& val : node.m_vals ) { - this->context.equate_types_coerce(node.span(), inner_ty, val); + this->equate_types_inner_coerce(node.span(), inner_ty, val); } for( auto& val : node.m_vals ) { @@ -1018,7 +1065,7 @@ namespace { this->context.equate_types(node.span(), node.m_res_type, ty); // Equate with coercions const auto& inner_ty = *ty.m_data.as_Array().inner; - this->context.equate_types_coerce(node.span(), inner_ty, node.m_val); + this->equate_types_inner_coerce(node.span(), inner_ty, node.m_val); this->context.equate_types(node.span(), ::HIR::TypeRef(::HIR::CoreType::Usize), node.m_size->m_res_type); node.m_val->visit( *this ); @@ -1258,6 +1305,7 @@ namespace { this->context.equate_types_coerce( node.span(), node.m_return, node.m_code ); + auto _ = this->push_inner_coerce_scoped(true); this->closure_ret_types.push_back( &node.m_return ); node.m_code->visit( *this ); this->closure_ret_types.pop_back( ); @@ -1295,6 +1343,40 @@ namespace { ) ) } + + class InnerCoerceGuard { + ExprVisitor_Enum& t; + public: + InnerCoerceGuard(ExprVisitor_Enum& t): t(t) {} + ~InnerCoerceGuard() { t.inner_coerce_enabled_stack.pop_back(); } + }; + InnerCoerceGuard push_inner_coerce_scoped(bool val) { + this->inner_coerce_enabled_stack.push_back(val); + return InnerCoerceGuard(*this); + } + void push_inner_coerce(bool val) { + this->inner_coerce_enabled_stack.push_back(val); + } + void pop_inner_coerce() { + assert( this->inner_coerce_enabled_stack.size() ); + this->inner_coerce_enabled_stack.pop_back(); + } + bool can_coerce_inner_result() const { + if( this->inner_coerce_enabled_stack.size() == 0 ) { + return true; + } + else { + return this->inner_coerce_enabled_stack.back(); + } + } + void equate_types_inner_coerce(const Span& sp, const ::HIR::TypeRef& target, ::HIR::ExprNodeP& node) { + if( can_coerce_inner_result() ) { + this->context.equate_types_coerce(sp, target, node); + } + else { + this->context.equate_types(sp, target, node->m_res_type); + } + } }; // ----------------------------------------------------------------------- @@ -1415,6 +1497,7 @@ namespace { this->m_completed = true; break; case ::HIR::InferClass::None: + case ::HIR::InferClass::Diverge: break; } ), @@ -1664,6 +1747,7 @@ namespace { if( node.m_args.size()+1 != node.m_cache.m_arg_types.size() - 1 ) { ERROR(node.span(), E0000, "Incorrect number of arguments to " << fcn_path); } + DEBUG("- fcn_path=" << node.m_method_path); // Link arguments // 1+ because it's a method call (#0 is Self) @@ -1891,6 +1975,12 @@ void Context::equate_types(const Span& sp, const ::HIR::TypeRef& li, const ::HIR const auto& l_t = this->m_resolve.expand_associated_types(sp, this->m_ivars.get_type(li), l_tmp); const auto& r_t = this->m_resolve.expand_associated_types(sp, this->m_ivars.get_type(ri), r_tmp); + #if 0 + if( l_t.m_data.is_Diverge() || r_t.m_data.is_Diverge() ) { + return ; + } + #endif + DEBUG("- l_t = " << l_t << ", r_t = " << r_t); TU_IFLET(::HIR::TypeRef::Data, r_t.m_data, Infer, r_e, TU_IFLET(::HIR::TypeRef::Data, l_t.m_data, Infer, l_e, @@ -1921,12 +2011,29 @@ void Context::equate_types(const Span& sp, const ::HIR::TypeRef& li, const ::HIR // If either side is !, return early // TODO: Should ! end up in an ivar? - TU_IFLET(::HIR::TypeRef::Data, l_t.m_data, Diverge, l_e, + #if 1 + if( l_t.m_data.is_Diverge() && r_t.m_data.is_Diverge() ) { return ; - ) - TU_IFLET(::HIR::TypeRef::Data, r_t.m_data, Diverge, r_e, + } + else if( l_t.m_data.is_Diverge() ) { + TU_IFLET(::HIR::TypeRef::Data, li.m_data, Infer, l_e, + this->m_ivars.set_ivar_to(l_e.index, r_t.clone()); + ) return ; - ) + } + else if( r_t.m_data.is_Diverge() ) { + TU_IFLET(::HIR::TypeRef::Data, ri.m_data, Infer, r_e, + this->m_ivars.set_ivar_to(r_e.index, l_t.clone()); + ) + return ; + } + else { + } + #else + if( l_t.m_data.is_Diverge() || r_t.m_data.is_Diverge() ) { + return ; + } + #endif // - If the destructuring would fail //if( l_t.compare_with_placeholders(sp, r_t, this->m_ivars.callback_resolve_infer()) == ::HIR::Compare::Unequal ) @@ -3289,7 +3396,7 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR: const unsigned int MAX_ITERATIONS = 100; unsigned int count = 0; - while( context.take_changed() && context.has_rules() && count < MAX_ITERATIONS ) + while( context.take_changed() /*&& context.has_rules()*/ && count < MAX_ITERATIONS ) { TRACE_FUNCTION_F("=== PASS " << count << " ==="); context.dump(); diff --git a/src/hir_typeck/expr_simple.cpp b/src/hir_typeck/expr_simple.cpp index 49bfdccc..e4406fb7 100644 --- a/src/hir_typeck/expr_simple.cpp +++ b/src/hir_typeck/expr_simple.cpp @@ -17,6 +17,7 @@ namespace typeck { switch(ic) { case ::HIR::InferClass::None: + case ::HIR::InferClass::Diverge: break; case ::HIR::InferClass::Float: switch(ct) @@ -539,6 +540,7 @@ namespace typeck { switch(e.ty_class) { case ::HIR::InferClass::None: + case ::HIR::InferClass::Diverge: return false; case ::HIR::InferClass::Integer: case ::HIR::InferClass::Float: diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index a19a9761..e9d2d754 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -319,6 +319,11 @@ bool HMTypeInferrence::apply_defaults() { case ::HIR::InferClass::None: break; + case ::HIR::InferClass::Diverge: + rv = true; + DEBUG("- " << *v.type << " -> !"); + *v.type = ::HIR::TypeRef(::HIR::TypeRef::Data::make_Diverge({})); + break; case ::HIR::InferClass::Integer: rv = true; DEBUG("- " << *v.type << " -> i32"); @@ -674,6 +679,7 @@ void HMTypeInferrence::set_ivar_to(unsigned int slot, ::HIR::TypeRef type) switch(e.ty_class) { case ::HIR::InferClass::None: + case ::HIR::InferClass::Diverge: break; case ::HIR::InferClass::Integer: case ::HIR::InferClass::Float: @@ -688,9 +694,21 @@ void HMTypeInferrence::set_ivar_to(unsigned int slot, ::HIR::TypeRef type) break; } ) + #if 0 + else TU_IFLET(::HIR::TypeRef::Data, root_ivar.type->m_data, Diverge, e, + // Overwriting ! with anything is valid (it's like a magic ivar) + ) + #endif else { BUG(sp, "Overwriting ivar " << slot << " (" << *root_ivar.type << ") with " << type); } + + #if 1 + TU_IFLET(::HIR::TypeRef::Data, type.m_data, Diverge, e, + root_ivar.type->m_data.as_Infer().ty_class = ::HIR::InferClass::Diverge; + ) + else + #endif root_ivar.type = box$( mv$(type) ); } @@ -1545,33 +1563,62 @@ void TraitResolution::expand_associated_types__UfcsKnown(const Span& sp, ::HIR:: //pe.trait = mv$(trait_path); DEBUG("Searching for impl"); + bool can_fuzz = true; + unsigned int count = 0; ImplRef best_impl; rv = this->find_trait_impls_crate(sp, trait_path.m_path, trait_path.m_params, *pe.type, [&](auto impl, auto qual) { - DEBUG("Found " << impl); - if( impl.type_is_specializable(pe.item.c_str()) ) { - if( impl.more_specific_than( best_impl ) ) { - best_impl = mv$(impl); + DEBUG("[expand_associated_types__UfcsKnown] Found " << impl << " qual=" << qual); + // If it's a fuzzy match, keep going (but count if a concrete hasn't been found) + if( qual == ::HIR::Compare::Fuzzy ) { + if( can_fuzz ) + { + count += 1; + if( count == 1 ) { + best_impl = mv$(impl); + } } return false; } else { - auto ty = impl.get_type( pe.item.c_str() ); + // If a fuzzy match could have been seen, ensure that best_impl is unsed + if( can_fuzz ) { + best_impl = ImplRef(); + can_fuzz = false; + } + + // If the type is specialisable + if( impl.type_is_specializable(pe.item.c_str()) ) { + // Check if this is more specific + if( impl.more_specific_than( best_impl ) ) { + best_impl = mv$(impl); + } + return false; + } + else { + auto ty = impl.get_type( pe.item.c_str() ); + if( ty == ::HIR::TypeRef() ) + ERROR(sp, E0000, "Couldn't find assocated type " << pe.item << " in " << pe.trait); + + // TODO: What if there's multiple impls? + DEBUG("Converted UfcsKnown - " << e.path << " = " << ty); + input = mv$(ty); + return true; + } + } + }); + if( !rv && best_impl.is_valid() ) { + if( can_fuzz && count > 1 ) { + // Fuzzy match with multiple choices - can't know yet + } + else { + auto ty = best_impl.get_type( pe.item.c_str() ); if( ty == ::HIR::TypeRef() ) ERROR(sp, E0000, "Couldn't find assocated type " << pe.item << " in " << pe.trait); DEBUG("Converted UfcsKnown - " << e.path << " = " << ty); input = mv$(ty); - return true; + rv = true; } - }); - if( !rv && best_impl.is_valid() ) { - auto ty = best_impl.get_type( pe.item.c_str() ); - if( ty == ::HIR::TypeRef() ) - ERROR(sp, E0000, "Couldn't find assocated type " << pe.item << " in " << pe.trait); - - DEBUG("Converted UfcsKnown - " << e.path << " = " << ty); - input = mv$(ty); - rv = true; } if( rv ) { input = this->expand_associated_types(sp, mv$(input)); |