summaryrefslogtreecommitdiff
path: root/source/slang/slang-check-decl.cpp
diff options
context:
space:
mode:
authorSai Praveen Bangaru <31557731+saipraveenb25@users.noreply.github.com>2024-05-02 19:01:21 -0400
committerGitHub <noreply@github.com>2024-05-02 16:01:21 -0700
commitc763750a7305fbf12c1f5c177260294a32fe286d (patch)
treeec544212bd5bf0ac72cbe3c01d2ed85fc3f05cd9 /source/slang/slang-check-decl.cpp
parente5d49cf21db7a398afe6cfdb76f6b4a028e9eecb (diff)
Handle case where types can be used as their own `Differential` type. (#4057)
* Avoid synthesis for when types can be used as their own differenial + Add test * Add missing files.. * Fix issue with method synthesis for self-differential types + Add a generic test * Fix * Fix issue with out-of-date type resolution cache. Witness tables created during the conformance checking phase not being taken into account during the decl type resolution phase because the epoch is not updated after conformance checking. This leads to certain complex associated-type lookup chains (such as the one in tests/compute/assoctype-nested-lookup) not resolving properly and causing errors. * Delete self-differential-type-synthesis-extension.slang * Quick fix to repopulate stdlib cache for deferred stdlib loading * Update slang-check-decl.cpp
Diffstat (limited to 'source/slang/slang-check-decl.cpp')
-rw-r--r--source/slang/slang-check-decl.cpp44
1 files changed, 43 insertions, 1 deletions
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index 921bd38e9..0d089874e 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -2144,7 +2144,40 @@ namespace Slang
SLANG_RELEASE_ASSERT(aggTypeDecl);
synth.pushContainerScope(aggTypeDecl);
}
- else
+
+ // If we did not find an existing empty struct, we may need to synthesize one.
+ // But first, we check if the parent type can be used as its own differential type.
+ //
+ if (!aggTypeDecl
+ && as<AggTypeDecl>(context->parentDecl)
+ && canStructBeUsedAsSelfDifferentialType(as<AggTypeDecl>(context->parentDecl)))
+ {
+ // If the parent type can be used as its own differential type, we will create a typealias
+ // to itself as the differential type.
+ //
+ auto assocTypeDef = m_astBuilder->create<TypeDefDecl>();
+ assocTypeDef->nameAndLoc.name = getName("Differential");
+ assocTypeDef->type.type = context->conformingType;
+ assocTypeDef->parentDecl = context->parentDecl;
+ assocTypeDef->setCheckState(DeclCheckState::DefinitionChecked);
+ context->parentDecl->members.add(assocTypeDef);
+
+ markSelfDifferentialMembersOfType(as<AggTypeDecl>(context->parentDecl), context->conformingType);
+
+ if (doesTypeSatisfyAssociatedTypeConstraintRequirement(context->conformingType, requirementDeclRef, witnessTable))
+ {
+ witnessTable->add(requirementDeclRef.getDecl(), RequirementWitness(context->conformingType));
+
+ // Increase the epoch so that future calls to Type::getCanonicalType will return the up-to-date folded types.
+ m_astBuilder->incrementEpoch();
+ return true;
+ }
+
+ // Something went wrong.
+ return false;
+ }
+
+ if (!aggTypeDecl)
{
aggTypeDecl = m_astBuilder->create<StructDecl>();
aggTypeDecl->parentDecl = context->parentDecl;
@@ -5741,6 +5774,15 @@ namespace Slang
{
checkConformance(type, inheritanceDecl, decl);
}
+
+ // Successful conformance checking may have created new witness tables.
+ // Increment epoch to invalidate the cache, so subsequent canonical types are
+ // re-calculated.
+ //
+ // TODO: Is it really necessary to invalidate globally? Maybe there's a way to invalidate only the
+ // types that are affected by these interface decls.
+ //
+ astBuilder->incrementEpoch();
}
}