diff options
| author | aidanfnv <aidanf@nvidia.com> | 2025-07-23 18:42:24 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-24 01:42:24 +0000 |
| commit | 26b9a176e08ec6918d6fdebe1d7b586336f6f0fd (patch) | |
| tree | 5a625c1dd35754ba559d9d30fdbf3afcd1190f7d /source | |
| parent | 9666fbcab891156fb058d6a1b8f427ccc3ffecab (diff) | |
Skip creating transitive witnesses for interface conformances that are inherited through structs (#7597)
* Eliminate null-pointer reference in multilevel struct interface inheritance
* Add test
* Replace witness nullptr guard with conformance check to skip the witness
* Update test
* Skip creating transitive witness entirely for struct-struct-interface
* format code (#14)
Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com>
* Removes casts, check for identity witness
---------
Co-authored-by: slangbot <ellieh+slangbot@nvidia.com>
Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com>
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/slang-check-inheritance.cpp | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/source/slang/slang-check-inheritance.cpp b/source/slang/slang-check-inheritance.cpp index 164828bac..49ca3d3ac 100644 --- a/source/slang/slang-check-inheritance.cpp +++ b/source/slang/slang-check-inheritance.cpp @@ -858,13 +858,37 @@ void SharedSemanticsContext::_mergeFacetLists( // SubtypeWitness* baseIsSubtypeOfFacet = foundFacet->subtypeWitness; - auto selfIsSubtypeOfFacet = _getASTBuilder()->getTransitiveSubtypeWitness( - selfIsSubtypeOfBase, - baseIsSubtypeOfFacet); + // Check if this would create an unwanted struct->struct->interface conformance + // We want to prevent transitive witnesses of the form: struct Child -> struct Parent -> + // interface IFoo + bool shouldSkipTransitiveWitness = false; - indirectFacet->setSubtypeWitness(_getASTBuilder(), selfIsSubtypeOfFacet); + auto selfType = selfIsSubtypeOfBase->getSub(); + auto baseType = selfIsSubtypeOfBase->getSup(); + auto facetType = baseIsSubtypeOfFacet->getSup(); - ioMergedFacets.add(indirectFacet); + if (selfType && baseType && facetType) + { + auto selfDeclRef = isDeclRefTypeOf<StructDecl>(selfType); + auto baseDeclRef = isDeclRefTypeOf<StructDecl>(baseType); + auto facetDeclRef = isDeclRefTypeOf<InterfaceDecl>(facetType); + + // Only skip if we have struct->struct->interface + // and the struct->struct witness is not the identity witness + shouldSkipTransitiveWitness = selfDeclRef && baseDeclRef && facetDeclRef && + !isTypeEqualityWitness(selfIsSubtypeOfBase); + } + + if (!shouldSkipTransitiveWitness) + { + auto selfIsSubtypeOfFacet = _getASTBuilder()->getTransitiveSubtypeWitness( + selfIsSubtypeOfBase, + baseIsSubtypeOfFacet); + + indirectFacet->setSubtypeWitness(_getASTBuilder(), selfIsSubtypeOfFacet); + + ioMergedFacets.add(indirectFacet); + } } // We picked one `foundFacet` above to be added to the merged |
