diff options
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 16 | ||||
-rw-r--r-- | src/hir_typeck/helpers.cpp | 165 | ||||
-rw-r--r-- | src/hir_typeck/helpers.hpp | 14 |
3 files changed, 166 insertions, 29 deletions
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index cdfff8b5..f8b3c4cd 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -453,7 +453,11 @@ 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 ); + #if 0 this->push_inner_coerce(false); + #else + this->push_inner_coerce(true); + #endif } // otherwise coercions apply else { @@ -1387,18 +1391,24 @@ namespace { ExprVisitor_Enum& t; public: InnerCoerceGuard(ExprVisitor_Enum& t): t(t) {} - ~InnerCoerceGuard() { t.inner_coerce_enabled_stack.pop_back(); } + ~InnerCoerceGuard() { + t.inner_coerce_enabled_stack.pop_back(); + DEBUG("inner_coerce POP (S) " << t.can_coerce_inner_result()); + } }; InnerCoerceGuard push_inner_coerce_scoped(bool val) { + DEBUG("inner_coerce PUSH (S) " << val); this->inner_coerce_enabled_stack.push_back(val); return InnerCoerceGuard(*this); } void push_inner_coerce(bool val) { + DEBUG("inner_coerce PUSH " << 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(); + DEBUG("inner_coerce POP " << can_coerce_inner_result()); } bool can_coerce_inner_result() const { if( this->inner_coerce_enabled_stack.size() == 0 ) { @@ -1409,6 +1419,7 @@ namespace { } } void equate_types_inner_coerce(const Span& sp, const ::HIR::TypeRef& target, ::HIR::ExprNodeP& node) { + DEBUG("can_coerce_inner_result() = " << can_coerce_inner_result()); if( can_coerce_inner_result() ) { this->context.equate_types_coerce(sp, target, node); } @@ -1573,6 +1584,7 @@ namespace { const auto& idx_ty = this->context.get_type(node.m_index->m_res_type); TRACE_FUNCTION_F("Index: val=" << val_ty << ", idx=" << idx_ty << ""); + this->context.equate_types_shadow(node.span(), node.m_res_type); // NOTE: Indexing triggers autoderef unsigned int deref_count = 0; @@ -1600,6 +1612,7 @@ namespace { return false; }); if( rv ) { + // TODO: Node's result type could be an &-ptr? this->context.equate_types(node.span(), node.m_res_type, possible_res_type); break; } @@ -1626,6 +1639,7 @@ namespace { if( current_ty ) { + DEBUG("Found impl on type " << *current_ty << " with " << deref_count << " derefs"); assert( deref_count == deref_res_types.size() ); for(auto& ty_r : deref_res_types) { diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index 16b036f6..ad4183a9 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -316,9 +316,100 @@ void HMTypeInferrence::dump() const i ++ ; } } +void HMTypeInferrence::check_for_loops() +{ + struct LoopChecker { + ::std::vector<unsigned int> m_indexes; + + void check_pathparams(const HMTypeInferrence& ivars, const ::HIR::PathParams& pp) { + for(const auto& ty : pp.m_types) + this->check_ty(ivars, ty); + } + void check_ty(const HMTypeInferrence& ivars, const ::HIR::TypeRef& ty) { + TU_MATCH( ::HIR::TypeRef::Data, (ty.m_data), (e), + (Infer, + for(auto idx : m_indexes) + ASSERT_BUG(Span(), e.index != idx, "Recursion in ivar #" << m_indexes.front() << " " << *ivars.m_ivars[m_indexes.front()].type + << " - loop with " << idx << " " << *ivars.m_ivars[idx].type); + m_indexes.push_back( e.index ); + const auto& ivd = ivars.get_pointed_ivar(e.index); + assert( !ivd.is_alias() ); + if( !ivd.type->m_data.is_Infer() ) { + this->check_ty(ivars, *ivd.type); + } + ), + (Primitive, + ), + (Diverge, ), + (Generic, ), + (Path, + TU_MATCH(::HIR::Path::Data, (e.path.m_data), (pe), + (Generic, + this->check_pathparams(ivars, pe.m_params); + ), + (UfcsKnown, + this->check_ty(ivars, *pe.type); + this->check_pathparams(ivars, pe.trait.m_params); + this->check_pathparams(ivars, pe.params); + ), + (UfcsInherent, + this->check_ty(ivars, *pe.type); + this->check_pathparams(ivars, pe.params); + ), + (UfcsUnknown, + BUG(Span(), "UfcsUnknown"); + ) + ) + ), + (Borrow, + this->check_ty(ivars, *e.inner); + ), + (Pointer, + this->check_ty(ivars, *e.inner); + ), + (Slice, + this->check_ty(ivars, *e.inner); + ), + (Array, + this->check_ty(ivars, *e.inner); + ), + (Closure, + ), + (Function, + for(const auto& arg : e.m_arg_types) { + this->check_ty(ivars, arg); + } + this->check_ty(ivars, *e.m_rettype); + ), + (TraitObject, + this->check_pathparams(ivars, e.m_trait.m_path.m_params); + for(const auto& marker : e.m_markers) { + this->check_pathparams(ivars, marker.m_params); + } + ), + (Tuple, + for(const auto& st : e) { + this->check_ty(ivars, st); + } + ) + ) + } + }; + unsigned int i = 0; + for(const auto& v : m_ivars) + { + if( !v.is_alias() && !v.type->m_data.is_Infer() ) + { + DEBUG("- " << i << " " << *v.type); + (LoopChecker { {i} }).check_ty(*this, *v.type); + } + i ++; + } +} void HMTypeInferrence::compact_ivars() { - #if 1 + this->check_for_loops(); + unsigned int i = 0; for(auto& v : m_ivars) { @@ -347,7 +438,6 @@ void HMTypeInferrence::compact_ivars() } i ++; } - #endif } bool HMTypeInferrence::apply_defaults() @@ -821,7 +911,9 @@ bool HMTypeInferrence::pathparams_contain_ivars(const ::HIR::PathParams& pps) co return false; } bool HMTypeInferrence::type_contains_ivars(const ::HIR::TypeRef& ty) const { - TU_MATCH(::HIR::TypeRef::Data, (this->get_type(ty).m_data), (e), + TRACE_FUNCTION_F("ty = " << ty); + //TU_MATCH(::HIR::TypeRef::Data, (this->get_type(ty).m_data), (e), + TU_MATCH(::HIR::TypeRef::Data, (ty.m_data), (e), (Infer, return true; ), (Primitive, return false; ), (Diverge, return false; ), @@ -1326,6 +1418,8 @@ bool TraitResolution::find_trait_impls(const Span& sp, void TraitResolution::compact_ivars(HMTypeInferrence& m_ivars) { + m_ivars.check_for_loops(); + //m_ivars.compact_ivars([&](const ::HIR::TypeRef& t)->auto{ return this->expand_associated_types(Span(), t.clone); }); unsigned int i = 0; for(auto& v : m_ivars.m_ivars) @@ -1448,19 +1542,23 @@ bool TraitResolution::has_associated_type(const ::HIR::TypeRef& input) const ) BUG(Span(), "Fell off the end of has_associated_type - input=" << input); } -::HIR::TypeRef TraitResolution::expand_associated_types(const Span& sp, ::HIR::TypeRef input) const +void TraitResolution::expand_associated_types_inplace(const Span& sp, ::HIR::TypeRef& input, LList<const ::HIR::TypeRef*> stack) const { + for(const auto& ty : m_eat_active_stack) + { + if( input == ty ) { + DEBUG("Recursive lookup, skipping - input = " << input); + return ; + } + } //TRACE_FUNCTION_F(input); TU_MATCH(::HIR::TypeRef::Data, (input.m_data), (e), (Infer, auto& ty = this->m_ivars.get_type(input); if( ty != input ) { - input = expand_associated_types(sp, ty.clone()); - return input; + input = ty.clone(); + expand_associated_types_inplace(sp, input, stack); } - else { - } - return input; ), (Diverge, ), @@ -1470,7 +1568,7 @@ bool TraitResolution::has_associated_type(const ::HIR::TypeRef& input) const TU_MATCH(::HIR::Path::Data, (e.path.m_data), (pe), (Generic, for(auto& arg : pe.m_params.m_types) - arg = expand_associated_types(sp, mv$(arg)); + expand_associated_types_inplace(sp, arg, stack); ), (UfcsInherent, TODO(sp, "Path - UfcsInherent - " << e.path); @@ -1478,9 +1576,8 @@ bool TraitResolution::has_associated_type(const ::HIR::TypeRef& input) const (UfcsKnown, // - Only try resolving if the binding isn't known if( !e.binding.is_Unbound() ) - return input; - this->expand_associated_types__UfcsKnown(sp, input); - return input; + return ; + this->expand_associated_types_inplace__UfcsKnown(sp, input, stack); ), (UfcsUnknown, BUG(sp, "Encountered UfcsUnknown"); @@ -1493,21 +1590,21 @@ bool TraitResolution::has_associated_type(const ::HIR::TypeRef& input) const // Recurse? ), (Array, - *e.inner = expand_associated_types(sp, mv$(*e.inner)); + expand_associated_types_inplace(sp, *e.inner, stack); ), (Slice, - *e.inner = expand_associated_types(sp, mv$(*e.inner)); + expand_associated_types_inplace(sp, *e.inner, stack); ), (Tuple, for(auto& sub : e) { - sub = expand_associated_types(sp, mv$(sub)); + expand_associated_types_inplace(sp, sub , stack); } ), (Borrow, - *e.inner = expand_associated_types(sp, mv$(*e.inner)); + expand_associated_types_inplace(sp, *e.inner, stack); ), (Pointer, - *e.inner = expand_associated_types(sp, mv$(*e.inner)); + expand_associated_types_inplace(sp, *e.inner, stack); ), (Function, // Recurse? @@ -1516,18 +1613,32 @@ bool TraitResolution::has_associated_type(const ::HIR::TypeRef& input) const // Recurse? ) ) - return input; } -void TraitResolution::expand_associated_types__UfcsKnown(const Span& sp, ::HIR::TypeRef& input) const +void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp, ::HIR::TypeRef& input, LList<const ::HIR::TypeRef*> prev_stack) const { TRACE_FUNCTION_FR("input=" << input, input); auto& e = input.m_data.as_Path(); auto& pe = e.path.m_data.as_UfcsKnown(); - // TODO: If opaque, still search a list of known equalities - *pe.type = expand_associated_types(sp, mv$(*pe.type)); + struct D { + const TraitResolution& m_tr; + D(const TraitResolution& tr, ::HIR::TypeRef v): m_tr(tr) { + tr.m_eat_active_stack.push_back( mv$(v) ); + } + ~D() { + m_tr.m_eat_active_stack.pop_back(); + } + }; + D _(*this, input.clone()); + LList<const ::HIR::TypeRef*> stack(&prev_stack, &m_eat_active_stack.back()); + + // TODO: State stack to avoid infinite recursion + // Example: + // IVar 181 = <::ops::Range<<_/*181*/ as ::iter::iterator::Iterator>::Item/*U*/,>/*S*/ as ::iter::traits::IntoIterator>::IntoIter/*U*/ + // The above infinitely recurses due to the recursion here. + expand_associated_types_inplace(sp, *pe.type, stack); // - If it's a closure, then the only trait impls are those generated by typeck TU_IFLET(::HIR::TypeRef::Data, pe.type->m_data, Closure, te, @@ -1634,7 +1745,10 @@ void TraitResolution::expand_associated_types__UfcsKnown(const Span& sp, ::HIR:: input = a->second.clone(); } } - input = this->expand_associated_types(sp, mv$(input)); + else { + DEBUG("- Found replacement: " << input); + } + this->expand_associated_types_inplace(sp, input, stack); return ; } @@ -1675,7 +1789,8 @@ void TraitResolution::expand_associated_types__UfcsKnown(const Span& sp, ::HIR:: else { input = it->second.clone(); } - input = this->expand_associated_types(sp, mv$(input)); + DEBUG("- Found replacement: " << input); + this->expand_associated_types_inplace(sp, input, stack); return ; } } @@ -1750,7 +1865,7 @@ void TraitResolution::expand_associated_types__UfcsKnown(const Span& sp, ::HIR:: } } if( rv ) { - input = this->expand_associated_types(sp, mv$(input)); + expand_associated_types_inplace(sp, input, stack); return ; } diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp index 19e97787..70813635 100644 --- a/src/hir_typeck/helpers.hpp +++ b/src/hir_typeck/helpers.hpp @@ -129,6 +129,7 @@ public: ::HIR::TypeRef& get_type(::HIR::TypeRef& type); const ::HIR::TypeRef& get_type(const ::HIR::TypeRef& type) const; + void check_for_loops(); void expand_ivars(::HIR::TypeRef& type); void expand_ivars_params(::HIR::PathParams& params); @@ -141,7 +142,6 @@ private: IVar& get_pointed_ivar(unsigned int slot) const; }; - class TraitResolution { const HMTypeInferrence& m_ivars; @@ -152,6 +152,7 @@ class TraitResolution ::std::map< ::HIR::TypeRef, ::HIR::TypeRef> m_type_equalities; + mutable ::std::vector< ::HIR::TypeRef> m_eat_active_stack; public: TraitResolution(const HMTypeInferrence& ivars, const ::HIR::Crate& crate, const ::HIR::GenericParams* impl_params, const ::HIR::GenericParams* item_params): m_ivars(ivars), @@ -182,8 +183,11 @@ public: bool has_associated_type(const ::HIR::TypeRef& ty) const; /// Expand any located associated types in the input, operating in-place and returning the result - ::HIR::TypeRef expand_associated_types(const Span& sp, ::HIR::TypeRef input) const; - void expand_associated_types__UfcsKnown(const Span& sp, ::HIR::TypeRef& input) const; + ::HIR::TypeRef expand_associated_types(const Span& sp, ::HIR::TypeRef input) const { + expand_associated_types_inplace(sp, input, LList<const ::HIR::TypeRef*>()); + return mv$(input); + } + const ::HIR::TypeRef& expand_associated_types(const Span& sp, const ::HIR::TypeRef& input, ::HIR::TypeRef& tmp) const { if( this->has_associated_type(input) ) { return (tmp = this->expand_associated_types(sp, input.clone())); @@ -230,5 +234,9 @@ public: /// Locates a named method in a trait, and returns the path of the trait that contains it (with fixed parameters) bool trait_contains_method(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::std::string& name, ::HIR::GenericPath& out_path) const; bool trait_contains_type(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::std::string& name, ::HIR::GenericPath& out_path) const; + +private: + void expand_associated_types_inplace(const Span& sp, ::HIR::TypeRef& input, LList<const ::HIR::TypeRef*> stack) const; + void expand_associated_types_inplace__UfcsKnown(const Span& sp, ::HIR::TypeRef& input, LList<const ::HIR::TypeRef*> stack) const; }; |