diff options
| author | Yong He <yonghe@outlook.com> | 2024-09-05 11:24:19 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-09-05 11:24:19 -0700 |
| commit | d655302465457c5d3285ae5339201a0769cc38dc (patch) | |
| tree | 4c0946ba4ea4879831133370d2203f569c135c35 /source/slang/slang-check-decl.cpp | |
| parent | a88055c6f5190ca62bb4aa853b4f0fa11546278f (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.cpp | 63 |
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); } |
