summaryrefslogtreecommitdiff
path: root/source/slang/slang-check-decl.cpp
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2024-09-05 11:24:19 -0700
committerGitHub <noreply@github.com>2024-09-05 11:24:19 -0700
commitd655302465457c5d3285ae5339201a0769cc38dc (patch)
tree4c0946ba4ea4879831133370d2203f569c135c35 /source/slang/slang-check-decl.cpp
parenta88055c6f5190ca62bb4aa853b4f0fa11546278f (diff)
Support `where` clause and type equality constraint. (#4986)
* Support `where` clause. * Fix. * Fix parser. * Enhance test to cover traditional __generic syntax. * Update user-guide. * Support `where` clause on associatedtype. * Fix. * Put in more comments.
Diffstat (limited to 'source/slang/slang-check-decl.cpp')
-rw-r--r--source/slang/slang-check-decl.cpp63
1 files changed, 40 insertions, 23 deletions
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index ad3f94fc3..02e3241a9 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -2278,14 +2278,18 @@ namespace Slang
markSelfDifferentialMembersOfType(as<AggTypeDecl>(context->parentDecl), context->conformingType);
+ witnessTable->add(requirementDeclRef.getDecl(), RequirementWitness(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;
}
+ else
+ {
+ witnessTable->m_requirementDictionary.remove(requirementDeclRef.getDecl());
+ }
// Something went wrong.
return false;
@@ -2471,19 +2475,16 @@ namespace Slang
// conformance on the synthesized decl.
checkAggTypeConformance(aggTypeDecl);
- if (doesTypeSatisfyAssociatedTypeConstraintRequirement(satisfyingType, requirementDeclRef, witnessTable))
+ witnessTable->add(requirementDeclRef.getDecl(), RequirementWitness(satisfyingType));
+ if (!doesTypeSatisfyAssociatedTypeConstraintRequirement(satisfyingType, requirementDeclRef, witnessTable))
{
- witnessTable->add(requirementDeclRef.getDecl(), RequirementWitness(satisfyingType));
-
- // Incrase the epoch so that future calls to Type::getCanonicalType will return the up-to-date folded types.
- m_astBuilder->incrementEpoch();
- return true;
+ // Note: the call to `doesTypeSatisfyAssociatedTypeConstraintRequirement` should always succeed.
+ // If not, there is something wrong with the code synthesis logic. For now we just return false
+ // instead of crashing so the user can work around the issues.
+ witnessTable->m_requirementDictionary.remove(requirementDeclRef.getDecl());
+ return false;
}
-
- // Note: the call to `doesTypeSatisfyAssociatedTypeConstraintRequirement` should always succeed.
- // If not, there is something wrong with the code synthesis logic. For now we just return false
- // instead of crashing so the user can work around the issues.
- return false;
+ return true;
}
void SemanticsDeclHeaderVisitor::visitGenericTypeConstraintDecl(GenericTypeConstraintDecl* decl)
@@ -2497,7 +2498,7 @@ namespace Slang
CheckConstraintSubType(decl->sub);
decl->sub = TranslateTypeNodeForced(decl->sub);
decl->sup = TranslateTypeNodeForced(decl->sup);
- if (!isValidGenericConstraintType(decl->sup) && !as<ErrorType>(decl->sub.type))
+ if (!decl->isEqualityConstraint && !isValidGenericConstraintType(decl->sup) && !as<ErrorType>(decl->sub.type))
{
getSink()->diagnose(decl->sup.exp, Diagnostics::invalidTypeForConstraint, decl->sup);
}
@@ -3548,18 +3549,28 @@ namespace Slang
bool SemanticsVisitor::doesTypeSatisfyAssociatedTypeConstraintRequirement(Type* satisfyingType, DeclRef<AssocTypeDecl> requiredAssociatedTypeDeclRef, RefPtr<WitnessTable> witnessTable)
{
+ SLANG_UNUSED(satisfyingType);
+
// We will enumerate the type constraints placed on the
// associated type and see if they can be satisfied.
//
bool conformance = true;
Val* witness = nullptr;
- for (auto requiredConstraintDeclRef : getMembersOfType<TypeConstraintDecl>(m_astBuilder, requiredAssociatedTypeDeclRef))
+ for (auto requiredConstraintDeclRef : getMembersOfType<GenericTypeConstraintDecl>(m_astBuilder, requiredAssociatedTypeDeclRef))
{
// Grab the type we expect to conform to from the constraint.
auto requiredSuperType = getSup(m_astBuilder, requiredConstraintDeclRef);
+ auto subType = getSub(m_astBuilder, requiredConstraintDeclRef);
+
// Perform a search for a witness to the subtype relationship.
- witness = tryGetSubtypeWitness(satisfyingType, requiredSuperType);
+ witness = tryGetSubtypeWitness(subType, requiredSuperType);
+ if (witness)
+ {
+ auto genConstraint = as<GenericTypeConstraintDecl>(requiredConstraintDeclRef.getDecl());
+ if (genConstraint && genConstraint->isEqualityConstraint && !isTypeEqualityWitness(witness))
+ witness = nullptr;
+ }
if (witness)
{
// If a subtype witness was found, then the conformance
@@ -3588,6 +3599,15 @@ namespace Slang
if (declRefType->getDeclRef().getDecl()->hasModifier<ToBeSynthesizedModifier>())
return false;
}
+
+ // Register the satisfying type to the witness table
+ // before checking the constraints, since the subtype of
+ // the constraints maybe referencing the satisfying type via
+ // witness lookups.
+ auto requirementWitness = RequirementWitness(satisfyingType->getCanonicalType());
+ witnessTable->m_requirementDictionary[requiredAssociatedTypeDeclRef.getDecl()]
+ = requirementWitness;
+
// We need to confirm that the chosen type `satisfyingType`,
// meets all the constraints placed on the associated type
// requirement `requiredAssociatedTypeDeclRef`.
@@ -3601,15 +3621,11 @@ namespace Slang
// TODO: if any conformance check failed, we should probably include
// that in an error message produced about not satisfying the requirement.
- if(conformance)
+ if (!conformance)
{
- // If all the constraints were satisfied, then the chosen
- // type can indeed satisfy the interface requirement.
- witnessTable->add(
- requiredAssociatedTypeDeclRef.getDecl(),
- RequirementWitness(satisfyingType->getCanonicalType()));
+ witnessTable->m_requirementDictionary.remove(requiredAssociatedTypeDeclRef.getDecl());
}
-
+
return conformance;
}
@@ -9667,7 +9683,8 @@ namespace Slang
ASTNodeType::DeclRefType);
auto typeParamDecl = as<DeclRefType>(genericTypeConstraintDecl.getDecl()->sub.type)->getDeclRef().getDecl();
List<Type*>* constraintTypes = genericConstraints.tryGetValue(typeParamDecl);
- assert(constraintTypes);
+ if (!constraintTypes)
+ continue;
constraintTypes->add(genericTypeConstraintDecl.getDecl()->getSup().type);
}