aboutsummaryrefslogtreecommitdiffstats
path: root/llvm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm.cpp')
-rw-r--r--llvm.cpp21
1 files changed, 19 insertions, 2 deletions
diff --git a/llvm.cpp b/llvm.cpp
index e963336..65632a4 100644
--- a/llvm.cpp
+++ b/llvm.cpp
@@ -234,12 +234,29 @@ AFn::liftCall(CEnv& cenv, const AType& argsT)
assert(gt != cenv.tenv.genericTypes.end());
AType* thisType = new AType(*gt->second);
Subst argsSubst;
+
if (!thisType->concrete()) {
// Build substitution to apply to generic type
assert(argsT.size() == prot()->size());
ATuple* genericProtT = gt->second->at(1)->as<ATuple*>();
- for (size_t i = 0; i < argsT.size(); ++i)
- argsSubst[genericProtT->at(i)->to<AType*>()] = argsT.at(i)->to<AType*>();
+ for (size_t i = 0; i < argsT.size(); ++i) {
+ const AType* genericArgT = genericProtT->at(i)->to<const AType*>();
+ AType* callArgT = argsT.at(i)->to<AType*>();
+ assert(genericArgT);
+ assert(callArgT);
+ if (callArgT->kind == AType::EXPR) {
+ assert(genericArgT->kind == AType::EXPR);
+ assert(callArgT->size() == genericArgT->size());
+ for (size_t i = 0; i < callArgT->size(); ++i) {
+ AType* gT = genericArgT->at(i)->to<AType*>();
+ AType* aT = callArgT->at(i)->to<AType*>();
+ if (gT && aT)
+ argsSubst[gT] = aT;
+ }
+ } else {
+ argsSubst[genericArgT] = callArgT;
+ }
+ }
// Apply substitution to get concrete type for this call
thisType = argsSubst.apply(thisType)->as<AType*>();