summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-check-decl.cpp
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2024-08-30 16:32:34 -0700
committerGitHub <noreply@github.com>2024-08-30 16:32:34 -0700
commit24df5515d6c2f8537683d0e48d27a161c394e7cd (patch)
treebbe71d5622514da5d7b60a55906adadf08f66639 /source/slang/slang-check-decl.cpp
parent49862e764c6c873d7ee694663f226631b8a41353 (diff)
Support extension on generic type. (#4968)
Diffstat (limited to 'source/slang/slang-check-decl.cpp')
-rw-r--r--source/slang/slang-check-decl.cpp55
1 files changed, 44 insertions, 11 deletions
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index 190433e2f..5654ac7a6 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -1075,12 +1075,13 @@ namespace Slang
DeclRef<ExtensionDecl> applyExtensionToType(
SemanticsVisitor* semantics,
ExtensionDecl* extDecl,
- Type* type)
+ Type* type,
+ Dictionary<Type*, SubtypeWitness*>* additionalSubtypeWitness)
{
if(!semantics)
return DeclRef<ExtensionDecl>();
- return semantics->applyExtensionToType(extDecl, type);
+ return semantics->applyExtensionToType(extDecl, type, additionalSubtypeWitness);
}
bool SemanticsVisitor::isDeclUsableAsStaticMember(
@@ -6320,7 +6321,7 @@ namespace Slang
{
// Force add IDefaultInitializable to any struct missing (transitively) `IDefaultInitializable`.
auto* defaultInitializableType = m_astBuilder->getDefaultInitializableType();
- if(!isSubtype(DeclRefType::create(m_astBuilder, decl), defaultInitializableType, IsSubTypeOptions::NotReadyForLookup))
+ if(!isSubtype(DeclRefType::create(m_astBuilder, decl), defaultInitializableType, IsSubTypeOptions::NoCaching))
{
InheritanceDecl* conformanceDecl = m_astBuilder->create<InheritanceDecl>();
conformanceDecl->parentDecl = decl;
@@ -8253,7 +8254,31 @@ namespace Slang
return;
}
+ else if (auto genericTypeParamDecl = targetDeclRefType->getDeclRef().as<GenericTypeParamDecl>())
+ {
+ // If we are extending a generic type parameter as in `extension<T:IFoo> T`,
+ // we want to register the extension with the interface type `IFoo` instead.
+ auto genericDecl = as<GenericDecl>(genericTypeParamDecl.getDecl()->parentDecl);
+ if (!genericDecl)
+ goto error;
+ if (genericDecl != decl->parentDecl)
+ goto error;
+ bool isTypeConstrained = false;
+ for (auto constraintDecl : genericDecl->getMembersOfType<GenericTypeConstraintDecl>())
+ {
+ ensureDecl(constraintDecl, DeclCheckState::ReadyForReference);
+ if (targetDeclRefType == constraintDecl->sub.type)
+ {
+ auto supTypeDeclRef = isDeclRefTypeOf<AggTypeDecl>(constraintDecl->sup.type);
+ getShared()->registerCandidateExtension(supTypeDeclRef.getDecl(), decl);
+ isTypeConstrained = true;
+ }
+ }
+ if (isTypeConstrained)
+ return;
+ }
}
+ error:;
if (!as<ErrorType>(decl->targetType.type))
{
getSink()->diagnose(decl->targetType.exp, Diagnostics::invalidExtensionOnType, decl->targetType);
@@ -8357,6 +8382,15 @@ namespace Slang
//
return DeclRefType::create(m_astBuilder, aggTypeDeclRef);
}
+ else if (auto genTypeParam = declRef.as<GenericTypeParamDecl>())
+ {
+ // We will reach here when we are checking `extension<T> T {...}`,
+ // where inside the extension, `This` type is the target type
+ // of the extension, in this case this is a DeclRefType to
+ // a GenericTypeParamDecl.
+ //
+ return DeclRefType::create(m_astBuilder, declRef);
+ }
else if (auto extDeclRef = declRef.as<ExtensionDecl>())
{
// In the body of an `extension`, the `This`
@@ -8661,7 +8695,8 @@ namespace Slang
DeclRef<ExtensionDecl> SemanticsVisitor::applyExtensionToType(
ExtensionDecl* extDecl,
- Type* type)
+ Type* type,
+ Dictionary<Type*, SubtypeWitness*>* additionalSubtypeWitnessesForType)
{
DeclRef<ExtensionDecl> extDeclRef = makeDeclRef(extDecl);
@@ -8674,6 +8709,11 @@ namespace Slang
ConstraintSystem constraints;
constraints.loc = extDecl->loc;
constraints.genericDecl = extGenericDecl;
+ if (additionalSubtypeWitnessesForType)
+ {
+ constraints.subTypeForAdditionalWitnesses = type;
+ constraints.additionalSubtypeWitnesses = additionalSubtypeWitnessesForType;
+ }
// Inside the body of an extension declaration, we may end up trying to apply that
// extension to its own target type.
@@ -8681,13 +8721,6 @@ namespace Slang
// without any additional substitutions.
if (extDecl->targetType->equals(type))
{
- /*
- auto subst = trySolveConstraintSystem(
- &constraints,
- DeclRef<Decl>(extGenericDecl, nullptr).as<GenericDecl>(),
- as<GenericSubstitution>(as<DeclRefType>(type)->declRef.substitutions.substitutions));
- return DeclRef<Decl>(extDecl, subst).as<ExtensionDecl>();
- */
return createDefaultSubstitutionsIfNeeded(m_astBuilder, this, extDeclRef).as<ExtensionDecl>();
}