summaryrefslogtreecommitdiffstats
path: root/source/slang/check.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/check.cpp')
-rw-r--r--source/slang/check.cpp102
1 files changed, 101 insertions, 1 deletions
diff --git a/source/slang/check.cpp b/source/slang/check.cpp
index 233a82eef..4b8f4f4c1 100644
--- a/source/slang/check.cpp
+++ b/source/slang/check.cpp
@@ -148,7 +148,6 @@ namespace Slang
return expr->type->As<DeclRefType>();
}
-
RefPtr<Expr> ConstructDeclRefExpr(
DeclRef<Decl> declRef,
RefPtr<Expr> baseExpr,
@@ -1998,6 +1997,22 @@ namespace Slang
decl->SetCheckState(DeclCheckState::Checked);
}
+ void visitGlobalGenericParamDecl(GlobalGenericParamDecl * decl)
+ {
+ if (decl->IsChecked(DeclCheckState::Checked)) return;
+ decl->SetCheckState(DeclCheckState::CheckedHeader);
+ // global generic param only allowed in global scope
+ auto program = decl->ParentDecl->As<ModuleDecl>();
+ if (!program)
+ getSink()->diagnose(decl, Slang::Diagnostics::globalGenParamInGlobalScopeOnly);
+ // Now check all of the member declarations.
+ for (auto member : decl->Members)
+ {
+ checkDecl(member);
+ }
+ decl->SetCheckState(DeclCheckState::Checked);
+ }
+
void visitAssocTypeDecl(AssocTypeDecl* decl)
{
if (decl->IsChecked(DeclCheckState::Checked)) return;
@@ -3703,6 +3718,19 @@ namespace Slang
return true;
}
}
+ // if an inheritance decl is not found, try to find a GenericTypeConstraintDecl
+ for (auto genConstraintDeclRef : getMembersOfType<GenericTypeConstraintDecl>(aggTypeDeclRef))
+ {
+ EnsureDecl(genConstraintDeclRef.getDecl());
+ auto inheritedType = GetSup(genConstraintDeclRef);
+ TypeWitnessBreadcrumb breadcrumb;
+ breadcrumb.prev = inBreadcrumbs;
+ breadcrumb.declRef = genConstraintDeclRef;
+ if (doesTypeConformToInterfaceImpl(originalType, inheritedType, interfaceDeclRef, outWitness, &breadcrumb))
+ {
+ return true;
+ }
+ }
}
else if( auto genericTypeParamDeclRef = declRef.As<GenericTypeParamDecl>() )
{
@@ -6582,6 +6610,78 @@ namespace Slang
// that we don't have to re-do this effort again later.
entryPoint->decl = entryPointFuncDecl;
+ // Lookup generic parameter types in global scope
+ for (auto name : entryPoint->genericParameterTypeNames)
+ {
+ if (!translationUnitSyntax->memberDictionary.TryGetValue(name, firstDeclWithName))
+ {
+ // If there doesn't appear to be any such declaration, then
+ // we need to diagnose it as an error, and then bail out.
+ sink->diagnose(translationUnitSyntax, Diagnostics::entryPointTypeParameterNotFound, name);
+ return;
+ }
+ RefPtr<Type> type;
+ if (auto aggType = firstDeclWithName->As<AggTypeDecl>())
+ {
+ type = DeclRefType::Create(entryPoint->compileRequest->mSession, DeclRef<Decl>(aggType, nullptr));
+ }
+ else if (auto typeDefDecl = firstDeclWithName->As<TypeDefDecl>())
+ {
+ type = GetType(DeclRef<TypeDefDecl>(typeDefDecl, nullptr));
+ }
+ else
+ {
+ sink->diagnose(firstDeclWithName, Diagnostics::entryPointTypeSymbolNotAType, name);
+ return;
+ }
+ entryPoint->genericParameterTypes.Add(type);
+ }
+ // check that user-provioded type arguments conforms to the generic type
+ // parameter declaration of this translation unit
+
+ // collect global generic parameters from all imported modules
+ List<RefPtr<GlobalGenericParamDecl>> globalGenericParams;
+ // add current translation unit first
+ {
+ auto globalGenParams = translationUnit->SyntaxNode->getMembersOfType<GlobalGenericParamDecl>();
+ for (auto p : globalGenParams)
+ globalGenericParams.Add(p);
+ }
+ // add imported modules
+ for (auto moduleDecl : entryPoint->compileRequest->loadedModulesList)
+ {
+ auto globalGenParams = moduleDecl->getMembersOfType<GlobalGenericParamDecl>();
+ for (auto p : globalGenParams)
+ globalGenericParams.Add(p);
+ }
+ if (globalGenericParams.Count() != entryPoint->genericParameterTypes.Count())
+ {
+ sink->diagnose(entryPoint->decl, Diagnostics::mismatchEntryPointTypeArgument, globalGenericParams.Count(),
+ entryPoint->genericParameterTypes.Count());
+ return;
+ }
+ // if number of entry-point type arguments matches parameters, try find
+ // SubtypeWitness for each argument
+ int index = 0;
+ for (auto & gParam : globalGenericParams)
+ {
+ for (auto constraint : gParam->getMembersOfType<GenericTypeConstraintDecl>())
+ {
+ auto interfaceType = GetSup(DeclRef<GenericTypeConstraintDecl>(constraint, nullptr));
+ SemanticsVisitor visitor(sink, entryPoint->compileRequest, translationUnit);
+ auto witness = visitor.tryGetSubtypeWitness(entryPoint->genericParameterTypes[index], interfaceType);
+ if (!witness)
+ {
+ sink->diagnose(gParam,
+ Diagnostics::typeArgumentDoesNotConformToInterface, gParam->nameAndLoc.name, entryPoint->genericParameterTypes[index],
+ interfaceType);
+ }
+ entryPoint->genericParameterWitnesses.Add(witness);
+ }
+ index++;
+ }
+ if (sink->errorCount != 0)
+ return;
// TODO: after all that work, we are now in a position to start
// validating the declaration itself. E.g., we should check if
// the declared input/output parameters have suitable semantics,