From 924193da89678161dd6d2f0f2dd2be5280bee402 Mon Sep 17 00:00:00 2001 From: Kalani Thielen Date: Mon, 27 Apr 2020 11:04:34 -0400 Subject: [PATCH] raise an error for instance generators not covering class members --- lib/hobbes/eval/cmodule.C | 2 ++ lib/hobbes/lang/preds/class.C | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/lib/hobbes/eval/cmodule.C b/lib/hobbes/eval/cmodule.C index 870a5bca3..98edcae78 100644 --- a/lib/hobbes/eval/cmodule.C +++ b/lib/hobbes/eval/cmodule.C @@ -332,6 +332,8 @@ void compile(const ModulePtr& m, cc* e, const InstanceDef* id) { } else { c->insert(TCInstanceFnPtr(new TCInstanceFn(id->className(), id->constraints(), targs, ms, id->la()))); } + } catch (annotated_error&) { + throw; } catch (std::exception& ex) { throw annotated_error(*id, ex.what()); } diff --git a/lib/hobbes/lang/preds/class.C b/lib/hobbes/lang/preds/class.C index ded7946b7..4cb979b46 100644 --- a/lib/hobbes/lang/preds/class.C +++ b/lib/hobbes/lang/preds/class.C @@ -106,6 +106,30 @@ void TClass::insert(const TCInstanceFnPtr& ifp) { ss << "Arity mismatch between instance generator definition (" << ifp->arity() << ") and type class definition (" << this->tvs << ")."; throw annotated_error(*ifp, ss.str()); } else { + // make sure that this instance generator covers all required members + auto mm = ifp->members(MonoTypeSubst()); + + std::ostringstream ss; + size_t errors = 0; + for (const auto& tcm : this->tcmembers) { + if (!mm.count(tcm.first)) { + ss << (errors?", ":"") << "expected definition of '" << tcm.first << "'"; + ++errors; + } + } + for (const auto& m : mm) { + if (!this->tcmembers.count(m.first)) { + ss << (errors?", ":"") << "unexpected definition of '" << m.first << "'"; + ++errors; + } + } + if (errors) { + std::ostringstream ess; + ess << "Can't introduce instance generator for '" << this->tcname << "': " << ss.str(); + throw annotated_error(*ifp, ess.str()); + } + + // insert the instance generator ifp->order = this->tcinstancefns.size(); this->tcinstancefns.push_back(ifp);