summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hir_typeck/expr_cs.cpp16
-rw-r--r--src/hir_typeck/helpers.cpp165
-rw-r--r--src/hir_typeck/helpers.hpp14
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;
};