From: Philip Herron <philip.herron@embecosm.com>
When we have a type query where by generic substitution occurs we can hit
the case where we need to Probe the bounds of the substited item to
determine whether the the bounds are compatible this can cause us to
end up querying the same type recursively.
Fixes #1550
gcc/rust/ChangeLog:
* typecheck/rust-hir-type-check-base.cc (TypeCheckBase::query_type):
Check for recursive queries.
* typecheck/rust-hir-type-check.h: New functions: `query_completed`,
`query_in_progress`, `insert_query`.
* typecheck/rust-tyty-bounds.cc (TypeBoundsProbe::scan): Use `query_type` API.
---
gcc/rust/typecheck/rust-hir-type-check-base.cc | 10 ++++++++++
gcc/rust/typecheck/rust-hir-type-check.h | 12 ++++++++++++
gcc/rust/typecheck/rust-tyty-bounds.cc | 5 +++--
3 files changed, 25 insertions(+), 2 deletions(-)
@@ -495,14 +495,20 @@ TypeCheckBase::resolve_generic_params (
bool
TypeCheckBase::query_type (HirId reference, TyTy::BaseType **result)
{
+ if (context->query_in_progress (reference))
+ return false;
+
if (context->lookup_type (reference, result))
return true;
+ context->insert_query (reference);
+
HIR::Item *item = mappings->lookup_hir_item (reference);
if (item != nullptr)
{
rust_debug_loc (item->get_locus (), "resolved item {%u} to", reference);
*result = TypeCheckItem::Resolve (*item);
+ context->query_completed (reference);
return true;
}
@@ -520,6 +526,7 @@ TypeCheckBase::query_type (HirId reference, TyTy::BaseType **result)
reference);
*result = TypeCheckItem::ResolveImplItem (*impl_block, *impl_item);
+ context->query_completed (reference);
return true;
}
@@ -530,6 +537,7 @@ TypeCheckBase::query_type (HirId reference, TyTy::BaseType **result)
if (found_impl_block_type)
{
*result = TypeCheckItem::ResolveImplBlockSelf (*impl_block_by_type);
+ context->query_completed (reference);
return true;
}
@@ -544,6 +552,7 @@ TypeCheckBase::query_type (HirId reference, TyTy::BaseType **result)
rust_assert (block != nullptr);
*result = TypeCheckTopLevelExternItem::Resolve (extern_item, *block);
+ context->query_completed (reference);
return true;
}
@@ -551,6 +560,7 @@ TypeCheckBase::query_type (HirId reference, TyTy::BaseType **result)
Location possible_locus = mappings->lookup_location (reference);
rust_debug_loc (possible_locus, "query system failed to resolve: [%u]",
reference);
+ context->query_completed (reference);
return false;
}
@@ -372,6 +372,15 @@ public:
return true;
}
+ void insert_query (HirId id) { querys_in_progress.insert (id); }
+
+ void query_completed (HirId id) { querys_in_progress.erase (id); }
+
+ bool query_in_progress (HirId id) const
+ {
+ return querys_in_progress.find (id) != querys_in_progress.end ();
+ }
+
private:
TypeCheckContext ();
@@ -406,6 +415,9 @@ private:
// predicates
std::map<HirId, TyTy::TypeBoundPredicate> predicates;
+
+ // query context lookups
+ std::set<HirId> querys_in_progress;
};
class TypeResolution
@@ -34,8 +34,9 @@ TypeBoundsProbe::scan ()
if (!impl->has_trait_ref ())
return true;
- TyTy::BaseType *impl_type = TypeCheckItem::ResolveImplBlockSelf (*impl);
- if (impl_type->get_kind () == TyTy::TypeKind::ERROR)
+ HirId impl_ty_id = impl->get_type ()->get_mappings ().get_hirid ();
+ TyTy::BaseType *impl_type = nullptr;
+ if (!query_type (impl_ty_id, &impl_type))
return true;
if (!receiver->can_eq (impl_type, false))