From 24df5515d6c2f8537683d0e48d27a161c394e7cd Mon Sep 17 00:00:00 2001 From: Yong He Date: Fri, 30 Aug 2024 16:32:34 -0700 Subject: Support extension on generic type. (#4968) --- source/slang/slang-check-decl.cpp | 55 +++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 11 deletions(-) (limited to 'source/slang/slang-check-decl.cpp') 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 applyExtensionToType( SemanticsVisitor* semantics, ExtensionDecl* extDecl, - Type* type) + Type* type, + Dictionary* additionalSubtypeWitness) { if(!semantics) return DeclRef(); - 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(); conformanceDecl->parentDecl = decl; @@ -8253,7 +8254,31 @@ namespace Slang return; } + else if (auto genericTypeParamDecl = targetDeclRefType->getDeclRef().as()) + { + // If we are extending a generic type parameter as in `extension T`, + // we want to register the extension with the interface type `IFoo` instead. + auto genericDecl = as(genericTypeParamDecl.getDecl()->parentDecl); + if (!genericDecl) + goto error; + if (genericDecl != decl->parentDecl) + goto error; + bool isTypeConstrained = false; + for (auto constraintDecl : genericDecl->getMembersOfType()) + { + ensureDecl(constraintDecl, DeclCheckState::ReadyForReference); + if (targetDeclRefType == constraintDecl->sub.type) + { + auto supTypeDeclRef = isDeclRefTypeOf(constraintDecl->sup.type); + getShared()->registerCandidateExtension(supTypeDeclRef.getDecl(), decl); + isTypeConstrained = true; + } + } + if (isTypeConstrained) + return; + } } + error:; if (!as(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()) + { + // We will reach here when we are checking `extension 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()) { // In the body of an `extension`, the `This` @@ -8661,7 +8695,8 @@ namespace Slang DeclRef SemanticsVisitor::applyExtensionToType( ExtensionDecl* extDecl, - Type* type) + Type* type, + Dictionary* additionalSubtypeWitnessesForType) { DeclRef 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(extGenericDecl, nullptr).as(), - as(as(type)->declRef.substitutions.substitutions)); - return DeclRef(extDecl, subst).as(); - */ return createDefaultSubstitutionsIfNeeded(m_astBuilder, this, extDeclRef).as(); } -- cgit v1.2.3