diff options
| author | Julius Ikkala <julius.ikkala@gmail.com> | 2025-06-28 05:39:24 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-28 02:39:24 +0000 |
| commit | 7349dc5cff49cf22c82eb912813e47f30cd7a757 (patch) | |
| tree | 4d7b3e14f119e7bb48623e52c890b461fd3d9701 /source/slang/slang-check-constraint.cpp | |
| parent | a13dda4f214274a10d39f37c79622fc3e62da310 (diff) | |
Minimal optional constraints (#7422)
* Parse optional witness syntax
* Allow failing optional constraint
* Make `is` work with optional constraint
* Allow using optional constraint in checked if statements
* Fix tests
* Make it work with structs
* Fix MSVC build error
* Disallow using `as` with optional constraints
* Update test to match split is/as errors
* Add tests
* Fix uninitialized variables in tests
* Add tests of incorrect uses & fix related bugs
* Mention optional constraints in docs
* format code
* Fix type unification with NoneWitness
* Fix formatting
---------
Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com>
Co-authored-by: Nathan V. Morrical <natemorrical@gmail.com>
Diffstat (limited to 'source/slang/slang-check-constraint.cpp')
| -rw-r--r-- | source/slang/slang-check-constraint.cpp | 46 |
1 files changed, 35 insertions, 11 deletions
diff --git a/source/slang/slang-check-constraint.cpp b/source/slang/slang-check-constraint.cpp index 3020554c8..7c55c440c 100644 --- a/source/slang/slang-check-constraint.cpp +++ b/source/slang/slang-check-constraint.cpp @@ -360,9 +360,12 @@ DeclRef<Decl> SemanticsVisitor::trySolveConstraintSystem( for (auto constraintDeclRef : getMembersOfType<GenericTypeConstraintDecl>(m_astBuilder, genericDeclRef)) { + ValUnificationContext unificationContext; + unificationContext.optionalConstraint = + constraintDeclRef.getDecl()->hasModifier<OptionalConstraintModifier>(); if (!TryUnifyTypes( *system, - ValUnificationContext(), + unificationContext, getSub(m_astBuilder, constraintDeclRef), getSup(m_astBuilder, constraintDeclRef))) return DeclRef<Decl>(); @@ -487,8 +490,11 @@ DeclRef<Decl> SemanticsVisitor::trySolveConstraintSystem( auto joinType = TryJoinTypes(system, type, cType); if (!joinType) { - // failure! - return DeclRef<Decl>(); + if (c.isOptional) + joinType = type; + else + // failure! + return DeclRef<Decl>(); } type = QualType(joinType, type.isLeftValue || cType.isLeftValue); } @@ -696,12 +702,22 @@ DeclRef<Decl> SemanticsVisitor::trySolveConstraintSystem( subTypeWitness = nullptr; } - if (subTypeWitness) + bool witnessIsOptional = isWitnessUncheckedOptional(subTypeWitness); + bool constraintIsOptional = constraintDecl->hasModifier<OptionalConstraintModifier>(); + + if (subTypeWitness && (!witnessIsOptional || constraintIsOptional)) { // We found a witness, so it will become an (implicit) argument. args.add(subTypeWitness); outBaseCost += subTypeWitness->getOverloadResolutionCost(); } + else if (!subTypeWitness && constraintIsOptional) + { + // Optional witness failed to resolve; not an error. + auto noneWitness = m_astBuilder->getOrCreate<NoneWitness>(); + args.add(noneWitness); + outBaseCost += kConversionCost_FailedOptionalConstraint; + } else { // No witness was found, so the inference will now fail. @@ -851,13 +867,20 @@ bool SemanticsVisitor::TryUnifyVals( // Two subtype witnesses can be unified if they exist (non-null) and // prove that some pair of types are subtypes of types that can be unified. // - if (auto fstWit = as<SubtypeWitness>(fst)) - { - if (auto sndWit = as<SubtypeWitness>(snd)) - { - return TryUnifyTypes(constraints, unifyCtx, fstWit->getSup(), sndWit->getSup()); - } - } + const auto fstSubtypeWitness = as<SubtypeWitness>(fst); + const auto sndSubtypeWitness = as<SubtypeWitness>(snd); + const auto fstNoneWitness = as<NoneWitness>(fst); + const auto sndNoneWitness = as<NoneWitness>(snd); + if (fstSubtypeWitness && sndSubtypeWitness) + return TryUnifyTypes( + constraints, + unifyCtx, + fstSubtypeWitness->getSup(), + sndSubtypeWitness->getSup()); + else if (fstNoneWitness && sndNoneWitness) + return true; + else if ((fstNoneWitness && sndSubtypeWitness) || (fstSubtypeWitness && sndNoneWitness)) + return false; SLANG_UNIMPLEMENTED_X("value unification case"); @@ -946,6 +969,7 @@ bool SemanticsVisitor::TryUnifyTypeParam( constraint.indexInPack = unificationContext.indexInTypePack; constraint.val = type; constraint.isUsedAsLValue = type.isLeftValue; + constraint.isOptional = unificationContext.optionalConstraint; constraints.constraints.add(constraint); return true; |
