From b7d318f48db2cb83a41d665f1727ae93fc555124 Mon Sep 17 00:00:00 2001 From: Yong He Date: Thu, 28 Sep 2023 18:07:40 -0700 Subject: Support `constref` parameters passing. (#3249) * Support `constref` parameters passing. * Fix. * Fix. * Add test and diagnostic on mix use of __constref and no_diff. * check for [constref] on differentiable member method. --------- Co-authored-by: Yong He --- source/slang/slang-check-decl.cpp | 64 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 5 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 56b0a991b..351d5a9cc 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -1843,6 +1843,14 @@ namespace Slang return false; } + if (satisfyingMemberDeclRef.getDecl()->hasModifier() + && !requiredMemberDeclRef.getDecl()->hasModifier()) + { + // A `[constref]` method can't satisfy a non-`[constref]` requirement, + // but vice-versa is okay. + return false; + } + if(satisfyingMemberDeclRef.getDecl()->hasModifier() != requiredMemberDeclRef.getDecl()->hasModifier()) { @@ -2710,7 +2718,14 @@ namespace Slang auto synMutatingAttr = m_astBuilder->create(); addModifier(synFuncDecl, synMutatingAttr); } - + if (requiredMemberDeclRef.getDecl()->hasModifier()) + { + // If the interface requirement is `[constref]` then our + // synthesized method should be too. + // + auto synConstRefAttr = m_astBuilder->create(); + addModifier(synFuncDecl, synConstRefAttr); + } if (requiredMemberDeclRef.getDecl()->hasModifier()) { auto noDiffThisAttr = m_astBuilder->create(); @@ -5161,6 +5176,11 @@ namespace Slang // if(fstParam.getDecl()->hasModifier() != sndParam.getDecl()->hasModifier()) return false; + + // If one parameter is `constref` and the other isn't, then they don't match. + // + if (fstParam.getDecl()->hasModifier() != sndParam.getDecl()->hasModifier()) + return false; } // Note(tfoley): return type doesn't enter into it, because we can't take @@ -5625,20 +5645,31 @@ namespace Slang // Remove all existing direction modifiers, and replace them with a single Ref modifier. List newModifiers; bool hasRefModifier = false; + bool isMutable = false; for (auto modifier : paramDecl->modifiers) { - if (as(modifier) || as(modifier) || as(modifier)) + if (as(modifier)) + { + continue; + } + else if (as(modifier) || as(modifier)) { + isMutable = true; continue; } - if (as(modifier)) + if (as(modifier) || as(modifier)) { hasRefModifier = true; } newModifiers.add(modifier); } if (!hasRefModifier) - newModifiers.add(this->getASTBuilder()->create()); + { + if (isMutable) + newModifiers.add(this->getASTBuilder()->create()); + else + newModifiers.add(this->getASTBuilder()->create()); + } paramDecl->modifiers.first = newModifiers.getFirst(); for (Index i = 0; i < newModifiers.getCount(); i++) { @@ -5774,6 +5805,9 @@ namespace Slang case ParameterDirection::kParameterDirection_Ref: addModifier(param, m_astBuilder->create()); break; + case ParameterDirection::kParameterDirection_ConstRef: + addModifier(param, m_astBuilder->create()); + break; default: break; } @@ -5879,7 +5913,9 @@ namespace Slang // specialization. for (auto paramDecl : decl->getParameters()) { - if (paramDecl->type.type && !isTypeDifferentiable(paramDecl->type.type)) + if (!paramDecl->type.type) + continue; + if (!isTypeDifferentiable(paramDecl->type.type)) { if (!paramDecl->hasModifier()) { @@ -5888,6 +5924,24 @@ namespace Slang addModifier(paramDecl, noDiffModifier); } } + if (!paramDecl->hasModifier()) + { + if (auto modifier = paramDecl->findModifier()) + { + getSink()->diagnose(modifier, Diagnostics::cannotUseConstRefOnDifferentiableParameter); + } + } + } + if (!isEffectivelyStatic(decl)) + { + auto constrefAttr = decl->findModifier(); + if (constrefAttr) + { + if (isTypeDifferentiable(calcThisType(getParentDecl(decl)))) + { + getSink()->diagnose(constrefAttr, Diagnostics::cannotUseConstRefOnDifferentiableMemberMethod); + } + } } } } -- cgit v1.2.3