From 6a23949f07f4eba38086b656e7073ce3bf8cd2fe Mon Sep 17 00:00:00 2001 From: Yong He Date: Fri, 13 Jun 2025 22:13:00 -0700 Subject: Allow interface methods to have default implementations. (#7439) --- source/slang/slang-lower-to-ir.cpp | 76 +++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 39 deletions(-) (limited to 'source/slang/slang-lower-to-ir.cpp') diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index 596a091d4..a03c75d7d 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -1495,6 +1495,15 @@ bool shouldDeclBeTreatedAsInterfaceRequirement(Decl* requirementDecl) else if (const auto varDecl = as(requirementDecl)) { } + else if (as(requirementDecl)) + { + } + else if (as(requirementDecl)) + { + // A default impl stub function represents a concrete function, not + // a requirement. + return false; + } else if (const auto genericDecl = as(requirementDecl)) { return shouldDeclBeTreatedAsInterfaceRequirement(genericDecl->inner); @@ -1511,6 +1520,11 @@ bool shouldDeclBeTreatedAsInterfaceRequirement(Decl* requirementDecl) IRStructKey* getInterfaceRequirementKey(IRGenContext* context, Decl* requirementDecl) { + // Only specific types of decls are treated as requirements, e.g. methods and asssociated types. + // Other types of decls are allowed but not regarded as a requirement. + if (!shouldDeclBeTreatedAsInterfaceRequirement(requirementDecl)) + return nullptr; + // TODO: this special case logic can be removed if we also clean up // `doesGenericSignatureMatchRequirement` Currently `doesGenericSignatureMatchRequirement` will // use the inner func decl as the key in AST WitnessTable. Therefore we need to match this @@ -1518,11 +1532,6 @@ IRStructKey* getInterfaceRequirementKey(IRGenContext* context, Decl* requirement if (auto genericDecl = as(requirementDecl)) return getInterfaceRequirementKey(context, genericDecl->inner); - // Only specific types of decls are treated as requirements, e.g. methods and asssociated types. - // Other types of decls are allowed but not regarded as a requirement. - if (!shouldDeclBeTreatedAsInterfaceRequirement(requirementDecl)) - return nullptr; - IRStructKey* requirementKey = nullptr; if (context->shared->interfaceRequirementKeys.tryGetValue(requirementDecl, requirementKey)) { @@ -3046,6 +3055,14 @@ static Type* _findReplacementThisParamType(IRGenContext* context, DeclRef return thisType; } + if (auto defaultImplDeclRef = parentDeclRef.as()) + { + auto thisType = DeclRefType::create( + context->astBuilder, + DeclRef(defaultImplDeclRef.getDecl()->thisTypeDecl)); + return thisType; + } + return nullptr; } @@ -3257,6 +3274,10 @@ void collectParameterLists( ParameterListCollectMode mode, ParameterDirection thisParamDirection) { + // Don't collect any parameters beyond certain decls. + if (as(declRef) || as(declRef)) + return; + // The parameters introduced by any "parent" declarations // will need to come first, so we'll deal with that // logic here. @@ -9221,28 +9242,29 @@ struct DeclLoweringVisitor : DeclVisitor UInt operandCount = 0; for (auto requirementDecl : decl->getDirectMemberDecls()) { + auto innerRequirementDecl = requirementDecl; + if (as(requirementDecl)) + continue; if (as(requirementDecl)) - requirementDecl = getInner(requirementDecl); + innerRequirementDecl = getInner(requirementDecl); - if (as(requirementDecl) || as(requirementDecl)) + if (as(innerRequirementDecl) || as(innerRequirementDecl)) { - for (auto accessorDecl : - as(requirementDecl)->getDirectMemberDeclsOfType()) + for (auto accessorDecl : as(innerRequirementDecl) + ->getDirectMemberDeclsOfType()) { SLANG_UNUSED(accessorDecl); operandCount++; } } if (!shouldDeclBeTreatedAsInterfaceRequirement(requirementDecl)) - { continue; - } operandCount++; // As a special case, any type constraints placed // on an associated type will *also* need to be turned // into requirement keys for this interface. - if (auto associatedTypeDecl = as(requirementDecl)) + if (auto associatedTypeDecl = as(innerRequirementDecl)) { operandCount += associatedTypeDecl->getMembersOfType().getCount(); @@ -9374,6 +9396,8 @@ struct DeclLoweringVisitor : DeclVisitor auto requirementKey = getInterfaceRequirementKey(requirementDecl); if (!requirementKey) { + if (as(requirementDecl)) + continue; if (auto genericDecl = as(requirementDecl)) { // We need to form a declref into the inner decls in case of a generic @@ -11361,33 +11385,7 @@ struct DeclLoweringVisitor : DeclVisitor LoweredValInfo visitGenericDecl(GenericDecl* genDecl) { - // TODO: Should this just always visit/lower the inner decl? - - if (auto innerFuncDecl = as(genDecl->inner)) - return ensureDecl(context, innerFuncDecl); - else if (auto innerStructDecl = as(genDecl->inner)) - { - ensureDecl(context, innerStructDecl); - return LoweredValInfo(); - } - else if (auto extensionDecl = as(genDecl->inner)) - { - return ensureDecl(context, extensionDecl); - } - else if (auto interfaceDecl = as(genDecl->inner)) - { - return ensureDecl(context, interfaceDecl); - } - else if (auto typedefDecl = as(genDecl->inner)) - { - return ensureDecl(context, typedefDecl); - } - else if (auto subscriptDecl = as(genDecl->inner)) - { - return ensureDecl(context, subscriptDecl); - } - SLANG_RELEASE_ASSERT(false); - UNREACHABLE_RETURN(LoweredValInfo()); + return ensureDecl(context, genDecl->inner); } LoweredValInfo visitFunctionDeclBase(FunctionDeclBase* decl) -- cgit v1.2.3