return tref;
}
+ DefId trait_id = trait_reference->get_mappings ().get_defid ();
+ if (context->trait_query_in_progress (trait_id))
+ {
+ rust_error_at (trait_reference->get_locus (), "trait cycle detected");
+ return &TraitReference::error_node ();
+ }
+
+ TraitQueryGuard guard (trait_id);
TyTy::BaseType *self = nullptr;
std::vector<TyTy::SubstitutionParamMapping> substitutions;
for (auto &generic_param : trait_reference->get_generic_params ())
HIR::TraitBound *b
= static_cast<HIR::TraitBound *> (bound.get ());
- // FIXME this might be recursive we need a check for that
auto predicate = get_predicate_from_bound (b->get_path ());
+ if (predicate.is_error ())
+ return &TraitReference::error_node ();
+
specified_bounds.push_back (predicate);
super_traits.push_back (predicate.get ());
}
return querys_in_progress.find (id) != querys_in_progress.end ();
}
+ void insert_trait_query (DefId id) { trait_queries_in_progress.insert (id); }
+
+ void trait_query_completed (DefId id)
+ {
+ trait_queries_in_progress.erase (id);
+ }
+
+ bool trait_query_in_progress (DefId id) const
+ {
+ return trait_queries_in_progress.find (id)
+ != trait_queries_in_progress.end ();
+ }
+
private:
TypeCheckContext ();
// query context lookups
std::set<HirId> querys_in_progress;
+ std::set<DefId> trait_queries_in_progress;
};
class TypeResolution
static void Resolve (HIR::Crate &crate);
};
+class TraitQueryGuard
+{
+public:
+ TraitQueryGuard (DefId id) : id (id), ctx (*TypeCheckContext::get ())
+ {
+ ctx.insert_trait_query (id);
+ }
+
+ ~TraitQueryGuard () { ctx.trait_query_completed (id); }
+
+private:
+ DefId id;
+ TypeCheckContext &ctx;
+};
+
} // namespace Resolver
} // namespace Rust
--- /dev/null
+pub trait A: B {}
+// { dg-error "trait cycle detected" "" { target *-*-* } .-1 }
+
+pub trait B: A {}
+// { dg-error "trait cycle detected" "" { target *-*-* } .-1 }